export class maskClass { constructor(args) { this.spec = args.spec; this.set = args.set; this.filter = args.filter; this.tol = args.tol; this.color = args.color; this.visible = args.visible; this.canvas = NaN; if (this.visible == true) { this.canvas = gtl.plots.add("Model") }; } __getModel() { let __model = this.spec.base; //массив точек базовой линии let imin = 0; //левая граница коридора let imax = 0; //правая граница коридора for (let i = 0; i < this.spec.peaks.length; i++) { let freq = this.spec.peaks[i].freq; //получаем значение частоты гармоники из массива обнаруженных гармоник let level = this.spec.peaks[i].level; //получаем значение уровня гармоники из массива обнаруженных гармоник imin = Math.round((freq - freq * 0.5 * this.tol / 100) / this.spec.resolution); imax = Math.round((freq + freq * 0.5 * this.tol / 100) / this.spec.resolution); if (imax > this.spec.base.length) { imax = this.spec.base.length - 1 }; //проверяем выход границы за размер массива for (let j = imin; j <= imax; j++) { __model[j] = this.spec.base[j] + level }; }; if (this.visible == true) { this.canvas.add({ color: this.color, name: this.spec.name + "_model", x: this.spec.resolution, y: __model }); }; //отрисовка модели спектра на plot return __model; } //построение упрощенной модели спектра __getMask(options) { let __model = options.model; //массив точек спектра для сравнения с портретом let __mask = options.mask.base; //массив точек базовой линии для построения портрета дефекта let harms = options.harms; //кол-во гармоник портрета if (options.freq * harms > options.mask.frequency) { harms = Math.trunc(options.mask.frequency / options.freq) }; //проверяем максимальное кол-во гармоник в портрете let df = 0; //отношение ширины фильтра частотному разрешению спектра let dl = options.lvl; //разность уровней гармонической и случайной составляющей вибрации if (options.filter != 0) { df = options.mask.frequency / options.filter.width; dl = 10 * Math.log10((options.lvl ** 2) / df + 1); }; let k = options.coef; //коэффициент затухания let x = 0; //индекс элемента массива для гармоники let dx = 0; //коридор индексов let xmin = 0; //левая граница коридора let xmax = 0; //правая граница коридора let correlation = 0; //коэффициент корреляции function corr(a, b) { let X = 0; //аргумент 1 let Y = 0; //аргумент 2 let Z = 0; //аргумент 3 let a_avg = a.reduce((acc, item) => (acc + item)) / a.length; //среднее значение массива 1 let b_avg = b.reduce((acc, item) => (acc + item)) / b.length; //среднее значение массива 2 for (let i = 0; i < a.length; i++) { X += (a[i] - a_avg) * (b[i] - b_avg); Y += (a[i] - a_avg) ** 2; Z += (b[i] - b_avg) ** 2; }; if (X <= 0) { return 0 } else { return X / (Math.sqrt(Y) * Math.sqrt(Z)) }; }; let arr1 = []; let arr2 = []; switch (options.type) { case 0: //обычный ряд for (let i = 1; i <= harms; i++) { x = Math.trunc(i * options.freq / options.mask.resolution); //определяем инднекс элемента массива для гармоники dx = Math.trunc(i * (options.freq * options.tol / 100) / options.mask.resolution); //коридор индексов массива для гармоники xmin = x - Math.round(dx / 2); //определяем индекс левой границы коридора xmax = x + Math.round(dx / 2); //определяем индекс правой границы коридора if (xmax > options.mask.base.length) { xmax = options.mask.base.length - 2 }; //проверяем выход границы за размер массива for (let j = xmin; j <= xmax; j++) { __mask[j] = options.mask.base[j] + dl }; //записываем значение глубины модуляции для коридора dl = dl - (k * dl); //снижаем глубину модуляции с коэффициентом затухания for (let j = xmin - 2; j <= xmax + 2; j++) { arr1.push(__mask[j]); arr2.push(__model[j]); }; //формируем массивы портретной гармоники и спектра (модели) под портретом correlation += corr(arr1, arr2); //рассчитываем корреляцию данных из массивов }; break; case 1: //четные составляющие for (let i = 1; i <= harms; i++) { x = Math.trunc(i * options.freq / options.mask.resolution); //инднекс элемента массива для гармоники dx = Math.trunc(i * (options.freq * options.tol / 100) / options.mask.resolution); //коридор индексов массива для гармоники xmin = x - Math.round(dx / 2); //определяем индекс левой границы коридора xmax = x + Math.round(dx / 2); //определяем индекс правой границы коридора if (xmax > options.mask.base.length) { xmax = options.mask.base.length - 2 }; //проверяем выход границы за размер массива if (i % 2 > 0) { for (let j = xmin; j <= xmax; j++) { __mask[j] = options.mask.base[j] + k * dl }; //записываем значение глубины модуляции для коридора (нечетная гармоника) } else { for (let j = xmin; j <= xmax; j++) { __mask[j] = options.mask.base[j] + dl }; //записываем значение глубины модуляции для коридора (четная гармоника) dl = dl - (k * dl); //снижаем глубину модуляции с коэффициентом затухания }; for (let j = xmin - 2; j <= xmax + 2; j++) { arr1.push(__mask[j]); arr2.push(__model[j]); }; //формируем массивы портретной гармоники и спектра (модели) под портретом correlation += corr(arr1, arr2); //рассчитываем корреляцию данных из массивов }; break; default: break; }; let __result = correlation / harms; if (this.visible == true) { this.canvas.add({ color: options.color, name: options.name + " (" + __result.toFixed(2) + ")", x: options.mask.resolution, y: __mask }); }; //отрисовка маски дефекта на plot return __result; } //построение маски дефекта getResult() { let __result = {}; //результат let __model = this.__getModel(); //рисуем модель спектра и получаем массив его данных let __rows = Object.keys(this.set); //массив ключей объекта (наименование портретов) for (let i = 0; i < __rows.length; i++) { let __name = __rows[i]; //имена портретов let __arr = this.set[__name]; //массив значений let __corr = this.__getMask( { name: __name, //имя маски дефекта model: __model, //модель спектра для анализа (объект) mask: this.spec, //базовый спектр для построения портрета (объект) filter: this.filter, //полосовой фильтр (для определения разницы амплитуд гармонической и случайной составляющей) tol: this.tol, //коридор обнаружения гармоники на портрете, % color: __arr[0], //цвет портрета в формате HEX freq: __arr[1], //функциональная частота, Гц harms: __arr[2], //кол-во гармоник в портрете, шт lvl: __arr[3], //глубина модуляции сильного дефекта для портрета, % type: __arr[4], //тип портрета (0 - обычный ряд, 1 - четные составляющие) coef: __arr[5] //коэффициент затухания гармоник портрета: дефект (0.05 - 0.10), износ (0.30 - 0.50) } ); //рисуем маску дефекта и получаем значение корреляции if (__corr >= 0.5) { __result[__name] = __corr }; //добавляем данные в результат gtl.log.info("Вероятность: " + __name, __corr); //выводим корреляцию гармоник в лог }; return __result; } //оценка состояния по маске дефекта }