Skip to content

Commit

Permalink
[Plots] Gracefully handle Float32Array breaking values (#7138)
Browse files Browse the repository at this point in the history
* WIP

* guaranteeing float32breaking values for swgs when option is set

* cleaning up and clarity

* more clarity

* removing randomization of float breaking number, as it is not necessary

* logging the values that could not be plotted for awareness

* remving auto-added imports

---------

Co-authored-by: Jesse Mazzella <ozyx@users.noreply.github.com>
  • Loading branch information
jvigliotta and ozyx committed Oct 24, 2023
1 parent 7bf9832 commit d94fe88
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 17 deletions.
6 changes: 4 additions & 2 deletions example/generator/GeneratorProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ define(['./WorkerInterface'], function (WorkerInterface) {
randomness: 0,
phase: 0,
loadDelay: 0,
infinityValues: false
infinityValues: false,
exceedFloat32: false
};

function GeneratorProvider(openmct, StalenessProvider) {
Expand All @@ -53,7 +54,8 @@ define(['./WorkerInterface'], function (WorkerInterface) {
'randomness',
'phase',
'loadDelay',
'infinityValues'
'infinityValues',
'exceedFloat32'
];

request = request || {};
Expand Down
78 changes: 70 additions & 8 deletions example/generator/generatorWorker.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@
data.offset,
data.phase,
data.randomness,
data.infinityValues
data.infinityValues,
data.exceedFloat32
),
wavelengths: wavelengths(),
intensities: intensities(),
Expand All @@ -96,7 +97,8 @@
data.offset,
data.phase,
data.randomness,
data.infinityValues
data.infinityValues,
data.exceedFloat32
)
}
});
Expand Down Expand Up @@ -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;
Expand All @@ -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
)
});
}

Expand All @@ -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 (
Expand All @@ -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 (
Expand All @@ -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) {
Expand Down
8 changes: 8 additions & 0 deletions example/generator/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -140,6 +147,7 @@ export default function (openmct) {
randomness: 0,
loadDelay: 0,
infinityValues: false,
exceedFloat32: false,
staleness: false
};
}
Expand Down
24 changes: 17 additions & 7 deletions src/plugins/plot/configuration/PlotSeries.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -64,6 +62,10 @@ import Model from './Model';
*
* @extends {Model<PlotSeriesModelType, PlotSeriesModelOptions>}
*/

const FLOAT32_MAX = 3.4e38;
const FLOAT32_MIN = -3.4e38;

export default class PlotSeries extends Model {
logMode = false;

Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}

/**
Expand Down

0 comments on commit d94fe88

Please sign in to comment.