未验证 提交 5661a556 编写于 作者: P Peter Pan 提交者: GitHub

bugs fix (#998)

* fix: minor bugs fix

* bump visualdl to 2.2.1
上级 4263641e
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
"packages": [ "packages": [
"packages/*" "packages/*"
], ],
"version": "2.2.0-1", "version": "2.2.1",
"npmClient": "yarn", "npmClient": "yarn",
"useWorkspaces": true, "useWorkspaces": true,
"command": { "command": {
......
...@@ -46,20 +46,20 @@ ...@@ -46,20 +46,20 @@
"version": "yarn format && git add -A" "version": "yarn format && git add -A"
}, },
"devDependencies": { "devDependencies": {
"@typescript-eslint/eslint-plugin": "4.26.1", "@typescript-eslint/eslint-plugin": "4.29.2",
"@typescript-eslint/parser": "4.26.1", "@typescript-eslint/parser": "4.29.2",
"eslint": "7.28.0", "eslint": "7.32.0",
"eslint-config-prettier": "8.3.0", "eslint-config-prettier": "8.3.0",
"eslint-plugin-license-header": "0.2.0", "eslint-plugin-license-header": "0.2.0",
"eslint-plugin-prettier": "3.4.0", "eslint-plugin-prettier": "3.4.1",
"eslint-plugin-react": "7.24.0", "eslint-plugin-react": "7.24.0",
"eslint-plugin-react-hooks": "4.2.0", "eslint-plugin-react-hooks": "4.2.0",
"lerna": "4.0.0", "lerna": "4.0.0",
"lint-staged": "11.0.0", "lint-staged": "11.1.2",
"prettier": "2.3.1", "prettier": "2.3.2",
"rimraf": "3.0.2", "rimraf": "3.0.2",
"typescript": "4.3.2", "typescript": "4.3.5",
"yarn": "1.22.10" "yarn": "1.22.11"
}, },
"engines": { "engines": {
"node": ">=10", "node": ">=10",
......
...@@ -53,5 +53,5 @@ export const SNOWPACK_PUBLIC_LANGUAGES = process.env.LANGUAGES || 'en,zh'; ...@@ -53,5 +53,5 @@ export const SNOWPACK_PUBLIC_LANGUAGES = process.env.LANGUAGES || 'en,zh';
export const SNOWPACK_PUBLIC_DEFAULT_LANGUAGE = process.env.DEFAULT_LANGUAGE || 'en'; export const SNOWPACK_PUBLIC_DEFAULT_LANGUAGE = process.env.DEFAULT_LANGUAGE || 'en';
// theme // theme
export const SNOWPACK_PUBLIC_THEME = process.env.THEME || ''; export const SNOWPACK_PUBLIC_THEME = process.env.THEME || '';
// demo // use mock data
export const SERVER = ''; export const MOCK = process.env.SERVER || process.env.API_URL ? '' : '1';
{ {
"name": "@visualdl/core", "name": "@visualdl/core",
"version": "2.2.0-1", "version": "2.2.1",
"description": "A platform to visualize the deep learning process and result.", "description": "A platform to visualize the deep learning process and result.",
"keywords": [ "keywords": [
"visualdl", "visualdl",
...@@ -39,35 +39,35 @@ ...@@ -39,35 +39,35 @@
], ],
"dependencies": { "dependencies": {
"@tippyjs/react": "4.2.5", "@tippyjs/react": "4.2.5",
"@visualdl/icons": "2.2.0-1", "@visualdl/icons": "2.2.1",
"@visualdl/netron": "2.2.0-1", "@visualdl/netron": "2.2.1",
"@visualdl/wasm": "2.2.0-1", "@visualdl/wasm": "2.2.1",
"bignumber.js": "9.0.1", "bignumber.js": "9.0.1",
"classnames": "2.3.1", "classnames": "2.3.1",
"d3": "6.7.0", "d3": "7.0.1",
"d3-format": "3.0.1", "d3-format": "3.0.1",
"echarts": "4.9.0", "echarts": "4.9.0",
"echarts-gl": "1.1.2", "echarts-gl": "1.1.2",
"eventemitter3": "4.0.7", "eventemitter3": "4.0.7",
"file-saver": "2.0.5", "file-saver": "2.0.5",
"i18next": "20.3.1", "i18next": "20.4.0",
"i18next-browser-languagedetector": "6.1.1", "i18next-browser-languagedetector": "6.1.2",
"i18next-fetch-backend": "3.0.0", "i18next-fetch-backend": "3.0.0",
"jszip": "3.6.0", "jszip": "3.7.1",
"lodash": "4.17.21", "lodash": "4.17.21",
"mime-types": "2.1.31", "mime-types": "2.1.32",
"moment": "2.29.1", "moment": "2.29.1",
"nprogress": "0.2.0", "nprogress": "0.2.0",
"numeric": "1.2.6", "numeric": "1.2.6",
"polished": "4.1.3", "polished": "4.1.3",
"query-string": "7.0.0", "query-string": "7.0.1",
"react": "17.0.2", "react": "17.0.2",
"react-content-loader": "6.0.3", "react-content-loader": "6.0.3",
"react-dnd": "14.0.2", "react-dnd": "14.0.3",
"react-dnd-html5-backend": "14.0.0", "react-dnd-html5-backend": "14.0.1",
"react-dom": "17.0.2", "react-dom": "17.0.2",
"react-helmet": "6.1.0", "react-helmet": "6.1.0",
"react-i18next": "11.10.0", "react-i18next": "11.11.4",
"react-input-range": "1.3.0", "react-input-range": "1.3.0",
"react-rangeslider": "2.2.0", "react-rangeslider": "2.2.0",
"react-redux": "7.2.4", "react-redux": "7.2.4",
...@@ -76,51 +76,51 @@ ...@@ -76,51 +76,51 @@
"react-table": "7.7.0", "react-table": "7.7.0",
"react-table-sticky": "1.1.3", "react-table-sticky": "1.1.3",
"react-toastify": "7.0.4", "react-toastify": "7.0.4",
"redux": "4.1.0", "redux": "4.1.1",
"styled-components": "5.3.0", "styled-components": "5.3.0",
"swr": "0.5.6", "swr": "0.5.6",
"three": "0.129.0", "three": "0.131.3",
"tippy.js": "6.3.1", "tippy.js": "6.3.1",
"umap-js": "1.3.3" "umap-js": "1.3.3"
}, },
"devDependencies": { "devDependencies": {
"@baiducloud/sdk": "1.0.0-rc.28", "@baiducloud/sdk": "1.0.0-rc.31",
"@simbathesailor/use-what-changed": "2.0.0", "@simbathesailor/use-what-changed": "2.0.0",
"@snowpack/plugin-dotenv": "2.1.0", "@snowpack/plugin-dotenv": "2.1.0",
"@snowpack/plugin-optimize": "0.2.13", "@snowpack/plugin-optimize": "0.2.13",
"@snowpack/plugin-react-refresh": "2.5.0", "@snowpack/plugin-react-refresh": "2.5.0",
"@snowpack/plugin-typescript": "1.2.1", "@snowpack/plugin-typescript": "1.2.1",
"@snowpack/web-test-runner-plugin": "0.2.2", "@snowpack/web-test-runner-plugin": "0.2.2",
"@testing-library/react": "11.2.7", "@testing-library/react": "12.0.0",
"@types/chai": "4.2.18", "@types/chai": "4.2.21",
"@types/d3": "6.7.0", "@types/d3": "7.0.0",
"@types/d3-format": "2.0.0", "@types/d3-format": "3.0.1",
"@types/echarts": "4.9.8", "@types/echarts": "4.9.10",
"@types/file-saver": "2.0.2", "@types/file-saver": "2.0.3",
"@types/lodash": "4.14.170", "@types/lodash": "4.14.172",
"@types/mime-types": "2.1.0", "@types/mime-types": "2.1.1",
"@types/nprogress": "0.2.0", "@types/nprogress": "0.2.0",
"@types/numeric": "1.2.1", "@types/numeric": "1.2.2",
"@types/react": "17.0.10", "@types/react": "17.0.19",
"@types/react-dom": "17.0.7", "@types/react-dom": "17.0.9",
"@types/react-helmet": "6.1.1", "@types/react-helmet": "6.1.2",
"@types/react-rangeslider": "2.2.3", "@types/react-rangeslider": "2.2.4",
"@types/react-redux": "7.1.16", "@types/react-redux": "7.1.18",
"@types/react-router-dom": "5.1.7", "@types/react-router-dom": "5.1.8",
"@types/react-table": "7.7.1", "@types/react-table": "7.7.2",
"@types/snowpack-env": "2.3.3", "@types/snowpack-env": "2.3.4",
"@types/styled-components": "5.1.10", "@types/styled-components": "5.1.12",
"@types/three": "0.129.1", "@types/three": "0.131.0",
"@visualdl/mock": "2.2.0-1", "@visualdl/mock": "2.2.1",
"@web/test-runner": "0.13.6", "@web/test-runner": "0.13.16",
"chai": "4.3.4", "chai": "4.3.4",
"chalk": "4.1.1", "chalk": "4.1.2",
"dotenv": "10.0.0", "dotenv": "10.0.0",
"enhanced-resolve": "5.8.2", "enhanced-resolve": "5.8.2",
"html-minifier": "4.0.0", "html-minifier": "4.0.0",
"snowpack": "3.5.6", "snowpack": "3.8.6",
"snowpack-plugin-copy": "1.0.1", "snowpack-plugin-copy": "1.0.1",
"typescript": "4.3.2" "typescript": "4.3.5"
}, },
"engines": { "engines": {
"node": ">=14", "node": ">=14",
......
...@@ -111,7 +111,7 @@ export default { ...@@ -111,7 +111,7 @@ export default {
}, },
packageOptions: { packageOptions: {
polyfillNode: true, polyfillNode: true,
knownEntrypoints: ['chai', '@testing-library/react'] knownEntrypoints: ['chai', '@testing-library/react', 'fetch-mock/esm/client']
}, },
buildOptions: { buildOptions: {
out: 'dist', out: 'dist',
......
...@@ -79,7 +79,7 @@ interface ScalarChartProps { ...@@ -79,7 +79,7 @@ interface ScalarChartProps {
xAxisType?: XAxisType; xAxisType?: XAxisType;
xRange?: Range; xRange?: Range;
yRange?: Range; yRange?: Range;
getTooltipTableData: (series: number[]) => TooltipTableData; getTooltipTableData: (series: number[], value: number) => TooltipTableData;
downloadData?: (type: keyof typeof DownloadDataTypes) => void; downloadData?: (type: keyof typeof DownloadDataTypes) => void;
} }
...@@ -107,7 +107,10 @@ const ScalarChart: FunctionComponent<ScalarChartProps> = ({ ...@@ -107,7 +107,10 @@ const ScalarChart: FunctionComponent<ScalarChartProps> = ({
const formatter = useCallback( const formatter = useCallback(
(params: EChartOption.Tooltip.Format | EChartOption.Tooltip.Format[]) => { (params: EChartOption.Tooltip.Format | EChartOption.Tooltip.Format[]) => {
const series: number[] = Array.isArray(params) ? params[0].data : params.data; const series: number[] = Array.isArray(params) ? params[0].data : params.data;
return renderToStaticMarkup(<TooltipTable run={t('common:runs')} {...getTooltipTableData(series)} />); const value: number = (Array.isArray(params) ? params[0].axisValue : params.axisValue) as number;
return renderToStaticMarkup(
<TooltipTable run={t('common:runs')} {...getTooltipTableData(series, value)} />
);
}, },
[getTooltipTableData, t] [getTooltipTableData, t]
); );
......
...@@ -74,7 +74,7 @@ const ScalarChart: FunctionComponent<ScalarChartProps> = ({ ...@@ -74,7 +74,7 @@ const ScalarChart: FunctionComponent<ScalarChartProps> = ({
const {t, i18n} = useTranslation(['scalar', 'common']); const {t, i18n} = useTranslation(['scalar', 'common']);
const { const {
data: datasets, data: datasetsWithNull,
error, error,
loading loading
} = useRunningRequest<(ScalarDataset | null)[]>( } = useRunningRequest<(ScalarDataset | null)[]>(
...@@ -83,11 +83,16 @@ const ScalarChart: FunctionComponent<ScalarChartProps> = ({ ...@@ -83,11 +83,16 @@ const ScalarChart: FunctionComponent<ScalarChartProps> = ({
(...urls) => cycleFetcher(urls) (...urls) => cycleFetcher(urls)
); );
const datasets = useMemo(
() => (datasetsWithNull?.filter(r => r != null).slice(0, runs.length) ?? []) as ScalarDataset[],
[datasetsWithNull, runs.length]
);
const xAxisType = useMemo(() => (xAxis === XAxis.WallTime ? XAxisType.time : XAxisType.value), [xAxis]); const xAxisType = useMemo(() => (xAxis === XAxis.WallTime ? XAxisType.time : XAxisType.value), [xAxis]);
const transformParams = useMemo( const transformParams = useMemo(
() => [ () => [
datasets?.map(data => data?.map(row => [row[0], row[1], Number.isFinite(row[2]) ? row[2] : null]) ?? []) ?? datasets.map(data => data.map(row => [row[0], row[1], Number.isFinite(row[2]) ? row[2] : null]) ?? []) ??
[], [],
smoothing smoothing
], ],
...@@ -122,13 +127,14 @@ const ScalarChart: FunctionComponent<ScalarChartProps> = ({ ...@@ -122,13 +127,14 @@ const ScalarChart: FunctionComponent<ScalarChartProps> = ({
const data = useMemo( const data = useMemo(
() => () =>
chartData({ chartData({
data: smoothedDatasets.slice(0, runs.length), data: smoothedDatasets,
rawData: datasets,
ranges: showMostValue ? datasetRanges ?? [] : [], ranges: showMostValue ? datasetRanges ?? [] : [],
runs, runs,
xAxis, xAxis,
smoothedOnly smoothedOnly
}), }),
[smoothedDatasets, datasetRanges, runs, xAxis, smoothedOnly, showMostValue] [smoothedDatasets, datasets, showMostValue, datasetRanges, runs, xAxis, smoothedOnly]
); );
const maxStepLength = useMemo( const maxStepLength = useMemo(
...@@ -136,14 +142,14 @@ const ScalarChart: FunctionComponent<ScalarChartProps> = ({ ...@@ -136,14 +142,14 @@ const ScalarChart: FunctionComponent<ScalarChartProps> = ({
[smoothedDatasets] [smoothedDatasets]
); );
const getTooltipTableData = useCallback( const getTooltipTableData = useCallback(
(series: number[]) => { (_, value: number) => {
const idx = xAxisMap[xAxis]; const idx = xAxisMap[xAxis];
const points = nearestPoint(smoothedDatasets ?? [], runs, idx, series[idx]).map(point => ({ const points = nearestPoint(smoothedDatasets, datasets, runs, idx, value).map(point => ({
...point, ...point,
...datasetRanges?.[runs.findIndex(run => run.label === point.run.label)] ...datasetRanges?.[runs.findIndex(run => run.label === point.run.label)]
})); }));
const sort = sortingMethodMap[sortingMethod]; const sort = sortingMethodMap[sortingMethod];
const sorted = sort(points, series); const sorted = sort(points, value);
const {columns, data} = tooltip(sorted, maxStepLength, i18n); const {columns, data} = tooltip(sorted, maxStepLength, i18n);
return { return {
runs: sorted.map(i => i.run), runs: sorted.map(i => i.run),
...@@ -151,7 +157,7 @@ const ScalarChart: FunctionComponent<ScalarChartProps> = ({ ...@@ -151,7 +157,7 @@ const ScalarChart: FunctionComponent<ScalarChartProps> = ({
data data
}; };
}, },
[smoothedDatasets, datasetRanges, runs, sortingMethod, xAxis, maxStepLength, i18n] [xAxis, smoothedDatasets, datasets, runs, sortingMethod, maxStepLength, i18n, datasetRanges]
); );
const downloadData = useCallback( const downloadData = useCallback(
......
...@@ -56,7 +56,7 @@ function render() { ...@@ -56,7 +56,7 @@ function render() {
} }
} }
if (import.meta.env.MODE === 'development' && !import.meta.env.SERVER) { if (import.meta.env.MODE === 'development' && import.meta.env.MOCK) {
import('@visualdl/mock').then(async ({initMock}) => { import('@visualdl/mock').then(async ({initMock}) => {
await initMock(); await initMock();
render(); render();
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
// cSpell:words maxs coord // cSpell:words maxs coord
import type {Dataset, Range, TooltipData, XAxis} from './types'; import type {Dataset, InvalidValue, Range, ScalarDataset, Step, TooltipData, Value, XAxis} from './types';
import {formatTime, humanizeDuration} from '~/utils'; import {formatTime, humanizeDuration} from '~/utils';
import type {EChartOption} from 'echarts'; import type {EChartOption} from 'echarts';
...@@ -27,6 +27,9 @@ import {xAxisMap} from './index'; ...@@ -27,6 +27,9 @@ import {xAxisMap} from './index';
const valueFormatter = format('.5'); const valueFormatter = format('.5');
const INF_VALUE = 'inf';
const NAN_VALUE = 'nan';
export const options = { export const options = {
legend: { legend: {
data: [] data: []
...@@ -38,12 +41,14 @@ export const options = { ...@@ -38,12 +41,14 @@ export const options = {
export const chartData = ({ export const chartData = ({
data, data,
rawData,
ranges, ranges,
runs, runs,
xAxis, xAxis,
smoothedOnly smoothedOnly
}: { }: {
data: Dataset[]; data: Dataset[];
rawData: ScalarDataset[];
ranges: Range[]; ranges: Range[];
runs: Run[]; runs: Run[];
xAxis: XAxis; xAxis: XAxis;
...@@ -60,6 +65,17 @@ export const chartData = ({ ...@@ -60,6 +65,17 @@ export const chartData = ({
const name = runs[i].label; const name = runs[i].label;
const color = runs[i].colors[0]; const color = runs[i].colors[0];
const colorAlt = runs[i].colors[1]; const colorAlt = runs[i].colors[1];
const xAxisIndex = xAxisMap[xAxis];
const singlePointIndices: number[] = [];
dataset.forEach((d, index) => {
if (d[2] != null) {
const prevV = index === 0 ? null : dataset[index - 1][2];
const nextV = index === dataset.length - 1 ? null : dataset[index + 1][2];
if (prevV == null && nextV == null) {
singlePointIndices.push(index);
}
}
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
const result: any[] = [ const result: any[] = [
{ {
...@@ -73,15 +89,28 @@ export const chartData = ({ ...@@ -73,15 +89,28 @@ export const chartData = ({
}, },
data: dataset, data: dataset,
encode: { encode: {
x: [xAxisMap[xAxis]], x: [xAxisIndex],
y: [3] y: [3]
},
markPoint: {
symbol: 'circle',
symbolSize: 4,
itemStyle: {
color: '#fff',
borderColor: color,
borderWidth: 1
},
label: {
show: false
},
data: singlePointIndices.map(index => ({
coord: [dataset[index][xAxisIndex], dataset[index][3]]
}))
} }
} }
]; ];
if (!smoothedOnly) { if (!smoothedOnly) {
const range = ranges[i]; const range = ranges[i];
// const mins = dataset.filter(item => item[2] === range?.min);
// const maxs = dataset.filter(item => item[2] === range?.max);
const min = dataset.find(item => item[2] === range?.min); const min = dataset.find(item => item[2] === range?.min);
const max = dataset.find(item => item[2] === range?.max); const max = dataset.find(item => item[2] === range?.max);
result.push({ result.push({
...@@ -95,7 +124,7 @@ export const chartData = ({ ...@@ -95,7 +124,7 @@ export const chartData = ({
}, },
data: dataset, data: dataset,
encode: { encode: {
x: [xAxisMap[xAxis]], x: [xAxisIndex],
y: [2] y: [2]
}, },
markPoint: { markPoint: {
...@@ -110,13 +139,73 @@ export const chartData = ({ ...@@ -110,13 +139,73 @@ export const chartData = ({
show: false show: false
}, },
data: [ data: [
...(min ? [{coord: [min[xAxisMap[xAxis]], min[2]]}] : []), ...singlePointIndices.map(index => ({
...(max ? [{coord: [max[xAxisMap[xAxis]], max[2]]}] : []) coord: [dataset[index][xAxisIndex], dataset[index][2]],
symbol: 'circle',
symbolSize: 4
})),
...(min ? [{coord: [min[xAxisIndex], min[2]]}] : []),
...(max ? [{coord: [max[xAxisIndex], max[2]]}] : [])
] ]
// data: [ }
// ...mins.map(item => ({coord: [item[xAxisMap[xAxis]], item[2]]})), });
// ...maxs.map(item => ({coord: [item[xAxisMap[xAxis]], item[2]]}))
// ] const rawDataset = rawData[i];
const infData: [Step, Value][] = [];
const nanData: [Step, Value][] = [];
let lastValidValue: Value = null;
rawDataset.forEach(([, x, y], j) => {
if (j > 0) {
if (dataset[j][2] != null) {
lastValidValue = dataset[j][2];
}
}
if (y === INF_VALUE) {
infData.push([x, lastValidValue]);
} else if (y === NAN_VALUE) {
nanData.push([x, lastValidValue]);
}
});
result.push({
data: infData,
symbolShow: false,
lineStyle: {
width: 0,
opacity: 0
},
markPoint: {
symbol: 'rect',
symbolSize: 6,
itemStyle: {
color: '#fff',
borderColor: colorAlt,
borderWidth: 1
},
label: {
show: false
},
data: infData.map(d => ({coord: d}))
}
});
result.push({
data: nanData,
symbolShow: false,
lineStyle: {
width: 0,
opacity: 0
},
markPoint: {
symbol: 'triangle',
symbolSize: 6,
itemStyle: {
color: '#fff',
borderColor: colorAlt,
borderWidth: 1
},
label: {
show: false
},
data: nanData.map(d => ({coord: d}))
} }
}); });
} }
...@@ -125,6 +214,15 @@ export const chartData = ({ ...@@ -125,6 +214,15 @@ export const chartData = ({
.flat(); .flat();
export const tooltip = (data: TooltipData[], stepLength: number, i18n: typeof I18n) => { export const tooltip = (data: TooltipData[], stepLength: number, i18n: typeof I18n) => {
const getValue = (value: Value | InvalidValue): string => {
if (value === INF_VALUE) {
return 'Inf';
}
if (value === NAN_VALUE) {
return 'NaN';
}
return value == null ? '--' : valueFormatter(value);
};
return { return {
columns: [ columns: [
{ {
...@@ -156,9 +254,9 @@ export const tooltip = (data: TooltipData[], stepLength: number, i18n: typeof I1 ...@@ -156,9 +254,9 @@ export const tooltip = (data: TooltipData[], stepLength: number, i18n: typeof I1
width: '4.285714286em' width: '4.285714286em'
} }
], ],
data: data.map(({min, max, item}) => [ data: data.map(({min, max, item, rawItem}) => [
valueFormatter(item[3] ?? Number.NaN), item[3] == null ? '--' : valueFormatter(item[3]),
valueFormatter(Number.isFinite(item[2]) ? (item[2] as number) : Number.NaN), getValue(rawItem[2]),
item[1], item[1],
valueFormatter(min ?? Number.NaN), valueFormatter(min ?? Number.NaN),
valueFormatter(max ?? Number.NaN), valueFormatter(max ?? Number.NaN),
......
...@@ -28,7 +28,13 @@ import {quantile} from '~/utils'; ...@@ -28,7 +28,13 @@ import {quantile} from '~/utils';
export const transform = ({datasets, smoothing}: {datasets: ScalarDataset[]; smoothing: number}) => export const transform = ({datasets, smoothing}: {datasets: ScalarDataset[]; smoothing: number}) =>
// https://en.wikipedia.org/wiki/Moving_average // https://en.wikipedia.org/wiki/Moving_average
datasets.map(seriesData => { datasets.map(seriesData => {
const data = seriesData.map<Dataset[number]>(s => [...s, Number.NaN, Number.NaN]); const data = seriesData.map<Dataset[number]>(s => [
s[0],
s[1],
Number.isFinite(s[2]) ? (s[2] as number) : null,
Number.NaN,
Number.NaN
]);
let last = new BigNumber(data.length > 0 ? 0 : Number.NaN); let last = new BigNumber(data.length > 0 ? 0 : Number.NaN);
let numAccum = 0; let numAccum = 0;
let startValue = 0; let startValue = 0;
...@@ -122,8 +128,8 @@ export const axisRange = ({datasets, outlier}: {datasets: Dataset[]; outlier: bo ...@@ -122,8 +128,8 @@ export const axisRange = ({datasets, outlier}: {datasets: Dataset[]; outlier: bo
} }
}; };
export const nearestPoint = (data: Dataset[], runs: Run[], idx: number, value: number) => { export const nearestPoint = (data: Dataset[], rawItem: ScalarDataset[], runs: Run[], idx: number, value: number) => {
const result: {run: Run; item: Dataset[number]}[] = []; const result: {run: Run; item: Dataset[number]; rawItem: ScalarDataset[number]}[] = [];
data.forEach((series, index) => { data.forEach((series, index) => {
const run = runs[index]; const run = runs[index];
let d = Number.POSITIVE_INFINITY; let d = Number.POSITIVE_INFINITY;
...@@ -138,7 +144,18 @@ export const nearestPoint = (data: Dataset[], runs: Run[], idx: number, value: n ...@@ -138,7 +144,18 @@ export const nearestPoint = (data: Dataset[], runs: Run[], idx: number, value: n
} }
} }
} }
result.push(...series.filter(s => s[idx] === dv).map(item => ({run, item}))); result.push(
...series.reduce<typeof result>((m, c, i) => {
if (c[idx] === dv) {
m.push({
run,
item: c,
rawItem: rawItem[index][i]
});
}
return m;
}, [])
);
}); });
return result; return result;
}; };
......
...@@ -26,13 +26,13 @@ export const xAxisMap = { ...@@ -26,13 +26,13 @@ export const xAxisMap = {
} as const; } as const;
export const sortingMethod = [SM.Default, SM.Descending, SM.Ascending, SM.Nearest] as const; export const sortingMethod = [SM.Default, SM.Descending, SM.Ascending, SM.Nearest] as const;
export const sortingMethodMap: Record<SM, (points: TooltipData[], data: number[]) => TooltipData[]> = { export const sortingMethodMap: Record<SM, (points: TooltipData[], value: number) => TooltipData[]> = {
[SM.Default]: (points: TooltipData[]) => points, [SM.Default]: (points: TooltipData[]) => points,
[SM.Descending]: (points: TooltipData[]) => sortBy(points, point => point.item[3]).reverse(), [SM.Descending]: (points: TooltipData[]) => sortBy(points, point => point.item[3]).reverse(),
[SM.Ascending]: (points: TooltipData[]) => sortBy(points, point => point.item[3]), [SM.Ascending]: (points: TooltipData[]) => sortBy(points, point => point.item[3]),
// Compare other points width the trigger point, calculate the nearest sort. // Compare other points with the trigger point, calculate the nearest sort.
[SM.Nearest]: (points: TooltipData[], data: number[]) => [SM.Nearest]: (points: TooltipData[], value: number) =>
sortBy(points, point => (point.item[3] ?? Number.NaN) - data[2]) sortBy(points, point => (point.item[1] ?? Number.NaN) - value)
} as const; } as const;
export type {Dataset, ScalarDataset, Range, TooltipData} from './types'; export type {Dataset, ScalarDataset, Range, TooltipData} from './types';
......
...@@ -18,15 +18,15 @@ import {Run, TimeMode} from '~/types'; ...@@ -18,15 +18,15 @@ import {Run, TimeMode} from '~/types';
export type {Range} from '~/types'; export type {Range} from '~/types';
type InvalidValue = 'NaN' | 'Inf' | '-Inf'; export type InvalidValue = 'nan' | 'inf';
export type Value = number | null | InvalidValue; export type Value = number | null;
type WallTime = number; type WallTime = number;
type Step = number; export type Step = number;
type Smoothed = number | null; type Smoothed = number | null;
type Relative = number; type Relative = number;
export type Dataset = [WallTime, Step, Value, Smoothed, Relative][]; export type Dataset = [WallTime, Step, Value, Smoothed, Relative][];
export type ScalarDataset = [WallTime, Step, Value][]; export type ScalarDataset = [WallTime, Step, Value | InvalidValue][];
export {TimeMode as XAxis}; export {TimeMode as XAxis};
export enum SortingMethod { export enum SortingMethod {
...@@ -39,6 +39,7 @@ export enum SortingMethod { ...@@ -39,6 +39,7 @@ export enum SortingMethod {
export type TooltipData = { export type TooltipData = {
run: Run; run: Run;
item: Dataset[number]; item: Dataset[number];
rawItem: ScalarDataset[number];
min?: number; min?: number;
max?: number; max?: number;
}; };
...@@ -24,7 +24,7 @@ export const formatTime = (value: number, language: string, formatter = 'L LTS') ...@@ -24,7 +24,7 @@ export const formatTime = (value: number, language: string, formatter = 'L LTS')
export const humanizeDuration = (ms: number) => { export const humanizeDuration = (ms: number) => {
const time = moment.duration(ms); const time = moment.duration(ms);
const hour = time.hours(); const hour = Math.floor(time.asHours());
if (hour) { if (hour) {
time.subtract(hour, 'hour'); time.subtract(hour, 'hour');
} }
...@@ -32,8 +32,8 @@ export const humanizeDuration = (ms: number) => { ...@@ -32,8 +32,8 @@ export const humanizeDuration = (ms: number) => {
if (minute) { if (minute) {
time.subtract(minute, 'minute'); time.subtract(minute, 'minute');
} }
const second = time.asSeconds(); const second = Math.floor(time.seconds());
let str = Math.floor(second) + 's'; let str = `${second}s`;
if (hour) { if (hour) {
str = `${hour}h${minute}m${str}`; str = `${hour}h${minute}m${str}`;
} else if (minute) { } else if (minute) {
......
{ {
"name": "@visualdl/demo", "name": "@visualdl/demo",
"version": "2.2.0-1", "version": "2.2.1",
"description": "A platform to visualize the deep learning process and result.", "description": "A platform to visualize the deep learning process and result.",
"keywords": [ "keywords": [
"visualdl", "visualdl",
...@@ -33,19 +33,19 @@ ...@@ -33,19 +33,19 @@
"test": "echo \"Error: no test specified\" && exit 0" "test": "echo \"Error: no test specified\" && exit 0"
}, },
"devDependencies": { "devDependencies": {
"@types/express": "4.17.12", "@types/express": "4.17.13",
"@types/mkdirp": "1.0.1", "@types/mkdirp": "1.0.2",
"@types/node": "15.12.2", "@types/node": "16.7.1",
"@types/node-fetch": "2.5.10", "@types/node-fetch": "2.5.12",
"@types/rimraf": "3.0.0", "@types/rimraf": "3.0.2",
"cpy-cli": "3.1.1", "cpy-cli": "3.1.1",
"get-port": "5.1.1", "get-port": "5.1.1",
"mime-types": "2.1.31", "mime-types": "2.1.32",
"mkdirp": "1.0.4", "mkdirp": "1.0.4",
"node-fetch": "2.6.1", "node-fetch": "2.6.1",
"rimraf": "3.0.2", "rimraf": "3.0.2",
"ts-node": "10.0.0", "ts-node": "10.2.1",
"typescript": "4.3.2" "typescript": "4.3.5"
}, },
"peerDependencies": { "peerDependencies": {
"express": "^4.17.1" "express": "^4.17.1"
......
{ {
"name": "@visualdl/icons", "name": "@visualdl/icons",
"version": "2.2.0-1", "version": "2.2.1",
"description": "A platform to visualize the deep learning process and result.", "description": "A platform to visualize the deep learning process and result.",
"keywords": [ "keywords": [
"visualdl", "visualdl",
...@@ -37,14 +37,14 @@ ...@@ -37,14 +37,14 @@
"test": "echo \"Error: no test specified\" && exit 0" "test": "echo \"Error: no test specified\" && exit 0"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "7.14.3", "@babel/core": "7.15.0",
"@babel/preset-react": "7.13.13", "@babel/preset-react": "7.14.5",
"@svgr/core": "5.5.0", "@svgr/core": "5.5.0",
"@svgr/plugin-jsx": "5.5.0", "@svgr/plugin-jsx": "5.5.0",
"@svgr/plugin-svgo": "5.5.0", "@svgr/plugin-svgo": "5.5.0",
"camelcase": "6.2.0", "camelcase": "6.2.0",
"fs-extra": "10.0.0", "fs-extra": "10.0.0",
"svgo": "2.3.0" "svgo": "2.4.0"
}, },
"peerDependencies": { "peerDependencies": {
"react": "^16.0.0 || ^17.0.0" "react": "^16.0.0 || ^17.0.0"
......
{ {
"name": "@visualdl/mock", "name": "@visualdl/mock",
"version": "2.2.0-1", "version": "2.2.1",
"description": "A platform to visualize the deep learning process and result.", "description": "A platform to visualize the deep learning process and result.",
"keywords": [ "keywords": [
"visualdl", "visualdl",
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
"dependencies": { "dependencies": {
"fetch-mock": "9.11.0", "fetch-mock": "9.11.0",
"isomorphic-fetch": "3.0.0", "isomorphic-fetch": "3.0.0",
"mime-types": "2.1.31" "mime-types": "2.1.32"
}, },
"devDependencies": { "devDependencies": {
"express": "4.17.1" "express": "4.17.1"
......
{ {
"name": "@visualdl/netron", "name": "@visualdl/netron",
"version": "2.2.0-1", "version": "2.2.1",
"description": "A platform to visualize the deep learning process and result.", "description": "A platform to visualize the deep learning process and result.",
"keywords": [ "keywords": [
"visualdl", "visualdl",
...@@ -40,19 +40,19 @@ ...@@ -40,19 +40,19 @@
"pako": "1.0.11" "pako": "1.0.11"
}, },
"devDependencies": { "devDependencies": {
"autoprefixer": "10.2.6", "autoprefixer": "10.3.1",
"copy-webpack-plugin": "9.0.0", "copy-webpack-plugin": "9.0.1",
"css-loader": "5.2.6", "css-loader": "6.2.0",
"html-webpack-plugin": "5.3.1", "html-webpack-plugin": "5.3.2",
"mini-css-extract-plugin": "1.6.0", "mini-css-extract-plugin": "2.2.0",
"postcss": "8.3.0", "postcss": "8.3.6",
"postcss-loader": "5.3.0", "postcss-loader": "6.1.1",
"rimraf": "3.0.2", "rimraf": "3.0.2",
"sass": "1.34.1", "sass": "1.38.0",
"sass-loader": "12.0.0", "sass-loader": "12.1.0",
"terser": "5.7.0", "terser": "5.7.1",
"webpack": "5.38.1", "webpack": "5.51.1",
"webpack-cli": "4.7.2" "webpack-cli": "4.8.0"
}, },
"engines": { "engines": {
"node": ">=12", "node": ">=12",
......
{ {
"name": "@visualdl/server", "name": "@visualdl/server",
"version": "2.2.0-1", "version": "2.2.1",
"description": "A platform to visualize the deep learning process and result.", "description": "A platform to visualize the deep learning process and result.",
"keywords": [ "keywords": [
"visualdl", "visualdl",
...@@ -36,25 +36,25 @@ ...@@ -36,25 +36,25 @@
"dist" "dist"
], ],
"dependencies": { "dependencies": {
"@visualdl/core": "2.2.0-1", "@visualdl/core": "2.2.1",
"dotenv": "10.0.0", "dotenv": "10.0.0",
"enhanced-resolve": "5.8.2", "enhanced-resolve": "5.8.2",
"express": "4.17.1", "express": "4.17.1",
"http-proxy-middleware": "2.0.0", "http-proxy-middleware": "2.0.1",
"pm2": "5.0.4" "pm2": "5.1.1"
}, },
"devDependencies": { "devDependencies": {
"@types/enhanced-resolve": "3.0.6", "@types/enhanced-resolve": "3.0.7",
"@types/express": "4.17.12", "@types/express": "4.17.13",
"@types/node": "15.12.2", "@types/node": "16.7.1",
"@visualdl/mock": "2.2.0-1", "@visualdl/mock": "2.2.1",
"cross-env": "7.0.3", "cross-env": "7.0.3",
"nodemon": "2.0.7", "nodemon": "2.0.12",
"ts-node": "10.0.0", "ts-node": "10.2.1",
"typescript": "4.3.2" "typescript": "4.3.5"
}, },
"optionalDependencies": { "optionalDependencies": {
"@visualdl/demo": "2.2.0-1" "@visualdl/demo": "2.2.1"
}, },
"engines": { "engines": {
"node": ">=12", "node": ">=12",
......
{ {
"name": "@visualdl/wasm", "name": "@visualdl/wasm",
"version": "2.2.0-1", "version": "2.2.1",
"title": "VisualDL", "title": "VisualDL",
"description": "A platform to visualize the deep learning process and result.", "description": "A platform to visualize the deep learning process and result.",
"keywords": [ "keywords": [
......
...@@ -105,14 +105,14 @@ pub fn axis_range(datasets: &Vec<Vec<Smoothed>>, outlier: bool) -> Range { ...@@ -105,14 +105,14 @@ pub fn axis_range(datasets: &Vec<Vec<Smoothed>>, outlier: bool) -> Range {
continue; continue;
} }
let (sorted, values) = sort_values(data); let (sorted, _) = sort_values(data);
if !outlier { if !outlier {
ranges.push(Range::new(sorted[0], sorted[sorted.len() - 1])); ranges.push(Range::new(sorted[0], sorted[sorted.len() - 1]));
} else { } else {
ranges.push(Range::new( ranges.push(Range::new(
quantile(&sorted, 0.05_f64), quantile(&sorted, 0.05_f64),
quantile(&values, 0.95), quantile(&sorted, 0.95),
)); ));
} }
} }
......
此差异已折叠。
...@@ -13,4 +13,4 @@ ...@@ -13,4 +13,4 @@
# limitations under the License. # limitations under the License.
# ======================================================================= # =======================================================================
vdl_version = '2.2.0' vdl_version = '2.2.1'
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册