diff --git a/example/generator/GeneratorProvider.js b/example/generator/GeneratorProvider.js index b74915ef12c..2aeee687a2f 100644 --- a/example/generator/GeneratorProvider.js +++ b/example/generator/GeneratorProvider.js @@ -29,7 +29,8 @@ define(['./WorkerInterface'], function (WorkerInterface) { randomness: 0, phase: 0, loadDelay: 0, - infinityValues: false + infinityValues: false, + exceedFloat32: false }; function GeneratorProvider(openmct, StalenessProvider) { @@ -53,7 +54,8 @@ define(['./WorkerInterface'], function (WorkerInterface) { 'randomness', 'phase', 'loadDelay', - 'infinityValues' + 'infinityValues', + 'exceedFloat32' ]; request = request || {}; diff --git a/example/generator/generatorWorker.js b/example/generator/generatorWorker.js index 6a83fe2ba8a..024f54032d7 100644 --- a/example/generator/generatorWorker.js +++ b/example/generator/generatorWorker.js @@ -85,7 +85,8 @@ data.offset, data.phase, data.randomness, - data.infinityValues + data.infinityValues, + data.exceedFloat32 ), wavelengths: wavelengths(), intensities: intensities(), @@ -96,7 +97,8 @@ data.offset, data.phase, data.randomness, - data.infinityValues + data.infinityValues, + data.exceedFloat32 ) } }); @@ -136,6 +138,7 @@ var randomness = request.randomness; var loadDelay = Math.max(request.loadDelay, 0); var infinityValues = request.infinityValues; + var exceedFloat32 = request.exceedFloat32; var step = 1000 / dataRateInHz; var nextStep = start - (start % step) + step; @@ -146,10 +149,28 @@ data.push({ utc: nextStep, yesterday: nextStep - 60 * 60 * 24 * 1000, - sin: sin(nextStep, period, amplitude, offset, phase, randomness, infinityValues), + sin: sin( + nextStep, + period, + amplitude, + offset, + phase, + randomness, + infinityValues, + exceedFloat32 + ), wavelengths: wavelengths(), intensities: intensities(), - cos: cos(nextStep, period, amplitude, offset, phase, randomness, infinityValues) + cos: cos( + nextStep, + period, + amplitude, + offset, + phase, + randomness, + infinityValues, + exceedFloat32 + ) }); } @@ -176,9 +197,26 @@ }); } - function cos(timestamp, period, amplitude, offset, phase, randomness, infinityValues) { - if (infinityValues && Math.random() > 0.5) { + function cos( + timestamp, + period, + amplitude, + offset, + phase, + randomness, + infinityValues, + exceedFloat32 + ) { + if (infinityValues && exceedFloat32) { + if (Math.random() > 0.5) { + return Number.POSITIVE_INFINITY; + } else if (Math.random() < 0.01) { + return getRandomFloat32OverflowValue(); + } + } else if (infinityValues && Math.random() > 0.5) { return Number.POSITIVE_INFINITY; + } else if (exceedFloat32 && Math.random() < 0.01) { + return getRandomFloat32OverflowValue(); } return ( @@ -188,9 +226,26 @@ ); } - function sin(timestamp, period, amplitude, offset, phase, randomness, infinityValues) { - if (infinityValues && Math.random() > 0.5) { + function sin( + timestamp, + period, + amplitude, + offset, + phase, + randomness, + infinityValues, + exceedFloat32 + ) { + if (infinityValues && exceedFloat32) { + if (Math.random() > 0.5) { + return Number.POSITIVE_INFINITY; + } else if (Math.random() < 0.01) { + return getRandomFloat32OverflowValue(); + } + } else if (infinityValues && Math.random() > 0.5) { return Number.POSITIVE_INFINITY; + } else if (exceedFloat32 && Math.random() < 0.01) { + return getRandomFloat32OverflowValue(); } return ( @@ -200,6 +255,13 @@ ); } + // Values exceeding float32 range (Positive: 3.4+38, Negative: -3.4+38) + function getRandomFloat32OverflowValue() { + const sign = Math.random() > 0.5 ? 1 : -1; + + return sign * 3.4e39; + } + function wavelengths() { let values = []; while (values.length < 5) { diff --git a/example/generator/plugin.js b/example/generator/plugin.js index d4191961562..6f60cd83d43 100644 --- a/example/generator/plugin.js +++ b/example/generator/plugin.js @@ -122,6 +122,13 @@ export default function (openmct) { key: 'infinityValues', property: ['telemetry', 'infinityValues'] }, + { + name: 'Exceed Float32 Limits', + control: 'toggleSwitch', + cssClass: 'l-input', + key: 'exceedFloat32', + property: ['telemetry', 'exceedFloat32'] + }, { name: 'Provide Staleness Updates', control: 'toggleSwitch', @@ -140,6 +147,7 @@ export default function (openmct) { randomness: 0, loadDelay: 0, infinityValues: false, + exceedFloat32: false, staleness: false }; } diff --git a/src/plugins/plot/configuration/PlotSeries.js b/src/plugins/plot/configuration/PlotSeries.js index 7d9edd6b7c6..00a2e41bf0e 100644 --- a/src/plugins/plot/configuration/PlotSeries.js +++ b/src/plugins/plot/configuration/PlotSeries.js @@ -19,8 +19,6 @@ * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ -import _ from 'lodash'; - import configStore from '../configuration/ConfigStore'; import { MARKER_SHAPES } from '../draw/MarkerShapes'; import { symlog } from '../mathUtils'; @@ -64,6 +62,10 @@ import Model from './Model'; * * @extends {Model} */ + +const FLOAT32_MAX = 3.4e38; +const FLOAT32_MIN = -3.4e38; + export default class PlotSeries extends Model { logMode = false; @@ -371,7 +373,7 @@ export default class PlotSeries extends Model { let stats = this.get('stats'); let changed = false; if (!stats) { - if ([Infinity, -Infinity].includes(value)) { + if ([Infinity, -Infinity].includes(value) || !this.isValidFloat32(value)) { return; } @@ -383,13 +385,13 @@ export default class PlotSeries extends Model { }; changed = true; } else { - if (stats.maxValue < value && value !== Infinity) { + if (stats.maxValue < value && value !== Infinity && this.isValidFloat32(value)) { stats.maxValue = value; stats.maxPoint = point; changed = true; } - if (stats.minValue > value && value !== -Infinity) { + if (stats.minValue > value && value !== -Infinity && this.isValidFloat32(value)) { stats.minValue = value; stats.minPoint = point; changed = true; @@ -425,7 +427,7 @@ export default class PlotSeries extends Model { const lastYVal = this.getYVal(data[insertIndex - 1]); if (this.isValueInvalid(currentYVal) && this.isValueInvalid(lastYVal)) { - console.warn('[Plot] Invalid Y Values detected'); + console.warn(`[Plot] Invalid Y Values detected: ${currentYVal} ${lastYVal}`); return; } @@ -453,7 +455,15 @@ export default class PlotSeries extends Model { * @private */ isValueInvalid(val) { - return Number.isNaN(val) || this.unPlottableValues.includes(val); + return Number.isNaN(val) || this.unPlottableValues.includes(val) || !this.isValidFloat32(val); + } + + /** + * + * @private + */ + isValidFloat32(val) { + return val < FLOAT32_MAX && val > FLOAT32_MIN; } /**