blob: c129aae03fbbc629f1612418d6c16ff2a3bf458a [file] [log] [blame]
import { MISSING_DATA_SENTINEL } from '../const/const';
import { Anomaly } from '../json';
import { AnomalyData } from '../plot-simple-sk/plot-simple-sk';
import { ChartAxisFormat, ChartData, DataPoint } from './plot-builder';
// findMatchingAnomaly will search if the (trace, x and y coordinate) is an
// anomaly from the anomaly set.
function findMatchingAnomaly(
traceKey: string,
current_x: number | Date,
current_y: number,
anomalies: { [key: string]: AnomalyData[] }
): Anomaly | null {
const anomalyTraceKeys = Object.keys(anomalies);
if (!(traceKey in anomalyTraceKeys)) {
return null;
}
for (let x = 0; x < anomalies[traceKey].length; x++) {
const ad = anomalies[traceKey][x];
if (ad.x === current_x && ad.y === current_y) {
return ad.anomaly;
}
}
return null;
}
/**
* Create the chart data object from the traceSet.
* @param traceSet The traceset input.
* @param xLabels Labels for the xAxis. The length of the labels should be equal to the length
* of the values array for each trace.
* @returns ChartData for the provided input.
*/
export function CreateChartDataFromTraceSet(
traceSet: { [key: string]: number[] },
xLabels: (number | Date)[],
chartAxisFormat: ChartAxisFormat,
anomalies: { [key: string]: AnomalyData[] }
): ChartData {
const chartData: ChartData = {
lines: {},
xLabel: chartAxisFormat.toString(),
yLabel: 'Value',
chartAxisFormat: chartAxisFormat,
start: xLabels[0],
end: xLabels[xLabels.length - 1],
};
const traceKeys = Object.keys(traceSet);
traceKeys.forEach((key) => {
const trace = traceSet[key];
const traceDataPoints: DataPoint[] = [];
for (let i = 0; i < trace.length; i++) {
const x_coordinate = xLabels[i];
const y_coordinate = trace[i];
// Anomalies are formatted to a map of trace_id: AnomalyData[], where each AnomalyData
// defines it's own (x, y) coordinates, and details of the anomaly (wrapped in an Anomaly)
// interface. Adding this loop should not impact performance significantly because
// it becomes O(n * (m + x)) where n = # traces, m = # y axis coordinates and x = #
// of anomalies for the trace.
const anomaly_data = findMatchingAnomaly(
key,
x_coordinate,
y_coordinate,
anomalies
);
// The MISSING_DATA_SENTINEL const is used to define missing data points
// at the given x value in the trace. We should ignore these points when
// we create the chart data since the charts library will automatically handle
// this scenario.
if (trace[i] !== MISSING_DATA_SENTINEL) {
const dataPoint: DataPoint = {
x: x_coordinate,
y: y_coordinate,
anomaly: anomaly_data,
};
traceDataPoints.push(dataPoint);
}
}
chartData.lines[key] = traceDataPoints;
});
return chartData;
}