From 2f829cd1879499934059b9e24d014c0c53193324 Mon Sep 17 00:00:00 2001 From: Peter Pan Date: Tue, 23 Jun 2020 15:48:02 +0800 Subject: [PATCH] fix #672 (#673) * chore: code polishment * fix: calculate step width in tooltip (#672) --- .../components/ScalarsPage/ScalarChart.tsx | 24 +++-- .../packages/core/resource/scalars/chart.ts | 10 +- .../packages/core/resource/scalars/data.ts | 8 +- .../packages/core/resource/scalars/types.ts | 9 +- frontend/packages/core/utils/chart.ts | 3 +- frontend/packages/wasm/Cargo.lock | 97 +++++++++---------- frontend/packages/wasm/Cargo.toml | 14 +-- .../packages/wasm/src/high_dimensional.rs | 22 +++-- frontend/packages/wasm/src/histogram.rs | 8 +- frontend/packages/wasm/src/main.rs | 34 ++++--- frontend/packages/wasm/src/scalar.rs | 10 +- 11 files changed, 127 insertions(+), 112 deletions(-) diff --git a/frontend/packages/core/components/ScalarsPage/ScalarChart.tsx b/frontend/packages/core/components/ScalarsPage/ScalarChart.tsx index e49f83a5..d6c6de82 100644 --- a/frontend/packages/core/components/ScalarsPage/ScalarChart.tsx +++ b/frontend/packages/core/components/ScalarsPage/ScalarChart.tsx @@ -1,6 +1,7 @@ +import LineChart, {LineChartRef} from '~/components/LineChart'; import { - Dataset, Range, + ScalarDataset, SortingMethod, XAxis, chartData, @@ -13,7 +14,6 @@ import { transform, xAxisMap } from '~/resource/scalars'; -import LineChart, {LineChartRef} from '~/components/LineChart'; import React, {FunctionComponent, useCallback, useMemo, useRef, useState} from 'react'; import {rem, size} from '~/utils/style'; @@ -22,6 +22,7 @@ import {EChartOption} from 'echarts'; import {Run} from '~/types'; import {cycleFetcher} from '~/utils/fetch'; import ee from '~/utils/event'; +import {format} from 'd3-format'; import queryString from 'query-string'; import styled from 'styled-components'; import useHeavyWork from '~/hooks/useHeavyWork'; @@ -110,7 +111,7 @@ const ScalarChart: FunctionComponent = ({ const echart = useRef(null); - const {data: datasets, error, loading} = useRunningRequest<(Dataset | null)[]>( + const {data: datasets, error, loading} = useRunningRequest<(ScalarDataset | null)[]>( runs.map(run => `/scalars/list?${queryString.stringify({run: run.label, tag})}`), !!running, (...urls) => cycleFetcher(urls) @@ -171,15 +172,20 @@ const ScalarChart: FunctionComponent = ({ [smoothedDatasets, runs, xAxis] ); + const maxStepLength = useMemo( + () => String(Math.max(...smoothedDatasets.map(i => Math.max(...i.map(j => j[1]))))).length, + [smoothedDatasets] + ); + const formatter = useCallback( (params: EChartOption.Tooltip.Format | EChartOption.Tooltip.Format[]) => { const data = Array.isArray(params) ? params[0].data : params.data; const step = data[1]; const points = nearestPoint(smoothedDatasets ?? [], runs, step); const sort = sortingMethodMap[sortingMethod]; - return tooltip(sort ? sort(points, data) : points, i18n); + return tooltip(sort ? sort(points, data) : points, maxStepLength, i18n); }, - [smoothedDatasets, runs, sortingMethod, i18n] + [smoothedDatasets, runs, sortingMethod, maxStepLength, i18n] ); const options = useMemo( @@ -191,7 +197,13 @@ const ScalarChart: FunctionComponent = ({ }, xAxis: { type: xAxisType, - ...ranges.x + ...ranges.x, + axisPointer: { + label: { + formatter: + xAxisType === XAxisType.time ? undefined : ({value}: {value: number}) => format('.8')(value) + } + } }, yAxis: { type: yAxisType, diff --git a/frontend/packages/core/resource/scalars/chart.ts b/frontend/packages/core/resource/scalars/chart.ts index 4998472c..a102fe2b 100644 --- a/frontend/packages/core/resource/scalars/chart.ts +++ b/frontend/packages/core/resource/scalars/chart.ts @@ -65,7 +65,7 @@ export const chartData = ({data, runs, xAxis}: {data: Dataset[]; runs: Run[]; xA .flat(); // TODO: make it better, don't concat html -export const tooltip = (data: TooltipData[], i18n: I18n) => { +export const tooltip = (data: TooltipData[], stepLength: number, i18n: I18n) => { const indexPropMap = { time: 0, step: 1, @@ -73,10 +73,10 @@ export const tooltip = (data: TooltipData[], i18n: I18n) => { smoothed: 3, relative: 4 } as const; - const widthPropMap = { - run: [60, 180] as [number, number], + const widthPropMap: Record = { + run: [60, 180], time: 150, - step: 40, + step: Math.max(stepLength * 8, 40), value: 60, smoothed: 70, relative: 60 @@ -103,7 +103,7 @@ export const tooltip = (data: TooltipData[], i18n: I18n) => { } as const; }); - const renderContent = (content: string, width: number | [number, number]) => + const renderContent = (content: string, width: number | readonly [number, number]) => `
, showing: bool) -> Self { + pub fn new(name: &str, value: Vec, showing: bool) -> Self { Point { - name, + name: String::from(name), value, showing, } @@ -23,25 +23,27 @@ impl DividedPoints { } pub fn divide( - points: Vec>, - labels: Vec, + points: &Vec>, + labels: &Vec, visibility: bool, - keyword: String, + keyword: &str, ) -> DividedPoints { let mut matched: Vec = vec![]; let mut missing: Vec = vec![]; for (i, point) in points.iter().enumerate() { - let mut name: String = String::from(""); + let mut name: &str = ""; let ptr: *const String = &labels[i]; if !ptr.is_null() { - name = labels[i].clone(); + unsafe { + name = &(*ptr)[..]; + } } - let point_with_label: Point = Point::new(name.clone(), point.to_vec(), visibility); - if keyword == String::from("") { + let point_with_label: Point = Point::new(name, point.to_vec(), visibility); + if let "" = keyword { missing.push(point_with_label); } else { - if name.contains(&keyword) { + if String::from(name).contains(&keyword) { matched.push(point_with_label); } else { missing.push(point_with_label); diff --git a/frontend/packages/wasm/src/histogram.rs b/frontend/packages/wasm/src/histogram.rs index 499c03b1..48e66a7c 100644 --- a/frontend/packages/wasm/src/histogram.rs +++ b/frontend/packages/wasm/src/histogram.rs @@ -1,5 +1,3 @@ -use std::f64; - trait FloatIterExt { fn float_min(&mut self) -> f64; fn float_max(&mut self) -> f64; @@ -108,7 +106,7 @@ fn compute_histogram( return result; } -pub fn transform_overlay(data: Vec) -> Overlay { +pub fn transform_overlay(data: &Vec) -> Overlay { struct Temp { time: f64, step: f64, @@ -154,8 +152,8 @@ pub fn transform_overlay(data: Vec) -> Overlay { }; } -pub fn transform_offset(data: Vec) -> Offset { - let overlay: Overlay = transform_overlay(data); +pub fn transform_offset(data: &Vec) -> Offset { + let overlay: Overlay = transform_overlay(&data); let mut min_step: f64 = std::f64::INFINITY; let mut max_step: f64 = std::f64::NEG_INFINITY; let mut min_z: f64 = std::f64::INFINITY; diff --git a/frontend/packages/wasm/src/main.rs b/frontend/packages/wasm/src/main.rs index dccd5f55..ce84b245 100644 --- a/frontend/packages/wasm/src/main.rs +++ b/frontend/packages/wasm/src/main.rs @@ -14,31 +14,33 @@ pub fn main() {} pub fn scalar_transform(js_datasets: &JsValue, smoothing: f64) -> JsValue { utils::set_panic_hook(); let datasets: Vec> = js_datasets.into_serde().unwrap(); - let result: Vec> = scalar::transform(datasets, smoothing); - return JsValue::from_serde(&result).unwrap(); + let result: Vec> = scalar::transform(&datasets, smoothing); + JsValue::from_serde(&result).unwrap() } #[wasm_bindgen] pub fn scalar_range(js_datasets: &JsValue, outlier: bool) -> JsValue { utils::set_panic_hook(); let datasets: Vec> = js_datasets.into_serde().unwrap(); - let result = scalar::range(datasets, outlier); - return JsValue::from_serde(&result).unwrap(); + let result = scalar::range(&datasets, outlier); + JsValue::from_serde(&result).unwrap() } #[wasm_bindgen] -pub fn histogram_transform(js_data: &JsValue, mode: String) -> JsValue { +pub fn histogram_transform(js_data: &JsValue, mode: &str) -> JsValue { utils::set_panic_hook(); let data: Vec = js_data.into_serde().unwrap(); - if mode == String::from("overlay") { - let result = histogram::transform_overlay(data); - return JsValue::from_serde(&result).unwrap(); + match mode { + "overlay" => { + let result = histogram::transform_overlay(&data); + JsValue::from_serde(&result).unwrap() + } + "offset" => { + let result = histogram::transform_offset(&data); + JsValue::from_serde(&result).unwrap() + } + _ => JsValue::null(), } - if mode == String::from("offset") { - let result = histogram::transform_offset(data); - return JsValue::from_serde(&result).unwrap(); - } - return JsValue::null(); } #[wasm_bindgen] @@ -46,12 +48,12 @@ pub fn high_dimensional_divide( js_points: &JsValue, js_labels: &JsValue, visibility: bool, - keyword: String, + keyword: &str, ) -> JsValue { utils::set_panic_hook(); let points: Vec> = js_points.into_serde().unwrap(); let labels: Vec = js_labels.into_serde().unwrap(); let result: high_dimensional::DividedPoints = - high_dimensional::divide(points, labels, visibility, keyword); - return JsValue::from_serde(&result).unwrap(); + high_dimensional::divide(&points, &labels, visibility, keyword); + JsValue::from_serde(&result).unwrap() } diff --git a/frontend/packages/wasm/src/scalar.rs b/frontend/packages/wasm/src/scalar.rs index ddadebf0..61f91de8 100644 --- a/frontend/packages/wasm/src/scalar.rs +++ b/frontend/packages/wasm/src/scalar.rs @@ -15,7 +15,7 @@ impl Range { } } -fn quantile(values: Vec, p: f64) -> f64 { +fn quantile(values: &Vec, p: f64) -> f64 { let n: usize = values.len(); if n == 0 { return std::f64::NAN; @@ -33,7 +33,7 @@ fn quantile(values: Vec, p: f64) -> f64 { return value0 + (value1 - value0) * (i - (i0 as f64)); } -pub fn transform(datasets: Vec>, smoothing: f64) -> Vec> { +pub fn transform(datasets: &Vec>, smoothing: f64) -> Vec> { let mut result: Vec> = vec![]; for dataset in datasets.iter() { let mut row: Vec = vec![]; @@ -72,7 +72,7 @@ pub fn transform(datasets: Vec>, smoothing: f64) -> Vec>, outlier: bool) -> Range { +pub fn range(datasets: &Vec>, outlier: bool) -> Range { let mut ranges: Vec = vec![]; for data in datasets.iter() { @@ -90,8 +90,8 @@ pub fn range(datasets: Vec>, outlier: bool) -> Range { ranges.push(Range::new(sorted[0], sorted[n - 1])); } else { ranges.push(Range::new( - quantile(sorted, 0.05_f64), - quantile(values, 0.95), + quantile(&sorted, 0.05_f64), + quantile(&values, 0.95), )); } } -- GitLab