gtld2-diag-scripts/peakVM.js

279 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 function getCorr(src1, src2) {
let X = 0; //аргумент 1
let Y = 0; //аргумент 2
let Z = 0; //аргумент 3
let __avg1 = src1.reduce((acc, item) => (acc + item)) / src1.length; //среднее значение массива 1
let __avg2 = src2.reduce((acc, item) => (acc + item)) / src2.length; //среднее значение массива 2
for (let i = 0; i < arr1.length; i++) {
X += (src1[i] - __avg1) * (src2[i] - __avg2);
Y += (src1[i] - __avg1) ** 2;
Z += (src2[i] - __avg2) ** 2;
};
return X / (Math.sqrt(Y) * Math.sqrt(Z));
}; //рассчет корреляции
export function getAutoCorr(options) {
let result = {}; //результат
let plot = []; //массив значений корреляции для графика
let arr = options.src.values;
let arr2 = arr.concat(arr); //расширяем массив данных
let lag = 0.5;
let X = 0; //аргумент 1
let Y = 0; //аргумент 2
if (options.lag <= 0.5) { lag = options.lag } else { lag = 0.5 };
let T = Math.floor(arr.length * lag); //определяем количество индексов (шагов) для смещения массива
let avg = arr.reduce((acc, item) => (acc + item)) / arr.length; //среднее значение массива
Y = arr.reduce((acc, item) => (acc + (item - avg) ** 2), 0); //рассчитываем знаменатель функции
for (let i = 0; i < T; i++) {
X = 0;
for (let j = 0; j < arr.length; j++) { X += (arr[j] - avg) * (arr2[j + i] - avg) };
plot.push(X / Y); //записываем значение в массив коэффициентов
}; //смещение массива
let plot0 = plot.slice(Math.floor(0.01 * plot.length)); //убираем из массива первый 1% значений коэффициента (т.к. в нуле всегда значение 1.0)
let akf_avg = plot0.reduce((acc, item) => (acc + Math.abs(item)), 0) / plot0.length; //среднее значение коэффициента
let akf_sqr = plot0.reduce((acc, item) => (acc + item ** 2), 0); //сумма квадратов значений
let akf_rms = Math.sqrt(akf_sqr / plot0.length); //СКЗ коэффициента
let akf_max = Math.max(...plot0); //определяем максимальное значение коэффициента
result["avg"] = akf_avg;
result["rms"] = akf_rms;
result["ampl"] = akf_max;
result["data"] = plot;
if (options.canvas != undefined) {
options.canvas.add(
{
color: options.color,
name: options.name,
x: options.src.time,
y: plot
}
);
}; //отрисовка графика на plot
return result;
}; //рассчет автокорреляции
export function getWave(options) {
let __src = options.src; //источник данных
let __allert = 0;
let __fault = 0;
if (options.lvl != undefined) {
__allert = options.lvl;
__fault = 2 * __allert;
};
if (options.canvas != undefined) {
options.canvas.add(
{
color: __src.color,
name: __src.name,
x: __src.time,
y: __src.values
}
); //рисуем Waveform
if (__allert != 0) {
let __alr = __src.values.map((item) => (item = __allert));
let __flt = __src.values.map((item) => (item = __fault));
options.canvas.add(
{
color: 0xFFFF00,
name: "allert",
x: __src.time,
y: __alr
}
); //рисуем линию предупреждения
options.canvas.add(
{
color: 0xFF0000,
name: "fault",
x: __src.time,
y: __flt
}
); //рисуем линию опасности
};
};
return {
color: __src.color,
name: __src.name,
time: __src.time,
values: __src.values
}
}; //пиковая форма сигнала
export function getParams(freq) {
let rpm = freq * 60; //частота в об/мин
let wdt = 0; //граничная частота ФВЧ
let frq = 40 * freq; //граничная частота спектра
let lns = 800; //количество линий спектра
let avg = 1; //количество усреднений спектра
switch (true) {
case rpm <= 700:
wdt = 500;
lns = 800;
break;
case (rpm > 700) && (rpm <= 1500):
wdt = 1000;
lns = 800;
break;
case (rpm > 1500) && (rpm <= 3000):
wdt = 2000;
lns = 1600;
break;
case (rpm > 3000) && (rpm <= 4000):
wdt = 2000;
lns = 1600;
case rpm > 4000:
wdt = 5000;
lns = 1600;
default:
break;
};
return {
filter: { frequency: wdt },
spec: {
frequency: frq,
lines: lns,
resolution: frq / lns,
avg: avg
}
};
}; //рассчет параметров спектра
export function getLevels(freq) {
let rpm = freq * 60; //частота в об/мин
let alr = 0; //уровень предупреждения, g
switch (true) {
case rpm <= 900:
alr = 1.5 * (rpm / 900) ** 0.75; //1.5 => 3.0 для формы Peak-To-Peak
break;
case (rpm > 900) && (rpm <= 4000):
alr = 1.5; //1.5 => 3.0 для формы Peak-To-Peak
break;
case (rpm > 4000) && (rpm <= 10000):
alr = 1.5 * (rpm / 4000) ** 0.5; //1.5 => 3.0 для формы Peak-To-Peak
break;
case rpm > 10000:
alr = 3.0; //3.0 => 5.0 для формы Peak-To-Peak
default:
break;
};
return alr
}; //рассчет пороговых уровней
export function specSquare(spec, L, R) {
let __base = spec.base; //массив значений средней линии
let __data = spec.data; //массив значений амплитуд
let __lines = spec.data.length; //количества линий спектра
let __res = spec.resolution; //частотное разрешения спектра (высота прямоугольной трапеции)
let __start = 0; //стартовый индекс в массиве
let __end = __lines; //конечный индекс в массиве
let s0 = 0; //площадь под базовой линией
let s1 = 0; //площадь всего спектра
let s2 = 0; //площадь над базовой линией
let s3 = 0; //площадь обнаруженных гармоник
if (L != undefined) { __start = Math.round(L / __res) };
if (R != undefined) { __end = Math.round(R / __res) };
for (let i = __start; i <= __end - 1; i++) {
s0 += __base[i] * __res;
s1 += __data[i] * __res;
let __delta = __data[i] - __base[i];
if (__delta >= 0) { s2 += __delta * __res };
if (__delta >= spec.peak_level) { s3 += __delta * __res };
};
return {
base: s0,
spec: s1,
harm: s2,
peak: s3
};
}; //определение площадей спектра
export function getPeak(options) {
let __result = {}; //результат
let __wav = options.src; //массив данных пиковой формы
let __freq = options.freq; //частота вращения
let __mech = 0; //механические проблемы
let __lubr = 0; //проблемы со смазкой
let __allert = getLevels(__freq); //определяем уровень предупреждения, g
let __form = getWave(
{
src: __wav, //объект с данными максимальных амплитуд
lvl: __allert, //пороговый уровень предупреждения, g
canvas: options.canvas1 //координатная плоскость для отрисовки графика
}
); //получаем пиковую форму сигнала с порогами
let __crr = getAutoCorr(
{
name: "Корреляционная функция", //имя для графика
src: __wav, //объект с данными максимальных амплитуд
lag: 0.5, //коэффициент смещения сигнала
color: 0x00A550, //цвет отрисовки графика в формате HEX
canvas: options.canvas2 //координатная плоскость для отрисовки графика
}
); //вычисляем автокорреляционную функцию
let MaxPK = Math.max(...__wav.values); //максимальное значение амплитуды на пиковой форме, g
let FaultLevel = 2 * __allert; //уровень аварии для пиковой формы (Fault = 2 * Allert)
let EstPE = Math.sqrt(__crr.ampl) * 100; //расчетный процент периодической энергии
if (options.spec != undefined) {
let __spc = options.spec; //объект спектра пиковой формы
let GS = MaxPK / FaultLevel; //общая серьезность проблемы
let SQpeak = specSquare(__spc).peak; //площадь обнаруженных гармонических составляющих
let SQspec = specSquare(__spc).harm; //площадь над базовой линией
let PE = (SQpeak ** 2 / SQspec ** 2); //доля периодической энергии
let NPE = (SQspec ** 2 - SQpeak ** 2) / SQspec ** 2; //доля непериодической энергии
__mech = GS * PE * 100;
__lubr = GS * NPE * 100;
__result = {
mechBS: __mech,
lubrBS: __lubr,
//mechInd: __mech * 0.8, //нормализованное значение (для индикатора 0-100 единиц)
//lubrInd: __lubr * 0.8 //нормализованное значение (для индикатора 0-100 единиц)
};
} else {
switch (true) {
case EstPE >= 50:
__mech = EstPE * MaxPK / FaultLevel;
__lubr = (100 - EstPE) * MaxPK / FaultLevel;
break;
case (EstPE <= 50) && (EstPE > 30):
EstPE = EstPE / 2;
__mech = EstPE * MaxPK / FaultLevel;
__lubr = (100 - EstPE) * MaxPK / FaultLevel;
break;
case EstPE < 30:
__mech = 0
__lubr = MaxPK / FaultLevel;
break;
default:
break;
}; //определяем действительный расчетный процент периодической энергии
__result = {
mechBS: __mech,
lubrBS: __lubr
};
};
return __result;
}; //оценка состояния методом PeakVM