mirror of
https://github.com/nasa/openmct.git
synced 2025-01-30 08:04:03 +00:00
[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 <ozyx@users.noreply.github.com>
This commit is contained in:
parent
7bf983210c
commit
d94fe8806b
@ -29,7 +29,8 @@ define(['./WorkerInterface'], function (WorkerInterface) {
|
|||||||
randomness: 0,
|
randomness: 0,
|
||||||
phase: 0,
|
phase: 0,
|
||||||
loadDelay: 0,
|
loadDelay: 0,
|
||||||
infinityValues: false
|
infinityValues: false,
|
||||||
|
exceedFloat32: false
|
||||||
};
|
};
|
||||||
|
|
||||||
function GeneratorProvider(openmct, StalenessProvider) {
|
function GeneratorProvider(openmct, StalenessProvider) {
|
||||||
@ -53,7 +54,8 @@ define(['./WorkerInterface'], function (WorkerInterface) {
|
|||||||
'randomness',
|
'randomness',
|
||||||
'phase',
|
'phase',
|
||||||
'loadDelay',
|
'loadDelay',
|
||||||
'infinityValues'
|
'infinityValues',
|
||||||
|
'exceedFloat32'
|
||||||
];
|
];
|
||||||
|
|
||||||
request = request || {};
|
request = request || {};
|
||||||
|
@ -85,7 +85,8 @@
|
|||||||
data.offset,
|
data.offset,
|
||||||
data.phase,
|
data.phase,
|
||||||
data.randomness,
|
data.randomness,
|
||||||
data.infinityValues
|
data.infinityValues,
|
||||||
|
data.exceedFloat32
|
||||||
),
|
),
|
||||||
wavelengths: wavelengths(),
|
wavelengths: wavelengths(),
|
||||||
intensities: intensities(),
|
intensities: intensities(),
|
||||||
@ -96,7 +97,8 @@
|
|||||||
data.offset,
|
data.offset,
|
||||||
data.phase,
|
data.phase,
|
||||||
data.randomness,
|
data.randomness,
|
||||||
data.infinityValues
|
data.infinityValues,
|
||||||
|
data.exceedFloat32
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -136,6 +138,7 @@
|
|||||||
var randomness = request.randomness;
|
var randomness = request.randomness;
|
||||||
var loadDelay = Math.max(request.loadDelay, 0);
|
var loadDelay = Math.max(request.loadDelay, 0);
|
||||||
var infinityValues = request.infinityValues;
|
var infinityValues = request.infinityValues;
|
||||||
|
var exceedFloat32 = request.exceedFloat32;
|
||||||
|
|
||||||
var step = 1000 / dataRateInHz;
|
var step = 1000 / dataRateInHz;
|
||||||
var nextStep = start - (start % step) + step;
|
var nextStep = start - (start % step) + step;
|
||||||
@ -146,10 +149,28 @@
|
|||||||
data.push({
|
data.push({
|
||||||
utc: nextStep,
|
utc: nextStep,
|
||||||
yesterday: nextStep - 60 * 60 * 24 * 1000,
|
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(),
|
wavelengths: wavelengths(),
|
||||||
intensities: intensities(),
|
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) {
|
function cos(
|
||||||
if (infinityValues && Math.random() > 0.5) {
|
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;
|
return Number.POSITIVE_INFINITY;
|
||||||
|
} else if (exceedFloat32 && Math.random() < 0.01) {
|
||||||
|
return getRandomFloat32OverflowValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -188,9 +226,26 @@
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function sin(timestamp, period, amplitude, offset, phase, randomness, infinityValues) {
|
function sin(
|
||||||
if (infinityValues && Math.random() > 0.5) {
|
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;
|
return Number.POSITIVE_INFINITY;
|
||||||
|
} else if (exceedFloat32 && Math.random() < 0.01) {
|
||||||
|
return getRandomFloat32OverflowValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
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() {
|
function wavelengths() {
|
||||||
let values = [];
|
let values = [];
|
||||||
while (values.length < 5) {
|
while (values.length < 5) {
|
||||||
|
@ -122,6 +122,13 @@ export default function (openmct) {
|
|||||||
key: 'infinityValues',
|
key: 'infinityValues',
|
||||||
property: ['telemetry', 'infinityValues']
|
property: ['telemetry', 'infinityValues']
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'Exceed Float32 Limits',
|
||||||
|
control: 'toggleSwitch',
|
||||||
|
cssClass: 'l-input',
|
||||||
|
key: 'exceedFloat32',
|
||||||
|
property: ['telemetry', 'exceedFloat32']
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'Provide Staleness Updates',
|
name: 'Provide Staleness Updates',
|
||||||
control: 'toggleSwitch',
|
control: 'toggleSwitch',
|
||||||
@ -140,6 +147,7 @@ export default function (openmct) {
|
|||||||
randomness: 0,
|
randomness: 0,
|
||||||
loadDelay: 0,
|
loadDelay: 0,
|
||||||
infinityValues: false,
|
infinityValues: false,
|
||||||
|
exceedFloat32: false,
|
||||||
staleness: false
|
staleness: false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,6 @@
|
|||||||
* this source code distribution or the Licensing information page available
|
* this source code distribution or the Licensing information page available
|
||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
import _ from 'lodash';
|
|
||||||
|
|
||||||
import configStore from '../configuration/ConfigStore';
|
import configStore from '../configuration/ConfigStore';
|
||||||
import { MARKER_SHAPES } from '../draw/MarkerShapes';
|
import { MARKER_SHAPES } from '../draw/MarkerShapes';
|
||||||
import { symlog } from '../mathUtils';
|
import { symlog } from '../mathUtils';
|
||||||
@ -64,6 +62,10 @@ import Model from './Model';
|
|||||||
*
|
*
|
||||||
* @extends {Model<PlotSeriesModelType, PlotSeriesModelOptions>}
|
* @extends {Model<PlotSeriesModelType, PlotSeriesModelOptions>}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
const FLOAT32_MAX = 3.4e38;
|
||||||
|
const FLOAT32_MIN = -3.4e38;
|
||||||
|
|
||||||
export default class PlotSeries extends Model {
|
export default class PlotSeries extends Model {
|
||||||
logMode = false;
|
logMode = false;
|
||||||
|
|
||||||
@ -371,7 +373,7 @@ export default class PlotSeries extends Model {
|
|||||||
let stats = this.get('stats');
|
let stats = this.get('stats');
|
||||||
let changed = false;
|
let changed = false;
|
||||||
if (!stats) {
|
if (!stats) {
|
||||||
if ([Infinity, -Infinity].includes(value)) {
|
if ([Infinity, -Infinity].includes(value) || !this.isValidFloat32(value)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -383,13 +385,13 @@ export default class PlotSeries extends Model {
|
|||||||
};
|
};
|
||||||
changed = true;
|
changed = true;
|
||||||
} else {
|
} else {
|
||||||
if (stats.maxValue < value && value !== Infinity) {
|
if (stats.maxValue < value && value !== Infinity && this.isValidFloat32(value)) {
|
||||||
stats.maxValue = value;
|
stats.maxValue = value;
|
||||||
stats.maxPoint = point;
|
stats.maxPoint = point;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stats.minValue > value && value !== -Infinity) {
|
if (stats.minValue > value && value !== -Infinity && this.isValidFloat32(value)) {
|
||||||
stats.minValue = value;
|
stats.minValue = value;
|
||||||
stats.minPoint = point;
|
stats.minPoint = point;
|
||||||
changed = true;
|
changed = true;
|
||||||
@ -425,7 +427,7 @@ export default class PlotSeries extends Model {
|
|||||||
const lastYVal = this.getYVal(data[insertIndex - 1]);
|
const lastYVal = this.getYVal(data[insertIndex - 1]);
|
||||||
|
|
||||||
if (this.isValueInvalid(currentYVal) && this.isValueInvalid(lastYVal)) {
|
if (this.isValueInvalid(currentYVal) && this.isValueInvalid(lastYVal)) {
|
||||||
console.warn('[Plot] Invalid Y Values detected');
|
console.warn(`[Plot] Invalid Y Values detected: ${currentYVal} ${lastYVal}`);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -453,7 +455,15 @@ export default class PlotSeries extends Model {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
isValueInvalid(val) {
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user