Skip to content

Commit d94fe88

Browse files
jvigliottaozyx
andauthored
[Plots] Gracefully handle Float32Array breaking values (#7138)
* 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 <[email protected]>
1 parent 7bf9832 commit d94fe88

File tree

4 files changed

+99
-17
lines changed

4 files changed

+99
-17
lines changed

example/generator/GeneratorProvider.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ define(['./WorkerInterface'], function (WorkerInterface) {
2929
randomness: 0,
3030
phase: 0,
3131
loadDelay: 0,
32-
infinityValues: false
32+
infinityValues: false,
33+
exceedFloat32: false
3334
};
3435

3536
function GeneratorProvider(openmct, StalenessProvider) {
@@ -53,7 +54,8 @@ define(['./WorkerInterface'], function (WorkerInterface) {
5354
'randomness',
5455
'phase',
5556
'loadDelay',
56-
'infinityValues'
57+
'infinityValues',
58+
'exceedFloat32'
5759
];
5860

5961
request = request || {};

example/generator/generatorWorker.js

+70-8
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@
8585
data.offset,
8686
data.phase,
8787
data.randomness,
88-
data.infinityValues
88+
data.infinityValues,
89+
data.exceedFloat32
8990
),
9091
wavelengths: wavelengths(),
9192
intensities: intensities(),
@@ -96,7 +97,8 @@
9697
data.offset,
9798
data.phase,
9899
data.randomness,
99-
data.infinityValues
100+
data.infinityValues,
101+
data.exceedFloat32
100102
)
101103
}
102104
});
@@ -136,6 +138,7 @@
136138
var randomness = request.randomness;
137139
var loadDelay = Math.max(request.loadDelay, 0);
138140
var infinityValues = request.infinityValues;
141+
var exceedFloat32 = request.exceedFloat32;
139142

140143
var step = 1000 / dataRateInHz;
141144
var nextStep = start - (start % step) + step;
@@ -146,10 +149,28 @@
146149
data.push({
147150
utc: nextStep,
148151
yesterday: nextStep - 60 * 60 * 24 * 1000,
149-
sin: sin(nextStep, period, amplitude, offset, phase, randomness, infinityValues),
152+
sin: sin(
153+
nextStep,
154+
period,
155+
amplitude,
156+
offset,
157+
phase,
158+
randomness,
159+
infinityValues,
160+
exceedFloat32
161+
),
150162
wavelengths: wavelengths(),
151163
intensities: intensities(),
152-
cos: cos(nextStep, period, amplitude, offset, phase, randomness, infinityValues)
164+
cos: cos(
165+
nextStep,
166+
period,
167+
amplitude,
168+
offset,
169+
phase,
170+
randomness,
171+
infinityValues,
172+
exceedFloat32
173+
)
153174
});
154175
}
155176

@@ -176,9 +197,26 @@
176197
});
177198
}
178199

