From 51300f474936c2de00ce4325b5dbf2f3bca3e86e Mon Sep 17 00:00:00 2001 From: Vladimir Demidov Date: Mon, 5 May 2025 22:51:55 +0300 Subject: [PATCH] Revert "Added power spectral density curves at the spectrum chart (#820)" This reverts commit a263152356d0e889a286e5aa9474adbb672b3547. --- index.html | 1 - src/graph_spectrum.js | 9 --- src/graph_spectrum_calc.js | 148 +------------------------------------ src/graph_spectrum_plot.js | 116 +++-------------------------- 4 files changed, 14 insertions(+), 260 deletions(-) diff --git a/index.html b/index.html index 3f41083f..5218a8d4 100644 --- a/index.html +++ b/index.html @@ -459,7 +459,6 @@

Workspace

- diff --git a/src/graph_spectrum.js b/src/graph_spectrum.js index 5d07c588..c89251a5 100644 --- a/src/graph_spectrum.js +++ b/src/graph_spectrum.js @@ -116,10 +116,6 @@ export function FlightLogAnalyser(flightLog, canvas, analyserCanvas) { fftData = GraphSpectrumCalc.dataLoadPidErrorVsSetpoint(); break; - case SPECTRUM_TYPE.POWER_SPECTRAL_DENSITY: - fftData = GraphSpectrumCalc.dataLoadPSD(analyserZoomY); - break; - case SPECTRUM_TYPE.FREQUENCY: default: fftData = GraphSpectrumCalc.dataLoadFrequency(); @@ -191,11 +187,6 @@ export function FlightLogAnalyser(flightLog, canvas, analyserCanvas) { debounce(100, function () { analyserZoomY = 1 / (analyserZoomYElem.val() / 100); GraphSpectrumPlot.setZoom(analyserZoomX, analyserZoomY); - // Recalculate PSD with updated samples per segment count - if (userSettings.spectrumType == SPECTRUM_TYPE.POWER_SPECTRAL_DENSITY) { - dataLoad(); - GraphSpectrumPlot.setData(fftData, userSettings.spectrumType); - } that.refresh(); }) ) diff --git a/src/graph_spectrum_calc.js b/src/graph_spectrum_calc.js index da9b24e3..b358dc22 100644 --- a/src/graph_spectrum_calc.js +++ b/src/graph_spectrum_calc.js @@ -106,33 +106,6 @@ GraphSpectrumCalc.dataLoadFrequency = function() { return fftData; }; -GraphSpectrumCalc.dataLoadPSD = function(analyserZoomY) { - const flightSamples = this._getFlightSamplesFreq(false); - - let pointsPerSegment = 512; - const multiplier = Math.floor(1 / analyserZoomY); // 0. ... 10 - if (multipiler == 0) { - pointsPerSegment = 256; - } else if (multiplier > 1) { - pointsPerSegment *= 2 ** Math.floor(multiplier / 2); - } - pointsPerSegment = Math.min(pointsPerSegment, flightSamples.samples.length); - const overlapCount = Math.floor(pointsPerSegment / 2); - - const psd = this._psd(flightSamples.samples, pointsPerSegment, overlapCount); - - const psdData = { - fieldIndex : this._dataBuffer.fieldIndex, - fieldName : this._dataBuffer.fieldName, - psdLength : psd.psdOutput.length, - psdOutput : psd.psdOutput, - blackBoxRate : this._blackBoxRate, - minimum: psd.min, - maximum: psd.max, - maxNoiseIdx: psd.maxNoiseIdx, - }; - return psdData; -}; GraphSpectrumCalc._dataLoadFrequencyVsX = function(vsFieldNames, minValue = Infinity, maxValue = -Infinity) { @@ -310,7 +283,7 @@ GraphSpectrumCalc._getFlightChunks = function() { return allChunks; }; -GraphSpectrumCalc._getFlightSamplesFreq = function(scaled = true) { +GraphSpectrumCalc._getFlightSamplesFreq = function() { const allChunks = this._getFlightChunks(); @@ -320,11 +293,7 @@ GraphSpectrumCalc._getFlightSamplesFreq = function(scaled = true) { let samplesCount = 0; for (const chunk of allChunks) { for (const frame of chunk.frames) { - if (scaled) { - samples[samplesCount] = this._dataBuffer.curve.lookupRaw(frame[this._dataBuffer.fieldIndex]); - } else { - samples[samplesCount] = frame[this._dataBuffer.fieldIndex]; - } + samples[samplesCount] = (this._dataBuffer.curve.lookupRaw(frame[this._dataBuffer.fieldIndex])); samplesCount++; } } @@ -516,116 +485,3 @@ GraphSpectrumCalc._normalizeFft = function(fftOutput, fftLength) { return fftData; }; - -/** - * Compute PSD for data samples by Welch method follow Python code - */ -GraphSpectrumCalc._psd = function(samples, pointsPerSegment, overlapCount, scaling = 'density') { -// Compute FFT for samples segments - const fftOutput = this._fft_segmented(samples, pointsPerSegment, overlapCount); - - const dataCount = fftOutput[0].length; - const segmentsCount = fftOutput.length; - const psdOutput = new Float64Array(dataCount); - -// Compute power scale coef - let scale = 1; - if (userSettings.analyserHanning) { - const window = Array(pointsPerSegment).fill(1); - this._hanningWindow(window, pointsPerSegment); - if (scaling == 'density') { - let skSum = 0; - for (const value of window) { - skSum += value ** 2; - } - scale = 1 / (this._blackBoxRate * skSum); - } else if (scaling == 'spectrum') { - let sum = 0; - for (const value of window) { - sum += value; - } - scale = 1 / sum ** 2; - } - } else if (scaling == 'density') { - scale = 1 / pointsPerSegment; - } else if (scaling == 'spectrum') { - scale = 1 / pointsPerSegment ** 2; - } - -// Compute average for scaled power - let min = 1e6, - max = -1e6; - // Early exit if no segments were processed - if (segmentsCount === 0) { - return { - psdOutput: new Float64Array(0), - min: 0, - max: 0, - maxNoiseIdx: 0 - }; - } - const maxFrequency = (this._blackBoxRate / 2.0); - const noise50HzIdx = 50 / maxFrequency * dataCount; - const noise3HzIdx = 3 / maxFrequency * dataCount; - let maxNoiseIdx = 0; - let maxNoise = -100; - for (let i = 0; i < dataCount; i++) { - psdOutput[i] = 0.0; - for (let j = 0; j < segmentsCount; j++) { - let p = scale * fftOutput[j][i] ** 2; - if (i != dataCount - 1) { - p *= 2; - } - psdOutput[i] += p; - } - - const min_avg = 1e-7; // limit min value for -70db - let avg = psdOutput[i] / segmentsCount; - avg = Math.max(avg, min_avg); - psdOutput[i] = 10 * Math.log10(avg); - if (i > noise3HzIdx) { // Miss big zero freq magnitude - min = Math.min(psdOutput[i], min); - max = Math.max(psdOutput[i], max); - } - if (i > noise50HzIdx && psdOutput[i] > maxNoise) { - maxNoise = psdOutput[i]; - maxNoiseIdx = i; - } - } - - const maxNoiseFrequency = maxNoiseIdx / dataCount * maxFrequency; - - return { - psdOutput: psdOutput, - min: min, - max: max, - maxNoiseIdx: maxNoiseFrequency, - }; -}; - - -/** - * Compute FFT for samples segments by lenghts as n_per_seg with n_overlap overlap points count - */ -GraphSpectrumCalc._fft_segmented = function(samples, n_per_seg, n_overlap) { - const samplesCount = samples.length; - let output = []; - for (let i = 0; i < samplesCount - n_per_seg; i += n_per_seg - n_overlap) { - const fftInput = samples.slice(i, i + n_per_seg); - - if (userSettings.analyserHanning) { - this._hanningWindow(fftInput, n_per_seg); - } - - const fftComplex = this._fft(fftInput); - const magnitudes = new Float64Array(n_per_seg / 2); - for (let i = 0; i < n_per_seg / 2; i++) { - const re = fftComplex[2 * i]; - const im = fftComplex[2 * i + 1]; - magnitudes[i] = Math.hypot(re, im); - } - output.push(magnitudes); - } - - return output; -}; diff --git a/src/graph_spectrum_plot.js b/src/graph_spectrum_plot.js index 2ff35470..b43d4aea 100644 --- a/src/graph_spectrum_plot.js +++ b/src/graph_spectrum_plot.js @@ -17,7 +17,6 @@ export const SPECTRUM_TYPE = { FREQ_VS_THROTTLE: 1, PIDERROR_VS_SETPOINT: 2, FREQ_VS_RPM: 3, - POWER_SPECTRAL_DENSITY: 4, }; export const SPECTRUM_OVERDRAW_TYPE = { @@ -172,10 +171,6 @@ GraphSpectrumPlot._drawGraph = function (canvasCtx) { case SPECTRUM_TYPE.PIDERROR_VS_SETPOINT: this._drawPidErrorVsSetpointGraph(canvasCtx); break; - - case SPECTRUM_TYPE.POWER_SPECTRAL_DENSITY: - this._drawPowerSpectralDensityGraph(canvasCtx); - break; } }; @@ -299,64 +294,7 @@ GraphSpectrumPlot._drawFrequencyGraph = function (canvasCtx) { this._fftData.fieldName, WIDTH - 4, HEIGHT - 6, - "right", - ); - this._drawHorizontalGridLines( - canvasCtx, - PLOTTED_BLACKBOX_RATE / 2, - LEFT, - TOP, - WIDTH, - HEIGHT, - MARGIN, - "Hz", - ); -}; - -GraphSpectrumPlot._drawPowerSpectralDensityGraph = function (canvasCtx) { - const HEIGHT = canvasCtx.canvas.height - MARGIN; - const ACTUAL_MARGIN_LEFT = this._getActualMarginLeft(); - const WIDTH = canvasCtx.canvas.width - ACTUAL_MARGIN_LEFT; - const LEFT = canvasCtx.canvas.offsetLeft + ACTUAL_MARGIN_LEFT; - const TOP = canvasCtx.canvas.offsetTop; - - const PLOTTED_BLACKBOX_RATE = this._fftData.blackBoxRate / this._zoomX; - - canvasCtx.save(); - canvasCtx.translate(LEFT, TOP); - this._drawGradientBackground(canvasCtx, WIDTH, HEIGHT); - - const pointsCount = this._fftData.psdLength; - const scaleX = 2 * WIDTH / PLOTTED_BLACKBOX_RATE * this._zoomX; - canvasCtx.beginPath(); - canvasCtx.lineWidth = 1; - canvasCtx.strokeStyle = "white"; - - // Allign y axis range by 10db - const dbStep = 10; - const minY = Math.floor(this._fftData.minimum / dbStep) * dbStep; - const maxY = (Math.floor(this._fftData.maximum / dbStep) + 1) * dbStep; - const ticksCount = (maxY - minY) / dbStep; - const scaleY = HEIGHT / (maxY - minY); - //Store vsRange for _drawMousePosition - this._fftData.vsRange = { - min: minY, - max: maxY, - }; - canvasCtx.moveTo(0, 0); - for (let pointNum = 0; pointNum < pointsCount; pointNum++) { - const freq = PLOTTED_BLACKBOX_RATE / 2 * pointNum / pointsCount; - const y = HEIGHT - (this._fftData.psdOutput[pointNum] - minY) * scaleY; - canvasCtx.lineTo(freq * scaleX, y); - } - canvasCtx.stroke(); - - this._drawAxisLabel( - canvasCtx, - this._fftData.fieldName, - WIDTH - 4, - HEIGHT - 6, - "right", + "right" ); this._drawHorizontalGridLines( canvasCtx, @@ -366,33 +304,8 @@ GraphSpectrumPlot._drawPowerSpectralDensityGraph = function (canvasCtx) { WIDTH, HEIGHT, MARGIN, - "Hz", - ); - this._drawVerticalGridLines( - canvasCtx, - LEFT, - TOP, - WIDTH, - HEIGHT, - minY, - maxY, - "dBm/Hz", - ticksCount, - ); - const offset = 1; - this._drawInterestFrequency( - canvasCtx, - this._fftData.maxNoiseIdx, - PLOTTED_BLACKBOX_RATE, - "Max noise", - WIDTH, - HEIGHT, - 15 * offset + MARGIN, - "rgba(255,0,0,0.50)", - 3, + "Hz" ); - - canvasCtx.restore(); }; GraphSpectrumPlot._drawFrequencyVsXGraph = function (canvasCtx) { @@ -949,7 +862,7 @@ GraphSpectrumPlot._drawFiltersAndMarkers = function (canvasCtx) { canvasCtx, this._fftData.maxNoiseIdx, PLOTTED_BLACKBOX_RATE, - "Max noise", + "Max motor noise", WIDTH, HEIGHT, 15 * offset + MARGIN, @@ -1080,22 +993,22 @@ GraphSpectrumPlot._drawVerticalGridLines = function ( HEIGHT, minValue, maxValue, - label, - ticks = 5, + label ) { + const TICKS = 5; - for (let i = 0; i <= ticks; i++) { + for (let i = 0; i <= TICKS; i++) { canvasCtx.beginPath(); canvasCtx.lineWidth = 1; canvasCtx.strokeStyle = "rgba(255,255,255,0.25)"; - const verticalPosition = i * (HEIGHT / ticks); + const verticalPosition = i * (HEIGHT / TICKS); canvasCtx.moveTo(0, verticalPosition); canvasCtx.lineTo(WIDTH, verticalPosition); canvasCtx.stroke(); const verticalAxisValue = ( - (maxValue - minValue) * ((ticks - i) / ticks) + + (maxValue - minValue) * ((TICKS - i) / TICKS) + minValue ).toFixed(0); let textBaseline; @@ -1103,7 +1016,7 @@ GraphSpectrumPlot._drawVerticalGridLines = function ( case 0: textBaseline = "top"; break; - case ticks: + case TICKS: textBaseline = "bottom"; break; default: @@ -1216,8 +1129,8 @@ GraphSpectrumPlot._drawGradientBackground = function ( ); if (this._isFullScreen) { - backgroundGradient.addColorStop(1, "rgba(0,0,0,1)"); - backgroundGradient.addColorStop(0, "rgba(0,0,0,0.9)"); + backgroundGradient.addColorStop(1, "rgba(0,0,0,0.9)"); + backgroundGradient.addColorStop(0, "rgba(0,0,0,0.7)"); } else { backgroundGradient.addColorStop(1, "rgba(255,255,255,0.25)"); backgroundGradient.addColorStop(0, "rgba(255,255,255,0)"); @@ -1446,8 +1359,7 @@ GraphSpectrumPlot._drawMousePosition = function ( if ( this._spectrumType === SPECTRUM_TYPE.FREQUENCY || this._spectrumType === SPECTRUM_TYPE.FREQ_VS_THROTTLE || - this._spectrumType === SPECTRUM_TYPE.FREQ_VS_RPM || - this._spectrumType === SPECTRUM_TYPE.POWER_SPECTRAL_DENSITY + this._spectrumType === SPECTRUM_TYPE.FREQ_VS_RPM ) { // Calculate frequency at mouse const sampleRate = this._fftData.blackBoxRate / this._zoomX; @@ -1479,9 +1391,6 @@ GraphSpectrumPlot._drawMousePosition = function ( case SPECTRUM_TYPE.FREQ_VS_RPM: unitLabel = "Hz"; break; - case SPECTRUM_TYPE.POWER_SPECTRAL_DENSITY: - unitLabel = "dBm/Hz"; - break; default: unitLabel = null; break; @@ -1557,7 +1466,6 @@ GraphSpectrumPlot._getActualMarginLeft = function () { switch (this._spectrumType) { case SPECTRUM_TYPE.FREQ_VS_THROTTLE: case SPECTRUM_TYPE.FREQ_VS_RPM: - case SPECTRUM_TYPE.POWER_SPECTRAL_DENSITY: actualMarginLeft = this._isFullScreen ? MARGIN_LEFT_FULLSCREEN : MARGIN_LEFT;