Skip to content

Commit

Permalink
[ML] Extend population preview chart to show actual and typical value…
Browse files Browse the repository at this point in the history
…s as well in focusData
  • Loading branch information
qn895 committed May 27, 2020
1 parent 2c70571 commit 1f1974b
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
getTickValues,
numTicksForDateFormat,
removeLabelOverlap,
chartExtendedLimits,
} from '../../util/chart_utils';
import { LoadingIndicator } from '../../components/loading_indicator/loading_indicator';
import { getTimeBucketsFromCache } from '../../util/time_buckets';
Expand Down Expand Up @@ -137,22 +138,20 @@ export class ExplorerChartDistribution extends React.Component {
});

if (chartType === CHART_TYPE.POPULATION_DISTRIBUTION) {
const focusData = chartData
.filter((d) => {
return d.entity === highlight;
})
.map((d) => d.value);
const focusExtent = d3.extent(focusData);

const focusData = chartData.filter((d) => {
return d.entity === highlight;
});
// calculate the max y domain based on value, typical, and actual
const { min: yScaleDomainMin, max: yScaleDomainMax } = chartExtendedLimits(focusData);
// now again filter chartData to include only the data points within the domain
chartData = chartData.filter((d) => {
return d.value <= focusExtent[1];
return d.value <= yScaleDomainMax;
});

lineChartYScale = d3.scale
.linear()
.range([chartHeight, 0])
.domain([0, focusExtent[1]])
.domain([yScaleDomainMin < 0 ? yScaleDomainMin : 0, yScaleDomainMax])
.nice();
} else if (chartType === CHART_TYPE.EVENT_DISTRIBUTION) {
// avoid overflowing the border of the highlighted area
Expand Down
32 changes: 32 additions & 0 deletions x-pack/plugins/ml/public/application/util/chart_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,38 @@ export function chartLimits(data = []) {
return limits;
}

export function chartExtendedLimits(data = []) {
let _min = Infinity;
let _max = -Infinity;
data.forEach((d) => {
let metricValue = d.value;
const actualValue = Array.isArray(d.actual) ? d.actual[0] : d.actual;
const typicalValue = Array.isArray(d.typical) ? d.typical[0] : d.typical;

if (metricValue === null && d.anomalyScore !== undefined && d.actual !== undefined) {
// If an anomaly coincides with a gap in the data, use the anomaly actual value.
metricValue = actualValue;
}

if (d.anomalyScore !== undefined) {
_min = Math.min(_min, metricValue, actualValue, typicalValue);
_max = Math.max(_max, metricValue, actualValue, typicalValue);
} else {
_min = Math.min(_min, metricValue);
_max = Math.max(_max, metricValue);
}
});
const limits = { max: _max, min: _min };

// add padding of 5% of the difference between max and min
// if we ended up with the same value for both of them
if (limits.max === limits.min) {
const padding = limits.max * 0.05;
limits.max += padding;
limits.min -= padding;
}
return limits;
}
export function drawLineChartDots(data, lineChartGroup, lineChartValuesLine, radius = 1.5) {
// We need to do this because when creating a line for a chart which has data gaps,
// if there are single datapoints without any valid data before and after them,
Expand Down

0 comments on commit 1f1974b

Please sign in to comment.