-
-
Notifications
You must be signed in to change notification settings - Fork 152
Added power spectral density charts #827
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 9 commits
d9a1696
12de34e
b9c24b7
a8bfb8c
ebef462
0c282ba
01a0c98
7a59f8a
c128b2a
7546815
effb820
871a012
30b62b1
3877f84
6334c89
77acf1e
b1bd761
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -18,6 +18,8 @@ export const SPECTRUM_TYPE = { | |||||||||||||||||||||||||||
PIDERROR_VS_SETPOINT: 2, | ||||||||||||||||||||||||||||
FREQ_VS_RPM: 3, | ||||||||||||||||||||||||||||
POWER_SPECTRAL_DENSITY: 4, | ||||||||||||||||||||||||||||
PSD_VS_THROTTLE: 5, | ||||||||||||||||||||||||||||
PSD_VS_RPM: 6, | ||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
export const SPECTRUM_OVERDRAW_TYPE = { | ||||||||||||||||||||||||||||
|
@@ -169,6 +171,14 @@ GraphSpectrumPlot._drawGraph = function (canvasCtx) { | |||||||||||||||||||||||||||
this._drawFrequencyVsXGraph(canvasCtx); | ||||||||||||||||||||||||||||
break; | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
case SPECTRUM_TYPE.PSD_VS_THROTTLE: | ||||||||||||||||||||||||||||
this._drawFrequencyVsXGraph(canvasCtx, true); | ||||||||||||||||||||||||||||
break; | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
case SPECTRUM_TYPE.PSD_VS_RPM: | ||||||||||||||||||||||||||||
this._drawFrequencyVsXGraph(canvasCtx, true); | ||||||||||||||||||||||||||||
break; | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
case SPECTRUM_TYPE.PIDERROR_VS_SETPOINT: | ||||||||||||||||||||||||||||
this._drawPidErrorVsSetpointGraph(canvasCtx); | ||||||||||||||||||||||||||||
break; | ||||||||||||||||||||||||||||
|
@@ -395,7 +405,12 @@ GraphSpectrumPlot._drawPowerSpectralDensityGraph = function (canvasCtx) { | |||||||||||||||||||||||||||
canvasCtx.restore(); | ||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
GraphSpectrumPlot._drawFrequencyVsXGraph = function (canvasCtx) { | ||||||||||||||||||||||||||||
GraphSpectrumPlot.getPSDbyFreq = function(frequency) { | ||||||||||||||||||||||||||||
const freqIndex = Math.round(2 * frequency / this._fftData.blackBoxRate * (this._fftData.psdOutput.length - 1) ); | ||||||||||||||||||||||||||||
return this._fftData.psdOutput[freqIndex]; | ||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add bounds checking to getPSDbyFreq This new method lacks validation for the calculated index and doesn't handle potential null/undefined values in the FFT data. GraphSpectrumPlot.getPSDbyFreq = function(frequency) {
+ if (!this._fftData || !this._fftData.psdOutput || !this._fftData.psdOutput.length) {
+ return 0; // Return safe default if data is missing
+ }
const freqIndex = Math.round(2 * frequency / this._fftData.blackBoxRate * (this._fftData.psdOutput.length - 1));
+ // Ensure freqIndex is within valid bounds
+ const safeIndex = Math.max(0, Math.min(freqIndex, this._fftData.psdOutput.length - 1));
- return this._fftData.psdOutput[freqIndex];
+ return this._fftData.psdOutput[safeIndex];
}; 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
GraphSpectrumPlot._drawFrequencyVsXGraph = function (canvasCtx, drawPSD = false) { | ||||||||||||||||||||||||||||
const PLOTTED_BLACKBOX_RATE = this._fftData.blackBoxRate / this._zoomX; | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
const ACTUAL_MARGIN_LEFT = this._getActualMarginLeft(); | ||||||||||||||||||||||||||||
|
@@ -407,7 +422,7 @@ GraphSpectrumPlot._drawFrequencyVsXGraph = function (canvasCtx) { | |||||||||||||||||||||||||||
canvasCtx.translate(LEFT, TOP); | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
if (this._cachedDataCanvas == null) { | ||||||||||||||||||||||||||||
this._cachedDataCanvas = this._drawHeatMap(); | ||||||||||||||||||||||||||||
this._cachedDataCanvas = this._drawHeatMap(drawPSD); | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
canvasCtx.drawImage(this._cachedDataCanvas, 0, 0, WIDTH, HEIGHT); | ||||||||||||||||||||||||||||
|
@@ -442,7 +457,8 @@ GraphSpectrumPlot._drawFrequencyVsXGraph = function (canvasCtx) { | |||||||||||||||||||||||||||
"Hz" | ||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
if (this._spectrumType === SPECTRUM_TYPE.FREQ_VS_THROTTLE) { | ||||||||||||||||||||||||||||
if (this._spectrumType === SPECTRUM_TYPE.FREQ_VS_THROTTLE || | ||||||||||||||||||||||||||||
this._spectrumType === SPECTRUM_TYPE.PSD_VS_THROTTLE) { | ||||||||||||||||||||||||||||
this._drawVerticalGridLines( | ||||||||||||||||||||||||||||
canvasCtx, | ||||||||||||||||||||||||||||
LEFT, | ||||||||||||||||||||||||||||
|
@@ -453,7 +469,8 @@ GraphSpectrumPlot._drawFrequencyVsXGraph = function (canvasCtx) { | |||||||||||||||||||||||||||
this._fftData.vsRange.max, | ||||||||||||||||||||||||||||
"%" | ||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||
} else if (this._spectrumType === SPECTRUM_TYPE.FREQ_VS_RPM) { | ||||||||||||||||||||||||||||
} else if (this._spectrumType === SPECTRUM_TYPE.FREQ_VS_RPM || | ||||||||||||||||||||||||||||
this._spectrumType === SPECTRUM_TYPE.PSD_VS_RPM) { | ||||||||||||||||||||||||||||
this._drawVerticalGridLines( | ||||||||||||||||||||||||||||
canvasCtx, | ||||||||||||||||||||||||||||
LEFT, | ||||||||||||||||||||||||||||
|
@@ -467,7 +484,7 @@ GraphSpectrumPlot._drawFrequencyVsXGraph = function (canvasCtx) { | |||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
GraphSpectrumPlot._drawHeatMap = function () { | ||||||||||||||||||||||||||||
GraphSpectrumPlot._drawHeatMap = function (drawPSD = false) { | ||||||||||||||||||||||||||||
const THROTTLE_VALUES_SIZE = 100; | ||||||||||||||||||||||||||||
const SCALE_HEATMAP = 1.3; // Value decided after some tests to be similar to the scale of frequency graph | ||||||||||||||||||||||||||||
// This value will be maximum color | ||||||||||||||||||||||||||||
|
@@ -485,9 +502,17 @@ GraphSpectrumPlot._drawHeatMap = function () { | |||||||||||||||||||||||||||
for (let j = 0; j < 100; j++) { | ||||||||||||||||||||||||||||
// Loop for frequency | ||||||||||||||||||||||||||||
for (let i = 0; i < this._fftData.fftLength; i++) { | ||||||||||||||||||||||||||||
const valuePlot = Math.round( | ||||||||||||||||||||||||||||
Math.min(this._fftData.fftOutput[j][i] * fftColorScale, 100) | ||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||
let valuePlot; | ||||||||||||||||||||||||||||
if (drawPSD) { | ||||||||||||||||||||||||||||
const min = -40, max = 10; //limit values dBm | ||||||||||||||||||||||||||||
valuePlot = Math.max(this._fftData.fftOutput[j][i], min); | ||||||||||||||||||||||||||||
valuePlot = Math.min(valuePlot, max); | ||||||||||||||||||||||||||||
valuePlot = Math.round((valuePlot - min) * 100 / (max - min)); | ||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||
valuePlot = Math.round( | ||||||||||||||||||||||||||||
Math.min(this._fftData.fftOutput[j][i] * fftColorScale, 100) | ||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
// The fillStyle is slow, but I haven't found a way to do this faster... | ||||||||||||||||||||||||||||
canvasCtx.fillStyle = `hsl(360, 100%, ${valuePlot}%)`; | ||||||||||||||||||||||||||||
|
@@ -503,6 +528,17 @@ GraphSpectrumPlot._drawHeatMap = function () { | |||||||||||||||||||||||||||
return heatMapCanvas; | ||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
GraphSpectrumPlot.getValueFromMatrixFFT = function(frequency, vsArgument) { | ||||||||||||||||||||||||||||
const NUM_VS_BINS = 100; // redefinition of value from graph_spectrum_calc.js module! | ||||||||||||||||||||||||||||
const matrixFFT = this._fftData; | ||||||||||||||||||||||||||||
let vsArgumentIndex = Math.round(NUM_VS_BINS * (vsArgument - matrixFFT.vsRange.min) / (matrixFFT.vsRange.max - matrixFFT.vsRange.min)); | ||||||||||||||||||||||||||||
if (vsArgumentIndex === NUM_VS_BINS) { | ||||||||||||||||||||||||||||
vsArgumentIndex = NUM_VS_BINS - 1; | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
const freqIndex = Math.round(2 * frequency / matrixFFT.blackBoxRate * (matrixFFT.fftOutput[0].length - 1) ); | ||||||||||||||||||||||||||||
return matrixFFT.fftOutput[vsArgumentIndex][freqIndex]; | ||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||
demvlad marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
GraphSpectrumPlot._drawPidErrorVsSetpointGraph = function (canvasCtx) { | ||||||||||||||||||||||||||||
const ACTUAL_MARGIN_LEFT = this._getActualMarginLeft(); | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
|
@@ -1443,17 +1479,20 @@ GraphSpectrumPlot._drawMousePosition = function ( | |||||||||||||||||||||||||||
lineWidth | ||||||||||||||||||||||||||||
) { | ||||||||||||||||||||||||||||
// X axis | ||||||||||||||||||||||||||||
let mouseFrequency = 0; | ||||||||||||||||||||||||||||
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.POWER_SPECTRAL_DENSITY || | ||||||||||||||||||||||||||||
this._spectrumType === SPECTRUM_TYPE.PSD_VS_THROTTLE || | ||||||||||||||||||||||||||||
this._spectrumType === SPECTRUM_TYPE.PSD_VS_RPM | ||||||||||||||||||||||||||||
) { | ||||||||||||||||||||||||||||
// Calculate frequency at mouse | ||||||||||||||||||||||||||||
const sampleRate = this._fftData.blackBoxRate / this._zoomX; | ||||||||||||||||||||||||||||
const marginLeft = this._getActualMarginLeft(); | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
const mouseFrequency = | ||||||||||||||||||||||||||||
mouseFrequency = | ||||||||||||||||||||||||||||
((mouseX - marginLeft) / WIDTH) * | ||||||||||||||||||||||||||||
(this._fftData.blackBoxRate / this._zoomX / 2); | ||||||||||||||||||||||||||||
if (mouseFrequency >= 0 && mouseFrequency <= sampleRate) { | ||||||||||||||||||||||||||||
|
@@ -1470,13 +1509,26 @@ 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", | ||||||||||||||||||||||||||||
demvlad marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
// Y axis | ||||||||||||||||||||||||||||
let unitLabel; | ||||||||||||||||||||||||||||
switch (this._spectrumType) { | ||||||||||||||||||||||||||||
case SPECTRUM_TYPE.FREQ_VS_THROTTLE: | ||||||||||||||||||||||||||||
case SPECTRUM_TYPE.PSD_VS_THROTTLE: | ||||||||||||||||||||||||||||
unitLabel = "%"; | ||||||||||||||||||||||||||||
break; | ||||||||||||||||||||||||||||
case SPECTRUM_TYPE.FREQ_VS_RPM: | ||||||||||||||||||||||||||||
case SPECTRUM_TYPE.PSD_VS_RPM: | ||||||||||||||||||||||||||||
unitLabel = "Hz"; | ||||||||||||||||||||||||||||
break; | ||||||||||||||||||||||||||||
case SPECTRUM_TYPE.POWER_SPECTRAL_DENSITY: | ||||||||||||||||||||||||||||
|
@@ -1489,12 +1541,12 @@ GraphSpectrumPlot._drawMousePosition = function ( | |||||||||||||||||||||||||||
if (unitLabel !== null) { | ||||||||||||||||||||||||||||
const val_min = this._fftData.vsRange.min; | ||||||||||||||||||||||||||||
const val_max = this._fftData.vsRange.max; | ||||||||||||||||||||||||||||
const mouseValue = (1 - mouseY / HEIGHT) * (val_max - val_min) + val_min; | ||||||||||||||||||||||||||||
if (mouseValue >= val_min && mouseValue <= val_max) { | ||||||||||||||||||||||||||||
const valueLabel = `${mouseValue.toFixed(0)}${unitLabel}`; | ||||||||||||||||||||||||||||
const vsArgValue = (1 - mouseY / HEIGHT) * (val_max - val_min) + val_min; | ||||||||||||||||||||||||||||
if (vsArgValue >= val_min && vsArgValue <= val_max) { | ||||||||||||||||||||||||||||
const valueLabel = `${vsArgValue.toFixed(0)}${unitLabel}`; | ||||||||||||||||||||||||||||
this._drawHorizontalMarkerLine( | ||||||||||||||||||||||||||||
canvasCtx, | ||||||||||||||||||||||||||||
mouseValue, | ||||||||||||||||||||||||||||
vsArgValue, | ||||||||||||||||||||||||||||
val_min, | ||||||||||||||||||||||||||||
val_max, | ||||||||||||||||||||||||||||
valueLabel, | ||||||||||||||||||||||||||||
|
@@ -1504,6 +1556,18 @@ GraphSpectrumPlot._drawMousePosition = function ( | |||||||||||||||||||||||||||
stroke, | ||||||||||||||||||||||||||||
lineWidth | ||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
if (this._spectrumType == SPECTRUM_TYPE.PSD_VS_THROTTLE || | ||||||||||||||||||||||||||||
this._spectrumType == SPECTRUM_TYPE.PSD_VS_RPM) { | ||||||||||||||||||||||||||||
demvlad marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||
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) { | ||||||||||||||||||||||||||||
|
@@ -1557,6 +1621,8 @@ GraphSpectrumPlot._getActualMarginLeft = function () { | |||||||||||||||||||||||||||
switch (this._spectrumType) { | ||||||||||||||||||||||||||||
case SPECTRUM_TYPE.FREQ_VS_THROTTLE: | ||||||||||||||||||||||||||||
case SPECTRUM_TYPE.FREQ_VS_RPM: | ||||||||||||||||||||||||||||
case SPECTRUM_TYPE.PSD_VS_THROTTLE: | ||||||||||||||||||||||||||||
case SPECTRUM_TYPE.PSD_VS_RPM: | ||||||||||||||||||||||||||||
case SPECTRUM_TYPE.POWER_SPECTRAL_DENSITY: | ||||||||||||||||||||||||||||
actualMarginLeft = this._isFullScreen | ||||||||||||||||||||||||||||
? MARGIN_LEFT_FULLSCREEN | ||||||||||||||||||||||||||||
|
Uh oh!
There was an error while loading. Please reload this page.