export function specModel(spec, tol, color, canvas) { let result = {}; //результат let model = spec.base; //массив точек базовой линии для построения упрощенной модели спектра let imin = 0; //левая граница коридора let imax = 0; //правая граница коридора for (let i = 0; i < spec.peaks.length; i++) { let freq = spec.peaks[i].freq; //получаем значение частоты гармоники из массива обнаруженных гармоник let level = spec.peaks[i].level; //получаем значение уровня гармоники из массива обнаруженных гармоник imin = Math.round((freq - freq * 0.5 * tol / 100) / spec.resolution); imax = Math.round((freq + freq * 0.5 * tol / 100) / spec.resolution); if (imax > spec.base.length) { imax = spec.base.length - 1 }; //проверяем выход границы за размер массива for (let j = imin; j <= imax; j++) { model[j] = spec.base[j] + level }; }; //формируем результат result["name"] = "model_" + spec.name; result["resolution"] = spec.resolution; result["data"] = model; //отрисовка графика на plot if (canvas != undefined) { canvas.add( { color: color, name: result.name, x: result.resolution, y: model } ); }; return result; }; //построение упрощенной модели спектра export function getMask(options) { let result = {}; //результат let data = options.src1.data; //массив точек спектра для сравнения с портретом let mask = options.src2.base; //массив точек базовой линии для построения портрета дефекта let harms = options.harms; //кол-во гармоник портрета if (options.freq * harms > options.src2.frequency) { harms = Math.trunc(options.src2.frequency / options.freq) }; //проверяем максимальное кол-во гармоник в портрете let df = 0; //отношение ширины фильтра частотному разрешению спектра let dl = options.lvl; //разность уровней гармонической и случайной составляющей вибрации if (options.filter != 0) { df = options.src2.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 a_sum = 0; //сумма значений массива 1 let b_sum = 0; //сумма значений массива 2 let X = 0; //аргумент 1 let Y = 0; //аргумент 2 let Z = 0; //аргумент 3 for (let i = 0; i < a.length; i++) { a_sum += a[i] }; for (let i = 0; i < b.length; i++) { b_sum += b[i] }; let a_avg = a_sum / a.length; let b_avg = b_sum / b.length; 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; }; //gtl.log.info("Корреляция гармоники:", X / (Math.sqrt(Y) * Math.sqrt(Z))); 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.src2.resolution); //определяем инднекс элемента массива для гармоники dx = Math.trunc(i * (options.freq * options.tol / 100) / options.src2.resolution); //коридор индексов массива для гармоники xmin = x - Math.round(dx / 2); //определяем индекс левой границы коридора xmax = x + Math.round(dx / 2); //определяем индекс правой границы коридора if (xmax > options.src2.base.length) { xmax = options.src2.base.length - 2 }; //проверяем выход границы за размер массива for (let j = xmin; j <= xmax; j++) { mask[j] = options.src2.base[j] + dl }; //записываем значение глубины модуляции для коридора dl = dl - (k * dl); //снижаем глубину модуляции с коэффициентом затухания for (let j = xmin - 2; j <= xmax + 2; j++) { arr1.push(mask[j]); arr2.push(data[j]); }; //формируем массивы портретной гармоники и спектра (модели) под портретом correlation += corr(arr1, arr2); //рассчитываем корреляцию данных из массивов }; break; case 1: //четные составляющие for (let i = 1; i <= harms; i++) { x = Math.trunc(i * options.freq / options.src2.resolution); //инднекс элемента массива для гармоники dx = Math.trunc(i * (options.freq * options.tol / 100) / options.src2.resolution); //коридор индексов массива для гармоники xmin = x - Math.round(dx / 2); //определяем индекс левой границы коридора xmax = x + Math.round(dx / 2); //определяем индекс правой границы коридора if (xmax > options.src2.base.length) { xmax = options.src2.base.length - 2 }; //проверяем выход границы за размер массива if (i % 2 > 0) { for (let j = xmin; j <= xmax; j++) { mask[j] = options.src2.base[j] + k * dl }; //записываем значение глубины модуляции для коридора (нечетная гармоника) } else { for (let j = xmin; j <= xmax; j++) { mask[j] = options.src2.base[j] + dl }; //записываем значение глубины модуляции для коридора (четная гармоника) dl = dl - (k * dl); //снижаем глубину модуляции с коэффициентом затухания }; for (let j = xmin - 2; j <= xmax + 2; j++) { arr1.push(mask[j]); arr2.push(data[j]); }; //формируем массивы портретной гармоники и спектра (модели) под портретом correlation += corr(arr1, arr2); //рассчитываем корреляцию данных из массивов }; break; default: break; }; //формируем результат result["name"] = options.name; //имя маски дефекта result["corr"] = correlation / harms; //средняя корреляция result["data"] = mask; //массив данных портрета //отрисовка графика на plot if (options.canvas != undefined) { options.canvas.add( { color: options.color, name: options.name + " (" + result.corr.toFixed(2) + ")", x: options.src2.resolution, y: mask } ); }; return result; }; //построение портрета дефекта export function corr(spec1, spec2) { let result = {}; //результат let plot = []; //массив значений корреляции для графика let corr = 0; //коэффициент корреляции let arr1 = spec1.data; let arr2 = spec2.data; let arr1_sum = 0; //сумма значений массива 1 let arr2_sum = 0; //сумма значений массива 2 let X = 0; //аргумент 1 let Y = 0; //аргумент 2 let Z = 0; //аргумент 3 for (let i = 0; i < arr1.length; i++) { arr1_sum += arr1[i] }; for (let i = 0; i < arr2.length; i++) { arr2_sum += arr2[i] }; let arr1_avg = arr1_sum / arr1.length; let arr2_avg = arr2_sum / arr2.length; for (let i = 0; i < arr1.length; i++) { X += (arr1[i] - arr1_avg) * (arr2[i] - arr2_avg); Y += (arr1[i] - arr1_avg) ** 2; Z += (arr2[i] - arr2_avg) ** 2; plot.push(X / (Math.sqrt(Y) * Math.sqrt(Z))); }; corr = X / (Math.sqrt(Y) * Math.sqrt(Z)); result["corr"] = corr; result["plot"] = plot; return result; }; //рассчет корреляции спектров