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); +};