gtld2-diag-scripts/classes/maskClass.js

163 lines
11 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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;
} //оценка состояния по маске дефекта
}