From 2a28f85b1285bed9cc009fec4f90475113bab664 Mon Sep 17 00:00:00 2001
From: Yaliang <49084640+ylwu-amzn@users.noreply.github.com>
Date: Sun, 10 May 2020 00:37:00 -0700
Subject: [PATCH] show scientific notation for number less than 0.01 on live
chart (#124)
* show scientific notation for number less than 0.01 on live chart
* fix typo
* change toFixedNumberForAnomaly to use 0.01 as threshold
---
.../containers/AnomalyResultsLiveChart.tsx | 5 +++--
.../containers/AnomalyResultsTable.tsx | 9 +--------
public/pages/utils/anomalyResultUtils.ts | 20 +++++++++----------
server/routes/ad.ts | 8 ++++----
server/utils/helpers.ts | 15 ++++++++++++++
5 files changed, 33 insertions(+), 24 deletions(-)
diff --git a/public/pages/DetectorResults/containers/AnomalyResultsLiveChart.tsx b/public/pages/DetectorResults/containers/AnomalyResultsLiveChart.tsx
index c300c473..e527d47a 100644
--- a/public/pages/DetectorResults/containers/AnomalyResultsLiveChart.tsx
+++ b/public/pages/DetectorResults/containers/AnomalyResultsLiveChart.tsx
@@ -57,6 +57,7 @@ import { DETECTOR_STATE } from '../../../utils/constants';
import { dateFormatter } from '../../utils/helpers';
import { darkModeEnabled } from '../../../utils/kibanaUtils';
import { EuiIcon } from '@elastic/eui';
+import { formatAnomalyNumber } from '../../../../server/utils/helpers';
interface AnomalyResultsLiveChartProps {
detector: Detector;
@@ -321,13 +322,13 @@ export const AnomalyResultsLiveChart = (
/>
diff --git a/public/pages/DetectorResults/containers/AnomalyResultsTable.tsx b/public/pages/DetectorResults/containers/AnomalyResultsTable.tsx
index e1c67fc4..82391c4b 100644
--- a/public/pages/DetectorResults/containers/AnomalyResultsTable.tsx
+++ b/public/pages/DetectorResults/containers/AnomalyResultsTable.tsx
@@ -30,7 +30,6 @@ import { ListControls } from '../components/ListControls/ListControls';
import { DetectorResultsQueryParams } from 'server/models/types';
import { AnomalyData } from '../../../models/interfaces';
import { getTitleWithCount } from '../../../utils/utils';
-import { toFixedNumber } from '../../../../server/utils/helpers';
interface AnomalyResultsTableProps {
anomalies: AnomalyData[];
@@ -69,13 +68,7 @@ export function AnomalyResultsTable(props: AnomalyResultsTableProps) {
useEffect(() => {
const anomalies = props.anomalies
- ? props.anomalies.filter(anomaly => anomaly.anomalyGrade > 0).map(anomaly => {
- return {
- ...anomaly,
- anomalyGrade: toFixedNumber(anomaly.anomalyGrade),
- confidence: toFixedNumber(anomaly.confidence),
- }
- })
+ ? props.anomalies.filter(anomaly => anomaly.anomalyGrade > 0)
: [];
anomalies.sort(
diff --git a/public/pages/utils/anomalyResultUtils.ts b/public/pages/utils/anomalyResultUtils.ts
index 36494d25..68700e1e 100644
--- a/public/pages/utils/anomalyResultUtils.ts
+++ b/public/pages/utils/anomalyResultUtils.ts
@@ -32,7 +32,7 @@ import {
} from '../../models/interfaces';
import { MAX_ANOMALIES } from '../../utils/constants';
import { minuteDateFormatter } from './helpers';
-import { toFixedNumber } from '../../../server/utils/helpers';
+import { toFixedNumberForAnomaly } from '../../../server/utils/helpers';
export const getLiveAnomalyResults = (
dispatch: Dispatch,
@@ -359,8 +359,8 @@ export const parseBucketizedAnomalyResults = (result: any): Anomalies => {
const rawAnomaly = get(item, 'top_anomaly_hits.hits.hits.0._source');
if (get(rawAnomaly, 'anomaly_grade') !== undefined) {
anomalies.push({
- anomalyGrade: toFixedNumber(get(rawAnomaly, 'anomaly_grade')),
- confidence: toFixedNumber(get(rawAnomaly, 'confidence')),
+ anomalyGrade: toFixedNumberForAnomaly(get(rawAnomaly, 'anomaly_grade')),
+ confidence: toFixedNumberForAnomaly(get(rawAnomaly, 'confidence')),
startTime: get(rawAnomaly, 'data_start_time'),
endTime: get(rawAnomaly, 'data_end_time'),
plotTime: get(rawAnomaly, 'data_end_time'),
@@ -372,7 +372,7 @@ export const parseBucketizedAnomalyResults = (result: any): Anomalies => {
featureData[get(feature, 'feature_id')] = [];
}
featureData[get(feature, 'feature_id')].push({
- data: toFixedNumber(get(feature, 'data')),
+ data: toFixedNumberForAnomaly(get(feature, 'data')),
startTime: get(rawAnomaly, 'data_start_time'),
endTime: get(rawAnomaly, 'data_end_time'),
plotTime: get(rawAnomaly, 'data_end_time'),
@@ -398,7 +398,7 @@ export const parseAnomalySummary = (
return {
anomalyOccurrence: anomalyCount,
minAnomalyGrade: anomalyCount
- ? toFixedNumber(
+ ? toFixedNumberForAnomaly(
get(
anomalySummaryResult,
'data.response.aggregations.min_anomaly_grade.value'
@@ -406,7 +406,7 @@ export const parseAnomalySummary = (
)
: 0,
maxAnomalyGrade: anomalyCount
- ? toFixedNumber(
+ ? toFixedNumberForAnomaly(
get(
anomalySummaryResult,
'data.response.aggregations.max_anomaly_grade.value'
@@ -414,7 +414,7 @@ export const parseAnomalySummary = (
)
: 0,
minConfidence: anomalyCount
- ? toFixedNumber(
+ ? toFixedNumberForAnomaly(
get(
anomalySummaryResult,
'data.response.aggregations.min_confidence.value'
@@ -422,7 +422,7 @@ export const parseAnomalySummary = (
)
: 0,
maxConfidence: anomalyCount
- ? toFixedNumber(
+ ? toFixedNumberForAnomaly(
get(
anomalySummaryResult,
'data.response.aggregations.max_confidence.value'
@@ -453,8 +453,8 @@ export const parsePureAnomalies = (
anomaliesHits.forEach((item: any) => {
const rawAnomaly = get(item, '_source');
anomalies.push({
- anomalyGrade: get(rawAnomaly, 'anomaly_grade'),
- confidence: get(rawAnomaly, 'confidence'),
+ anomalyGrade: toFixedNumberForAnomaly(get(rawAnomaly, 'anomaly_grade')),
+ confidence: toFixedNumberForAnomaly(get(rawAnomaly, 'confidence')),
startTime: get(rawAnomaly, 'data_start_time'),
endTime: get(rawAnomaly, 'data_end_time'),
plotTime: get(rawAnomaly, 'data_end_time'),
diff --git a/server/routes/ad.ts b/server/routes/ad.ts
index 61c68c3c..ae464966 100644
--- a/server/routes/ad.ts
+++ b/server/routes/ad.ts
@@ -32,7 +32,7 @@ import {
} from '../models/types';
import { Router } from '../router';
import { SORT_DIRECTION, AD_DOC_FIELDS } from '../utils/constants';
-import { mapKeysDeep, toCamel, toSnake, toFixedNumber } from '../utils/helpers';
+import { mapKeysDeep, toCamel, toSnake, toFixedNumberForAnomaly } from '../utils/helpers';
import {
anomalyResultMapper,
convertDetectorKeysToCamelCase,
@@ -593,13 +593,13 @@ const getAnomalyResults = async (
result._source.confidence != null &&
result._source.confidence !== 'NaN' &&
result._source.confidence > 0
- ? toFixedNumber(Number.parseFloat(result._source.confidence))
+ ? toFixedNumberForAnomaly(Number.parseFloat(result._source.confidence))
: 0,
anomalyGrade:
result._source.anomaly_grade != null &&
result._source.anomaly_grade !== 'NaN' &&
result._source.anomaly_grade > 0
- ? toFixedNumber(Number.parseFloat(result._source.anomaly_grade))
+ ? toFixedNumberForAnomaly(Number.parseFloat(result._source.anomaly_grade))
: 0,
});
result._source.feature_data.forEach((featureData: any) => {
@@ -612,7 +612,7 @@ const getAnomalyResults = async (
plotTime: result._source.data_end_time,
data:
featureData.data != null && featureData.data !== 'NaN'
- ? toFixedNumber(Number.parseFloat(featureData.data))
+ ? toFixedNumberForAnomaly(Number.parseFloat(featureData.data))
: 0,
});
});
diff --git a/server/utils/helpers.ts b/server/utils/helpers.ts
index a0f2e9f8..e04ccebb 100644
--- a/server/utils/helpers.ts
+++ b/server/utils/helpers.ts
@@ -23,6 +23,7 @@ import {
} from 'lodash';
import { MIN_IN_MILLI_SECS } from './constants';
+import { SHOW_DECIMAL_NUMBER_THRESHOLD } from '../../public/pages/Dashboard/utils/constants';
export function mapKeysDeep(obj: object, fn: any): object | any[] {
if (Array.isArray(obj)) {
@@ -47,3 +48,17 @@ export const toFixedNumber = (num: number, digits?: number, base?: number) => {
var pow = Math.pow(base || 10, digits || 2);
return Math.round(num * pow) / pow;
};
+
+// 1.If num>0.01, will keep two digits;
+// 2.If num<0.01, will use scientific notation, for example 0.001234 will become 1.23e-3
+export const toFixedNumberForAnomaly = (num: number): number => {
+ return num >= SHOW_DECIMAL_NUMBER_THRESHOLD
+ ? toFixedNumber(num, 2)
+ : Number(num.toExponential(2));
+};
+
+export const formatAnomalyNumber = (num: number): string => {
+ return num >= SHOW_DECIMAL_NUMBER_THRESHOLD
+ ? num.toFixed(2)
+ : num.toExponential(2);
+};