179-
function cos(timestamp, period, amplitude, offset, phase, randomness, infinityValues) {
180-
if (infinityValues && Math.random() > 0.5) {
200+
function cos(
201+
timestamp,
202+
period,
203+
amplitude,
204+
offset,
205+
phase,
206+
randomness,
207+
infinityValues,
208+
exceedFloat32
209+
) {
210+
if (infinityValues && exceedFloat32) {
211+
if (Math.random() > 0.5) {
212+
return Number.POSITIVE_INFINITY;
213+
} else if (Math.random() < 0.01) {
214+
return getRandomFloat32OverflowValue();
215+
}
216+
} else if (infinityValues && Math.random() > 0.5) {
181217
return Number.POSITIVE_INFINITY;
218+
} else if (exceedFloat32 && Math.random() < 0.01) {
219+
return getRandomFloat32OverflowValue();
182220
}
183221

184222
return (
@@ -188,9 +226,26 @@
188226
);
189227
}
190228

191-
function sin(timestamp, period, amplitude, offset, phase, randomness, infinityValues) {
192-
if (infinityValues && Math.random() > 0.5) {
229+
function sin(
230+
timestamp,
231+
period,
232+
amplitude,
233+
offset,
234+
phase,
235+
randomness,
236+
infinityValues,
237+
exceedFloat32
238+
) {
239+
if (infinityValues && exceedFloat32) {
240+
if (Math.random() > 0.5) {
241+
return Number.POSITIVE_INFINITY;
242+
} else if (Math.random() < 0.01) {
243+
return getRandomFloat32OverflowValue();
244+
}
245+
} else if (infinityValues && Math.random() > 0.5) {
193246
return Number.POSITIVE_INFINITY;
247+
} else if (exceedFloat32 && Math.random() < 0.01) {
248+
return getRandomFloat32OverflowValue();
194249
}
195250

196251
return (
@@ -200,6 +255,13 @@
200255
);
201256
}
202257

258+
// Values exceeding float32 range (Positive: 3.4+38, Negative: -3.4+38)
259+
function getRandomFloat32OverflowValue() {
260+
const sign = Math.random() > 0.5 ? 1 : -1;
261+
262+
return sign * 3.4e39;
263+
}
264+
203265
function wavelengths() {
204266
let values = [];
205267
while (values.length < 5) {

example/generator/plugin.js

+8
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,13 @@ export default function (openmct) {
122122
key: 'infinityValues',
123123
property: ['telemetry', 'infinityValues']
124124
},
125+
{
126+
name: 'Exceed Float32 Limits',
127+
control: 'toggleSwitch',
128+
cssClass: 'l-input',
129+
key: 'exceedFloat32',
130+
property: ['telemetry', 'exceedFloat32']
131+
},
125132
{
126133
name: 'Provide Staleness Updates',
127134
control: 'toggleSwitch',
@@ -140,6 +147,7 @@ export default function (openmct) {
140147
randomness: 0,
141148
loadDelay: 0,
142149
infinityValues: false,
150+
exceedFloat32: false,
143151
staleness: false
144152
};
145153
}

src/plugins/plot/configuration/PlotSeries.js

+17-7
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@
1919
* this source code distribution or the Licensing information page available
2020
* at runtime from the About dialog for additional information.
2121
*****************************************************************************/
22-
import _ from 'lodash';
23-
2422
import configStore from '../configuration/ConfigStore';
2523
import { MARKER_SHAPES } from '../draw/MarkerShapes';
2624
import { symlog } from '../mathUtils';
@@ -64,6 +62,10 @@ import Model from './Model';
6462
*
6563
* @extends {Model<PlotSeriesModelType, PlotSeriesModelOptions>}
6664
*/
65+
66+
const FLOAT32_MAX = 3.4e38;
67+
const FLOAT32_MIN = -3.4e38;
68+
6769
export default class PlotSeries extends Model {
6870
logMode = false;
6971

@@ -371,7 +373,7 @@ export default class PlotSeries extends Model {
371373
let stats = this.get('stats');
372374
let changed = false;
373375
if (!stats) {
374-
if ([Infinity, -Infinity].includes(value)) {
376+
if ([Infinity, -Infinity].includes(value) || !this.isValidFloat32(value)) {
375377
return;
376378
}
377379

@@ -383,13 +385,13 @@ export default class PlotSeries extends Model {
383385
};
384386
changed = true;
385387
} else {
386-
if (stats.maxValue < value && value !== Infinity) {
388+
if (stats.maxValue < value && value !== Infinity && this.isValidFloat32(value)) {
387389
stats.maxValue = value;
388390
stats.maxPoint = point;
389391
changed = true;
390392
}
391393

392-
if (stats.minValue > value && value !== -Infinity) {
394+
if (stats.minValue > value && value !== -Infinity && this.isValidFloat32(value)) {
393395
stats.minValue = value;
394396
stats.minPoint = point;
395397
changed = true;
@@ -425,7 +427,7 @@ export default class PlotSeries extends Model {
425427
const lastYVal = this.getYVal(data[insertIndex - 1]);
426428

427429
if (this.isValueInvalid(currentYVal) && this.isValueInvalid(lastYVal)) {
428-
console.warn('[Plot] Invalid Y Values detected');
430+
console.warn(`[Plot] Invalid Y Values detected: ${currentYVal} ${lastYVal}`);
429431

430432
return;
431433
}
@@ -453,7 +455,15 @@ export default class PlotSeries extends Model {
453455
* @private
454456
*/
455457
isValueInvalid(val) {
456-
return Number.isNaN(val) || this.unPlottableValues.includes(val);
458+
return Number.isNaN(val) || this.unPlottableValues.includes(val) || !this.isValidFloat32(val);
459+
}
460+
461+
/**
462+
*
463+
* @private
464+
*/
465+
isValidFloat32(val) {
466+
return val < FLOAT32_MAX && val > FLOAT32_MIN;
457467
}
458468

459469
/**

0 commit comments

Comments
 (0)