From 6db382796ca1badeb7bd0ddd44648f3b74b90117 Mon Sep 17 00:00:00 2001 From: demvlad Date: Wed, 9 Jul 2025 14:05:52 +0300 Subject: [PATCH 01/35] Added graph_imported_curves module for import curves --- src/graph_imported_curves.js | 75 ++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 src/graph_imported_curves.js diff --git a/src/graph_imported_curves.js b/src/graph_imported_curves.js new file mode 100644 index 00000000..c5e2de7d --- /dev/null +++ b/src/graph_imported_curves.js @@ -0,0 +1,75 @@ +export function ImportedCurves(curvesChanged) { + const maxImportCount = 5; + this._curvesData = []; + let _that = this; + this.minX = Number.MAX_VALUE; + this.maxX = -Number.MAX_VALUE; + this.minY = Number.MAX_VALUE; + this.maxY = -Number.MAX_VALUE; + + this.curvesCount = function() { + return this._curvesData.length; + } + + this.importCurvesFromCSV = function(files) { + let importsLeft = maxImportCount - this._curvesData.length; + + for (const file of files) { + if (importsLeft-- == 0) { + break; + } + const reader = new FileReader(); + reader.onload = function (e) { + try { + const stringRows = e.target.result.split("\n"); + + const header = stringRows[0].split(","); + if (header.length != 2 || header[0] != "x" || header[1] != "y") { + throw new SyntaxError("Wrong curves CSV data format"); + } + + stringRows.shift(); + //remove bad last row + if (stringRows.at(-1) == "") { + stringRows.pop(); + } + + const curvesData = stringRows.map( function(row) { + const data = row.split(","), + x = parseFloat(data[0]), + y = parseFloat(data[1]); + _that.minX = Math.min(x, _that.minX); + _that.maxX = Math.max(x, _that.maxX); + _that.minY = Math.min(y, _that.minY); + _that.maxY = Math.max(y, _that.maxY); + return { + x: x, + y: y, + }; + }); + + const curve = { + name: file.name.split('.')[0], + points: curvesData, + }; + _that._curvesData.push(curve); + curvesChanged(); + } catch (e) { + alert('Curves data import error: ' + e.message); + return; + } + }; + + reader.readAsText(file); + } + }; + + this.removeCurves = function() { + this._curvesData.length = 0; + this.minX = Number.MAX_VALUE; + this.maxX = -Number.MAX_VALUE; + this.minY = Number.MAX_VALUE; + this.maxY = -Number.MAX_VALUE; + curvesChanged(); + } +} \ No newline at end of file From ddf5d631ee10ce411f3324008e5739d477b9a8fa Mon Sep 17 00:00:00 2001 From: demvlad Date: Wed, 9 Jul 2025 14:30:30 +0300 Subject: [PATCH 02/35] Spectrum export/import code refactoring --- .../js/webworkers/spectrum-export-worker.js | 4 +- src/graph_spectrum.js | 56 +++------ src/graph_spectrum_plot.js | 113 ++++++++++-------- 3 files changed, 87 insertions(+), 86 deletions(-) diff --git a/public/js/webworkers/spectrum-export-worker.js b/public/js/webworkers/spectrum-export-worker.js index 124ba8b7..eda7865b 100644 --- a/public/js/webworkers/spectrum-export-worker.js +++ b/public/js/webworkers/spectrum-export-worker.js @@ -4,8 +4,8 @@ onmessage = function(event) { const spectrumDataLength = fftOutput.length / 2; const frequencyStep = 0.5 * event.data.blackBoxRate / spectrumDataLength; - let outText = "freq" + columnDelimiter + "value" + "\n"; - for (let index = 0; index < spectrumDataLength; index += 10) { + let outText = "x" + columnDelimiter + "y" + "\n"; + for (let index = 0; index < spectrumDataLength; index++) { const frequency = frequencyStep * index; outText += frequency.toString() + columnDelimiter + fftOutput[index].toString() + "\n"; } diff --git a/src/graph_spectrum.js b/src/graph_spectrum.js index 1f5db1fe..bda854c9 100644 --- a/src/graph_spectrum.js +++ b/src/graph_spectrum.js @@ -351,7 +351,9 @@ export function FlightLogAnalyser(flightLog, canvas, analyserCanvas) { !psdHeatMapSelected, ); - $("#spectrumComparison").css("visibility", (optionSelected == 0 ? "visible" : "hidden")); + + const showSpectrumsComparisonPanel = optionSelected === SPECTRUM_TYPE.FREQUENCY || optionSelected === SPECTRUM_TYPE.POWER_SPECTRAL_DENSITY; + $("#spectrumComparison").css("visibility", (showSpectrumsComparisonPanel ? "visible" : "hidden")); }) .change(); @@ -416,48 +418,28 @@ export function FlightLogAnalyser(flightLog, canvas, analyserCanvas) { }; this.importSpectrumFromCSV = function(files) { - const maxImportCount = 5; - let importsLeft = maxImportCount - GraphSpectrumPlot.getImportedSpectrumCount(); + GraphSpectrumPlot.importCurvesFromCSV(files); + }; - for (const file of files) { - if (importsLeft-- == 0) { - break; - } - const reader = new FileReader(); - reader.onload = function (e) { - try { - const stringRows = e.target.result.split("\n"); - - const header = stringRows[0].split(","); - if (header.length != 2 || header[0] != "freq" || header[1] != "value") { - throw new SyntaxError("Wrong spectrum CSV data format"); - } - - stringRows.shift(); - const spectrumData = stringRows.map( function(row) { - const data = row.split(","); - return { - freq: parseFloat(data[0]), - value: parseFloat(data[1]), - }; - }); - - GraphSpectrumPlot.addImportedSpectrumData(spectrumData, file.name); - } catch (e) { - alert('Spectrum data import error: ' + e.message); - return; - } - }; + this.removeImportedSpectrums = function() { + GraphSpectrumPlot.removeImportedCurves(); + }; - reader.readAsText(file); + this.getExportedFileName = function() { + let fileName = null; + switch (userSettings.spectrumType) { + case SPECTRUM_TYPE.FREQUENCY: + fileName = "bf_spectrum"; + break; + case SPECTRUM_TYPE.POWER_SPECTRAL_DENSITY: + fileName = "bf_psd"; + break; } + return fileName; }; } catch (e) { console.error(`Failed to create analyser... error: ${e}`); } - - this.clearImportedSpectrums = function() { - GraphSpectrumPlot.clearImportedSpectrums(); - }; } + diff --git a/src/graph_spectrum_plot.js b/src/graph_spectrum_plot.js index 960ca343..ac3fa9e3 100644 --- a/src/graph_spectrum_plot.js +++ b/src/graph_spectrum_plot.js @@ -1,6 +1,7 @@ import { FILTER_TYPE } from "./flightlog_fielddefs"; import { constrain } from "./tools"; import { NUM_VS_BINS } from "./graph_spectrum_calc"; +import { ImportedCurves } from "./graph_imported_curves"; const BLUR_FILTER_PIXEL = 1, DEFAULT_FONT_FACE = "Verdana, Arial, sans-serif", @@ -56,10 +57,20 @@ export const GraphSpectrumPlot = window.GraphSpectrumPlot || { fontSizeFrameLabel: "6", fontSizeFrameLabelFullscreen: "9", }, - _importedSpectrumsData: [], + _importedSpectrums: null, + _importedPSD: null, + curvesColors : [ + "Blue", + "Purple", + "DeepPink", + "DarkCyan", + "Chocolate", + ] }; GraphSpectrumPlot.initialize = function (canvas, sysConfig) { + this._importedSpectrums = new ImportedCurves(() => GraphSpectrumPlot.redraw()); + this._importedPSD = new ImportedCurves(() => GraphSpectrumPlot.redraw()); this._canvasCtx = canvas.getContext("2d"); this._sysConfig = sysConfig; this._invalidateCache(); @@ -126,16 +137,7 @@ GraphSpectrumPlot.setData = function (fftData, spectrumType) { this._invalidateDataCache(); }; -GraphSpectrumPlot.getImportedSpectrumCount = function () { - return this._importedSpectrumsData.length; -}; - -GraphSpectrumPlot.addImportedSpectrumData = function (curvesData, name) { - const curve = { - points: curvesData, - name: name, - }; - this._importedSpectrumsData.push(curve); +GraphSpectrumPlot.redraw = function () { this._invalidateCache(); this._invalidateDataCache(); GraphSpectrumPlot.draw(); @@ -268,26 +270,17 @@ GraphSpectrumPlot._drawFrequencyGraph = function (canvasCtx) { x += stepX; } - //Draw imported spectrums - const curvesColors = [ - "Blue", - "Purple", - "DeepPink", - "DarkCyan", - "Chocolate", - ]; - - const spectrumCount = this._importedSpectrumsData.length; - for (let spectrumNum = 0; spectrumNum < spectrumCount; spectrumNum++) { - const curvesPonts = this._importedSpectrumsData[spectrumNum].points; +const spectrumCount = this._importedSpectrums._curvesData.length; + for (let spectrumNum = 0; spectrumNum < spectrumCount; spectrumNum++) { + const curvesPonts = this._importedSpectrums._curvesData[spectrumNum].points; const pointsCount = curvesPonts.length; const scaleX = 2 * WIDTH / PLOTTED_BLACKBOX_RATE * this._zoomX; canvasCtx.beginPath(); canvasCtx.lineWidth = 1; - canvasCtx.strokeStyle = curvesColors[spectrumNum]; + canvasCtx.strokeStyle = this.curvesColors[spectrumNum]; canvasCtx.moveTo(0, HEIGHT); - const filterPointsCount = 50; + const filterPointsCount = 100; for (let pointNum = 0; pointNum < pointsCount; pointNum++) { // Apply moving average filter at spectrum points to get visible line let filterStartPoint = pointNum - filterPointsCount / 2; @@ -304,37 +297,18 @@ GraphSpectrumPlot._drawFrequencyGraph = function (canvasCtx) { } let middleValue = 0; for (let i = filterStartPoint; i < filterStopPoint; i++) { - middleValue += curvesPonts[i].value; + middleValue += curvesPonts[i].y; } middleValue /= filterPointsCount; - canvasCtx.lineTo(curvesPonts[pointNum].freq * scaleX, HEIGHT - middleValue * fftScale); + canvasCtx.lineTo(curvesPonts[pointNum].x * scaleX, HEIGHT - middleValue * fftScale); } canvasCtx.stroke(); } //Legend draw if (this._isFullScreen && spectrumCount > 0) { - const legendPosX = 0.84 * WIDTH, - legendPosY = 0.6 * HEIGHT, - rowHeight = 16, - padding = 4, - legendWidth = 0.13 * WIDTH + padding, - legendHeight = spectrumCount * rowHeight + 3 * padding; - - const legendArea = new Path2D(); - legendArea.rect(legendPosX, legendPosY, legendWidth, legendHeight); - canvasCtx.clip(legendArea); - canvasCtx.strokeStyle = "gray"; - canvasCtx.strokeRect(legendPosX, legendPosY, legendWidth, legendHeight); - canvasCtx.font = `${this._drawingParams.fontSizeFrameLabelFullscreen}pt ${DEFAULT_FONT_FACE}`; - canvasCtx.textAlign = "left"; - for (let row = 0; row < spectrumCount; row++) { - const curvesName = this._importedSpectrumsData[row].name.split('.')[0]; - const Y = legendPosY + padding + rowHeight * (row + 1); - canvasCtx.strokeStyle = curvesColors[row]; - canvasCtx.strokeText(curvesName, legendPosX + padding, Y); - } + this._drawLegend(canvasCtx, WIDTH, HEIGHT, this._importedSpectrums._curvesData); } canvasCtx.restore(); @@ -442,6 +416,29 @@ GraphSpectrumPlot._drawPowerSpectralDensityGraph = function (canvasCtx) { canvasCtx.restore(); }; +GraphSpectrumPlot._drawLegend = function (canvasCtx, WIDTH, HEIGHT, importedCurves) { + const spectrumCount = importedCurves.length, + legendPosX = 0.84 * WIDTH, + legendPosY = 0.6 * HEIGHT, + rowHeight = 16, + padding = 4, + legendWidth = 0.13 * WIDTH + padding, + legendHeight = spectrumCount * rowHeight + 3 * padding, + legendArea = new Path2D(); + + legendArea.rect(legendPosX, legendPosY, legendWidth, legendHeight); + canvasCtx.clip(legendArea); + canvasCtx.strokeStyle = "gray"; + canvasCtx.strokeRect(legendPosX, legendPosY, legendWidth, legendHeight); + canvasCtx.font = `${this._drawingParams.fontSizeFrameLabelFullscreen}pt ${DEFAULT_FONT_FACE}`; + canvasCtx.textAlign = "left"; + for (let row = 0; row < spectrumCount; row++) { + const curvesName = importedCurves[row].name; + const Y = legendPosY + padding + rowHeight * (row + 1); + canvasCtx.strokeStyle = this.curvesColors[row]; + canvasCtx.strokeText(curvesName, legendPosX + padding, Y); + } +} GraphSpectrumPlot.getPSDbyFreq = function(frequency) { let freqIndex = Math.round(2 * frequency / this._fftData.blackBoxRate * (this._fftData.psdOutput.length - 1) ); freqIndex = Math.min(freqIndex, this._fftData.psdOutput.length - 1); @@ -1755,3 +1752,25 @@ GraphSpectrumPlot._drawRateWarning = function (canvasCtx) { canvasCtx.restore(); } }; + +GraphSpectrumPlot.importCurvesFromCSV = function(files) { + switch (this._spectrumType) { + case SPECTRUM_TYPE.FREQUENCY: + this._importedSpectrums.importCurvesFromCSV(files); + break; + case SPECTRUM_TYPE.POWER_SPECTRAL_DENSITY: + this._importedPSD.importCurvesFromCSV(files); + break; + } +}; + +GraphSpectrumPlot.removeImportedCurves = function() { + switch (this._spectrumType) { + case SPECTRUM_TYPE.FREQUENCY: + this._importedSpectrums.removeCurves(); + break; + case SPECTRUM_TYPE.POWER_SPECTRAL_DENSITY: + this._importedPSD.removeCurves(); + break; + } +}; From 79b5c83b653d4f6d35c519e7538af49fac273424 Mon Sep 17 00:00:00 2001 From: demvlad Date: Wed, 9 Jul 2025 14:51:04 +0300 Subject: [PATCH 03/35] Added export/import PSD curves data --- src/graph_spectrum.js | 1 - src/graph_spectrum_calc.js | 4 ++-- src/graph_spectrum_plot.js | 17 +++++------------ src/main.js | 18 ++++++++++++------ 4 files changed, 19 insertions(+), 21 deletions(-) diff --git a/src/graph_spectrum.js b/src/graph_spectrum.js index bda854c9..3073e5b1 100644 --- a/src/graph_spectrum.js +++ b/src/graph_spectrum.js @@ -442,4 +442,3 @@ export function FlightLogAnalyser(flightLog, canvas, analyserCanvas) { console.error(`Failed to create analyser... error: ${e}`); } } - diff --git a/src/graph_spectrum_calc.js b/src/graph_spectrum_calc.js index e5d07190..ba7267f7 100644 --- a/src/graph_spectrum_calc.js +++ b/src/graph_spectrum_calc.js @@ -130,8 +130,8 @@ GraphSpectrumCalc.dataLoadPSD = function(analyserZoomY) { const psdData = { fieldIndex : this._dataBuffer.fieldIndex, fieldName : this._dataBuffer.fieldName, - psdLength : psd.psdOutput.length, - psdOutput : psd.psdOutput, + fftLength : psd.psdOutput.length, + fftOutput : psd.psdOutput, blackBoxRate : this._blackBoxRate, minimum: psd.min, maximum: psd.max, diff --git a/src/graph_spectrum_plot.js b/src/graph_spectrum_plot.js index ac3fa9e3..a619102c 100644 --- a/src/graph_spectrum_plot.js +++ b/src/graph_spectrum_plot.js @@ -143,13 +143,6 @@ GraphSpectrumPlot.redraw = function () { GraphSpectrumPlot.draw(); }; -GraphSpectrumPlot.clearImportedSpectrums = function (curvesData) { - this._importedSpectrumsData.length = 0; - this._invalidateCache(); - this._invalidateDataCache(); - GraphSpectrumPlot.draw(); -}; - GraphSpectrumPlot.setOverdraw = function (overdrawType) { this._overdrawType = overdrawType; this._invalidateCache(); @@ -344,7 +337,7 @@ GraphSpectrumPlot._drawPowerSpectralDensityGraph = function (canvasCtx) { canvasCtx.translate(LEFT, TOP); this._drawGradientBackground(canvasCtx, WIDTH, HEIGHT); - const pointsCount = this._fftData.psdLength; + const pointsCount = this._fftData.fftLength; const scaleX = 2 * WIDTH / PLOTTED_BLACKBOX_RATE * this._zoomX; canvasCtx.beginPath(); canvasCtx.lineWidth = 1; @@ -367,7 +360,7 @@ GraphSpectrumPlot._drawPowerSpectralDensityGraph = function (canvasCtx) { 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; + const y = HEIGHT - (this._fftData.fftOutput[pointNum] - minY) * scaleY; canvasCtx.lineTo(freq * scaleX, y); } canvasCtx.stroke(); @@ -440,10 +433,10 @@ GraphSpectrumPlot._drawLegend = function (canvasCtx, WIDTH, HEIGHT, importedCurv } } GraphSpectrumPlot.getPSDbyFreq = function(frequency) { - let freqIndex = Math.round(2 * frequency / this._fftData.blackBoxRate * (this._fftData.psdOutput.length - 1) ); - freqIndex = Math.min(freqIndex, this._fftData.psdOutput.length - 1); + let freqIndex = Math.round(2 * frequency / this._fftData.blackBoxRate * (this._fftData.fftOutput.length - 1) ); + freqIndex = Math.min(freqIndex, this._fftData.fftOutput.length - 1); freqIndex = Math.max(freqIndex, 0); - return this._fftData.psdOutput.length ? this._fftData.psdOutput[freqIndex] : 0; + return this._fftData.fftOutput.length ? this._fftData.fftOutput[freqIndex] : 0; }; GraphSpectrumPlot._drawFrequencyVsXGraph = function (canvasCtx, drawPSD = false) { diff --git a/src/main.js b/src/main.js index 83d2088d..95a15ec9 100644 --- a/src/main.js +++ b/src/main.js @@ -1149,11 +1149,17 @@ function BlackboxLogViewer() { CsvExporter(flightLog, options).dump(onSuccess); } - function exportSpectrumToCsv(file, options = {}) { + function exportSpectrumToCsv(options = {}) { + const fileName = graph.getAnalyser().getExportedFileName(); + if (fileName == null) { + console.warn("The export is not supported for this spectrum type"); + return; + } + const onSuccess = createExportCallback( "csv", "text/csv", - file, + fileName, performance.now(), ); graph.getAnalyser().exportSpectrumToCSV(onSuccess, options); @@ -1732,7 +1738,7 @@ function BlackboxLogViewer() { }); $("#btn-spectrum-export").click(function (e) { - exportSpectrumToCsv("bf_spectrum"); + exportSpectrumToCsv(); e.preventDefault(); }); @@ -1741,12 +1747,12 @@ function BlackboxLogViewer() { e.preventDefault(); e.target.value = ""; }); - + $("#btn-spectrum-clear").click(function (e) { - graph.getAnalyser().clearImportedSpectrums(); + graph.getAnalyser().removeImportedSpectrums(); e.preventDefault(); }); - + $(".btn-gpx-export").click(function (e) { setGraphState(GRAPH_STATE_PAUSED); exportGpx(); From 1647d06e57aa7b2bbe6cd0c55f8978893bb04e3b Mon Sep 17 00:00:00 2001 From: demvlad Date: Wed, 9 Jul 2025 20:22:49 +0300 Subject: [PATCH 04/35] Added drawing of imported PSD curves --- src/graph_spectrum_plot.js | 58 +++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/src/graph_spectrum_plot.js b/src/graph_spectrum_plot.js index a619102c..37b03635 100644 --- a/src/graph_spectrum_plot.js +++ b/src/graph_spectrum_plot.js @@ -330,33 +330,35 @@ GraphSpectrumPlot._drawPowerSpectralDensityGraph = function (canvasCtx) { 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.fftLength; - const scaleX = 2 * WIDTH / PLOTTED_BLACKBOX_RATE * this._zoomX; - canvasCtx.beginPath(); - canvasCtx.lineWidth = 1; - canvasCtx.strokeStyle = "white"; - // Allign y axis range by 10db + const minimum = Math.min(this._fftData.minimum, this._importedPSD.minY), + maximum = Math.max(this._fftData.maximum, this._importedPSD.maxY); const dbStep = 10; - const minY = Math.floor(this._fftData.minimum / dbStep) * dbStep; - let maxY = (Math.floor(this._fftData.maximum / dbStep) + 1) * dbStep; + const minY = Math.floor(minimum / dbStep) * dbStep; + let maxY = (Math.floor(maximum / dbStep) + 1) * dbStep; if (minY == maxY) { maxY = minY + 1; // prevent divide by zero } - const ticksCount = (maxY - minY) / dbStep; - const scaleY = HEIGHT / (maxY - minY); //Store vsRange for _drawMousePosition this._fftData.vsRange = { min: minY, max: maxY, }; + + const ticksCount = (maxY - minY) / dbStep; + const pointsCount = this._fftData.fftLength; + const scaleX = 2 * WIDTH / PLOTTED_BLACKBOX_RATE * this._zoomX; + const scaleY = HEIGHT / (maxY - minY); + + canvasCtx.save(); + canvasCtx.translate(LEFT, TOP); + this._drawGradientBackground(canvasCtx, WIDTH, HEIGHT); + + canvasCtx.beginPath(); + canvasCtx.lineWidth = 1; + canvasCtx.strokeStyle = "white"; canvasCtx.moveTo(0, 0); for (let pointNum = 0; pointNum < pointsCount; pointNum++) { const freq = PLOTTED_BLACKBOX_RATE / 2 * pointNum / pointsCount; @@ -365,6 +367,29 @@ GraphSpectrumPlot._drawPowerSpectralDensityGraph = function (canvasCtx) { } canvasCtx.stroke(); + const spectrumCount = this._importedPSD.curvesCount(); + for (let spectrumNum = 0; spectrumNum < spectrumCount; spectrumNum++) { + const curvesPonts = this._importedPSD._curvesData[spectrumNum].points; + const pointsCount = curvesPonts.length; + + canvasCtx.beginPath(); + canvasCtx.lineWidth = 1; + canvasCtx.strokeStyle = this.curvesColors[spectrumNum]; + canvasCtx.moveTo(0, HEIGHT); + const filterPointsCount = 100; + for (const point of curvesPonts) { + canvasCtx.lineTo(point.x * scaleX, HEIGHT - (point.y - minY) * scaleY); + } + canvasCtx.stroke(); + } + +//Legend draw + if (this._isFullScreen && spectrumCount > 0) { + canvasCtx.save(); + this._drawLegend(canvasCtx, WIDTH, HEIGHT, this._importedPSD._curvesData); + canvasCtx.restore(); + } + this._drawAxisLabel( canvasCtx, this._fftData.fieldName, @@ -405,8 +430,6 @@ GraphSpectrumPlot._drawPowerSpectralDensityGraph = function (canvasCtx) { "rgba(255,0,0,0.50)", 3, ); - - canvasCtx.restore(); }; GraphSpectrumPlot._drawLegend = function (canvasCtx, WIDTH, HEIGHT, importedCurves) { @@ -432,6 +455,7 @@ GraphSpectrumPlot._drawLegend = function (canvasCtx, WIDTH, HEIGHT, importedCurv canvasCtx.strokeText(curvesName, legendPosX + padding, Y); } } + GraphSpectrumPlot.getPSDbyFreq = function(frequency) { let freqIndex = Math.round(2 * frequency / this._fftData.blackBoxRate * (this._fftData.fftOutput.length - 1) ); freqIndex = Math.min(freqIndex, this._fftData.fftOutput.length - 1); From 6b580c692d9c2a61c26d7c58a6615545db925bf7 Mon Sep 17 00:00:00 2001 From: demvlad Date: Wed, 9 Jul 2025 20:44:46 +0300 Subject: [PATCH 05/35] Resolved code issues --- src/graph_imported_curves.js | 4 ++-- src/graph_spectrum_plot.js | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/graph_imported_curves.js b/src/graph_imported_curves.js index c5e2de7d..600daf5e 100644 --- a/src/graph_imported_curves.js +++ b/src/graph_imported_curves.js @@ -9,7 +9,7 @@ export function ImportedCurves(curvesChanged) { this.curvesCount = function() { return this._curvesData.length; - } + }; this.importCurvesFromCSV = function(files) { let importsLeft = maxImportCount - this._curvesData.length; @@ -71,5 +71,5 @@ export function ImportedCurves(curvesChanged) { this.minY = Number.MAX_VALUE; this.maxY = -Number.MAX_VALUE; curvesChanged(); - } + }; } \ No newline at end of file diff --git a/src/graph_spectrum_plot.js b/src/graph_spectrum_plot.js index 37b03635..ad8f60c2 100644 --- a/src/graph_spectrum_plot.js +++ b/src/graph_spectrum_plot.js @@ -65,7 +65,7 @@ export const GraphSpectrumPlot = window.GraphSpectrumPlot || { "DeepPink", "DarkCyan", "Chocolate", - ] + ], }; GraphSpectrumPlot.initialize = function (canvas, sysConfig) { @@ -376,7 +376,6 @@ GraphSpectrumPlot._drawPowerSpectralDensityGraph = function (canvasCtx) { canvasCtx.lineWidth = 1; canvasCtx.strokeStyle = this.curvesColors[spectrumNum]; canvasCtx.moveTo(0, HEIGHT); - const filterPointsCount = 100; for (const point of curvesPonts) { canvasCtx.lineTo(point.x * scaleX, HEIGHT - (point.y - minY) * scaleY); } @@ -454,7 +453,7 @@ GraphSpectrumPlot._drawLegend = function (canvasCtx, WIDTH, HEIGHT, importedCurv canvasCtx.strokeStyle = this.curvesColors[row]; canvasCtx.strokeText(curvesName, legendPosX + padding, Y); } -} +}; GraphSpectrumPlot.getPSDbyFreq = function(frequency) { let freqIndex = Math.round(2 * frequency / this._fftData.blackBoxRate * (this._fftData.fftOutput.length - 1) ); From c96f43017f4da7d383a1d122bf6e59cb14c0e910 Mon Sep 17 00:00:00 2001 From: demvlad Date: Wed, 9 Jul 2025 20:47:52 +0300 Subject: [PATCH 06/35] Resolved code issues --- src/graph_spectrum_plot.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/graph_spectrum_plot.js b/src/graph_spectrum_plot.js index ad8f60c2..365304a5 100644 --- a/src/graph_spectrum_plot.js +++ b/src/graph_spectrum_plot.js @@ -370,7 +370,6 @@ GraphSpectrumPlot._drawPowerSpectralDensityGraph = function (canvasCtx) { const spectrumCount = this._importedPSD.curvesCount(); for (let spectrumNum = 0; spectrumNum < spectrumCount; spectrumNum++) { const curvesPonts = this._importedPSD._curvesData[spectrumNum].points; - const pointsCount = curvesPonts.length; canvasCtx.beginPath(); canvasCtx.lineWidth = 1; From 48444a17ac81aea1a71cd1aef75cfcaa9098b55f Mon Sep 17 00:00:00 2001 From: demvlad Date: Thu, 10 Jul 2025 09:23:48 +0300 Subject: [PATCH 07/35] Code style improvement --- src/graph_spectrum_plot.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/graph_spectrum_plot.js b/src/graph_spectrum_plot.js index 365304a5..87fa876e 100644 --- a/src/graph_spectrum_plot.js +++ b/src/graph_spectrum_plot.js @@ -226,7 +226,6 @@ GraphSpectrumPlot._drawFrequencyGraph = function (canvasCtx) { const PLOTTED_BUFFER_LENGTH = this._fftData.fftLength / this._zoomX; const PLOTTED_BLACKBOX_RATE = this._fftData.blackBoxRate / this._zoomX; - canvasCtx.save(); canvasCtx.translate(LEFT, TOP); this._drawGradientBackground(canvasCtx, WIDTH, HEIGHT); @@ -263,8 +262,8 @@ GraphSpectrumPlot._drawFrequencyGraph = function (canvasCtx) { x += stepX; } -const spectrumCount = this._importedSpectrums._curvesData.length; - for (let spectrumNum = 0; spectrumNum < spectrumCount; spectrumNum++) { + const spectrumCount = this._importedSpectrums.curvesCount(); + for (let spectrumNum = 0; spectrumNum < spectrumCount; spectrumNum++) { const curvesPonts = this._importedSpectrums._curvesData[spectrumNum].points; const pointsCount = curvesPonts.length; const scaleX = 2 * WIDTH / PLOTTED_BLACKBOX_RATE * this._zoomX; @@ -303,7 +302,6 @@ const spectrumCount = this._importedSpectrums._curvesData.length; if (this._isFullScreen && spectrumCount > 0) { this._drawLegend(canvasCtx, WIDTH, HEIGHT, this._importedSpectrums._curvesData); } - canvasCtx.restore(); this._drawAxisLabel( canvasCtx, @@ -352,7 +350,6 @@ GraphSpectrumPlot._drawPowerSpectralDensityGraph = function (canvasCtx) { const scaleX = 2 * WIDTH / PLOTTED_BLACKBOX_RATE * this._zoomX; const scaleY = HEIGHT / (maxY - minY); - canvasCtx.save(); canvasCtx.translate(LEFT, TOP); this._drawGradientBackground(canvasCtx, WIDTH, HEIGHT); @@ -383,9 +380,7 @@ GraphSpectrumPlot._drawPowerSpectralDensityGraph = function (canvasCtx) { //Legend draw if (this._isFullScreen && spectrumCount > 0) { - canvasCtx.save(); this._drawLegend(canvasCtx, WIDTH, HEIGHT, this._importedPSD._curvesData); - canvasCtx.restore(); } this._drawAxisLabel( @@ -440,6 +435,7 @@ GraphSpectrumPlot._drawLegend = function (canvasCtx, WIDTH, HEIGHT, importedCurv legendHeight = spectrumCount * rowHeight + 3 * padding, legendArea = new Path2D(); + canvasCtx.save(); legendArea.rect(legendPosX, legendPosY, legendWidth, legendHeight); canvasCtx.clip(legendArea); canvasCtx.strokeStyle = "gray"; @@ -452,6 +448,7 @@ GraphSpectrumPlot._drawLegend = function (canvasCtx, WIDTH, HEIGHT, importedCurv canvasCtx.strokeStyle = this.curvesColors[row]; canvasCtx.strokeText(curvesName, legendPosX + padding, Y); } + canvasCtx.restore(); }; GraphSpectrumPlot.getPSDbyFreq = function(frequency) { From 10364a29fee8aafa06dff099c4af3947bd54e33c Mon Sep 17 00:00:00 2001 From: demvlad Date: Thu, 10 Jul 2025 11:36:54 +0300 Subject: [PATCH 08/35] Resolved issue wrong frequency definition in exported file --- public/js/webworkers/spectrum-export-worker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/js/webworkers/spectrum-export-worker.js b/public/js/webworkers/spectrum-export-worker.js index eda7865b..a2160aad 100644 --- a/public/js/webworkers/spectrum-export-worker.js +++ b/public/js/webworkers/spectrum-export-worker.js @@ -1,7 +1,7 @@ onmessage = function(event) { const columnDelimiter = event.data.opts.columnDelimiter; const fftOutput = event.data.fftOutput; - const spectrumDataLength = fftOutput.length / 2; + const spectrumDataLength = fftOutput.length; const frequencyStep = 0.5 * event.data.blackBoxRate / spectrumDataLength; let outText = "x" + columnDelimiter + "y" + "\n"; From 622177f91e67260c34273e3bd76013d62146d1e0 Mon Sep 17 00:00:00 2001 From: demvlad Date: Thu, 10 Jul 2025 11:49:58 +0300 Subject: [PATCH 09/35] Code improvement --- src/graph_spectrum_plot.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/graph_spectrum_plot.js b/src/graph_spectrum_plot.js index 87fa876e..e97db1c9 100644 --- a/src/graph_spectrum_plot.js +++ b/src/graph_spectrum_plot.js @@ -222,7 +222,6 @@ GraphSpectrumPlot._drawFrequencyGraph = function (canvasCtx) { const WIDTH = canvasCtx.canvas.width; const LEFT = canvasCtx.canvas.left; const TOP = canvasCtx.canvas.top; - const PLOTTED_BUFFER_LENGTH = this._fftData.fftLength / this._zoomX; const PLOTTED_BLACKBOX_RATE = this._fftData.blackBoxRate / this._zoomX; @@ -262,11 +261,11 @@ GraphSpectrumPlot._drawFrequencyGraph = function (canvasCtx) { x += stepX; } + const scaleX = 2 * WIDTH / PLOTTED_BLACKBOX_RATE * this._zoomX; const spectrumCount = this._importedSpectrums.curvesCount(); for (let spectrumNum = 0; spectrumNum < spectrumCount; spectrumNum++) { const curvesPonts = this._importedSpectrums._curvesData[spectrumNum].points; const pointsCount = curvesPonts.length; - const scaleX = 2 * WIDTH / PLOTTED_BLACKBOX_RATE * this._zoomX; canvasCtx.beginPath(); canvasCtx.lineWidth = 1; @@ -460,7 +459,6 @@ GraphSpectrumPlot.getPSDbyFreq = function(frequency) { GraphSpectrumPlot._drawFrequencyVsXGraph = function (canvasCtx, drawPSD = false) { const PLOTTED_BLACKBOX_RATE = this._fftData.blackBoxRate / this._zoomX; - const ACTUAL_MARGIN_LEFT = this._getActualMarginLeft(); const WIDTH = canvasCtx.canvas.width - ACTUAL_MARGIN_LEFT; const HEIGHT = canvasCtx.canvas.height - MARGIN_BOTTOM; From 340a7b626e6d5e5d06cd725c5a7f4cf74530f169 Mon Sep 17 00:00:00 2001 From: demvlad Date: Thu, 10 Jul 2025 14:19:55 +0300 Subject: [PATCH 10/35] The legend is moved to right-up corner --- src/graph_spectrum_plot.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/graph_spectrum_plot.js b/src/graph_spectrum_plot.js index e97db1c9..e88cc604 100644 --- a/src/graph_spectrum_plot.js +++ b/src/graph_spectrum_plot.js @@ -271,7 +271,7 @@ GraphSpectrumPlot._drawFrequencyGraph = function (canvasCtx) { canvasCtx.lineWidth = 1; canvasCtx.strokeStyle = this.curvesColors[spectrumNum]; canvasCtx.moveTo(0, HEIGHT); - const filterPointsCount = 100; + const filterPointsCount = 200; for (let pointNum = 0; pointNum < pointsCount; pointNum++) { // Apply moving average filter at spectrum points to get visible line let filterStartPoint = pointNum - filterPointsCount / 2; @@ -426,11 +426,11 @@ GraphSpectrumPlot._drawPowerSpectralDensityGraph = function (canvasCtx) { GraphSpectrumPlot._drawLegend = function (canvasCtx, WIDTH, HEIGHT, importedCurves) { const spectrumCount = importedCurves.length, - legendPosX = 0.84 * WIDTH, - legendPosY = 0.6 * HEIGHT, + legendPosX = WIDTH - 180, + legendPosY = 50, rowHeight = 16, padding = 4, - legendWidth = 0.13 * WIDTH + padding, + legendWidth = 150 + padding, legendHeight = spectrumCount * rowHeight + 3 * padding, legendArea = new Path2D(); From cc01fee46d7a192eae86602ccf96ed7d328b81bb Mon Sep 17 00:00:00 2001 From: demvlad Date: Thu, 10 Jul 2025 14:45:14 +0300 Subject: [PATCH 11/35] The exported spectrums .csv file name is log name with _sp, _psd postfix --- src/graph_spectrum.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/graph_spectrum.js b/src/graph_spectrum.js index 3073e5b1..8b82f11a 100644 --- a/src/graph_spectrum.js +++ b/src/graph_spectrum.js @@ -426,13 +426,13 @@ export function FlightLogAnalyser(flightLog, canvas, analyserCanvas) { }; this.getExportedFileName = function() { - let fileName = null; + let fileName = $(".log-filename").text().split(".")[0]; switch (userSettings.spectrumType) { case SPECTRUM_TYPE.FREQUENCY: - fileName = "bf_spectrum"; + fileName = fileName + "_sp"; break; case SPECTRUM_TYPE.POWER_SPECTRAL_DENSITY: - fileName = "bf_psd"; + fileName = fileName + "_psd"; break; } return fileName; From d26c67e1bc454523a5fe853fd1d3a582a9986069 Mon Sep 17 00:00:00 2001 From: demvlad Date: Thu, 10 Jul 2025 19:51:03 +0300 Subject: [PATCH 12/35] Resolved issue of imported curves frequency scaling --- src/graph_spectrum_plot.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/graph_spectrum_plot.js b/src/graph_spectrum_plot.js index e88cc604..0c3a5480 100644 --- a/src/graph_spectrum_plot.js +++ b/src/graph_spectrum_plot.js @@ -261,7 +261,7 @@ GraphSpectrumPlot._drawFrequencyGraph = function (canvasCtx) { x += stepX; } - const scaleX = 2 * WIDTH / PLOTTED_BLACKBOX_RATE * this._zoomX; + const scaleX = 2 * WIDTH / PLOTTED_BLACKBOX_RATE; const spectrumCount = this._importedSpectrums.curvesCount(); for (let spectrumNum = 0; spectrumNum < spectrumCount; spectrumNum++) { const curvesPonts = this._importedSpectrums._curvesData[spectrumNum].points; @@ -346,7 +346,7 @@ GraphSpectrumPlot._drawPowerSpectralDensityGraph = function (canvasCtx) { const ticksCount = (maxY - minY) / dbStep; const pointsCount = this._fftData.fftLength; - const scaleX = 2 * WIDTH / PLOTTED_BLACKBOX_RATE * this._zoomX; + const scaleX = 2 * WIDTH / PLOTTED_BLACKBOX_RATE; const scaleY = HEIGHT / (maxY - minY); canvasCtx.translate(LEFT, TOP); @@ -357,7 +357,10 @@ GraphSpectrumPlot._drawPowerSpectralDensityGraph = function (canvasCtx) { canvasCtx.strokeStyle = "white"; canvasCtx.moveTo(0, 0); for (let pointNum = 0; pointNum < pointsCount; pointNum++) { - const freq = PLOTTED_BLACKBOX_RATE / 2 * pointNum / pointsCount; + const freq = this._fftData.blackBoxRate / 2 * pointNum / pointsCount; + if(freq > PLOTTED_BLACKBOX_RATE / 2) { + break; + } const y = HEIGHT - (this._fftData.fftOutput[pointNum] - minY) * scaleY; canvasCtx.lineTo(freq * scaleX, y); } @@ -372,6 +375,9 @@ GraphSpectrumPlot._drawPowerSpectralDensityGraph = function (canvasCtx) { canvasCtx.strokeStyle = this.curvesColors[spectrumNum]; canvasCtx.moveTo(0, HEIGHT); for (const point of curvesPonts) { + if(point.x > PLOTTED_BLACKBOX_RATE / 2) { + break; + } canvasCtx.lineTo(point.x * scaleX, HEIGHT - (point.y - minY) * scaleY); } canvasCtx.stroke(); From c3c1df2f28572fe30a3ae395411317e80a72542d Mon Sep 17 00:00:00 2001 From: demvlad Date: Fri, 11 Jul 2025 10:42:47 +0300 Subject: [PATCH 13/35] Code refactoring: PLOTTED_BLACKBOX_RATE is replace to MAXIMAL_PLOTTED_FREQUENCY in graph_spectrum_plot.js --- src/graph_spectrum_plot.js | 83 +++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 42 deletions(-) diff --git a/src/graph_spectrum_plot.js b/src/graph_spectrum_plot.js index 0c3a5480..fca214c2 100644 --- a/src/graph_spectrum_plot.js +++ b/src/graph_spectrum_plot.js @@ -223,7 +223,7 @@ GraphSpectrumPlot._drawFrequencyGraph = function (canvasCtx) { const LEFT = canvasCtx.canvas.left; const TOP = canvasCtx.canvas.top; const PLOTTED_BUFFER_LENGTH = this._fftData.fftLength / this._zoomX; - const PLOTTED_BLACKBOX_RATE = this._fftData.blackBoxRate / this._zoomX; + const MAXIMAL_PLOTTED_FREQUENCY = 0.5 * this._fftData.blackBoxRate / this._zoomX; canvasCtx.translate(LEFT, TOP); @@ -261,7 +261,7 @@ GraphSpectrumPlot._drawFrequencyGraph = function (canvasCtx) { x += stepX; } - const scaleX = 2 * WIDTH / PLOTTED_BLACKBOX_RATE; + const scaleX = WIDTH / MAXIMAL_PLOTTED_FREQUENCY; const spectrumCount = this._importedSpectrums.curvesCount(); for (let spectrumNum = 0; spectrumNum < spectrumCount; spectrumNum++) { const curvesPonts = this._importedSpectrums._curvesData[spectrumNum].points; @@ -311,7 +311,7 @@ GraphSpectrumPlot._drawFrequencyGraph = function (canvasCtx) { ); this._drawHorizontalGridLines( canvasCtx, - PLOTTED_BLACKBOX_RATE / 2, + MAXIMAL_PLOTTED_FREQUENCY, LEFT, TOP, WIDTH, @@ -327,7 +327,7 @@ GraphSpectrumPlot._drawPowerSpectralDensityGraph = function (canvasCtx) { 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; + const MAXIMAL_PLOTTED_FREQUENCY = 0.5 * this._fftData.blackBoxRate / this._zoomX; // Allign y axis range by 10db const minimum = Math.min(this._fftData.minimum, this._importedPSD.minY), @@ -346,7 +346,7 @@ GraphSpectrumPlot._drawPowerSpectralDensityGraph = function (canvasCtx) { const ticksCount = (maxY - minY) / dbStep; const pointsCount = this._fftData.fftLength; - const scaleX = 2 * WIDTH / PLOTTED_BLACKBOX_RATE; + const scaleX = WIDTH / MAXIMAL_PLOTTED_FREQUENCY; const scaleY = HEIGHT / (maxY - minY); canvasCtx.translate(LEFT, TOP); @@ -358,7 +358,7 @@ GraphSpectrumPlot._drawPowerSpectralDensityGraph = function (canvasCtx) { canvasCtx.moveTo(0, 0); for (let pointNum = 0; pointNum < pointsCount; pointNum++) { const freq = this._fftData.blackBoxRate / 2 * pointNum / pointsCount; - if(freq > PLOTTED_BLACKBOX_RATE / 2) { + if(freq > MAXIMAL_PLOTTED_FREQUENCY) { break; } const y = HEIGHT - (this._fftData.fftOutput[pointNum] - minY) * scaleY; @@ -375,7 +375,7 @@ GraphSpectrumPlot._drawPowerSpectralDensityGraph = function (canvasCtx) { canvasCtx.strokeStyle = this.curvesColors[spectrumNum]; canvasCtx.moveTo(0, HEIGHT); for (const point of curvesPonts) { - if(point.x > PLOTTED_BLACKBOX_RATE / 2) { + if(point.x > MAXIMAL_PLOTTED_FREQUENCY) { break; } canvasCtx.lineTo(point.x * scaleX, HEIGHT - (point.y - minY) * scaleY); @@ -397,7 +397,7 @@ GraphSpectrumPlot._drawPowerSpectralDensityGraph = function (canvasCtx) { ); this._drawHorizontalGridLines( canvasCtx, - PLOTTED_BLACKBOX_RATE / 2, + MAXIMAL_PLOTTED_FREQUENCY, LEFT, TOP, WIDTH, @@ -420,7 +420,7 @@ GraphSpectrumPlot._drawPowerSpectralDensityGraph = function (canvasCtx) { this._drawInterestFrequency( canvasCtx, this._fftData.maxNoiseFrequency, - PLOTTED_BLACKBOX_RATE, + MAXIMAL_PLOTTED_FREQUENCY, "Max noise", WIDTH, HEIGHT, @@ -464,7 +464,7 @@ GraphSpectrumPlot.getPSDbyFreq = function(frequency) { }; GraphSpectrumPlot._drawFrequencyVsXGraph = function (canvasCtx, drawPSD = false) { - const PLOTTED_BLACKBOX_RATE = this._fftData.blackBoxRate / this._zoomX; + const MAXIMAL_PLOTTED_FREQUENCY = 0.5 * this._fftData.blackBoxRate / this._zoomX; const ACTUAL_MARGIN_LEFT = this._getActualMarginLeft(); const WIDTH = canvasCtx.canvas.width - ACTUAL_MARGIN_LEFT; const HEIGHT = canvasCtx.canvas.height - MARGIN_BOTTOM; @@ -500,7 +500,7 @@ GraphSpectrumPlot._drawFrequencyVsXGraph = function (canvasCtx, drawPSD = false) ); this._drawHorizontalGridLines( canvasCtx, - PLOTTED_BLACKBOX_RATE / 2, + MAXIMAL_PLOTTED_FREQUENCY, LEFT, TOP, WIDTH, @@ -771,7 +771,7 @@ GraphSpectrumPlot._drawPidErrorVsSetpointGraphGroups = function ( GraphSpectrumPlot._drawFiltersAndMarkers = function (canvasCtx) { const HEIGHT = this._canvasCtx.canvas.height - MARGIN; const WIDTH = this._canvasCtx.canvas.width - this._getActualMarginLeft(); - const PLOTTED_BLACKBOX_RATE = this._fftData.blackBoxRate / this._zoomX; + const MAXIMAL_PLOTTED_FREQUENCY = 0.5 * this._fftData.blackBoxRate / this._zoomX; let offset = 2; // make some space! Includes the space for the mouse frequency. In this way the other elements don't move in the screen when used @@ -799,7 +799,7 @@ GraphSpectrumPlot._drawFiltersAndMarkers = function (canvasCtx) { canvasCtx, this._sysConfig.gyro_lowpass_dyn_hz[0], this._sysConfig.gyro_lowpass_dyn_hz[1], - PLOTTED_BLACKBOX_RATE, + MAXIMAL_PLOTTED_FREQUENCY, label, WIDTH, HEIGHT, @@ -820,7 +820,7 @@ GraphSpectrumPlot._drawFiltersAndMarkers = function (canvasCtx) { this._drawLowpassFilter( canvasCtx, this._sysConfig.gyro_lowpass_hz, - PLOTTED_BLACKBOX_RATE, + MAXIMAL_PLOTTED_FREQUENCY, label, WIDTH, HEIGHT, @@ -842,7 +842,7 @@ GraphSpectrumPlot._drawFiltersAndMarkers = function (canvasCtx) { this._drawLowpassFilter( canvasCtx, this._sysConfig.gyro_lowpass2_hz, - PLOTTED_BLACKBOX_RATE, + MAXIMAL_PLOTTED_FREQUENCY, label, WIDTH, HEIGHT, @@ -868,7 +868,7 @@ GraphSpectrumPlot._drawFiltersAndMarkers = function (canvasCtx) { canvasCtx, this._sysConfig.gyro_notch_hz[i], this._sysConfig.gyro_notch_cutoff[i], - PLOTTED_BLACKBOX_RATE, + MAXIMAL_PLOTTED_FREQUENCY, "GYRO Notch", WIDTH, HEIGHT, @@ -888,7 +888,7 @@ GraphSpectrumPlot._drawFiltersAndMarkers = function (canvasCtx) { canvasCtx, this._sysConfig.gyro_notch_hz, this._sysConfig.gyro_notch_cutoff, - PLOTTED_BLACKBOX_RATE, + MAXIMAL_PLOTTED_FREQUENCY, "GYRO Notch", WIDTH, HEIGHT, @@ -913,7 +913,7 @@ GraphSpectrumPlot._drawFiltersAndMarkers = function (canvasCtx) { this._drawLowpassFilter( canvasCtx, this._sysConfig.yaw_lpf_hz, - PLOTTED_BLACKBOX_RATE, + MAXIMAL_PLOTTED_FREQUENCY, "YAW LPF cutoff", WIDTH, HEIGHT, @@ -948,7 +948,7 @@ GraphSpectrumPlot._drawFiltersAndMarkers = function (canvasCtx) { canvasCtx, this._sysConfig.dterm_lpf_dyn_hz[0], this._sysConfig.dterm_lpf_dyn_hz[1], - PLOTTED_BLACKBOX_RATE, + MAXIMAL_PLOTTED_FREQUENCY, label, WIDTH, HEIGHT, @@ -971,7 +971,7 @@ GraphSpectrumPlot._drawFiltersAndMarkers = function (canvasCtx) { this._drawLowpassFilter( canvasCtx, this._sysConfig.dterm_lpf_hz, - PLOTTED_BLACKBOX_RATE, + MAXIMAL_PLOTTED_FREQUENCY, label, WIDTH, HEIGHT, @@ -995,7 +995,7 @@ GraphSpectrumPlot._drawFiltersAndMarkers = function (canvasCtx) { this._drawLowpassFilter( canvasCtx, this._sysConfig.dterm_lpf2_hz, - PLOTTED_BLACKBOX_RATE, + MAXIMAL_PLOTTED_FREQUENCY, label, WIDTH, HEIGHT, @@ -1018,7 +1018,7 @@ GraphSpectrumPlot._drawFiltersAndMarkers = function (canvasCtx) { canvasCtx, this._sysConfig.dterm_notch_hz, this._sysConfig.dterm_notch_cutoff, - PLOTTED_BLACKBOX_RATE, + MAXIMAL_PLOTTED_FREQUENCY, "D-TERM Notch", WIDTH, HEIGHT, @@ -1038,7 +1038,7 @@ GraphSpectrumPlot._drawFiltersAndMarkers = function (canvasCtx) { this._drawInterestFrequency( canvasCtx, this._fftData.maxNoiseFrequency, - PLOTTED_BLACKBOX_RATE, + MAXIMAL_PLOTTED_FREQUENCY, "Max noise", WIDTH, HEIGHT, @@ -1265,7 +1265,8 @@ GraphSpectrumPlot._drawHorizontalMarkerLine = function ( let realLineWidth = lineWidth || DEFAULT_MARK_LINE_WIDTH; if (realLineWidth > 5) { // is the linewidth specified as a frequency band - realLineWidth = (WIDTH * (2 * realLineWidth)) / (sampleRate / 2); + const maximalFrequency = 0.5 * this._fftData.blackBoxRate / this._zoomX; + realLineWidth = (WIDTH * (2 * realLineWidth)) / maximalFrequency; } if (realLineWidth < 1) { realLineWidth = 1; @@ -1320,7 +1321,7 @@ GraphSpectrumPlot._drawGradientBackground = function ( GraphSpectrumPlot._drawInterestFrequency = function ( canvasCtx, frequency, - sampleRate, + maximalFrequency, label, WIDTH, HEIGHT, @@ -1339,7 +1340,7 @@ GraphSpectrumPlot._drawInterestFrequency = function ( return this._drawVerticalMarkerLine( canvasCtx, frequency, - sampleRate / 2, + maximalFrequency, interestLabel, WIDTH, HEIGHT, @@ -1352,7 +1353,7 @@ GraphSpectrumPlot._drawInterestFrequency = function ( GraphSpectrumPlot._drawLowpassFilter = function ( canvasCtx, frequency, - sampleRate, + maximalFrequency, label, WIDTH, HEIGHT, @@ -1364,7 +1365,7 @@ GraphSpectrumPlot._drawLowpassFilter = function ( return this._drawVerticalMarkerLine( canvasCtx, frequency, - sampleRate / 2, + maximalFrequency, lpfLabel, WIDTH, HEIGHT, @@ -1378,7 +1379,7 @@ GraphSpectrumPlot._drawLowpassDynFilter = function ( canvasCtx, frequency1, frequency2, - sampleRate, + maximalFrequency, label, WIDTH, HEIGHT, @@ -1393,7 +1394,7 @@ GraphSpectrumPlot._drawLowpassDynFilter = function ( const x1 = this._drawVerticalMarkerLine( canvasCtx, frequency1, - sampleRate / 2, + maximalFrequency, dynFilterLabel, WIDTH, HEIGHT, @@ -1413,7 +1414,7 @@ GraphSpectrumPlot._drawLowpassDynFilter = function ( const x2 = this._drawVerticalMarkerLine( canvasCtx, frequency2, - sampleRate / 2, + maximalFrequency, null, WIDTH, HEIGHT, @@ -1438,7 +1439,7 @@ GraphSpectrumPlot._drawLowpassDynFilter = function ( * frequency = (throttle - (throttle * throttle * throttle) / 3.0f) * 1.5f; * but need to scale the 1.5f using the max value of the dyn filter */ - const scale = frequency2 / (sampleRate / 2); + const scale = frequency2 / (maximalFrequency); const NUMBER_OF_POINTS = this._isFullScreen ? 30 : 10; let startPlot = false; @@ -1480,7 +1481,7 @@ GraphSpectrumPlot._drawNotchFilter = function ( canvasCtx, center, cutoff, - sampleRate, + maximalFrequency, label, WIDTH, HEIGHT, @@ -1488,8 +1489,8 @@ GraphSpectrumPlot._drawNotchFilter = function ( stroke, lineWidth ) { - const cutoffX = (WIDTH * cutoff) / (sampleRate / 2); - const centerX = (WIDTH * center) / (sampleRate / 2); + const cutoffX = (WIDTH * cutoff) / (maximalFrequency); + const centerX = (WIDTH * center) / (maximalFrequency); canvasCtx.beginPath(); canvasCtx.lineWidth = lineWidth || DEFAULT_MARK_LINE_WIDTH; @@ -1525,7 +1526,7 @@ GraphSpectrumPlot._drawNotchFilter = function ( this._drawVerticalMarkerLine( canvasCtx, center, - sampleRate / 2, + maximalFrequency, labelNotch, WIDTH, HEIGHT, @@ -1556,17 +1557,15 @@ GraphSpectrumPlot._drawMousePosition = function ( this._spectrumType === SPECTRUM_TYPE.PSD_VS_RPM ) { // Calculate frequency at mouse - const sampleRate = this._fftData.blackBoxRate / this._zoomX; + const maximalFrequency = 0.5 * this._fftData.blackBoxRate / this._zoomX; const marginLeft = this._getActualMarginLeft(); - mouseFrequency = - ((mouseX - marginLeft) / WIDTH) * - (this._fftData.blackBoxRate / this._zoomX / 2); - if (mouseFrequency >= 0 && mouseFrequency <= sampleRate) { + mouseFrequency = ((mouseX - marginLeft) / WIDTH) * maximalFrequency; + if (mouseFrequency >= 0 && mouseFrequency <= maximalFrequency) { this._drawInterestFrequency( canvasCtx, mouseFrequency, - sampleRate, + maximalFrequency, "", WIDTH, HEIGHT, From 5f255ac36c46e1f3810ef1d10958381d2c00d967 Mon Sep 17 00:00:00 2001 From: demvlad Date: Fri, 11 Jul 2025 14:15:27 +0300 Subject: [PATCH 14/35] Analyser legend position is added in user settings --- index.html | 23 +++++++++++++++++++++++ src/graph_spectrum_plot.js | 6 +++--- src/user_settings_dialog.js | 20 ++++++++++++++++++++ 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index fb31e032..ab9494e3 100644 --- a/index.html +++ b/index.html @@ -2989,6 +2989,29 @@

%

+ + + + + + + +

%

+ + + + +

%

+ + + + +

%

+ + diff --git a/src/graph_spectrum_plot.js b/src/graph_spectrum_plot.js index fca214c2..de3503cc 100644 --- a/src/graph_spectrum_plot.js +++ b/src/graph_spectrum_plot.js @@ -432,11 +432,11 @@ GraphSpectrumPlot._drawPowerSpectralDensityGraph = function (canvasCtx) { GraphSpectrumPlot._drawLegend = function (canvasCtx, WIDTH, HEIGHT, importedCurves) { const spectrumCount = importedCurves.length, - legendPosX = WIDTH - 180, - legendPosY = 50, + legendPosX = parseInt(userSettings.analyser_legend.left) / 100 * WIDTH, + legendPosY = parseInt(userSettings.analyser_legend.top) / 100 * HEIGHT, rowHeight = 16, padding = 4, - legendWidth = 150 + padding, + legendWidth = parseInt(userSettings.analyser_legend.width) / 100 * WIDTH, legendHeight = spectrumCount * rowHeight + 3 * padding, legendArea = new Path2D(); diff --git a/src/user_settings_dialog.js b/src/user_settings_dialog.js index c525d1f1..161041f7 100644 --- a/src/user_settings_dialog.js +++ b/src/user_settings_dialog.js @@ -231,6 +231,11 @@ export function UserSettingsDialog(dialog, onLoad, onSave) { top: "60%", // position from top (as a percentage of height) size: "35%", // size (as a percentage of width) }, + analyser_legend: { + left: "88%", // position from left (as a percentage of width) + top: "7%", // position from top (as a percentage of height) + width: "10%", // legend width + }, map: { left: "2%", // position from left (as a percentage of width) top: "5%", // position from top (as a percentage of height) @@ -301,6 +306,11 @@ export function UserSettingsDialog(dialog, onLoad, onSave) { left: `${$('.analyser-settings input[name="analyser-left"]').val()}%`, size: `${$('.analyser-settings input[name="analyser-size"]').val()}%`, }, + analyser_legend: { + top: `${$('.analyser-settings input[name="analyser-legend-top"]').val()}%`, + left: `${$('.analyser-settings input[name="analyser-legend-left"]').val()}%`, + width: `${$('.analyser-settings input[name="analyser-legend-width"]').val()}%`, + }, map: { top: `${$('.map-settings input[name="map-top"]').val()}%`, left: `${$('.map-settings input[name="map-left"]').val()}%`, @@ -649,6 +659,16 @@ export function UserSettingsDialog(dialog, onLoad, onSave) { $('.analyser-settings input[name="analyser-size"]').val( parseInt(currentSettings.analyser.size) ); + + $('.analyser-settings input[name="analyser-legend-top"]').val( + parseInt(currentSettings.analyser_legend.top) + ); + $('.analyser-settings input[name="analyser-legend-left"]').val( + parseInt(currentSettings.analyser_legend.left) + ); + $('.analyser-settings input[name="analyser-legend-width"]').val( + parseInt(currentSettings.analyser_legend.width) + ); $('.map-settings input[name="map-top"]').val( parseInt(currentSettings.map.top) ); From 62aa2ac3132a9089f22a1d3a4757b3941dd227f4 Mon Sep 17 00:00:00 2001 From: demvlad Date: Fri, 11 Jul 2025 17:20:47 +0300 Subject: [PATCH 15/35] Added check of valid userSetting in _drawLegend method --- src/graph_spectrum_plot.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/graph_spectrum_plot.js b/src/graph_spectrum_plot.js index de3503cc..8283df96 100644 --- a/src/graph_spectrum_plot.js +++ b/src/graph_spectrum_plot.js @@ -431,6 +431,9 @@ GraphSpectrumPlot._drawPowerSpectralDensityGraph = function (canvasCtx) { }; GraphSpectrumPlot._drawLegend = function (canvasCtx, WIDTH, HEIGHT, importedCurves) { + if (!userSettings?.analyser_legend) { + return; + } const spectrumCount = importedCurves.length, legendPosX = parseInt(userSettings.analyser_legend.left) / 100 * WIDTH, legendPosY = parseInt(userSettings.analyser_legend.top) / 100 * HEIGHT, From 4e81572bc19026089747fc11e2cf3b281f71da12 Mon Sep 17 00:00:00 2001 From: demvlad Date: Fri, 11 Jul 2025 17:35:15 +0300 Subject: [PATCH 16/35] Added warning for specrum type what have not spectrum import --- src/graph_spectrum_plot.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/graph_spectrum_plot.js b/src/graph_spectrum_plot.js index 8283df96..e6087d4b 100644 --- a/src/graph_spectrum_plot.js +++ b/src/graph_spectrum_plot.js @@ -1779,6 +1779,9 @@ GraphSpectrumPlot.importCurvesFromCSV = function(files) { case SPECTRUM_TYPE.POWER_SPECTRAL_DENSITY: this._importedPSD.importCurvesFromCSV(files); break; + default: + console.warn(`Import not supported for spectrum type: ${this._spectrumType}`); + break; } }; From 0cc128c82d698e8635ed6604cd5beac60b7391c7 Mon Sep 17 00:00:00 2001 From: Vladimir Demidov Date: Mon, 14 Jul 2025 21:07:26 +0300 Subject: [PATCH 17/35] Added newline on EOF in src/graph_imported_curves.js Co-authored-by: Mark Haslinghuis --- src/graph_imported_curves.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graph_imported_curves.js b/src/graph_imported_curves.js index 600daf5e..923bc454 100644 --- a/src/graph_imported_curves.js +++ b/src/graph_imported_curves.js @@ -72,4 +72,4 @@ export function ImportedCurves(curvesChanged) { this.maxY = -Number.MAX_VALUE; curvesChanged(); }; -} \ No newline at end of file +} From 2caf5deb1f8f966d943879aa927e3d74774f1100 Mon Sep 17 00:00:00 2001 From: demvlad Date: Tue, 15 Jul 2025 14:18:01 +0300 Subject: [PATCH 18/35] Changed mouse cursor info for single and multiple PSD curves --- src/graph_spectrum_plot.js | 47 +++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/src/graph_spectrum_plot.js b/src/graph_spectrum_plot.js index e6087d4b..4132dadc 100644 --- a/src/graph_spectrum_plot.js +++ b/src/graph_spectrum_plot.js @@ -1578,17 +1578,6 @@ GraphSpectrumPlot._drawMousePosition = function ( ); } - if (this._spectrumType === SPECTRUM_TYPE.POWER_SPECTRAL_DENSITY) { - const psdLabel = Math.round(this.getPSDbyFreq(mouseFrequency)).toString() + "dBm/Hz"; - this._drawAxisLabel( - canvasCtx, - psdLabel, - mouseX - 30, - mouseY - 4, - "left", - ); - } - // Y axis let unitLabel; switch (this._spectrumType) { @@ -1611,7 +1600,19 @@ GraphSpectrumPlot._drawMousePosition = function ( const val_min = this._fftData.vsRange.min; const val_max = this._fftData.vsRange.max; const vsArgValue = (1 - mouseY / HEIGHT) * (val_max - val_min) + val_min; - if (vsArgValue >= val_min && vsArgValue <= val_max) { + + if (this._spectrumType === SPECTRUM_TYPE.POWER_SPECTRAL_DENSITY && this._importedPSD.curvesCount() == 0) { // single PSD spectrum + const currentPSD = this.getPSDbyFreq(mouseFrequency); + const posY = (val_max - currentPSD) / (val_max - val_min) * HEIGHT; + const psdLabel = Math.round(currentPSD).toString(); + this._drawAxisLabel( + canvasCtx, + psdLabel, + mouseX - 30, + posY - 4, + "left", + ); + } else if (vsArgValue >= val_min && vsArgValue <= val_max) { const valueLabel = `${vsArgValue.toFixed(0)}${unitLabel}`; this._drawHorizontalMarkerLine( canvasCtx, @@ -1625,19 +1626,27 @@ GraphSpectrumPlot._drawMousePosition = function ( stroke, lineWidth ); - - if (this._spectrumType === SPECTRUM_TYPE.PSD_VS_THROTTLE || - this._spectrumType === SPECTRUM_TYPE.PSD_VS_RPM) { - const label = Math.round(this.getValueFromMatrixFFT(mouseFrequency, vsArgValue)).toString() + "dBm/Hz"; - this._drawAxisLabel( + if (this._spectrumType === SPECTRUM_TYPE.POWER_SPECTRAL_DENSITY) { // multiple PSD spectrum + this._drawAxisLabel( canvasCtx, - label, + vsArgValue.toFixed(0), mouseX - 30, mouseY - 4, "left", ); } } + if (this._spectrumType === SPECTRUM_TYPE.PSD_VS_THROTTLE || + this._spectrumType === SPECTRUM_TYPE.PSD_VS_RPM) { + const label = Math.round(this.getValueFromMatrixFFT(mouseFrequency, vsArgValue)).toString() + "dBm/Hz"; + this._drawAxisLabel( + canvasCtx, + label, + mouseX - 30, + mouseY - 4, + "left", + ); + } } } else if (this._spectrumType === SPECTRUM_TYPE.PIDERROR_VS_SETPOINT) { const dataLimits = this._drawPidErrorVsSetpointGraphProcessData(); @@ -1794,4 +1803,4 @@ GraphSpectrumPlot.removeImportedCurves = function() { this._importedPSD.removeCurves(); break; } -}; +}; \ No newline at end of file From 8812bae6617a2659596d3a12bce865b8ccdda3e0 Mon Sep 17 00:00:00 2001 From: Vladimir Demidov Date: Tue, 15 Jul 2025 19:33:37 +0300 Subject: [PATCH 19/35] Code style improvement Co-authored-by: Mark Haslinghuis --- src/graph_spectrum_plot.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graph_spectrum_plot.js b/src/graph_spectrum_plot.js index 4132dadc..3c3faf30 100644 --- a/src/graph_spectrum_plot.js +++ b/src/graph_spectrum_plot.js @@ -1803,4 +1803,4 @@ GraphSpectrumPlot.removeImportedCurves = function() { this._importedPSD.removeCurves(); break; } -}; \ No newline at end of file +}; From d25b398a3a8106e987a11de24c2835ce5607ec11 Mon Sep 17 00:00:00 2001 From: demvlad Date: Tue, 15 Jul 2025 21:48:57 +0300 Subject: [PATCH 20/35] The mouse position cursor improvement for PSD curves --- src/graph_spectrum_plot.js | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/src/graph_spectrum_plot.js b/src/graph_spectrum_plot.js index 3c3faf30..aef2ad03 100644 --- a/src/graph_spectrum_plot.js +++ b/src/graph_spectrum_plot.js @@ -1603,14 +1603,18 @@ GraphSpectrumPlot._drawMousePosition = function ( if (this._spectrumType === SPECTRUM_TYPE.POWER_SPECTRAL_DENSITY && this._importedPSD.curvesCount() == 0) { // single PSD spectrum const currentPSD = this.getPSDbyFreq(mouseFrequency); - const posY = (val_max - currentPSD) / (val_max - val_min) * HEIGHT; - const psdLabel = Math.round(currentPSD).toString(); - this._drawAxisLabel( + const psdLabel = Math.round(currentPSD).toString() + unitLabel; + this._drawHorizontalMarkerLine( canvasCtx, + currentPSD, + val_min, + val_max, psdLabel, - mouseX - 30, - posY - 4, - "left", + WIDTH, + HEIGHT, + OFFSET, + stroke, + lineWidth ); } else if (vsArgValue >= val_min && vsArgValue <= val_max) { const valueLabel = `${vsArgValue.toFixed(0)}${unitLabel}`; @@ -1626,15 +1630,6 @@ GraphSpectrumPlot._drawMousePosition = function ( stroke, lineWidth ); - if (this._spectrumType === SPECTRUM_TYPE.POWER_SPECTRAL_DENSITY) { // multiple PSD spectrum - this._drawAxisLabel( - canvasCtx, - vsArgValue.toFixed(0), - mouseX - 30, - mouseY - 4, - "left", - ); - } } if (this._spectrumType === SPECTRUM_TYPE.PSD_VS_THROTTLE || this._spectrumType === SPECTRUM_TYPE.PSD_VS_RPM) { From a98744b39f61b5006f7eee0238f67e66a4d1c2a7 Mon Sep 17 00:00:00 2001 From: demvlad Date: Tue, 15 Jul 2025 22:11:58 +0300 Subject: [PATCH 21/35] Code style improvement --- src/graph_spectrum_plot.js | 2 +- src/user_settings_dialog.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/graph_spectrum_plot.js b/src/graph_spectrum_plot.js index aef2ad03..c1402485 100644 --- a/src/graph_spectrum_plot.js +++ b/src/graph_spectrum_plot.js @@ -1614,7 +1614,7 @@ GraphSpectrumPlot._drawMousePosition = function ( HEIGHT, OFFSET, stroke, - lineWidth + lineWidth, ); } else if (vsArgValue >= val_min && vsArgValue <= val_max) { const valueLabel = `${vsArgValue.toFixed(0)}${unitLabel}`; diff --git a/src/user_settings_dialog.js b/src/user_settings_dialog.js index 161041f7..0fc7928b 100644 --- a/src/user_settings_dialog.js +++ b/src/user_settings_dialog.js @@ -661,13 +661,13 @@ export function UserSettingsDialog(dialog, onLoad, onSave) { ); $('.analyser-settings input[name="analyser-legend-top"]').val( - parseInt(currentSettings.analyser_legend.top) + parseInt(currentSettings.analyser_legend.top), ); $('.analyser-settings input[name="analyser-legend-left"]').val( - parseInt(currentSettings.analyser_legend.left) + parseInt(currentSettings.analyser_legend.left), ); $('.analyser-settings input[name="analyser-legend-width"]').val( - parseInt(currentSettings.analyser_legend.width) + parseInt(currentSettings.analyser_legend.width), ); $('.map-settings input[name="map-top"]').val( parseInt(currentSettings.map.top) From 82125da8d3c6d3edb4f328f538ec64b748093236 Mon Sep 17 00:00:00 2001 From: Vladimir Demidov Date: Tue, 15 Jul 2025 23:51:42 +0300 Subject: [PATCH 22/35] Code style improvement Co-authored-by: Mark Haslinghuis --- src/graph_imported_curves.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graph_imported_curves.js b/src/graph_imported_curves.js index 923bc454..df507285 100644 --- a/src/graph_imported_curves.js +++ b/src/graph_imported_curves.js @@ -1,7 +1,7 @@ export function ImportedCurves(curvesChanged) { const maxImportCount = 5; this._curvesData = []; - let _that = this; + const _that = this; this.minX = Number.MAX_VALUE; this.maxX = -Number.MAX_VALUE; this.minY = Number.MAX_VALUE; From 2595258e422565481963be085a8c6c3c9e341312 Mon Sep 17 00:00:00 2001 From: Vladimir Demidov Date: Tue, 15 Jul 2025 23:52:41 +0300 Subject: [PATCH 23/35] Code style improvement Co-authored-by: Mark Haslinghuis --- src/graph_imported_curves.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graph_imported_curves.js b/src/graph_imported_curves.js index df507285..92f7d238 100644 --- a/src/graph_imported_curves.js +++ b/src/graph_imported_curves.js @@ -12,7 +12,7 @@ export function ImportedCurves(curvesChanged) { }; this.importCurvesFromCSV = function(files) { - let importsLeft = maxImportCount - this._curvesData.length; + const importsLeft = maxImportCount - this._curvesData.length; for (const file of files) { if (importsLeft-- == 0) { From bc3095134437bdd927f8aa590afced6464716c1e Mon Sep 17 00:00:00 2001 From: demvlad Date: Wed, 16 Jul 2025 00:06:30 +0300 Subject: [PATCH 24/35] Resolved const issue --- src/graph_imported_curves.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graph_imported_curves.js b/src/graph_imported_curves.js index 92f7d238..df507285 100644 --- a/src/graph_imported_curves.js +++ b/src/graph_imported_curves.js @@ -12,7 +12,7 @@ export function ImportedCurves(curvesChanged) { }; this.importCurvesFromCSV = function(files) { - const importsLeft = maxImportCount - this._curvesData.length; + let importsLeft = maxImportCount - this._curvesData.length; for (const file of files) { if (importsLeft-- == 0) { From bde57752c72f83ca7ca273cb8f611a30cc170a44 Mon Sep 17 00:00:00 2001 From: demvlad Date: Fri, 4 Jul 2025 08:39:42 +0300 Subject: [PATCH 25/35] The PSD heatmap low(cut) level is set like min value after min change --- src/graph_spectrum.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/graph_spectrum.js b/src/graph_spectrum.js index 8b82f11a..4367611e 100644 --- a/src/graph_spectrum.js +++ b/src/graph_spectrum.js @@ -246,9 +246,7 @@ export function FlightLogAnalyser(flightLog, canvas, analyserCanvas) { saveOneUserSetting("psdHeatmapMin", min); analyserLowLevelPSD.prop("min", min); analyserMaxPSD.prop("min", min + 5); - if (analyserLowLevelPSD.val() < min) { - analyserLowLevelPSD.val(min).trigger("input"); - } + analyserLowLevelPSD.val(min).trigger("input"); that.refresh(); }), ) From a6ceec0849e4d1b9aa5d57991b708bc02d16b15a Mon Sep 17 00:00:00 2001 From: demvlad Date: Fri, 4 Jul 2025 10:55:36 +0300 Subject: [PATCH 26/35] The input number element is added at html and css instead of slider for PSD segment length values input --- index.html | 5 +++++ src/css/main.css | 18 +++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/index.html b/index.html index ab9494e3..6b5004c7 100644 --- a/index.html +++ b/index.html @@ -493,6 +493,8 @@

Workspace

/> + Workspace + diff --git a/src/css/main.css b/src/css/main.css index e3be6f5a..5bdc6832 100644 --- a/src/css/main.css +++ b/src/css/main.css @@ -690,7 +690,9 @@ html.has-analyser-fullscreen.has-analyser .analyser input#analyserMaxPSD::-webkit-inner-spin-button, .analyser input#analyserMaxPSD::-webkit-outer-spin-button, .analyser input#analyserLowLevelPSD::-webkit-inner-spin-button, -.analyser input#analyserLowLevelPSD::-webkit-outer-spin-button { +.analyser input#analyserLowLevelPSD::-webkit-outer-spin-button, +.analyser input#analyserSegmentLengthPSD::-webkit-inner-spin-button, +.analyser input#analyserSegmentLengthPSD::-webkit-outer-spin-button { -webkit-appearance: auto !important; -moz-appearance: auto !important; appearance: auto !important; @@ -744,6 +746,20 @@ html.has-analyser-fullscreen.has-analyser font-size: 12px; } +.analyser input#analyserSegmentLengthPSD { + width: 100px; + height: 20px; + left: 0px; + top: 50px; +} + +.analyser label#analyserSegmentLengthPSDLabel { + width: 50px; + height: 20px; + left: 0px; + top: 30px; +} + .analyser input.onlyFullScreen { display: none; padding: 3px; From 0208d5e20a0931007a8a0941a7a1b652361285d8 Mon Sep 17 00:00:00 2001 From: demvlad Date: Fri, 4 Jul 2025 11:01:49 +0300 Subject: [PATCH 27/35] The input number element for psd segment length input is placed at form with shows logic --- src/graph_spectrum.js | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/graph_spectrum.js b/src/graph_spectrum.js index 4367611e..68a4b51c 100644 --- a/src/graph_spectrum.js +++ b/src/graph_spectrum.js @@ -35,6 +35,7 @@ export function FlightLogAnalyser(flightLog, canvas, analyserCanvas) { const analyserMinPSD = $("#analyserMinPSD"); const analyserMaxPSD = $("#analyserMaxPSD"); const analyserLowLevelPSD = $("#analyserLowLevelPSD"); + const analyserSegmentLengthPSD = $("#analyserSegmentLengthPSD"); const spectrumToolbarElem = $("#spectrumToolbar"); @@ -117,6 +118,12 @@ export function FlightLogAnalyser(flightLog, canvas, analyserCanvas) { $("#analyserLowLevelPSDLabel", parentElem).css({ left: `${newSize.width - 155}px`, }); + $("#analyserSegmentLengthPSD", parentElem).css({ + left: `${newSize.width - 150}px`, + }); + $("#analyserSegmentLengthPSDLabel", parentElem).css({ + left: `${newSize.width - 150}px`, + }); }; const dataLoad = function (fieldIndex, curve, fieldName) { @@ -319,10 +326,16 @@ export function FlightLogAnalyser(flightLog, canvas, analyserCanvas) { const psdHeatMapSelected = optionSelected === SPECTRUM_TYPE.PSD_VS_THROTTLE || optionSelected === SPECTRUM_TYPE.PSD_VS_RPM; + const psdCurveSelected = + optionSelected === SPECTRUM_TYPE.POWER_SPECTRAL_DENSITY; overdrawSpectrumTypeElem.toggle(!pidErrorVsSetpointSelected); analyserZoomYElem.toggleClass( "onlyFullScreenException", - pidErrorVsSetpointSelected || psdHeatMapSelected, + pidErrorVsSetpointSelected || psdHeatMapSelected || psdCurveSelected, + ); + analyserSegmentLengthPSD.toggleClass( + "onlyFullScreenException", + !psdCurveSelected, ); analyserLowLevelPSD.toggleClass( "onlyFullScreenException", @@ -348,6 +361,10 @@ export function FlightLogAnalyser(flightLog, canvas, analyserCanvas) { "onlyFullScreenException", !psdHeatMapSelected, ); + $("#analyserSegmentLengthPSDLabel").toggleClass( + "onlyFullScreenException", + !psdCurveSelected, + ); const showSpectrumsComparisonPanel = optionSelected === SPECTRUM_TYPE.FREQUENCY || optionSelected === SPECTRUM_TYPE.POWER_SPECTRAL_DENSITY; From ec62b9dde9f68075615705a44b5625507c9cdbf8 Mon Sep 17 00:00:00 2001 From: demvlad Date: Fri, 4 Jul 2025 11:05:41 +0300 Subject: [PATCH 28/35] Added update events handler to multiple/divide by 2 the PSD segment length --- src/graph_spectrum.js | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/src/graph_spectrum.js b/src/graph_spectrum.js index 68a4b51c..eba5fbe5 100644 --- a/src/graph_spectrum.js +++ b/src/graph_spectrum.js @@ -220,11 +220,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(); }), ) @@ -302,6 +297,31 @@ export function FlightLogAnalyser(flightLog, canvas, analyserCanvas) { }) .val(analyserMinPSD.val()); + let previousSegLenValue = 512; + analyserSegmentLengthPSD + .on( + "input", + function () { + const currentValue = parseInt($(this).val()); + if (currentValue > previousSegLenValue) { + previousSegLenValue *= 2; + } else { + previousSegLenValue /= 2; + } + $(this).val(previousSegLenValue); + // Recalculate PSD with updated samples per segment count + dataLoad(); + GraphSpectrumPlot.setData(fftData, userSettings.spectrumType); + that.refresh(); + }, + ) + .dblclick(function (e) { + if (e.ctrlKey) { + $(this).val(userSettings.psdHeatmapMax).trigger("input"); + } + }) + .val(512); + // Spectrum type to show userSettings.spectrumType = userSettings.spectrumType || SPECTRUM_TYPE.FREQUENCY; From 2476e1d70840ebb92e02931ef876adb16f5ab0f1 Mon Sep 17 00:00:00 2001 From: demvlad Date: Fri, 4 Jul 2025 14:22:52 +0300 Subject: [PATCH 29/35] Added points per segment count change from html input --- src/graph_spectrum.js | 32 ++++++++++++++++++++++---------- src/graph_spectrum_calc.js | 17 ++++++++++------- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/graph_spectrum.js b/src/graph_spectrum.js index eba5fbe5..8ff8537f 100644 --- a/src/graph_spectrum.js +++ b/src/graph_spectrum.js @@ -17,7 +17,8 @@ export function FlightLogAnalyser(flightLog, canvas, analyserCanvas) { const that = this, prefs = new PrefStorage(), DEFAULT_PSD_HEATMAP_MIN = -40, - DEFAULT_PSD_HEATMAP_MAX = 10; + DEFAULT_PSD_HEATMAP_MAX = 10, + DEFAULT_PSD_SEGMENT_LENGTH = 512; let analyserZoomX = 1.0 /* 100% */, analyserZoomY = 1.0 /* 100% */, dataReload = false, @@ -122,7 +123,7 @@ export function FlightLogAnalyser(flightLog, canvas, analyserCanvas) { left: `${newSize.width - 150}px`, }); $("#analyserSegmentLengthPSDLabel", parentElem).css({ - left: `${newSize.width - 150}px`, + left: `${newSize.width - 170}px`, }); }; @@ -297,19 +298,21 @@ export function FlightLogAnalyser(flightLog, canvas, analyserCanvas) { }) .val(analyserMinPSD.val()); - let previousSegLenValue = 512; + let segmentLenghtPSD = DEFAULT_PSD_SEGMENT_LENGTH; + GraphSpectrumCalc.setPointsPerSegmentPSD(segmentLenghtPSD); analyserSegmentLengthPSD .on( "input", function () { const currentValue = parseInt($(this).val()); - if (currentValue > previousSegLenValue) { - previousSegLenValue *= 2; - } else { - previousSegLenValue /= 2; + if (currentValue > segmentLenghtPSD) { + segmentLenghtPSD *= 2; + } else if (currentValue < segmentLenghtPSD){ + segmentLenghtPSD /= 2; } - $(this).val(previousSegLenValue); + $(this).val(segmentLenghtPSD); // Recalculate PSD with updated samples per segment count + GraphSpectrumCalc.setPointsPerSegmentPSD(segmentLenghtPSD); dataLoad(); GraphSpectrumPlot.setData(fftData, userSettings.spectrumType); that.refresh(); @@ -317,10 +320,19 @@ export function FlightLogAnalyser(flightLog, canvas, analyserCanvas) { ) .dblclick(function (e) { if (e.ctrlKey) { - $(this).val(userSettings.psdHeatmapMax).trigger("input"); + segmentLenghtPSD = DEFAULT_PSD_SEGMENT_LENGTH; + $(this).val(DEFAULT_PSD_SEGMENT_LENGTH).trigger("input"); } }) - .val(512); + .val(DEFAULT_PSD_SEGMENT_LENGTH); + + analyserSegmentLengthPSD + .on( + "keydown", + function (e) { + e.preventDefault(); + } + ); // Spectrum type to show userSettings.spectrumType = diff --git a/src/graph_spectrum_calc.js b/src/graph_spectrum_calc.js index ba7267f7..4c739f4e 100644 --- a/src/graph_spectrum_calc.js +++ b/src/graph_spectrum_calc.js @@ -35,6 +35,7 @@ export const GraphSpectrumCalc = { _flightLog : null, _sysConfig : null, _motorPoles : null, + _pointsPerSegmentPSD : 0, }; GraphSpectrumCalc.initialize = function(flightLog, sysConfig) { @@ -112,16 +113,18 @@ GraphSpectrumCalc.dataLoadFrequency = function() { return fftData; }; +GraphSpectrumCalc.setPointsPerSegmentPSD = function(pointsCount) { + this._pointsPerSegmentPSD = pointsCount; +}; + GraphSpectrumCalc.dataLoadPSD = function(analyserZoomY) { const flightSamples = this._getFlightSamplesFreq(false); - const multiplier = Math.floor(1 / analyserZoomY); // 0. ... 10 - let pointsPerSegment = 2 ** (8 + multiplier); //256, 512, 1024 ... - - let overlapCount; - if (pointsPerSegment > flightSamples.samples.length) { - pointsPerSegment = flightSamples.samples.length; // Use actual sample length. It will transform to power at 2 value inside the _psd() - fft_segmented - overlapCount = 0; + let pointsPerSegment, overlapCount; + if (this._pointsPerSegmentPSD > flightSamples.samples.length) { + pointsPerSegment = flightSamples.samples.length; // Use actual sample length. It will transform to power at 2 value inside the _psd() - fft_segmented + overlapCount = 0; } else { + pointsPerSegment = this._pointsPerSegmentPSD; overlapCount = pointsPerSegment / 2; } From 88a00b0e720169a749c907cd7bd786dd5c81cf78 Mon Sep 17 00:00:00 2001 From: demvlad Date: Fri, 4 Jul 2025 14:25:03 +0300 Subject: [PATCH 30/35] Edited html input element --- index.html | 2 +- src/css/main.css | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index 6b5004c7..70ed195d 100644 --- a/index.html +++ b/index.html @@ -493,7 +493,7 @@

Workspace

/> - diff --git a/src/css/main.css b/src/css/main.css index 5bdc6832..4bde1ba1 100644 --- a/src/css/main.css +++ b/src/css/main.css @@ -747,7 +747,7 @@ html.has-analyser-fullscreen.has-analyser } .analyser input#analyserSegmentLengthPSD { - width: 100px; + width: 80px; height: 20px; left: 0px; top: 50px; @@ -757,7 +757,7 @@ html.has-analyser-fullscreen.has-analyser width: 50px; height: 20px; left: 0px; - top: 30px; + top: 28px; } .analyser input.onlyFullScreen { From 32b7eb00d0a23c416ce43a741db803b1258fbd04 Mon Sep 17 00:00:00 2001 From: demvlad Date: Fri, 4 Jul 2025 14:56:23 +0300 Subject: [PATCH 31/35] Added computing of maximal points per segment PSD values --- src/graph_spectrum.js | 1 + src/graph_spectrum_calc.js | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/graph_spectrum.js b/src/graph_spectrum.js index 8ff8537f..459760b3 100644 --- a/src/graph_spectrum.js +++ b/src/graph_spectrum.js @@ -155,6 +155,7 @@ export function FlightLogAnalyser(flightLog, canvas, analyserCanvas) { case SPECTRUM_TYPE.POWER_SPECTRAL_DENSITY: fftData = GraphSpectrumCalc.dataLoadPSD(analyserZoomY); + analyserSegmentLengthPSD.prop("max", fftData.maximalSegmentsLength); break; case SPECTRUM_TYPE.FREQUENCY: diff --git a/src/graph_spectrum_calc.js b/src/graph_spectrum_calc.js index 4c739f4e..0e599460 100644 --- a/src/graph_spectrum_calc.js +++ b/src/graph_spectrum_calc.js @@ -125,7 +125,7 @@ GraphSpectrumCalc.dataLoadPSD = function(analyserZoomY) { overlapCount = 0; } else { pointsPerSegment = this._pointsPerSegmentPSD; - overlapCount = pointsPerSegment / 2; + overlapCount = pointsPerSegment * 3 / 4; } const psd = this._psd(flightSamples.samples, pointsPerSegment, overlapCount); @@ -139,6 +139,7 @@ GraphSpectrumCalc.dataLoadPSD = function(analyserZoomY) { minimum: psd.min, maximum: psd.max, maxNoiseFrequency: psd.maxNoiseFrequency, + maximalSegmentsLength: this.getNearPower2Value(flightSamples.samples.length), }; return psdData; }; From 93eb8aa559baf8d45d44b64834896ff372cd0fcd Mon Sep 17 00:00:00 2001 From: demvlad Date: Fri, 4 Jul 2025 15:01:09 +0300 Subject: [PATCH 32/35] Thde labels color is changed --- src/css/main.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/css/main.css b/src/css/main.css index 4bde1ba1..28106486 100644 --- a/src/css/main.css +++ b/src/css/main.css @@ -754,6 +754,8 @@ html.has-analyser-fullscreen.has-analyser } .analyser label#analyserSegmentLengthPSDLabel { + position:absolute; + color:gray; width: 50px; height: 20px; left: 0px; From 5ee8dfb46aa242a355a16b73d05e8a3281fa829d Mon Sep 17 00:00:00 2001 From: demvlad Date: Fri, 4 Jul 2025 21:51:44 +0300 Subject: [PATCH 33/35] Added missing comma --- src/graph_spectrum.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graph_spectrum.js b/src/graph_spectrum.js index 459760b3..c1d675d8 100644 --- a/src/graph_spectrum.js +++ b/src/graph_spectrum.js @@ -332,7 +332,7 @@ export function FlightLogAnalyser(flightLog, canvas, analyserCanvas) { "keydown", function (e) { e.preventDefault(); - } + }, ); // Spectrum type to show From c0089f80dc8633d479149b6dc8797d733eea16e1 Mon Sep 17 00:00:00 2001 From: demvlad Date: Fri, 4 Jul 2025 21:56:04 +0300 Subject: [PATCH 34/35] The segmentLenghtPSD variables name is changed to segmentLengthPSD --- src/graph_spectrum.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/graph_spectrum.js b/src/graph_spectrum.js index c1d675d8..4c22dbf0 100644 --- a/src/graph_spectrum.js +++ b/src/graph_spectrum.js @@ -299,21 +299,21 @@ export function FlightLogAnalyser(flightLog, canvas, analyserCanvas) { }) .val(analyserMinPSD.val()); - let segmentLenghtPSD = DEFAULT_PSD_SEGMENT_LENGTH; - GraphSpectrumCalc.setPointsPerSegmentPSD(segmentLenghtPSD); + let segmentLengthPSD = DEFAULT_PSD_SEGMENT_LENGTH; + GraphSpectrumCalc.setPointsPerSegmentPSD(segmentLengthPSD); analyserSegmentLengthPSD .on( "input", function () { const currentValue = parseInt($(this).val()); - if (currentValue > segmentLenghtPSD) { - segmentLenghtPSD *= 2; - } else if (currentValue < segmentLenghtPSD){ - segmentLenghtPSD /= 2; + if (currentValue > segmentLengthPSD) { + segmentLengthPSD *= 2; + } else if (currentValue < segmentLengthPSD){ + segmentLengthPSD /= 2; } - $(this).val(segmentLenghtPSD); + $(this).val(segmentLengthPSD); // Recalculate PSD with updated samples per segment count - GraphSpectrumCalc.setPointsPerSegmentPSD(segmentLenghtPSD); + GraphSpectrumCalc.setPointsPerSegmentPSD(segmentLengthPSD); dataLoad(); GraphSpectrumPlot.setData(fftData, userSettings.spectrumType); that.refresh(); @@ -321,7 +321,7 @@ export function FlightLogAnalyser(flightLog, canvas, analyserCanvas) { ) .dblclick(function (e) { if (e.ctrlKey) { - segmentLenghtPSD = DEFAULT_PSD_SEGMENT_LENGTH; + segmentLengthPSD = DEFAULT_PSD_SEGMENT_LENGTH; $(this).val(DEFAULT_PSD_SEGMENT_LENGTH).trigger("input"); } }) From 5513d867c56223aab100377cb26de0ea3b7c952d Mon Sep 17 00:00:00 2001 From: demvlad Date: Sun, 6 Jul 2025 20:25:41 +0300 Subject: [PATCH 35/35] The PSD segment length input elements are replaced --- index.html | 2 +- src/graph_spectrum.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index 70ed195d..f92185f2 100644 --- a/index.html +++ b/index.html @@ -511,7 +511,7 @@

Workspace

Limit dBm diff --git a/src/graph_spectrum.js b/src/graph_spectrum.js index 4c22dbf0..5f66e868 100644 --- a/src/graph_spectrum.js +++ b/src/graph_spectrum.js @@ -120,10 +120,10 @@ export function FlightLogAnalyser(flightLog, canvas, analyserCanvas) { left: `${newSize.width - 155}px`, }); $("#analyserSegmentLengthPSD", parentElem).css({ - left: `${newSize.width - 150}px`, + left: `${newSize.width - 120}px`, }); $("#analyserSegmentLengthPSDLabel", parentElem).css({ - left: `${newSize.width - 170}px`, + left: `${newSize.width - 135}px`, }); };