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

VisualDL 2.0 development in progress (#571)

* refactor: initialize VisualDL 2.0

* refactor: fix dev server problem

* refactor: add i18n

* refactor: fix i18n

* infra i18n支持

* styled-components for debug

* infra. essential hack for styled comopnent

* use yaml for translation

* fix: navbar url problem

* feat: add nuxt module to build locales

* fix: index route redirect error

* feat: add page title

* refactor: move i18n to module

* feat: add html lang attribute

* R.I.P

* Hello React

* refactor: initialize VisualDL 2.0

* fix: layout rerender

* add favicon

* add page title

* add meta tags

* feat: finish tag filter

* refactor: hook tastes good

* add single select

* finish components

* add api server

* scalars segregate metrics

* json-server sucks

* echarts

* add eslint

* bug fix

* finish scalars page

* change layout, fix aside

* add commit hook

* use tag filter hook

* add chart loading

* encapsulate run select

* samples page under construction

* finish images

* feat: graph page, still need some polishment

* finish high-dimensional

* fix mock data problem

* update readme

* fix build

* fix: use Buffer.from instead of constractor

* update Readme
Co-authored-by: NNiandalu <Niandalu@users.noreply.github.com>
上级 52e8a2c4
language: cpp matrix:
include:
- language: cpp
compiler: clang
cache:
- pip
- ccache
sudo: required
dist: trusty
compiler: clang os:
- linux
# much bug with osx environment
# TODO(ChunweiYan) support osx in the future
#- osx
cache: env:
- pip - MATRIX_EVAL="CC=clang-5.0 && CXX=clang++-5.0 && JOB=check_style"
- ccache - MATRIX_EVAL="CC=clang-5.0 && CXX=clang++-5.0 && JOB=test"
- yarn - MATRIX_EVAL="CC=clang-5.0 && CXX=clang++-5.0 && JOB=test_python3"
- npm - MATRIX_EVAL="CC=clang-5.0 && CXX=clang++-5.0 && JOB=build_doc"
sudo: required
dist: trusty
os: addons:
- linux apt:
# much bug with osx environment sources:
# TODO(ChunweiYan) support osx in the future - llvm-toolchain-trusty-5.0
#- osx packages:
- clang-5.0
- gcc-4.8
- g++-4.8
- git
- python
- python-pip
- python2.7-dev
- python-wheel
- python3-pip
- python3-dev
- python3-wheel
- clang-format-3.8
- ccache
ssh_known_hosts: 13.229.163.131
env: before_install:
- MATRIX_EVAL="CC=clang-5.0 && CXX=clang++-5.0 && JOB=check_style" - eval "${MATRIX_EVAL}"
- MATRIX_EVAL="CC=clang-5.0 && CXX=clang++-5.0 && JOB=test" - if [[ "$JOB" == "check_style" ]]; then sudo ln -s /usr/bin/clang-format-3.8 /usr/bin/clang-format; sudo pip install pre-commit flake8; fi
- MATRIX_EVAL="CC=clang-5.0 && CXX=clang++-5.0 && JOB=test_python3" - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi
- MATRIX_EVAL="CC=clang-5.0 && CXX=clang++-5.0 && JOB=build_doc" - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew upgrade python; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install brew-pip; fi
addons: script:
apt: - if [[ "$JOB" == "check_style" ]]; then ./scripts/check_style.sh; fi
sources: - if [[ "$JOB" == "test" ]]; then ./scripts/tests.sh all; fi
- llvm-toolchain-trusty-5.0 - if [[ "$JOB" == "test_python3" ]]; then WITH_PYTHON3=ON ./scripts/tests.sh all; fi
packages: - if [[ "$JOB" == "build_doc" ]]; then ./scripts/deploy_docs_on_travis.sh; fi;
- clang-5.0 - language: node_js
- gcc-4.8 dist: trusty
- g++-4.8 node_js:
- git - 12
- python sudo: false
- python-pip cache:
- python2.7-dev - npm
- python-wheel - yarn
- python3-pip env:
- python3-dev - NODE_ENV=production
- python3-wheel before_script:
- clang-format-3.8 - cd frontend
- ccache script:
- npm - if [[ "$JOB" == "check_style" ]]; then yarn lint; fi
- nodejs - if [[ "$JOB" == "test" ]]; then yarn test; fi
ssh_known_hosts: 13.229.163.131
before_install:
- eval "${MATRIX_EVAL}"
- if [[ "$JOB" == "check_style" ]]; then sudo ln -s /usr/bin/clang-format-3.8 /usr/bin/clang-format; sudo pip install pre-commit flake8; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew upgrade python; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install brew-pip; fi
script:
- if [[ "$JOB" == "check_style" ]]; then ./scripts/check_style.sh; fi
- if [[ "$JOB" == "test" ]]; then ./scripts/tests.sh all; fi
- if [[ "$JOB" == "test_python3" ]]; then WITH_PYTHON3=ON ./scripts/tests.sh all; fi
- if [[ "$JOB" == "build_doc" ]]; then ./scripts/deploy_docs_on_travis.sh; fi;
notifications: notifications:
email: email:
......
{
"presets": [
["es2015", {"modules": false}],
"stage-0"
],
"plugins": ["transform-class-properties"]
}
# editorconfig.org
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
module.exports = { module.exports = {
extends: [ env: {
'google', browser: true,
'plugin:vue/base', es6: true,
'plugin:vue/essential', node: true
'plugin:vue/strongly-recommended', },
], extends: [
parserOptions: { 'plugin:@typescript-eslint/recommended',
"sourceType": "module", 'plugin:react/recommended',
}, 'prettier/@typescript-eslint',
rules: { 'plugin:prettier/recommended'
// override/add rules settings here, such as: ],
'vue/no-unused-vars': 'warn', parser: '@typescript-eslint/parser',
'max-len': ["warn", 120], parserOptions: {
"vue/prop-name-casing": ["error"], ecmaFeatures: {
'vue/script-indent': 'error', jsx: true
},
// The following rules should apply eventually. Turn them off for now ecmaVersion: 2018,
// so we can have pre-commit running sourceType: 'module'
'no-invalid-this': 'off', },
'require-jsdoc': 'off', plugins: ['react', 'react-hooks', '@typescript-eslint'],
} settings: {
} react: {
version: 'detect'
}
},
rules: {
'@typescript-eslint/explicit-function-return-type': 'off',
'react/prop-types': 'off',
'react/react-in-jsx-scope': 'off',
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn'
}
};
node_modules/**/*
dep/**/*
test/**/*
mock/**/*
example/**/*
output/**/*
{
"files": [
"./src/**/*.san",
"./src/**/*.js",
"./template/**/*.html"
],
"eslint": {
"rules": {
"fecs-esnext-ext": [
"2",
[
"js",
"san"
]
],
"fecs-valid-jsdoc": [
"0"
]
}
},
"csshint": {},
"htmlcs": {},
"jformatter": {},
"esformatter": {},
"csscomb": {}
}
# Always validate the PR title AND all the commits
titleAndCommits: true
# Allows use of Merge commits (eg on github: "Merge branch 'master' into feature/ride-unicorns")
# this is only relevant when using commitsOnly: true (or titleAndCommits: true)
allowMergeCommits: true
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
/dist
# misc
.DS_Store
.env*
.vscode
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# FrontEnd of VisualDL
A platform to visualize the deep learning process and result.
[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier) [![License](https://img.shields.io/github/license/PaddlePaddle/VisualDL?style=flat-square)](https://github.com/PaddlePaddle/VisualDL/blob/develop/LICENSE) [![GitHub top language](https://img.shields.io/github/languages/top/PaddlePaddle/VisualDL?style=flat-square)](https://github.com/PaddlePaddle/VisualDL) [![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/PaddlePaddle/VisualDL?style=flat-square)](https://github.com/PaddlePaddle/VisualDL) [![GitHub issues](https://img.shields.io/github/issues/PaddlePaddle/VisualDL?style=flat-square)](https://github.com/PaddlePaddle/VisualDL/issues) [![GitHub All Releases](https://img.shields.io/github/downloads/PaddlePaddle/VisualDL/total?style=flat-square)](https://github.com/PaddlePaddle/VisualDL/releases) [![GitHub stars](https://img.shields.io/github/stars/PaddlePaddle/VisualDL?style=social)](https://github.com/PaddlePaddle/VisualDL/stargazers)
**🚧UNDER CONSTRUCTION🚧**
**🚧SOME FEATURE MAY NOT WORK PROPERLY🚧**
**🚧PULL REQUESTS WELCOMED🚧**
## Development
> nodejs ≥ 10 and npm ≥ 6 is required.
First, install all dependencies:
```bash
npm install
# or
yarn
```
Then you can start the development server:
```bash
yarn dev
```
Now open [http://localhost:8999](http://localhost:8999) with your browser.
You can change the port with `PORT` environment variable.
```bash
PORT=3000 yarn dev
```
## Learn More
This project is based on following projects:
- [Next.js](https://nextjs.org/)
- [React](https://reactjs.org/)
- [ECharts](https://echarts.apache.org/)
## License
Apache-2.0
module.exports = {
presets: ['next/babel'],
plugins: [
[
'styled-components',
{
ssr: true,
displayName: true,
preprocess: false
}
],
...(process.env.NODE_ENV !== 'production' ? ['babel-plugin-typescript-to-proptypes'] : [])
]
};
import React, {FunctionComponent} from 'react';
import styled from 'styled-components';
import {rem} from '~/utils/style';
const Divider = styled.hr<{height?: string | number}>`
background-color: transparent;
margin: 0;
border: none;
height: ${({height}) => (height ? ('number' === height ? rem(height) : height) : rem(30))};
`;
type AsideDividerProps = {
height?: string | number;
};
const AsideDivider: FunctionComponent<AsideDividerProps> = ({height}) => <Divider height={height} />;
export default AsideDivider;
import React, {FunctionComponent} from 'react';
import styled from 'styled-components';
import {
WithStyled,
em,
half,
textInvertColor,
primaryColor,
primaryFocusedColor,
primaryActiveColor,
duration,
easing,
ellipsis,
transitions
} from '~/utils/style';
import RawIcon from '~/components/Icon';
const height = em(36);
const Wrapper = styled.a`
cursor: pointer;
height: ${height};
line-height: ${height};
border-radius: ${half(height)};
background-color: ${primaryColor};
color: ${textInvertColor};
display: block;
text-align: center;
${transitions('background-color', `${duration} ${easing}`)}
${ellipsis()}
&:hover,
&:focus {
background-color: ${primaryFocusedColor};
}
&:active {
background-color: ${primaryActiveColor};
}
`;
const Icon = styled(RawIcon)`
margin-right: 4px;
`;
type ButtonProps = {
icon?: string;
onClick?: () => unknown;
};
const Button: FunctionComponent<ButtonProps & WithStyled> = ({icon, children, className, onClick}) => (
<Wrapper className={className} onClick={onClick}>
{icon && <Icon type={icon}></Icon>}
{children}
</Wrapper>
);
export default Button;
import React, {FunctionComponent} from 'react';
import styled from 'styled-components';
import {
WithStyled,
primaryColor,
backgroundColor,
borderColor,
borderRadius,
duration,
easing,
transitions,
math
} from '~/utils/style';
const Div = styled.div`
background-color: ${backgroundColor};
border: 1px solid ${borderColor};
border-radius: ${math(`${borderRadius} * 2`)};
${transitions(['border-color', 'box-shadow'], `${duration} ${easing}`)}
&:hover {
border-color: ${primaryColor};
box-shadow: 0 5px 6px 0 rgba(0, 0, 0, 0.05);
}
`;
const Chart: FunctionComponent<WithStyled> = ({className, children}) => {
return <Div className={className}>{children}</Div>;
};
export default Chart;
import React, {FunctionComponent, useState} from 'react';
import styled from 'styled-components';
import {WithStyled, rem} from '~/utils/style';
import Chart from '~/components/Chart';
import Pagination from '~/components/Pagination';
const Wrapper = styled.div`
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
align-items: stretch;
align-content: flex-start;
> * {
margin: 0 ${rem(20)} ${rem(20)} 0;
flex-shrink: 0;
flex-grow: 0;
}
`;
// TODO: add types
// eslint-disable-next-line
type ChartPageProps<T = any> = {
items?: T[];
withChart?: (item: T) => React.ReactNode;
};
const ChartPage: FunctionComponent<ChartPageProps & WithStyled> = ({items, withChart, className}) => {
const pageSize = 12;
const total = Math.ceil((items?.length ?? 0) / pageSize);
const [page, setPage] = useState(1);
const pageItems = items?.slice((page - 1) * pageSize, page * pageSize) ?? [];
return (
<div className={className}>
<Wrapper>
{pageItems.map((item, index) => (
<Chart key={index}>{withChart?.(item)}</Chart>
))}
</Wrapper>
<Pagination page={page} total={total} onChange={setPage} />
</div>
);
};
export default ChartPage;
import React, {FunctionComponent, useState} from 'react';
import styled from 'styled-components';
import {
WithStyled,
em,
textLighterColor,
textInvertColor,
backgroundColor,
primaryColor,
duration,
size,
easing,
ellipsis,
transitions,
math,
darken,
lighten
} from '~/utils/style';
const height = em(20);
const checkSize = em(16);
const checkMark =
// eslint-disable-next-line
'data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjgiIHZpZXdCb3g9IjAgMCAxMSA4IiB3aWR0aD0iMTEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0ibTkuNDc5NDI3MDggMTAuMTg3NWgtNS4yNXYtMS4zMTI1aDMuOTM3bC4wMDA1LTcuODc1aDEuMzEyNXoiIGZpbGw9IiNmNWY1ZjUiIGZpbGwtcnVsZT0iZXZlbm9kZCIgdHJhbnNmb3JtPSJtYXRyaXgoLjcwNzEwNjc4IC43MDcxMDY3OCAtLjcwNzEwNjc4IC43MDcxMDY3OCA0Ljk2Mjk5NCAtNi4yMDg0NCkiLz48L3N2Zz4=';
const Wrapper = styled.label<{disabled?: boolean}>`
position: relative;
display: inline-flex;
align-items: flex-start;
cursor: ${props => (props.disabled ? 'not-allowed' : 'pointer')};
`;
const Input = styled.input.attrs<{disabled?: boolean}>(props => ({
type: 'checkbox',
disabled: !!props.disabled
}))`
${size(0, 0)}
position: absolute;
left: 0;
top: 0;
opacity: 0;
pointer-events: none;
`;
const Inner = styled.div<{checked?: boolean; size?: string; disabled?: boolean}>`
color: ${props => (props.checked ? textInvertColor : 'transparent')};
flex-shrink: 0;
${props => size(math(`${checkSize} * ${props.size === 'small' ? 0.875 : 1}`))}
margin: ${math(`(${height} - ${checkSize}) / 2`)} 0;
margin-right: ${em(4)};
border: 1px solid ${props => (props.disabled || !props.checked ? textLighterColor : primaryColor)};
background-color: ${props =>
props.disabled
? props.checked
? textLighterColor
: lighten(0.333, textLighterColor)
: props.checked
? primaryColor
: backgroundColor};
background-image: ${props => (props.checked ? `url("${checkMark}")` : 'none')};
background-repeat: no-repeat;
background-position: center center;
background-size: ${em(10)} ${em(8)};
position: relative;
${transitions(['border-color', 'background-color', 'color'], `${duration} ${easing}`)}
${Wrapper}:hover > & {
border-color: ${props =>
props.disabled ? textLighterColor : props.checked ? primaryColor : darken(0.1, textLighterColor)};
}
`;
const Content = styled.div<{disabled?: boolean}>`
line-height: ${height};
flex-grow: 1;
${props => (props.disabled ? `color: ${textLighterColor};` : '')}
${ellipsis()}
`;
type CheckboxProps = {
value?: boolean;
onChange?: (value: boolean) => unknown;
size?: 'small';
disabled?: boolean;
};
const Checkbox: FunctionComponent<CheckboxProps & WithStyled> = ({
value,
children,
size,
disabled,
className,
onChange
}) => {
const [checked, setChecked] = useState(!!value);
const onChangeInput = (e: React.ChangeEvent<HTMLInputElement>) => {
if (disabled) {
return;
}
setChecked(e.target.checked);
onChange?.(e.target.checked);
};
return (
<Wrapper disabled={disabled} className={className}>
<Input onChange={onChangeInput} checked={checked} disabled={disabled} />
<Inner checked={checked} size={size} disabled={disabled} />
<Content disabled={disabled}>{children}</Content>
</Wrapper>
);
};
export default Checkbox;
import React, {FunctionComponent} from 'react';
import styled from 'styled-components';
import {rem, math, headerHeight, asideWidth, backgroundColor} from '~/utils/style';
const margin = rem(20);
const padding = rem(20);
const Section = styled.section`
/* trigger BFC */
overflow: hidden;
`;
const Article = styled.article<{aside?: boolean}>`
margin: ${margin};
margin-right: ${props => (props.aside ? math(`${margin} + ${asideWidth}`) : margin)};
padding: ${padding};
background-color: ${backgroundColor};
min-height: calc(100vh - ${math(`${margin} * 2 + ${headerHeight}`)});
`;
const Aside = styled.aside`
width: ${asideWidth};
padding: ${padding};
background-color: ${backgroundColor};
height: calc(100vh - ${headerHeight});
position: fixed;
top: ${headerHeight};
right: 0;
`;
type ContentProps = {
aside?: React.ReactNode;
};
const Content: FunctionComponent<ContentProps> = ({children, aside}) => (
<Section>
<Article aside={!!aside}>{children}</Article>
{aside && <Aside>{aside}</Aside>}
</Section>
);
export default Content;
import React, {FunctionComponent} from 'react';
import styled from 'styled-components';
import {WithStyled, rem} from '~/utils/style';
const Wrapper = styled.div`
& + & {
margin-top: ${rem(20)};
}
`;
const Label = styled.div`
margin-bottom: ${rem(10)};
`;
type FieldProps = {
label?: string;
};
const Field: FunctionComponent<FieldProps & WithStyled> = ({label, children, className}) => (
<Wrapper className={className}>
{label && <Label>{label}</Label>}
{children}
</Wrapper>
);
export default Field;
import React, {FunctionComponent} from 'react';
import {useTranslation, NextI18NextPage} from '~/utils/i18n';
import {NodeType, TypedNode} from '~/resource/graph';
const typeName: {[k in NodeType]: string} = {
[NodeType.Input]: 'input',
[NodeType.Output]: 'output',
[NodeType.Op]: 'operator'
};
export interface NodeInfoProps {
node?: TypedNode | {type: 'unknown'; guessType: NodeType; msg: string};
}
const NodeInfo: FunctionComponent<NodeInfoProps> = props => {
const {t} = useTranslation(['graphs']);
if (!props.node) {
return <p>{t('click-node')}</p>;
}
const node = props.node;
switch (node.type) {
case NodeType.Input:
case NodeType.Output:
return (
<ul>
<li>
{t('node-type')}: {typeName[node.type]}
</li>
<li>
{t('node-name')}: {node.name}
</li>
<li>
{t('node-data-shape')}: {node.shape}
</li>
<li>
{t('node-data-type')}: {node.data_type}
</li>
</ul>
);
case NodeType.Op:
return (
<ul>
<li>
{t('node-type')}: {typeName[node.type]}
</li>
<li>
{t('input')}: {node.input}
</li>
<li>
{t('op-type')}: {node.opType}
</li>
<li>
{t('output')}: {node.output}
</li>
</ul>
);
case 'unknown':
return (
<ul>
<li>
{t('node-type')}: {typeName[node.guessType]}
</li>
</ul>
);
default:
return <></>;
}
};
export default NodeInfo;
import React, {FunctionComponent} from 'react';
import {WithStyled} from '~/utils/style';
type IconProps = {
type: string;
};
const Icon: FunctionComponent<IconProps & WithStyled> = ({type, className}) => {
return <i className={`vdl-icon icon-${type} ${className}`} />;
};
export default Icon;
import React, {FunctionComponent, useEffect, useState, useRef} from 'react';
import {useTranslation} from '~/utils/i18n';
import fetch from 'isomorphic-unfetch';
type ImageProps = {
src?: string;
};
const Image: FunctionComponent<ImageProps> = ({src}) => {
const {t} = useTranslation('common');
const [url, setUrl] = useState('');
const [loading, setLoading] = useState(false);
const controller = useRef(null as AbortController | null);
useEffect(() => {
if (process.browser) {
let objectUrl: string | null = null;
(async () => {
setLoading(true);
controller.current?.abort();
controller.current = new AbortController();
try {
const result = await fetch(src ?? '', {signal: controller.current.signal});
const blob = await result.blob();
objectUrl = URL.createObjectURL(blob);
setUrl(objectUrl);
} catch {
// ignore abort error
} finally {
setLoading(false);
}
})();
return () => {
objectUrl && URL.revokeObjectURL(objectUrl);
};
}
}, [src]);
return loading ? <span>{t('loading')}</span> : <img src={url} />;
};
export default Image;
import React, {FunctionComponent} from 'react';
import styled from 'styled-components';
import {
WithStyled,
em,
textLighterColor,
borderColor,
borderFocusedColor,
borderRadius,
duration,
easing,
math
} from '~/utils/style';
export const padding = em(10);
export const height = em(36);
const StyledInput = styled.input<{rounded?: boolean}>`
padding: ${padding};
height: ${height};
line-height: ${height};
display: inline-block;
border: 1px solid ${borderColor};
border-radius: ${props => (props.rounded ? math(`${height} / 2`) : borderRadius)};
transition: border-color ${duration} ${easing};
outline: none;
&:hover,
&:focus {
border-color: ${borderFocusedColor};
}
&::placeholder {
color: ${textLighterColor};
}
`;
export type InputProps = {
rounded?: boolean;
placeholder?: string;
value?: string;
onChange?: (value: string) => unknown;
};
const Input: FunctionComponent<InputProps & WithStyled> = ({rounded, placeholder, value, onChange, className}) => (
<StyledInput
rounded={rounded}
placeholder={placeholder}
value={value}
type="text"
className={className}
onChange={e => onChange?.(e.target.value)}
></StyledInput>
);
export default Input;
import React, {FunctionComponent} from 'react';
import styled from 'styled-components';
import {headerHeight} from '~/utils/style';
import Navbar from '~/components/Navbar';
const Main = styled.main`
padding-top: ${headerHeight};
`;
const Header = styled.header`
position: fixed;
z-index: 10000;
width: 100%;
height: ${headerHeight};
top: 0;
left: 0;
right: 0;
`;
const Layout: FunctionComponent = ({children}) => (
<Main>
<Header>
<Navbar />
</Header>
{children}
</Main>
);
export default Layout;
import React, {FunctionComponent, useEffect, useCallback} from 'react';
import {EChartOption} from 'echarts';
import {WithStyled} from '~/utils/style';
import useECharts from '~/hooks/useECharts';
import * as chart from '~/utils/chart';
type LineChartProps = {
title?: string;
legend?: string[];
data?: Partial<NonNullable<EChartOption<EChartOption.SeriesLine>['series']>>;
xAxis?: string;
type?: EChartOption.BasicComponents.CartesianAxis.Type;
yRange?: {
min: number;
max: number;
};
tooltip?: string | EChartOption.Tooltip.Formatter;
loading?: boolean;
};
const LineChart: FunctionComponent<LineChartProps & WithStyled> = ({
title,
legend,
data,
xAxis,
type,
yRange,
tooltip,
loading,
className
}) => {
const [ref, echart] = useECharts<HTMLDivElement>(!!loading);
const xAxisFormatter = useCallback(
(value: number) => (type === 'time' ? new Date(value).toLocaleTimeString() : value),
[type]
);
useEffect(() => {
if (process.browser) {
echart.current?.setOption(
{
color: chart.color,
title: {
...chart.title,
text: title ?? ''
},
tooltip: {
...chart.tooltip,
...(tooltip
? {
formatter: tooltip
}
: {})
},
toolbox: chart.toolbox,
legend: {
...chart.legend,
data: legend ?? []
},
grid: chart.grid,
xAxis: {
...chart.xAxis,
name: xAxis || '',
type: type || 'value',
axisLabel: {
...chart.xAxis.axisLabel,
formatter: xAxisFormatter
}
},
yAxis: {
...chart.yAxis,
...(yRange || {})
},
series: data?.map(item => ({
...chart.series,
...item
}))
} as EChartOption,
{notMerge: true}
);
}
}, [data, title, legend, xAxis, type, xAxisFormatter, yRange, tooltip, echart]);
useEffect(() => {
if (process.browser) {
setTimeout(() => {
echart.current?.dispatchAction({
type: 'takeGlobalCursor',
key: 'dataZoomSelect',
dataZoomSelectActive: true
});
}, 0);
}
}, [echart]);
return <div className={className} ref={ref}></div>;
};
export default LineChart;
import React, {FunctionComponent} from 'react';
import styled from 'styled-components';
import {useRouter} from 'next/router';
import {useTranslation, Link} from '~/utils/i18n';
import {rem, headerColor, duration, easing, lighten, transitions} from '~/utils/style';
const navItems = ['scalars', 'samples', 'graphs', 'high-dimensional'];
const Nav = styled.nav`
background-color: ${headerColor};
color: #fff;
height: 100%;
width: 100%;
padding: 0 ${rem(20)};
display: flex;
justify-content: flex-start;
align-items: center;
`;
const Logo = styled.a`
font-size: ${rem(20)};
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif,
'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
font-weight: 600;
margin-right: ${rem(40)};
> img {
width: ${rem(98)};
height: ${rem(31)};
vertical-align: middle;
margin-right: ${rem(8)};
}
> span {
vertical-align: middle;
}
`;
const NavItem = styled.a<{active: boolean}>`
padding: 0 ${rem(20)};
height: 100%;
display: inline-flex;
justify-content: center;
align-items: center;
background-color: ${headerColor};
${transitions(['background-color'], `${duration} ${easing}`)}
&:hover {
background-color: ${lighten(0.05, headerColor)};
}
> span {
padding: ${rem(10)} 0 ${rem(7)};
border-bottom: ${rem(3)} solid ${props => (props.active ? '#596cd6' : 'transparent')};
${transitions(['border-bottom'], `${duration} ${easing}`)}
text-transform: uppercase;
}
`;
const Navbar: FunctionComponent = () => {
const {t} = useTranslation('common');
const {pathname} = useRouter();
return (
<Nav>
<Logo href="/">
<img alt="PaddlePaddle" src="/images/logo.svg" />
<span>VisualDL</span>
</Logo>
{navItems.map(name => {
const href = `/${name}`;
return (
// https://nextjs.org/docs/api-reference/next/link#if-the-child-is-a-custom-component-that-wraps-an-a-tag
<Link href={href} key={name} passHref>
<NavItem active={pathname === href}>
<span>{t(name)}</span>
</NavItem>
</Link>
);
})}
</Nav>
);
};
export default Navbar;
import React, {FunctionComponent} from 'react';
import styled from 'styled-components';
import {
WithStyled,
em,
primaryColor,
backgroundColor,
borderColor,
textInvertColor,
textColor,
borderRadius,
borderFocusedColor,
duration,
easing,
transitions,
size
} from '~/utils/style';
const height = em(36);
const Wrapper = styled.nav`
display: flex;
user-select: none;
`;
const Ul = styled.ul`
display: inline-flex;
list-style: none;
margin: 0;
padding: 0;
`;
const Li = styled.li`
list-style: none;
margin-left: ${em(10)};
&:first-child {
margin-left: 0;
}
`;
const A = styled.a<{current?: boolean}>`
cursor: pointer;
display: block;
background-color: ${props => (props.current ? primaryColor : backgroundColor)};
color: ${props => (props.current ? textInvertColor : textColor)};
height: ${height};
line-height: calc(${height} - 2px);
min-width: ${height};
padding: 0 ${em(10)};
text-align: center;
border: 1px solid ${props => (props.current ? primaryColor : borderColor)};
border-radius: ${borderRadius};
${transitions(['color', 'border-color', 'background-color'], `${duration} ${easing}`)}
&:hover {
border-color: ${props => (props.current ? primaryColor : borderFocusedColor)};
}
`;
const Span = styled.span`
display: block;
${size(height)}
line-height: ${height};
text-align: center;
`;
type PaginationProps = {
page: number;
total: number;
onChange?: (page: number) => unknown;
};
const Pagination: FunctionComponent<PaginationProps & WithStyled> = ({page, total, className, onChange}) => {
const padding = 2;
const around = 2;
const startEllipsis = page - padding - around - 1 > 0;
const endEllipsis = page + padding + around < total;
const start =
page - around - 1 <= 0 ? [] : Array.from(new Array(Math.min(padding, page - around - 1)), (_v, i) => i + 1);
const end =
page + around >= total
? []
: Array.from(
new Array(Math.min(padding, total - page - around)),
(_v, i) => total - padding + i + 1 + Math.max(padding - total + page + around, 0)
);
const before =
page - 1 <= 0
? []
: Array.from(
new Array(Math.min(around, page - 1)),
(_v, i) => page - around + i + Math.max(around - page + 1, 0)
);
const after = page >= total ? [] : Array.from(new Array(Math.min(around, total - page)), (_v, i) => page + i + 1);
const genLink = (arr: number[]) =>
arr.map(i => (
<Li key={i}>
<A onClick={() => onChange?.(i)}>{i}</A>
</Li>
));
const hellip = (
<Li>
<Span>&hellip;</Span>
</Li>
);
return (
<Wrapper className={className}>
<Ul>
{genLink(start)}
{startEllipsis && hellip}
{genLink(before)}
<Li>
<A current>{page}</A>
</Li>
{genLink(after)}
{endEllipsis && hellip}
{genLink(end)}
</Ul>
</Wrapper>
);
};
export default Pagination;
import React, {FunctionComponent, useContext} from 'react';
import styled from 'styled-components';
import {
WithStyled,
em,
textColor,
textInvertColor,
borderColor,
borderRadius,
backgroundColor,
primaryColor,
duration,
easing,
ellipsis,
transitions,
borderFocusedColor
} from '~/utils/style';
import {ValueContext, EventContext} from '~/components/RadioGroup';
const height = em(36);
const minWidth = em(72);
const maxWidth = em(144);
const Button = styled.a<{selected?: boolean}>`
cursor: pointer;
background-color: ${props => (props.selected ? primaryColor : backgroundColor)};
color: ${props => (props.selected ? textInvertColor : textColor)};
height: ${height};
line-height: calc(${height} - 2px);
min-width: ${minWidth};
${ellipsis(maxWidth)}
text-align: center;
border: 1px solid ${props => (props.selected ? primaryColor : borderColor)};
${transitions(['color', 'border-color', 'background-color'], `${duration} ${easing}`)}
/* bring selected one to top in order to cover the sibling's border */
${props => (props.selected ? 'position: relative;' : '')}
&:hover {
border-color: ${props => (props.selected ? primaryColor : borderFocusedColor)};
}
&:first-of-type {
border-top-left-radius: ${borderRadius};
border-bottom-left-radius: ${borderRadius};
}
&:last-of-type {
border-top-right-radius: ${borderRadius};
border-bottom-right-radius: ${borderRadius};
}
& + & {
margin-left: -1px;
}
`;
type RadioButtonProps = {
selected?: boolean;
title?: string;
value?: string | number | symbol;
};
const RadioButton: FunctionComponent<RadioButtonProps & WithStyled> = ({
className,
value,
selected,
title,
children
}) => {
const groupValue = useContext(ValueContext);
const onChange = useContext(EventContext);
const onClick = () => {
if (value && onChange && groupValue !== value) {
onChange(value);
}
};
return (
<Button className={className} title={title} selected={groupValue === value || selected} onClick={onClick}>
{children}
</Button>
);
};
export default RadioButton;
import React, {FunctionComponent, createContext, useState, useCallback} from 'react';
import styled from 'styled-components';
import {WithStyled} from '~/utils/style';
const Wrapper = styled.div`
display: inline-flex;
> * {
flex-shrink: 0;
align-items: flex-start;
}
`;
export const ValueContext = createContext(null as string | number | symbol | undefined | null);
// eslint-disable-next-line @typescript-eslint/no-empty-function
export const EventContext = createContext((() => {}) as ((value: string | number | symbol) => unknown) | undefined);
type RadioGroupProps = {
value?: string | number | symbol;
onChange?: (value: string | number | symbol) => unknown;
};
const RadioGroup: FunctionComponent<RadioGroupProps & WithStyled> = ({value, onChange, children, className}) => {
const [selected, setSelected] = useState(value);
const onSelectedChange = useCallback(
(value: string | number | symbol) => {
setSelected(value);
onChange?.(value);
},
[onChange]
);
return (
<EventContext.Provider value={onSelectedChange}>
<ValueContext.Provider value={selected}>
<Wrapper className={className}>{children}</Wrapper>
</ValueContext.Provider>
</EventContext.Provider>
);
};
export default RadioGroup;
import React, {FunctionComponent} from 'react';
import styled from 'styled-components';
import {WithStyled, em, size, half, math, primaryColor, textLighterColor, backgroundColor} from '~/utils/style';
import InputRange, {Range} from 'react-input-range';
const height = em(20);
const railHeight = em(4);
const thumbSize = em(12);
const railColor = '#DBDEEB';
const Wrapper = styled.div<{disabled?: boolean}>`
height: ${height};
.input-range {
height: 100%;
position: relative;
&__label {
display: none;
}
&__track {
cursor: ${props => (props.disabled ? 'not-allowed' : 'pointer')};
&--background {
height: ${railHeight};
width: 100%;
position: absolute;
top: 50%;
margin-top: -${half(railHeight)};
background-color: ${railColor};
border-radius: ${half(railHeight)};
}
&--active {
height: ${railHeight};
position: absolute;
background-color: ${props => (props.disabled ? textLighterColor : primaryColor)};
border-radius: ${half(railHeight)};
outline: none;
}
}
&__slider-container {
top: -${math(`(${thumbSize} - ${railHeight}) / 2`)};
margin-left: -${half(thumbSize)};
}
&__slider {
${size(thumbSize)}
border-radius: ${half(thumbSize)};
border: ${em(3)} solid ${props => (props.disabled ? textLighterColor : primaryColor)};
background-color: ${backgroundColor};
}
}
`;
type RangeSliderProps = {
min?: number;
max?: number;
step?: number;
value?: number;
disabled?: boolean;
onChange?: (value: number) => unknown;
onChangeComplete?: () => unknown;
};
const RangeSlider: FunctionComponent<RangeSliderProps & WithStyled> = ({
onChange,
onChangeComplete,
className,
min,
max,
step,
value,
disabled
}) => {
const onChangeRange = (range: number | Range) => onChange?.(range as number);
return (
<Wrapper className={className} disabled={disabled}>
<InputRange
minValue={min}
maxValue={max}
// there may be a warning when `minValue` equals `maxValue` though `allSameValue` is set to TRUE
// this is a bug of react-input-range
// ignore for now
allowSameValues
step={step}
disabled={disabled}
value={value as number}
onChange={onChangeRange}
onChangeComplete={() => onChangeComplete?.()}
/>
</Wrapper>
);
};
RangeSlider.defaultProps = {
min: 0,
max: 100,
step: 1,
value: 50
};
export default RangeSlider;
import React, {FunctionComponent} from 'react';
import styled from 'styled-components';
import {rem} from '~/utils/style';
import {useTranslation} from '~/utils/i18n';
import Select, {SelectValueType} from '~/components/Select';
const Title = styled.div`
font-size: ${rem(16)};
line-height: ${rem(16)};
font-weight: 700;
margin-bottom: ${rem(10)};
`;
type RunSelectProps = {
runs?: string[];
value?: string[];
onChange?: (value: string[]) => unknown;
};
const RunSelect: FunctionComponent<RunSelectProps> = ({runs, value, onChange}) => {
const {t} = useTranslation('common');
return (
<>
<Title>{t('select-runs')}</Title>
<Select
multiple
list={runs}
value={value}
onChange={(value: SelectValueType | SelectValueType[]) => onChange?.(value as string[])}
/>
</>
);
};
export default RunSelect;
import React, {FunctionComponent, useState, useCallback} from 'react';
import styled from 'styled-components';
import {rem} from '~/utils/style';
import {useTranslation} from '~/utils/i18n';
import Button from '~/components/Button';
const StyledButton = styled(Button)`
margin-top: ${rem(40)};
width: 100%;
text-transform: uppercase;
`;
type RunningToggleProps = {
running?: boolean;
onToggle?: (running: boolean) => unknown;
};
const RunningToggle: FunctionComponent<RunningToggleProps> = ({running, onToggle}) => {
const {t} = useTranslation('common');
const [state, setState] = useState(!!running);
const onClick = useCallback(() => {
setState(s => !s);
onToggle?.(state);
}, [state, onToggle]);
return <StyledButton onClick={onClick}>{t(state ? 'running' : 'stopped')}</StyledButton>;
};
export default RunningToggle;
import React, {FunctionComponent, useState} from 'react';
import styled from 'styled-components';
import useSWR from 'swr';
import {useTranslation} from '~/utils/i18n';
import {em, size, ellipsis, textLightColor} from '~/utils/style';
import StepSlider from '~/components/StepSlider';
import Image from '~/components/Image';
const width = em(430);
const height = em(384);
const Wrapper = styled.div`
${size(height, width)}
padding: ${em(20)};
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: stretch;
> * {
flex-grow: 0;
flex-shrink: 0;
}
`;
const Title = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: ${em(20)};
> h4 {
font-size: ${em(16)};
font-weight: 700;
flex-shrink: 1;
flex-grow: 1;
padding: 0;
margin: 0;
${ellipsis()}
}
> span {
font-size: ${em(14)};
flex-shrink: 0;
flex-grow: 0;
color: ${textLightColor};
}
`;
const Container = styled.div<{fit?: boolean}>`
flex-grow: 1;
flex-shrink: 1;
margin-top: ${em(20)};
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
> img {
width: 100%;
height: 100%;
object-fit: ${props => (props.fit ? 'contain' : 'scale-down')};
flex-shrink: 1;
}
`;
type ImageData = {
step: number;
wallTime: number;
};
type SampleChartProps = {
run: string;
tag: string;
fit?: boolean;
running?: boolean;
};
const getImageUrl = (index: number, run: string, tag: string, wallTime: number): string =>
`${process.env.API_URL}/images/individualImage?sample=0&index=${index}&ts=${wallTime}&run=${encodeURIComponent(
run
)}&tag=${encodeURIComponent(tag)}`;
const SampleChart: FunctionComponent<SampleChartProps> = ({run, tag, fit, running}) => {
const {t} = useTranslation('common');
const {data, error} = useSWR<ImageData[]>(
`/images/images?run=${encodeURIComponent(run)}&tag=${encodeURIComponent(tag)}`,
{
refreshInterval: running ? 15 * 1000 : 0
}
);
const [step, setStep] = useState(0);
return (
<Wrapper>
<Title>
<h4>{tag}</h4>
<span>{run}</span>
</Title>
<StepSlider value={step} steps={data?.map(item => item.step) ?? []} onChange={setStep} />
<Container fit={fit}>
{!data && !error && <span>{t('loading')}</span>}
{data && !error && <Image src={getImageUrl(step, run, tag, data[step].wallTime)} />}
</Container>
</Wrapper>
);
};
export default SampleChart;
import React, {FunctionComponent, useCallback, useMemo} from 'react';
import styled from 'styled-components';
import useSWR from 'swr';
import compact from 'lodash/compact';
import minBy from 'lodash/minBy';
import maxBy from 'lodash/maxBy';
import sortBy from 'lodash/sortBy';
import {EChartOption} from 'echarts';
import {em, size} from '~/utils/style';
import {useTranslation} from '~/utils/i18n';
import {cycleFetcher} from '~/utils/fetch';
import {transform, range, tooltip, TooltipData} from '~/utils/scalars';
import * as chart from '~/utils/chart';
import LineChart from '~/components/LineChart';
const width = em(430);
const height = em(320);
const StyledLineChart = styled(LineChart)`
${size(height, width)}
`;
export const xAxisMap = {
step: 1,
relative: 4,
wall: 0
};
export const sortingMethodMap = {
default: null,
descending: (points: TooltipData[]) => sortBy(points, point => point.item[3]).reverse(),
ascending: (points: TooltipData[]) => sortBy(points, point => point.item[3]),
// Compare other ponts width the trigger point, caculate the nearest sort.
nearest: (points: TooltipData[], data: number[]) => sortBy(points, point => point.item[3] - data[2])
};
type DataSet = number[][];
type ScalarChartProps = {
runs: string[];
tag: string;
smoothing: number;
xAxis: keyof typeof xAxisMap;
sortingMethod: keyof typeof sortingMethodMap;
outlier?: boolean;
running?: boolean;
};
const ScalarChart: FunctionComponent<ScalarChartProps> = ({
runs,
tag,
smoothing,
xAxis,
sortingMethod,
outlier,
running
}) => {
const {t} = useTranslation('scalars');
// TODO: maybe we can create a custom hook here
const {data: datasets, error} = useSWR<DataSet[]>(
runs.map(run => `/scalars/scalars?run=${encodeURIComponent(run)}&tag=${encodeURIComponent(tag)}`),
(...urls) => cycleFetcher(urls),
{
refreshInterval: running ? 15 * 1000 : 0
}
);
const type = xAxis === 'wall' ? 'time' : 'value';
const smooth = xAxis !== 'wall';
const smoothedDatasets = useMemo(() => datasets?.map(dataset => transform(dataset, smoothing)), [
datasets,
smoothing
]);
const data = useMemo(
() =>
smoothedDatasets
?.map((dataset, i) => {
// smoothed data:
// [0] wall time
// [1] step
// [2] orginal value
// [3] smoothed value
// [4] relative
const name = runs[i];
return [
{
name,
z: i,
lineStyle: {
width: chart.series.lineStyle.width,
opacity: 0.5
},
data: dataset,
encode: {
x: [xAxisMap[xAxis]],
y: [2]
},
smooth
},
{
name,
z: runs.length + i,
data: dataset,
encode: {
x: [xAxisMap[xAxis]],
y: [3]
},
smooth
}
];
})
.flat(),
[runs, smooth, smoothedDatasets, xAxis]
);
const yRange = useMemo(() => {
const ranges = compact(smoothedDatasets?.map(dataset => range(dataset, outlier)));
const min = minBy(ranges, range => range.min)?.min ?? 0;
const max = maxBy(ranges, range => range.max)?.max ?? 0;
if (!(min === 0 && max === 0)) {
return {
min: min > 0 ? min * 0.9 : min * 1.1,
max: max > 0 ? max * 1.1 : max * 0.9
};
}
}, [outlier, 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 =
smoothedDatasets?.map((series, index) => {
let nearestItem;
if (step === 0) {
nearestItem = series[0];
} else {
for (let i = 0; i < series.length; i++) {
const item = series[i];
if (item[1] === step) {
nearestItem = item;
break;
}
if (item[1] > step) {
nearestItem = series[i - 1 >= 0 ? i - 1 : 0];
break;
}
if (!nearestItem) {
nearestItem = series[series.length - 1];
}
}
}
return {
run: runs[index],
item: nearestItem || []
};
}) ?? [];
const sort = sortingMethodMap[sortingMethod];
return tooltip(sort ? sort(points, data) : points);
},
[smoothedDatasets, runs, sortingMethod]
);
return (
<StyledLineChart
title={tag}
legend={runs}
xAxis={t(`x-axis-value.${xAxis}`)}
yRange={yRange}
type={type}
tooltip={formatter}
data={data}
loading={!datasets && !error}
/>
);
};
export default ScalarChart;
import React, {FunctionComponent, useEffect} from 'react';
import {EChartOption} from 'echarts';
import {WithStyled, primaryColor} from '~/utils/style';
import useECharts from '~/hooks/useECharts';
import {Dimension} from '~/types';
type ScatterChartProps = {
data?: ([number, number] | [number, number, number])[];
labels?: string[];
loading?: boolean;
dimension?: Dimension;
};
const ScatterChart: FunctionComponent<ScatterChartProps & WithStyled> = ({
data,
labels,
loading,
dimension,
className
}) => {
const [ref, echart] = useECharts<HTMLDivElement>(!!loading);
useEffect(() => {
if (process.browser) {
(async () => {
const is3D = dimension === '3d';
if (is3D) {
await import('echarts-gl');
}
echart.current?.setOption(
{
...(is3D
? {
yAxis3D: {},
xAxis3D: {},
zAxis3D: {},
grid3D: {}
}
: {
xAxis: {},
yAxis: {}
}),
series: [
{
data,
label: {
show: true,
position: 'top',
formatter: (
params: EChartOption.Tooltip.Format | EChartOption.Tooltip.Format[]
) => {
if (!labels) {
return '';
}
const {dataIndex: index} = Array.isArray(params) ? params[0] : params;
if (index == null) {
return '';
}
return labels[index] ?? '';
}
},
symbolSize: 12,
itemStyle: {
color: primaryColor
},
type: is3D ? 'scatter3D' : 'scatter'
}
]
},
{notMerge: true}
);
})();
}
}, [data, labels, dimension, echart]);
return <div className={className} ref={ref}></div>;
};
export default ScatterChart;
import React, {FunctionComponent} from 'react';
import styled from 'styled-components';
import {WithStyled, em, math, textLighterColor} from '~/utils/style';
import Input, {padding, InputProps} from '~/components/Input';
import Icon from '~/components/Icon';
const iconSize = em(16);
const StyledInput = styled(Input)`
padding-right: ${math(`${iconSize} + ${padding} * 2`)};
width: 100%;
`;
const Control = styled.div`
background-color: #fff;
position: relative;
`;
const SearchIcon = styled(Icon)`
font-size: ${iconSize};
display: block;
position: absolute;
top: ${padding};
right: ${padding};
pointer-events: none;
color: ${textLighterColor};
`;
const SearchInput: FunctionComponent<InputProps & WithStyled> = ({className, ...props}) => (
<Control className={className}>
<StyledInput {...props} />
<SearchIcon type="search" />
</Control>
);
export default SearchInput;
import React, {FunctionComponent, useState, useCallback} from 'react';
import styled from 'styled-components';
import without from 'lodash/without';
import useClickOutside from '~/hooks/useClickOutside';
import {useTranslation} from '~/utils/i18n';
import {
WithStyled,
em,
backgroundColor,
backgroundFocusedColor,
textLighterColor,
selectedColor,
borderColor,
borderFocusedColor,
borderRadius,
duration,
easing,
ellipsis,
transitions,
css
} from '~/utils/style';
import Checkbox from '~/components/Checkbox';
import Icon from '~/components/Icon';
export const padding = em(10);
export const height = em(36);
const minWidth = em(160);
// prettier-ignore
const Wrapper = styled.div<{opened?: boolean}>`
height: ${height};
line-height: calc(${height} - 2px);
min-width: ${minWidth};
display: inline-block;
position: relative;
border: 1px solid ${borderColor};
/* eslint-disable-next-line */
border-radius: ${borderRadius} ${borderRadius} ${props => (props.opened ? '0 0' : `${borderRadius} ${borderRadius}`)};
transition: border-color ${duration} ${easing};
background-color: ${backgroundColor};
&:hover {
border-color: ${borderFocusedColor};
}
`;
const Trigger = styled.div<{selected?: boolean}>`
padding: ${padding};
display: inline-flex;
width: 100%;
height: 100%;
justify-content: space-between;
align-items: center;
cursor: pointer;
${props => (props.selected ? '' : `color: ${textLighterColor}`)}
`;
const TriggerIcon = styled(Icon)<{opened?: boolean}>`
width: ${em(14)};
height: ${em(14)};
text-align: center;
display: block;
flex-shrink: 0;
transform: rotate(${props => (props.opened ? '180' : '0')}deg) scale(${10 / 14});
transition: transform ${duration} ${easing};
`;
const Label = styled.span`
flex-grow: 1;
`;
const List = styled.div<{opened?: boolean; empty?: boolean}>`
position: absolute;
top: 100%;
width: calc(100% + 2px);
left: -1px;
padding: ${padding} 0;
border: inherit;
border-top-color: ${borderColor};
border-radius: 0 0 ${borderRadius} ${borderRadius};
display: ${props => (props.opened ? 'block' : 'none')};
z-index: 9999;
line-height: 1;
background-color: inherit;
box-shadow: 0 5px 6px 0 rgba(0, 0, 0, 0.05);
${props =>
props.empty
? `
color: ${textLighterColor};
text-align: center;
`
: ''}
`;
const listItem = css`
display: block;
cursor: pointer;
padding: 0 ${padding};
height: ${height};
line-height: ${height};
width: 100%;
${transitions(['color', 'background-color'], `${duration} ${easing}`)}
&:hover {
background-color: ${backgroundFocusedColor};
}
`;
const ListItem = styled.div<{selected?: boolean}>`
${ellipsis()}
${listItem}
${props => (props.selected ? `color: ${selectedColor};` : '')}
`;
const MultipleListItem = styled(Checkbox)<{selected?: boolean}>`
${listItem}
display: flex;
align-items: center;
`;
export type SelectValueType = string | number | symbol;
type SelectListItem<T> = {
value: T;
label: string;
};
type SelectProps<T> = {
list?: (SelectListItem<T> | string)[];
value?: T | T[];
onChange?: (value: T | T[]) => unknown;
multiple?: boolean;
placeholder?: string;
};
const Select: FunctionComponent<SelectProps<SelectValueType> & WithStyled> = ({
list: propList,
value: propValue,
placeholder,
multiple,
className,
onChange
}) => {
const {t} = useTranslation('common');
const [isOpened, setIsOpened] = useState(false);
const toggleOpened = useCallback(() => setIsOpened(!isOpened), [isOpened]);
const setIsOpenedFalse = useCallback(() => setIsOpened(false), []);
const [value, setValue] = useState(multiple ? (Array.isArray(propValue) ? propValue : []) : propValue);
const isSelected = !!(multiple ? value && (value as SelectValueType[]).length !== 0 : (value as SelectValueType));
const changeValue = (mutateValue: SelectValueType, checked?: boolean) => {
let newValue;
if (multiple) {
newValue = value as SelectValueType[];
if (checked) {
if (!newValue.includes(mutateValue)) {
newValue = [...newValue, mutateValue];
}
} else {
if (newValue.includes(mutateValue)) {
newValue = without(newValue, mutateValue);
}
}
} else {
newValue = mutateValue;
}
setValue(newValue);
onChange?.(newValue);
if (!multiple) {
setIsOpenedFalse();
}
};
const ref = useClickOutside(setIsOpenedFalse);
const list = propList?.map(item => ('string' === typeof item ? {value: item, label: item} : item)) ?? [];
const isListEmpty = list.length === 0;
const findLabelByValue = (v: SelectValueType) => list.find(item => item.value === v)?.label ?? '';
const label = isSelected
? multiple
? (value as SelectValueType[]).map(findLabelByValue).join(' / ')
: findLabelByValue(value as SelectValueType)
: placeholder || t('select');
return (
<Wrapper ref={ref} opened={isOpened} className={className}>
<Trigger onClick={toggleOpened} selected={isSelected} title={isSelected && label ? String(label) : ''}>
<Label>{label}</Label>
<TriggerIcon opened={isOpened} type="chevron-down" />
</Trigger>
<List opened={isOpened} empty={isListEmpty}>
{isListEmpty
? t('empty')
: list.map((item, index) => {
if (multiple) {
return (
<MultipleListItem
value={(value as SelectValueType[]).includes(item.value)}
key={index}
size="small"
onChange={checked => changeValue(item.value, checked)}
>
{item.label}
</MultipleListItem>
);
}
return (
<ListItem
selected={item.value === value}
key={index}
onClick={() => changeValue(item.value)}
>
{item.label}
</ListItem>
);
})}
</List>
</Wrapper>
);
};
export default Select;
import React, {FunctionComponent, useState} from 'react';
import styled from 'styled-components';
import {useTranslation} from '~/utils/i18n';
import Field from '~/components/Field';
import RangeSlider from '~/components/RangeSlider';
const FullWidthRangeSlider = styled(RangeSlider)`
width: 100%;
`;
type SmoothingSliderProps = {
value: number;
onChange?: (value: number) => unknown;
};
const SmoothingSlider: FunctionComponent<SmoothingSliderProps> = ({onChange, value}) => {
const {t} = useTranslation('scalars');
const [smoothing, setSmoothing] = useState(value);
return (
<Field label={`${t('smoothing')}: ${Math.round(smoothing * 100) / 100}`}>
<FullWidthRangeSlider
min={0}
max={0.99}
step={0.01}
value={smoothing}
onChange={setSmoothing}
onChangeComplete={() => onChange?.(smoothing)}
/>
</Field>
);
};
export default SmoothingSlider;
import React, {FunctionComponent, useState} from 'react';
import styled from 'styled-components';
import {em, textLightColor} from '~/utils/style';
import {useTranslation} from '~/utils/i18n';
import RangeSlider from '~/components/RangeSlider';
const Label = styled.div`
color: ${textLightColor};
font-size: ${em(12)};
margin-bottom: ${em(5)};
`;
const FullWidthRangeSlider = styled(RangeSlider)`
width: 100%;
`;
type StepSliderProps = {
value: number;
steps: number[];
onChange?: (value: number) => unknown;
};
const StepSlider: FunctionComponent<StepSliderProps> = ({onChange, value, steps}) => {
const {t} = useTranslation('samples');
const [step, setStep] = useState(value);
return (
<>
<Label>{`${t('step')}: ${steps[step]}`}</Label>
<FullWidthRangeSlider
min={0}
max={steps.length ? steps.length - 1 : 0}
step={1}
value={step}
onChange={setStep}
onChangeComplete={() => onChange?.(step)}
/>
</>
);
};
export default StepSlider;
import React, {FunctionComponent} from 'react';
import styled from 'styled-components';
import {
WithStyled,
em,
primaryColor,
lightColor,
lightFocusedColor,
lightActiveColor,
duration,
easing,
math,
transitions
} from '~/utils/style';
const height = em(36);
const Span = styled.span<{active?: boolean}>`
padding: 0 ${em(16)};
height: ${height};
line-height: ${height};
display: inline-block;
border-radius: ${math(`${height} / 2`)};
${transitions(['color', 'background-color'], `${duration} ${easing}`)}
color: ${prop => (prop.active ? '#FFF' : primaryColor)};
background-color: ${prop => (prop.active ? primaryColor : lightColor)};
cursor: pointer;
&:hover {
background-color: ${prop => (prop.active ? primaryColor : lightFocusedColor)};
}
&:active {
background-color: ${prop => (prop.active ? primaryColor : lightActiveColor)};
}
`;
type TagProps = {
title?: string;
active?: boolean;
onClick?: () => void;
};
const Tag: FunctionComponent<TagProps & WithStyled> = ({children, ...props}) => <Span {...props}>{children}</Span>;
export default Tag;
import React, {FunctionComponent, useState, useCallback} from 'react';
import styled from 'styled-components';
import groupBy from 'lodash/groupBy';
import sortBy from 'lodash/sortBy';
import {useTranslation} from '~/utils/i18n';
import {rem, math, ellipsis} from '~/utils/style';
import SearchInput from '~/components/SearchInput';
import Tag from '~/components/Tag';
import {Tag as TagType} from '~/types';
const margin = rem(16);
const Wrapper = styled.div`
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap: wrap;
`;
const Search = styled(SearchInput)`
width: ${rem(280)};
margin: 0 ${math(`${rem(5)} + ${margin}`)} ${margin} 0;
`;
const SearchTag = styled(Tag)`
margin: 0 ${margin} ${margin} 0;
vertical-align: middle;
`;
const SearchTagLabel = styled.span`
${ellipsis(rem(120))}
vertical-align: middle;
`;
type TagFilterProps = {
value?: string;
tags?: TagType[];
onChange?: (value: TagType[]) => unknown;
};
const TagFilter: FunctionComponent<TagFilterProps> = ({value, tags: propTags, onChange}) => {
type NonNullTags = NonNullable<typeof propTags>;
const {t} = useTranslation('common');
const tagGroups = sortBy(
Object.entries(groupBy<TagType>(propTags || [], tag => tag.label.split('/')[0])).map(([label, tags]) => ({
label,
tags
})),
tag => tag.label
);
const [matchedCount, setMatchedCount] = useState(propTags?.length ?? 0);
const [inputValue, setInputValue] = useState(value || '');
const [selectedValue, setSelectedValue] = useState('');
const hasSelectedValue = selectedValue !== '';
const allText = inputValue || t('all');
const onInputChange = useCallback(
(value: string) => {
setInputValue(value);
setSelectedValue('');
try {
const pattern = new RegExp(value);
const matchedTags = propTags?.filter(tag => pattern.test(tag.label)) ?? [];
setMatchedCount(matchedTags.length);
onChange?.(matchedTags);
} catch {
setMatchedCount(0);
}
},
[propTags, onChange]
);
const onClickTag = useCallback(
({label, tags}: {label: string; tags: NonNullTags}) => {
setSelectedValue(label);
onChange?.(tags);
},
[onChange]
);
const onClickAllTag = useCallback(() => {
setSelectedValue('');
onInputChange(inputValue);
}, [inputValue, onInputChange]);
return (
<Wrapper>
<Search placeholder={t('searchTagPlaceholder')} rounded onChange={onInputChange}></Search>
<SearchTag active={!hasSelectedValue} onClick={onClickAllTag} title={allText}>
<SearchTagLabel>{allText}</SearchTagLabel> ({inputValue ? matchedCount : propTags?.length ?? 0})
</SearchTag>
{tagGroups.map(group => (
<SearchTag
active={hasSelectedValue && group.label === selectedValue}
onClick={() => onClickTag(group)}
key={group.label}
title={group.label}
>
<SearchTagLabel>{group.label}</SearchTagLabel> ({group.tags.length})
</SearchTag>
))}
</Wrapper>
);
};
TagFilter.defaultProps = {
tags: [] as TagType[]
};
export default TagFilter;
import React, {FunctionComponent} from 'react';
import Head from 'next/head';
const Title: FunctionComponent = ({children: title}) => (
<Head>
<title>
{'string' === typeof title ? `${title} - ` : ''}
{process.env.title}
</title>
</Head>
);
export default Title;
<template>
<div id="app">
<ui-app-menu
selected="{{route}}"
on-item-click="menuChange($event)"
></ui-app-menu>
<div id="content-container" class="visual-dl-content-container">
<div id="app-content" class="visual-dl-app-content">
<div id="content"></div>
</div>
</div>
</div>
</template>
<script>
import AppMenu from './common/component/AppMenu';
import {router} from 'san-router';
import {routeTo} from './common/util/routeTo';
export default {
components: {
'ui-app-menu': AppMenu
},
initData() {
return {
route: 'scalars'
};
},
attached() {
router.start();
let route;
if (location.hash) {
route = /(\#\/)(\w*)([?|&]{0,1})/.exec(location.hash)[2];
this.data.set('route', route);
}
else {
location.hash = '#/scalars';
}
},
menuChange(dataItem) {
routeTo(dataItem.url);
}
};
</script>
<style lang="stylus">
@import './style/variables';
// modify component style for custom theme
.sm-appbar
background $-theme-color
.sm-pagination .page-selector span.current
background $-theme-color
.sm-text-field.has-label .sm-text-field-label
color $-right-font-color
.sm-text-field-input
color $-right-font-color
.sm-text-field-hint.state-show
color $-right-font-color
.sm-text-field
.sm-text-field-line
background $-right-font-color
.sm-text-field-focus-line
background $-theme-color
.sm-form-item .label
color $-right-font-color
.sm-slider-bg
background $-right-font-color
.sm-slider-fill,
.sm-slider-thumb
background $-theme-color
.sm-radio-icon-checked,
.sm-checkbox-icon-checked
color $-theme-color
.sm-radio .sm-radio-wrapper .sm-radio-label,
.sm-checkbox .sm-radio-wrapper .sm-radio-label,
.sm-radio .sm-checkbox-wrapper .sm-radio-label,
.sm-checkbox .sm-checkbox-wrapper .sm-radio-label,
.sm-radio .sm-radio-wrapper .sm-checkbox-label,
.sm-checkbox .sm-radio-wrapper .sm-checkbox-label,
.sm-radio .sm-checkbox-wrapper .sm-checkbox-label,
.sm-checkbox .sm-checkbox-wrapper .sm-checkbox-label
color $-right-font-color
.sm-button.variant-secondery.variant-raised,
.sm-button.variant-secondery.variant-floating
background $-theme-color
+prefix-classes('visual-dl-page-')
.container
padding-right 250px
position relative
background $-left-background-color
.left
width 100%
overflow scroll
border solid 1px $-left-border-clor
background $-left-border-clor
min-height 300px
padding 2%
box-sizing border-box
.right
overflow scroll
width 250px
min-height 300px
position absolute
right 0
top 0
box-sizing border-box
.config-com
color $-right-font-color
</style>
<template>
<div class="visual-dl-app-menu">
<san-appbar title=" ">
<san-menu slot="right">
<san-menu-item
s-for="item in items"
class="{{selected === item.name ? 'sm-menu-item-selected' : ''}}"
on-click="handleItemClick(item)"
title="{{item.title}}" />
</san-menu>
</san-appbar>
</div>
</template>
<script>
import Appbar from 'san-mui/AppBar';
import {MenuItem, Menu} from 'san-mui/Menu';
export default {
components: {
'san-appbar': Appbar,
'san-menu': Menu,
'san-menu-item': MenuItem
},
initData() {
return {
selected: 'scalars',
items: [
{
url: '/scalars',
title: 'SCALARS',
name: 'scalars'
},
{
url: '/images',
title: 'IMAGES',
name: 'images'
},
{
url: '/histograms',
title: 'HISTOGRAMS',
name: 'histograms'
},
{
url: '/graphs',
title: 'GRAPHS',
name: 'graphs'
}
]
};
},
handleItemClick(item) {
this.data.set('selected', item.name);
this.fire('item-click', item);
}
};
</script>
<style lang="stylus">
@import '../../style/variables';
+prefix-classes(prefix)
.app-menu
width 100%
.visual-dl-app-menu
.sm-appbar-title
font-size 24px
flex none
margin-right 50px
.sm-appbar-title
background url('./visualdl-logo.png') no-repeat
background-size cover
width 120px
height 50px
.sm-appbar-right
width 100%
.sm-menu
width 100%
height 100%
display flex
flex-direction row
.sm-menu-item
padding 0 30px
.sm-menu-item-content
color #fff
opacity 0.6
.sm-menu-item:hover
background none
opacity 1
.sm-menu-item-selected
.sm-menu-item-content
color #fff
opacity 1
</style>
<template>
<div class="sm-form-item">
<label class="label">{{label}}</label>
<div class="group-box">
<san-checkbox
s-if="showAll"
class="checkbox-all"
label="全选"
value="all"
on-change="handleAllChange($event)"
checked="{{All}}"
></san-checkbox>
<div class="san-form-check-group">
<san-checkbox
s-for="item in items"
label="{{item.name}}"
value="{{item.value}}"
disabled="{{item.disabled}}"
checked="{{value}}"
on-change="handleChange($event, item)"
></san-checkbox>
</div>
</div>
</div>
</template>
<script>
import Checkbox from 'san-mui/Checkbox';
import {DataTypes} from 'san';
export default {
components: {
'san-checkbox': Checkbox
},
dataTypes: {
items: DataTypes.array,
value: DataTypes.array
},
initData() {
return {
allValue: [],
items: {},
value: [],
All: [],
showAll: false
};
},
computed: {
allValue() {
let items = this.data.get('items') || [];
return items.map(item => item.value);
}
},
attached() {
this.jugdeAll();
this.watch('value', val => {
this.dispatch('UI:form-item-change');
this.jugdeAll();
});
},
handleChange(e, item) {
let checked = e.target.checked;
let valueItem = item.value;
if (checked) {
this.addValue(valueItem);
}
else {
this.removeValue(valueItem);
}
this.dispatch('UI:form-item-change');
this.jugdeAll();
},
handleAllChange(e) {
let checked = e.target.checked;
let allValue = this.data.get('allValue') || [];
if (checked) {
this.data.set('value', allValue.slice());
this.fire('valueChange', allValue.slice());
}
else {
this.data.set('value', []);
this.fire('valueChange', []);
}
this.dispatch('UI:form-item-change');
},
addValue(itemValue) {
let value = this.data.get('value') || [];
if (!value.includes(itemValue)) {
value.push(itemValue);
this.data.set('value', value.slice());
this.fire('valueChange', value.slice());
}
},
removeValue(itemValue) {
let value = this.data.get('value') || [];
if (value.includes(itemValue)) {
let index = value.indexOf(itemValue);
value.splice(index, 1);
this.data.set('value', value.slice());
this.fire('valueChange', value.slice());
}
},
jugdeAll() {
let allValue = this.data.get('allValue') || [];
let value = this.data.get('value') || [];
let isAll = allValue.every(val => value.includes(val));
if (isAll) {
this.data.set('All', ['all']);
}
else {
this.data.set('All', []);
}
}
};
</script>
<template>
<div class="sm-form-item">
<label class="label">{{label}}</label>
<san-drop-down-menu
error="{{error}}"
disabled="{{disabled}}"
value="{=value=}"
maxHeight="{{200}}"
autoWidth="{{false}}">
<san-menu-item
s-for="item in items"
on-change="menuItemChange(item)"
value="{{item.value}}"
label="{{item.name}}" />
</sm-drop-down-menu>
</div>
</template>
<script>
import {DataTypes} from 'san';
import {MenuItem, DropDownMenu} from 'san-mui/Menu';
export default {
components: {
'san-menu-item': MenuItem,
'san-drop-down-menu': DropDownMenu
},
dataTypes: {
value: DataTypes.string,
items: DataTypes.array,
disabled: DataTypes.bool
},
menuItemChange(item) {
let value = item.value;
this.fire('valueChange', value);
this.dispatch('UI:form-item-change');
},
initData() {
return {
value: '',
items: []
};
}
};
</script>
<template>
<div class="visaul-dl-expand-panel">
<h3
class="visaul-dl-expand-head"
on-click="handleHeadClick()"
>
<span>{{title}}</span>
<span class="visaul-dl-expand-head-info">
<ui-icon class="visaul-dl-expand-head-arrow" size="20">{{iconName}}</ui-icon>
<span class="visaul-dl-expand-head-num">({{info}})</span>
</span>
</h3>
<div
s-if="{{isShow}}"
class="visaul-dl-expand-panel-content"
>
<slot></slot>
</div>
</div>
</template>
<script>
import Icon from 'san-mui/Icon';
export default {
components: {
'ui-icon': Icon
},
computed: {
iconName() {
let isShow = this.data.get('isShow');
return isShow ? 'expand_less' : 'expand_more';
}
},
initData() {
return {
isShow: false
};
},
handleHeadClick() {
this.toogleShow();
},
toogleShow() {
let isShow = this.data.get('isShow');
this.data.set('isShow', !isShow);
}
};
</script>
<style lang="stylus">
.visaul-dl-expand-panel
.visaul-dl-expand-head
border solid 1px #ccc
line-height 50px
height 50px
padding 0 20px
cursor pointer
position relative
.visaul-dl-expand-head-info
position absolute
left 90%
.visaul-dl-expand-head-arrow
vertical-align middle
.visaul-dl-expand-head-num
line-height 20px
font-size 12px
font-weight normal
.visaul-dl-expand-panel-content
padding 0 20px
.visaul-dl-expand-panel-content:after
content: "";
clear: both;
display: block;
</style>
<template>
<div class="sm-form-item">
<label class="label">{{label}}</label>
<div class="group-box">
<san-radio
on-change="handleChange($event)"
s-for="item in items"
label="{{item.name}}"
value="{{item.value}}"
disabled="{{item.disabled}}"
checked="{=value=}"
></san-radio>
</div>
</div>
</template>
<script>
import Radio from 'san-mui/Radio';
import {DataTypes} from 'san';
export default {
components: {
'san-radio': Radio
},
dataTypes: {
items: DataTypes.array,
value: DataTypes.string
},
initData() {
return {
items: {},
value: [],
label: ''
};
},
attached(value) {
this.watch('value', val => {
this.dispatch('UI:form-item-change', val);
});
},
handleChange(val) {
this.fire('valueChange', val);
}
};
</script>
\ No newline at end of file
<template>
<div class="sm-form-item">
<label class="label">{{label}}</label>
<div class="input-box">
<san-slider
on-change="handleSlideChange($event)"
value="{{value}}"
min="{{min}}"
max="{{max}}"
step="{{step}}"
/>
<span>{{value}}</span>
</div>
</div>
</template>
<script>
import Slider from 'san-mui/Slider';
import InputNumber from 'san-mui/InputNumber';
import {debounce} from 'lodash';
export default {
components: {
'san-slider': Slider,
'san-input-number': InputNumber
},
initData() {
return {
value: '0',
label: '',
max: 0,
min: 0,
step: 0,
debounce: 400
};
},
inited() {
let debounceTime = this.data.get('debounce');
this.handleSlideChange = debounce(val => {
this.data.set('value', val.toString());
}, debounceTime);
this.handlerChange = debounce(e => {
this.data.set('value', e.target.value);
}, debounceTime);
}
};
</script>
<style lang="stylus">
.sm-form-item
.input-box
margin-top 10px
.sm-slider
display inline-block
margin-right 20px
margin-top 4px
float left
width 160px
.sm-slider-thumb
transform translate(0, -50%)
.sm-inputNumber
width 130px
display inline-block
</style>
<template>
<div class="visual-dl-page-container">
<div class="visual-dl-page-left">
<ui-chart
filtScreen="{{filtScreen}}"
download="{{download}}"
scale="{{config.scale}}"
></ui-chart>
</div>
<div class="visual-dl-page-right">
<div class="visual-dl-page-config-container">
<ui-config
runsItems="{{runsItems}}"
config="{=config=}"
on-fitScreen="handleFitScreen"
on-download="handleDownload"
></ui-config>
</div>
</div>
</div>
</template>
<script>
import autoAdjustHeight from '../common/util/autoAdjustHeight';
import config from './ui/config';
import chart from './ui/chart';
export default {
components: {
'ui-config': config,
'ui-chart': chart
},
initData() {
return {
runsArray: [],
tags: [],
config: {
groupNameReg: '.*',
horizontal: 'step',
chartType: 'offset',
runs: [],
running: true,
scale: 0.5
}
};
},
attached() {
autoAdjustHeight();
},
handleFitScreen() {
this.data.set('filtScreen', {
filtScreen: true
});
this.data.set('config.scale', 0.5);
},
handleDownload() {
this.data.set('download', {
filtScreen: true
});
}
};
</script>
<style lang="stylus">
</style>
import {router} from 'san-router';
import Graph from './Graph';
router.add({
target: '#content',
rule: '/graphs',
Component: Graph,
});
<template>
<div class="visual-dl-graph-charts">
<div s-if="graphUrl" class="visual-dl-img-box">
<div class="small-img-box">
<img class="small-img" width="30" src="{{graphUrl}}" />
<div class="screen-handler"></div>
</div>
<img class="draggable" width="{{computedWidth}}" src="{{graphUrl}}" />
</div>
</div>
</template>
<script>
// libs
import echarts from 'echarts';
import {
dragMovelHandler,
tansformElement,
relativeMove
} from './dragHelper';
// service
import {getPluginGraphsGraph} from '../../service';
// https://github.com/taye/interact.js
import interact from 'interactjs';
export default {
computed: {
computedWidth() {
let scale = this.data.get('scale');
return Math.floor(scale * 2 * 700);
}
},
initData() {
return {
width: 800,
height: 600,
data: [
{
name: 'train',
value: []
}
]
};
},
inited() {
this.watch('filtScreen', filtScreen => {
this.clearDragedTransform(this.getBigImgEl());
this.clearDragedTransform(this.getSmallImgDragHandler());
});
this.watch('download', download => {
let aEl = document.createElement('a');
aEl.href = this.data.get('graphUrl');
aEl.download = 'graph.png';
aEl.click();
});
},
attached() {
this.getOriginChartsData();
},
createChart() {
let el = this.el.getElementsByClassName('visual-dl-chart-box')[0];
this.myChart = echarts.init(el);
},
initChartOption(data) {
this.setChartOptions(data);
},
setChartOptions(data) {
this.myChart.setOption(data);
},
getOriginChartsData() {
getPluginGraphsGraph().then(({status, data}) => {
if (+status === 0 && data.url) {
this.data.set('graphUrl', data.url);
this.addDragEventForImg();
}
});
},
clearDragedTransform(dragImgEl) {
dragImgEl.style.transform = 'none';
dragImgEl.setAttribute('data-x', 0);
dragImgEl.setAttribute('data-y', 0);
},
getBigImgEl() {
return this.el.getElementsByClassName('draggable')[0];
},
getSmallImgEl() {
return this.el.getElementsByClassName('small-img')[0];
},
getSmallImgDragHandler() {
return this.el.getElementsByClassName('screen-handler')[0];
},
addDragEventForImg() {
let that = this;
// target elements with the "draggable" class
interact('.draggable').draggable({
// enable inertial throwing
inertia: true,
autoScroll: true,
// call this function on every dragmove event
onmove(event) {
dragMovelHandler(event, (target, x, y) => {
tansformElement(target, x, y);
// compute the proportional value
let triggerEl = that.getBigImgEl();
let relativeEl = that.getSmallImgDragHandler();
relativeMove({triggerEl, x, y}, relativeEl);
});
}
});
interact('.screen-handler').draggable({
// enable inertial throwing
inertia: true,
autoScroll: true,
restrict: {
restriction: 'parent',
endOnly: false,
elementRect: {
top: 0,
left: 0,
bottom: 1,
right: 1
}
},
// call this function on every dragmove event
onmove(event) {
dragMovelHandler(event, (target, x, y) => {
tansformElement(target, x, y);
// compute the proportional value
let triggerEl = that.getSmallImgEl();
let relativeEl = that.getBigImgEl();
relativeMove({triggerEl, x, y}, relativeEl);
});
}
});
}
};
</script>
<style lang="stylus">
.visual-dl-graph-charts
width 90%
margin 0 auto
margin-bottom 20px
.visual-dl-chart-box
height 600px
.visual-dl-img-box
border solid 1px #e4e4e4
position relative
background #f0f0f0
overflow hidden
img
box-sizing border-box
margin 0 auto
display block
.small-img-box
width 30px
box-sizing border-box
position absolute
right 0
top 0
border-left solid 1px #e4e4e4
border-bottom solid 1px #e4e4e4
background #f0f0f0
z-index 1
.screen-handler
box-sizing border-box
position absolute
width 30px
height 20px
border solid 1px #666
top 0
left -1px
</style>
<template>
<div class="visual-dl-graph-config-com">
<ui-button
class="visual-dl-graph-config-button"
on-click="handleFitScreen"
variants="raised secondery">
<ui-icon style="margin-right: 6px">fullscreen</ui-icon>
Fit &nbsp; to &nbsp; screen
</ui-button>
<ui-button
class="visual-dl-graph-config-button"
on-click="handleDownload"
variants="raised secondery">
<ui-icon style="margin-right: 6px">file_download</ui-icon>
Download image
</ui-button>
<ui-slider
label="Scale"
value="{=config.scale=}"
min="{{0.1}}"
max="{{1}}"
step="{{0.1}}"
/>
</div>
</template>
<script>
import Button from 'san-mui/Button';
import Icon from 'san-mui/Icon';
import Slider from '../../common/component/Slider';
import DropDownMenu from '../../common/component/DropDownMenu';
export default {
components: {
'ui-dropdown-menu': DropDownMenu,
'ui-button': Button,
'ui-icon': Icon,
'ui-slider': Slider
},
initData() {
return {
config: {
groupName: 'aa',
isActualImageSize: [],
runs: [],
scale: 0.5
},
sessionItems: [
{
name: 'step1',
value: 'step1'
},
{
name: 'step2',
value: 'step2'
},
{
name: 'step3',
value: 'step3'
}
]
};
},
handleFitScreen() {
this.fire('fitScreen');
},
handleDownload() {
this.fire('download');
}
};
</script>
<style lang="stylus">
@import '../../style/variables';
+prefix-classes('visual-dl-graph-')
.config-com
width 90%
margin 20px auto
color $-right-font-color
.config-button
width 200px
margin-top 20px
.visual-dl-graph-config-com
.sm-icon
width 36px
height 26px
</style>
<template>
<div class="visual-dl-page-container">
<div class="visual-dl-page-left">
<ui-chart-page
expand="{{true}}"
config="{{config}}"
runsItems="{{runsItems}}"
tagList="{{filteredTagsList}}"
title="Tags matching {{config.groupNameReg}}"
></ui-chart-page>
<ui-chart-page
s-for="item in groupedTags"
config="{{config}}"
runsItems="{{runsItems}}"
tagList="{{item.tags}}"
title="{{item.group}}"
></ui-chart-page>
</div>
<div class="visual-dl-page-right">
<div class="visual-dl-page-config-container">
<ui-config
runsItems="{{runsItems}}"
config="{=config=}"
></ui-config>
</div>
</div>
</div>
</template>
<script>
import {getPluginHistogramsTags, getRuns} from '../service';
import config from './ui/config';
import chartPage from './ui/chartPage';
import {debounce, flatten, uniq} from 'lodash';
import autoAdjustHeight from '../common/util/autoAdjustHeight';
export default {
components: {
'ui-config': config,
'ui-chart-page': chartPage
},
computed: {
runsItems() {
let runsArray = this.data.get('runsArray') || [];
return runsArray.map(item => {
return {
name: item,
value: item
};
});
},
tagsList() {
let tags = this.data.get('tags');
let runs = Object.keys(tags);
let tagsArray = runs.map(run => Object.keys(tags[run]));
let allUniqTags = uniq(flatten(tagsArray));
// get the data for every chart
return allUniqTags.map(tag => {
let tagList = runs.map(run => {
return {
run,
tag: tags[run][tag]
};
}).filter(item => item.tag !== undefined);
return {
tagList,
tag,
group: tag.split('/')[0]
};
});
},
groupedTags() {
let tagsList = this.data.get('tagsList') || [];
// put data in group
let groupData = {};
tagsList.forEach(item => {
let group = item.group;
if (groupData[group] === undefined) {
groupData[group] = [];
groupData[group].push(item);
}
else {
groupData[group].push(item);
}
});
// to array
let groups = Object.keys(groupData);
return groups.map(group => {
return {
group,
tags: groupData[group]
};
});
}
},
initData() {
return {
runsArray: [],
tags: [],
config: {
groupNameReg: '.*',
horizontal: 'step',
chartType: 'offset',
runs: [],
running: true
}
};
},
inited() {
getPluginHistogramsTags().then(({errno, data}) => {
this.data.set('tags', data);
// filter when inited
let groupNameReg = this.data.get('config.groupNameReg');
this.filterTagsList(groupNameReg);
});
getRuns().then(({errno, data}) => {
this.data.set('runsArray', data);
this.data.set('config.runs', data);
});
// Need debounce, can't use computed
this.watch('config.groupNameReg', debounce(this.filterTagsList, 300));
},
attached() {
autoAdjustHeight();
},
filterTagsList(groupNameReg) {
if (!groupNameReg) {
this.data.set('filteredTagsList', []);
return;
}
let tagsList = this.data.get('tagsList') || [];
let regExp = new RegExp(groupNameReg);
let filtedTagsList = tagsList.filter(item => regExp.test(item.tag));
this.data.set('filteredTagsList', filtedTagsList);
}
};
</script>
<style lang="stylus">
</style>
import {router} from 'san-router';
import Histogram from './Histogram';
router.add({
target: '#content',
rule: '/histograms',
Component: Histogram,
});
<template>
<div class="visual-dl-histogram-charts">
<div class="visual-dl-chart-box">
</div>
<div class="visual-dl-chart-actions">
<san-button on-click="expandArea">
<san-icon size="20">settings_overscan</san-icon>
</san-button>
</div>
</div>
</template>
<script>
// components
import Button from 'san-mui/Button';
import Icon from 'san-mui/Icon';
// libs
import echarts from 'echarts';
import {originDataToChartData} from '../histogramHelper';
import {format, precisionRound} from 'd3-format';
// service
import {getPluginHistogramsHistograms} from '../../service';
let zrDrawElement = {};
zrDrawElement.hoverDots = [];
// the time to refresh chart data
const intervalTime = 15;
const p = Math.max(0, precisionRound(0.01, 1.01) - 1);
const yValueFormat = format('.' + p + 'e');
export default {
components: {
'san-button': Button,
'san-icon': Icon
},
initData() {
return {
data: [
{
name: 'train',
value: []
}
]
};
},
inited() {
this.watch('originData', data => {
this.initChartOption();
});
this.watch('chartType', chartType => {
this.initChartOption();
});
},
attached() {
let tagInfo = this.data.get('tagInfo');
this.initChart(tagInfo);
if (this.data.get('running')) {
this.startInterval();
}
this.watch('running', running => {
running ? this.startInterval() : this.stopInterval();
});
},
detached() {
this.stopInterval();
},
initChart(tagInfo) {
this.createChart();
this.getOriginChartData(tagInfo);
},
createChart() {
let el = this.el.getElementsByClassName('visual-dl-chart-box')[0];
this.myChart = echarts.init(el);
},
initChartOption() {
this.myChart.clear();
let zr = this.myChart.getZr();
let hoverDots = zrDrawElement.hoverDots;
if (hoverDots != null && hoverDots.length !== 0) {
hoverDots.forEach(dot => zr.remove(dot));
}
let chartType = this.data.get('chartType');
let data = this.data.get('originData');
let visData = originDataToChartData(data);
let tagInfo = this.data.get('tagInfo');
let title = tagInfo.tag.displayName + '(' + tagInfo.run + ')';
this.setChartOptions(visData, title, chartType);
},
setChartOptions(visData, tag, chartType) {
let grid = {
left: '15%',
top: '15%',
right: '10%',
bottom: '8%'
};
let title = {
text: tag,
textStyle: {
fontSize: '12'
}
};
if (chartType === 'overlay') {
this.setOverlayChartOption(visData, title, grid);
}
else if (chartType === 'offset') {
this.setOffsetChartOption(visData, title, grid);
}
},
setOverlayChartOption({chartData, min, max}, title, grid) {
let seriesOption = chartData.map(({time, step, items}) => ({
name: 'step' + step,
type: 'line',
showSymbol: false,
hoverAnimation: false,
z: 0,
data: items,
animationDuration: 100,
lineStyle: {
normal: {
width: 1,
color: '#008c99'
}
},
encode: {
x: [2],
y: [3]
}
})
);
let option = {
title: title,
axisPointer: {
link: {xAxisIndex: 'all'},
show: true,
snap: true,
triggerTooltip: true
},
grid: grid,
xAxis: {
type: 'value'
},
yAxis: {
type: 'value',
axisLine: {
onZero: false
},
axisLabel: {
formatter(value, index) {
return yValueFormat(value);
}
},
axisPointer: {
label: {
formatter({value}) {
return yValueFormat(value);
}
}
}
},
series: seriesOption
};
let zr1 = this.myChart.getZr();
zr1.on('mousemove', function (e) {
zr1.remove(zrDrawElement.hoverLine);
zr1.remove(zrDrawElement.tooltip);
zr1.remove(zrDrawElement.tooltipX);
zr1.remove(zrDrawElement.tooltipY);
zrDrawElement.hoverDots.forEach(dot => zr1.remove(dot));
zrDrawElement.hoverDots.length = 0;
});
this.myChart.setOption(option, {notMerge: true});
},
setOffsetChartOption({chartData, min, max}, title, grid) {
let rawData = [];
let minX = min;
let maxX = max;
let minZ = Infinity;
let maxZ = -Infinity;
let ecChart = this.myChart;
let maxStep = -Infinity;
let minStep = Infinity;
grid.top = '42%';
grid.left = '4%';
grid.right = '15%';
chartData.forEach(function (dataItem) {
let lineData = [];
maxStep = Math.max(dataItem.step, maxStep);
minStep = Math.min(dataItem.step, minStep);
dataItem.items.forEach(([time, step, x, y]) => {
minZ = Math.min(minZ, y);
maxZ = Math.max(maxZ, y);
lineData.push(x, step, y);
});
rawData.push(lineData);
});
let option = {
title,
color: ['#006069'],
visualMap: {
type: 'continuous',
show: false,
min: minStep,
max: maxStep,
dimension: 1,
inRange: {
colorLightness: [0.2, 0.4]
}
},
xAxis: {
min: minX,
max: maxX,
axisLine: {
onZero: false
},
axisLabel: {
formatter: function (value) {
return Math.round(value * 100) / 100;
}
},
splitLine: {
show: false
}
},
yAxis: {
position: 'right',
axisLine: {
onZero: false
},
inverse: true,
splitLine: {
show: false
}
},
grid,
series: [{
type: 'custom',
dimensions: ['x', 'y'],
renderItem: function (params, api) {
let points = makePolyPoints(
params.dataIndex,
api.value,
api.coord,
params.coordSys.y - 10
);
return {
type: 'polygon',
silent: true,
shape: {
points
},
style: api.style({
stroke: '#bbb',
lineWidth: 1
})
};
},
data: rawData
}]
};
function makePolyPoints(dataIndex, getValue, getCoord, yValueMapHeight) {
let points = [];
for (let i = 0; i < rawData[dataIndex].length;) {
let x = getValue(i++);
let y = getValue(i++);
let z = getValue(i++);
points.push(getPoint(x, y, z, getCoord, yValueMapHeight));
}
return points;
}
function getPoint(x, y, z, getCoord, yValueMapHeight) {
let pt = getCoord([x, y]);
// linear map in z axis
pt[1] -= (z - minZ) / (maxZ - minZ) * yValueMapHeight;
return pt;
}
let zr = ecChart.getZr();
function removeTooltip() {
if (zrDrawElement.hoverLine) {
zr.remove(zrDrawElement.hoverLine);
zr.remove(zrDrawElement.tooltip);
zrDrawElement.hoverDots.forEach(dot => zr.remove(dot));
zrDrawElement.hoverDots.length = 0;
zr.remove(zrDrawElement.tooltipX);
zr.remove(zrDrawElement.tooltipY);
}
}
zr.on('mouseout', e => {
removeTooltip();
});
zr.on('mousemove', e => {
removeTooltip();
let nearestIndex = findNearestValue(e.offsetX, e.offsetY);
if (nearestIndex) {
let getCoord = function (pt) {
return ecChart.convertToPixel('grid', pt);
};
let gridRect = ecChart.getModel().getComponent('grid', 0).coordinateSystem.getRect();
let linePoints = makePolyPoints(
nearestIndex.itemIndex,
function (i) {
return rawData[nearestIndex.itemIndex][i];
},
getCoord,
gridRect.y - 10
);
zr.add(zrDrawElement.hoverLine = new echarts.graphic.Polyline({
silent: true,
shape: {
points: linePoints
},
style: {
stroke: '#5c5c5c',
lineWidth: 2
},
z: 999
}));
let itemX;
rawData.forEach(dataItem => {
let binIndex = nearestIndex.binIndex;
let x = dataItem[binIndex * 3];
let y = dataItem[binIndex * 3 + 1];
let z = dataItem[binIndex * 3 + 2];
let pt = getPoint(x, y, z, getCoord, gridRect.y - 10);
itemX = pt[0];
let dot = new echarts.graphic.Circle({
shape: {
cx: pt[0],
cy: pt[1],
r: 3
},
style: {
fill: '#000',
stroke: '#ccc',
lineWidth: 1
},
z: 1000
});
zr.add(dot);
zrDrawElement.hoverDots.push(dot);
});
let hoveredItem = chartData[nearestIndex.itemIndex];
zrDrawElement.tooltip = new echarts.graphic.Text({
position: [e.offsetX + 30, e.offsetY - 50],
style: {
text: yValueFormat(hoveredItem.items[nearestIndex.binIndex][3]),
textFill: '#000',
fontSize: 14,
textBackgroundColor: '#eee',
textBorderColor: '#008c99',
textBorderWidth: 2,
textBorderRadius: 5,
textPadding: 10,
rich: {}
},
z: 2000
});
zr.add(zrDrawElement.tooltip);
zrDrawElement.tooltipX = new echarts.graphic.Text({
position: [
itemX,
gridRect.y + gridRect.height
],
style: {
text: Math.round(hoveredItem.items[nearestIndex.binIndex][2] * 1000) / 1000,
textFill: '#fff',
textAlign: 'center',
fontSize: 12,
textBackgroundColor: '#333',
textBorderWidth: 2,
textPadding: [5, 7],
rich: {}
},
z: 2000
});
zr.add(zrDrawElement.tooltipX);
zrDrawElement.tooltipY = new echarts.graphic.Text({
position: [
gridRect.x + gridRect.width,
linePoints[linePoints.length - 1][1]
],
style: {
text: hoveredItem.step,
textFill: '#fff',
textVerticalAlign: 'middle',
fontSize: 12,
textBackgroundColor: '#333',
textBorderWidth: 2,
textPadding: [5, 7],
rich: {}
},
z: 2000
});
zr.add(zrDrawElement.tooltipY);
}
});
function findNearestValue(px, py) {
let value = ecChart.convertFromPixel('grid', [px, py]);
let itemIndex;
let nearestY = Infinity;
let binIndex;
chartData.forEach((item, index) => {
let dist = Math.abs(value[1] - item.step);
if (dist < nearestY) {
nearestY = dist;
itemIndex = index;
}
});
if (itemIndex != null) {
let dataItem = chartData[itemIndex];
let nearestX = Infinity;
dataItem.items.forEach((item, index) => {
let dist = Math.abs(item[2] - value[0]);
if (dist < nearestX) {
nearestX = dist;
binIndex = index;
}
});
if (binIndex != null) {
return {
itemIndex: itemIndex,
binIndex: binIndex
};
}
}
}
ecChart.setOption(option, {notMerge: true});
},
// get origin data per 60 seconds
startInterval() {
this.getOringDataInterval = setInterval(() => {
let tagInfo = this.data.get('tagInfo');
this.getOriginChartData(tagInfo);
}, intervalTime * 1000);
},
stopInterval() {
clearInterval(this.getOringDataInterval);
},
getOriginChartData({run, tag}) {
let params = {
run,
tag: tag.displayName
};
getPluginHistogramsHistograms(params).then(({status, data}) => {
if (status === 0) {
this.data.set('originData', data);
}
});
},
expandArea() {
let isExpand = this.data.get('isExpand');
let pageBoxWidth = document.getElementsByClassName('visual-dl-chart-page')[0].offsetWidth;
if (!isExpand) {
let el = this.el.getElementsByClassName('visual-dl-chart-box')[0];
el.style.width = pageBoxWidth + 'px';
el.style.height = '600px';
this.data.set('isExpand', true);
this.myChart.resize({
width: pageBoxWidth,
height: 600
});
}
else {
let el = this.el.getElementsByClassName('visual-dl-chart-box')[0];
el.style.width = '400px';
el.style.height = '300px';
this.data.set('isExpand', false);
this.myChart.resize({
width: 400,
height: 300
});
}
}
};
</script>
<style lang="stylus">
.visual-dl-histogram-charts
float left
margin-bottom 20px
margin 20px 30px 10px 0
background #fff
padding 10px
.visual-dl-chart-box
width 400px
height 300px
.visual-dl-chart-actions
height 50px
margin-left 10%
.sm-form-item
float left
width 100px
margin-top 0px
display block
.sm-button
float left
display block
height 20px
line-height 20px
margin-top 10px
padding 0 10px
</style>
<template>
<!-- ClassName visual-dl-chart-page used in chart.san, change they all if you need!-->
<div class="visual-dl-chart-page">
<ui-expand-panel isShow="{{expand}}" info="{{total}}" title="{{title}}">
<ui-chart
s-for="tag in filteredPageList"
tagInfo="{{tag}}"
runs="{{config.runs}}"
chartType="{{config.chartType}}"
running="{{config.running}}"
runsItems="{{runsItems}}"
></ui-chart>
<ui-pagination
s-if="total > pageSize"
on-pageChange="handlePageChange($event)"
current="{{currentPage}}"
pageSize="{{pageSize}}"
total="{{total}}"
showSizeChanger="{{false}}"
/>
</ui-expand-panel>
</div>
</template>
<script>
import ExpandPanel from '../../common/component/ExpandPanel';
import Chart from './chart';
import Pagination from 'san-mui/Pagination';
import {cloneDeep, flatten} from 'lodash';
export default {
components: {
'ui-chart': Chart,
'ui-expand-panel': ExpandPanel,
'ui-pagination': Pagination
},
computed: {
filteredRunsList() {
let tagList = this.data.get('tagList') || [];
let runs = this.data.get('config.runs') || [];
let list = cloneDeep(tagList);
return flatten(list.slice().map(item => {
return item.tagList.filter(one => runs.includes(one.run));
}));
},
filteredPageList() {
let list = this.data.get('filteredRunsList');
let currentPage = this.data.get('currentPage');
let pageSize = this.data.get('pageSize');
return list.slice((currentPage - 1) * pageSize, currentPage * pageSize);
},
total() {
let list = this.data.get('filteredRunsList') || [];
return list.length;
}
},
initData() {
return {
// current page
currentPage: 1,
// item per page
pageSize: 4
};
},
handlePageChange({pageNum}) {
this.data.set('currentPage', pageNum);
}
};
</script>
<style lang="stylus">
@import '../../style/variables';
+prefix-classes('visual-dl-')
.chart-page
.chart-box
float left
.chart-page-box:after
content: "";
clear: both;
display: block;
</style>
<template>
<div class="visual-dl-histogram-config-com">
<san-text-field
hintText="input a tag group name to search"
label="Group name RegExp"
inputValue="{=config.groupNameReg=}"
/>
<ui-radio-group
label="Histogram mode"
value="{=config.chartType=}"
items="{{charTypeItems}}"
/>
<ui-checkbox-group
value="{=config.runs=}"
label="Runs"
items="{{runsItems}}"
/>
<san-button
class="visual-dl-histogram-run-toggle"
variants="raised {{config.running ? 'secondery' : 'primary'}}"
on-click="toggleAllRuns"
>
{{config.running ? 'Running' : 'Stopped'}}
</san-button>
</div>
</template>
<script>
import TextField from 'san-mui/TextField';
import Slider from '../../common/component/Slider';
import RadioGroup from '../../common/component/RadioGroup';
import DropDownMenu from '../../common/component/DropDownMenu';
import CheckBoxGroup from '../../common/component/CheckBoxGroup';
import Button from 'san-mui/Button';
export default {
components: {
'san-text-field': TextField,
'ui-slider': Slider,
'ui-radio-group': RadioGroup,
'ui-dropdown-menu': DropDownMenu,
'ui-checkbox-group': CheckBoxGroup,
'san-button': Button
},
initData() {
return {
config: {
groupNameReg: '.*',
smoothing: '0.6',
horizontal: 'step',
sortingMethod: 'default',
downloadLink: [],
outlier: [],
running: true
},
horizontalItems: [
{
name: 'Step',
value: 'step'
},
{
name: 'Relative',
value: 'relative'
},
{
name: 'Wall',
value: 'wall'
}
],
runsItems: [],
charTypeItems: [
{
name: 'Overlay',
value: 'overlay'
},
{
name: 'Offset',
value: 'offset'
}
]
};
},
toggleAllRuns() {
let running = this.data.get('config.running');
this.data.set('config.running', !running);
this.fire('runningChange', running);
}
};
</script>
<style lang="stylus">
@import '../../style/variables';
+prefix-classes('visual-dl-histogram-')
.config-com
width 90%
margin 20px auto
.run-toggle
width 100%
margin-top 20px
</style>
<template>
<article>
<h1>
{{text}}
</h1>
</article>
</template>
<script>
export default {
initData() {
return {
text: 'welcome'
};
}
};
</script>
import {router} from 'san-router';
import HomePage from './Home';
router.add({
target: '#content',
rule: '/welcome',
Component: HomePage
});
<template>
<div class="visual-dl-page-container">
<div class="visual-dl-page-left">
<ui-chart-page
expand="{{true}}"
config="{{filteredConfig}}"
runsItems="{{runsItems}}"
tagList="{{filteredTagsList}}"
title="Tags matching {{config.groupNameReg}}"
></ui-chart-page>
<ui-chart-page
s-for="item in groupedTags"
config="{{filteredConfig}}"
runsItems="{{runsItems}}"
tagList="{{item.tags}}"
title="{{item.group}}"
></ui-chart-page>
</div>
<div class="visual-dl-page-right">
<div class="visual-dl-page-config-container">
<ui-config
runsItems="{{runsItems}}"
config="{=config=}"
></ui-config>
</div>
</div>
</div>
</template>
<script>
import {getPluginImagesTags, getRuns} from '../service';
import config from './ui/config';
import chartPage from './ui/chartPage';
import {debounce, flatten, uniq, isArray} from 'lodash';
import autoAdjustHeight from '../common/util/autoAdjustHeight';
export default {
components: {
'ui-config': config,
'ui-chart-page': chartPage
},
computed: {
runsItems() {
let runsArray = this.data.get('runsArray') || [];
return runsArray.map(item => {
return {
name: item,
value: item
};
});
},
tagsList() {
let tags = this.data.get('tags');
let runs = Object.keys(tags);
let tagsArray = runs.map(run => Object.keys(tags[run]));
let allUniqTags = uniq(flatten(tagsArray));
// get the data for every chart
return allUniqTags.map(tag => {
let tagList = runs.map(run => {
return {
run,
tag: tags[run][tag]
};
}).filter(item => item.tag !== undefined);
return {
tagList,
tag,
group: tag.split('/')[0]
};
});
},
groupedTags() {
let tagsList = this.data.get('tagsList') || [];
// put data in group
let groupData = {};
tagsList.forEach(item => {
let group = item.group;
if (groupData[group] === undefined) {
groupData[group] = [];
groupData[group].push(item);
}
else {
groupData[group].push(item);
}
});
// to array
let groups = Object.keys(groupData);
return groups.map(group => {
return {
group,
tags: groupData[group]
};
});
},
filteredConfig() {
let tansformArr = ['isActualImageSize'];
let config = this.data.get('config') || {};
let filteredConfig = {};
Object.keys(config).forEach(key => {
let val = config[key];
if (tansformArr.indexOf(key) > -1) {
filteredConfig[key] = isArray(val) && val[0] === 'yes';
}
else {
filteredConfig[key] = val;
}
});
return filteredConfig;
}
},
initData() {
return {
runsArray: [],
tags: [],
config: {
groupNameReg: '.*',
isActualImageSize: [],
runs: [],
running: true
}
};
},
inited() {
getPluginImagesTags().then(({errno, data}) => {
this.data.set('tags', data);
// filter when inited
let groupNameReg = this.data.get('config.groupNameReg');
this.filterTagsList(groupNameReg);
});
getRuns().then(({errno, data}) => {
this.data.set('runsArray', data);
this.data.set('config.runs', data);
});
// need debounce, can't use computed
this.watch('config.groupNameReg', debounce(this.filterTagsList, 300));
},
attached() {
autoAdjustHeight();
},
filterTagsList(groupNameReg) {
if (!groupNameReg) {
this.data.set('filteredTagsList', []);
return;
}
let tagsList = this.data.get('tagsList') || [];
let regExp = new RegExp(groupNameReg);
let filtedTagsList = tagsList.filter(item => regExp.test(item.tag));
this.data.set('filteredTagsList', filtedTagsList);
}
};
</script>
<style lang="stylus">
</style>
import {router} from 'san-router';
import Images from './Images';
router.add({
target: '#content',
rule: '/images',
Component: Images,
});
<template>
<div class="visual-dl-chart-page">
<ui-expand-panel isShow="{{expand}}" info="{{total}}" title="{{title}}">
<ui-image
class="visual-dl-chart-image"
s-for="tag in filteredPageList"
tagInfo="{{tag}}"
isActualImageSize="{{config.isActualImageSize}}"
runs="{{config.runs}}"
running="{{config.running}}"
runsItems="{{runsItems}}"
></ui-image>
<ui-pagination
class="visual-dl-sm-pagination"
s-if="total > pageSize"
on-pageChange="handlePageChange($event)"
current="{{currentPage}}"
pageSize="{{pageSize}}"
total="{{total}}"
showSizeChanger="{{false}}"
/>
</ui-expand-panel>
</div>
</template>
<script>
import ExpandPanel from '../../common/component/ExpandPanel';
import image from './image';
import Pagination from 'san-mui/Pagination';
import {cloneDeep, flatten} from 'lodash';
export default {
components: {
'ui-image': image,
'ui-expand-panel': ExpandPanel,
'ui-pagination': Pagination
},
computed: {
filteredRunsList() {
let tagList = this.data.get('tagList') || [];
let runs = this.data.get('config.runs') || [];
let list = cloneDeep(tagList);
return flatten(list.slice().map(item => {
return item.tagList.filter(one => runs.includes(one.run));
}));
},
filteredPageList() {
let list = this.data.get('filteredRunsList');
let currentPage = this.data.get('currentPage');
let pageSize = this.data.get('pageSize');
return list.slice((currentPage - 1) * pageSize, currentPage * pageSize);
},
total() {
let list = this.data.get('filteredRunsList') || [];
return list.length;
}
},
initData() {
return {
// current page
currentPage: 1,
// item per page
pageSize: 8
};
},
handlePageChange({pageNum}) {
this.data.set('currentPage', pageNum);
}
};
</script>
<style lang="stylus">
@import '../../style/variables';
+prefix-classes('visual-dl-')
.chart-page
.image-chart-box
overflow hidden
float left
.visual-dl-chart-image
float left
.image-chart-box:after
content ""
clear both
display block
.sm-pagination
height 50px
float left
width 100%
</style>
<template>
<div class="visual-dl-image-config-com">
<san-text-field
hintText="input a tag group name to search"
label="Group name RegExp"
inputValue="{=config.groupNameReg=}"
/>
<ui-checkbox-group
value="{=config.isActualImageSize=}"
items="{{imageSizeItems}}"
/>
<ui-checkbox-group
value="{=config.runs=}"
label="Runs"
items="{{runsItems}}"
/>
<san-button
class="visual-dl-image-run-toggle"
variants="raised {{config.running ? 'secondery' : 'primary'}}"
on-click="toggleAllRuns"
>
{{config.running ? 'Running' : 'Stopped'}}
</san-button>
</div>
</template>
<script>
import TextField from 'san-mui/TextField';
import CheckBoxGroup from '../../common/component/CheckBoxGroup';
import Button from 'san-mui/Button';
export default {
components: {
'san-text-field': TextField,
'ui-checkbox-group': CheckBoxGroup,
'san-button': Button
},
initData() {
return {
config: {
groupName: 'aa',
isActualImageSize: [],
runs: []
},
runsItems: [],
imageSizeItems: [
{
value: 'yes',
name: 'Show actual image size'
}
]
};
},
toggleAllRuns() {
let running = this.data.get('config.running');
this.data.set('config.running', !running);
this.fire('runningChange', running);
}
};
</script>
<style lang="stylus">
@import '../../style/variables';
+prefix-classes('visual-dl-image-')
.config-com
width 90%
margin 20px auto
.run-toggle
width 100%
margin-top 20px
</style>
<template>
<div class="visual-dl-image">
<h3 class="visual-dl-image-title">{{tagInfo.tag.displayName}}
<span class="visual-dl-image-run-icon">{{tagInfo.run}}</span>
</h3>
<p>
<span>Step:</span>
<span>{{imgData.step}};</span>
<span>{{imgData.wall_time | formatTime}}</span>
</p>
<san-slider
on-change="handleSlideChange($event)"
value="{{currentIndex}}"
min="{{slider.min}}"
max="{{steps}}"
step="{{1}}"
/>
<img style="{{computedImgStyle}}" src="{{imgData.imgSrc}}" />
</div>
</template>
<script>
import Slider from 'san-mui/Slider';
import {getPluginImagesImages} from '../../service';
const defaultImgWidth = 400;
const defaultImgHight = 300;
// the time to refresh chart data
const intervalTime = 30;
export default {
components: {
'san-slider': Slider
},
computed: {
steps() {
let data = this.data.get('data') || [];
return data.length - 1;
},
computedImgStyle() {
let isActualImageSize = this.data.get('isActualImageSize');
let width;
let height;
if (isActualImageSize) {
width = this.data.get('imgData.width');
height = this.data.get('imgData.height');
}
else {
width = defaultImgWidth;
height = defaultImgHight;
}
return 'width:' + width + 'px;height:' + height + 'px';
}
},
filters: {
formatTime(value) {
if (!value) {
return;
}
let time = new Date();
time.setTime(value.toString().split('.')[0]);
return time;
}
},
initData() {
return {
currentIndex: 0,
slider: {
value: '0',
label: '',
min: 0,
step: 1
}
};
},
inited() {
this.getOriginChartsData();
// currentIndex change event
this.watch('currentIndex', index => {
/* eslint-disable fecs-camelcase */
let currentImgInfo = this.data.get('data') ? this.data.get('data')[index] : {};
let {height, width, query, step, wall_time} = currentImgInfo;
let url = '/data/plugin/images/individualImage?ts=' + wall_time;
let imgSrc = [url, query].join('&');
this.data.set('imgData', {
imgSrc,
height,
width,
step,
wall_time
});
/* eslint-enable fecs-camelcase */
});
},
attached() {
if (this.data.get('running')) {
this.startInterval();
}
this.watch('running', running => {
running ? this.startInterval() : this.stopInterval();
});
},
detached() {
this.stopInterval();
},
stopInterval() {
clearInterval(this.getOringDataInterval);
},
// get origin data per {{intervalTime}} seconds
startInterval() {
this.getOringDataInterval = setInterval(() => {
this.getOriginChartsData();
}, intervalTime * 1000);
},
handleSlideChange(val) {
this.data.set('currentIndex', val);
},
getOriginChartsData() {
let {run, tag} = this.data.get('tagInfo');
let {displayName, samples} = tag;
let params = {
run,
tag: displayName,
samples
};
getPluginImagesImages(params).then(({status, data}) => {
if (status === 0) {
this.data.set('data', data);
this.data.set('currentIndex', data.length - 1);
}
});
}
};
</script>
<style lang="stylus">
.visual-dl-image
font-size 12px
width 400px
float left
margin 20px 30px 10px 0
background #fff
padding 10px
.visual-dl-image-title
font-size 14px
line-height 30px
.visual-dl-image-run-icon
background #e4e4e4
float right
margin-right 10px
padding 0 10px
border solid 1px #e4e4e4
border-radius 6px
line-height 20px
margin-top 4px
.visual-dl-chart-actions
.sm-form-item
width 300px
display inline-block
</style>
<template>
<div class="visual-dl-page-container">
<div class="visual-dl-page-left">
<ui-chart-page
expand="{{true}}"
config="{{filteredConfig}}"
runsItems="{{runsItems}}"
tagList="{{filteredTagsList}}"
title="Tags matching {{config.groupNameReg}}"
></ui-chart-page>
<ui-chart-page
s-for="item in groupedTags"
config="{{filteredConfig}}"
runsItems="{{runsItems}}"
tagList="{{item.tags}}"
title="{{item.group}}"
></ui-chart-page>
</div>
<div class="visual-dl-page-right">
<div class="visual-dl-page-config-container">
<ui-config
runsItems="{{runsItems}}"
config="{=config=}"
></ui-config>
</div>
</div>
</div>
</template>
<script>
import {getPluginScalarsTags, getRuns} from '../service';
import config from './ui/config';
import chartPage from './ui/chartPage';
import {debounce, flatten, uniq, isArray} from 'lodash';
import autoAdjustHeight from '../common/util/autoAdjustHeight';
export default {
components: {
'ui-config': config,
'ui-chart-page': chartPage
},
computed: {
runsItems() {
let runsArray = this.data.get('runsArray') || [];
return runsArray.map(item => {
return {
name: item,
value: item
};
});
},
tagsList() {
let tags = this.data.get('tags');
let runs = Object.keys(tags);
let tagsArray = runs.map(run => Object.keys(tags[run]));
let allUniqTags = uniq(flatten(tagsArray));
// get the data for every chart
return allUniqTags.map(tag => {
let tagList = runs.map(run => {
return {
run,
tag: tags[run][tag]
};
}).filter(item => item.tag !== undefined);
return {
tagList,
tag,
group: tag.split('/')[0]
};
});
},
groupedTags() {
let tagsList = this.data.get('tagsList') || [];
// put data in group
let groupData = {};
tagsList.forEach(item => {
let group = item.group;
if (groupData[group] === undefined) {
groupData[group] = [];
groupData[group].push(item);
}
else {
groupData[group].push(item);
}
});
// to array
let groups = Object.keys(groupData);
return groups.map(group => {
return {
group,
tags: groupData[group]
};
});
},
filteredConfig() {
let tansformArr = ['downloadLink', 'outlier'];
let config = this.data.get('config') || {};
let filteredConfig = {};
Object.keys(config).forEach(key => {
let val = config[key];
if (tansformArr.indexOf(key) > -1) {
filteredConfig[key] = isArray(val) && val[0] === 'yes';
}
else {
filteredConfig[key] = val;
}
});
return filteredConfig;
}
},
initData() {
return {
runsArray: [],
tags: [],
config: {
groupNameReg: '.*',
smoothing: 0.6,
horizontal: 'step',
sortingMethod: 'default',
downloadLink: [],
outlier: [],
runs: [],
running: true
}
};
},
inited() {
getPluginScalarsTags().then(({errno, data}) => {
this.data.set('tags', data);
// filter when inited
let groupNameReg = this.data.get('config.groupNameReg');
this.filterTagsList(groupNameReg);
});
getRuns().then(({errno, data}) => {
this.data.set('runsArray', data);
this.data.set('config.runs', data);
});
// need debounce, can't use computed
this.watch('config.groupNameReg', debounce(this.filterTagsList, 300));
},
attached() {
autoAdjustHeight();
},
filterTagsList(groupNameReg) {
if (!groupNameReg) {
this.data.set('filteredTagsList', []);
return;
}
let tagsList = this.data.get('tagsList') || [];
let regExp = new RegExp(groupNameReg);
let filtedTagsList = tagsList.filter(item => regExp.test(item.tag));
this.data.set('filteredTagsList', filtedTagsList);
}
};
</script>
<style lang="stylus">
</style>
import {router} from 'san-router';
import Scalar from './Scalars';
router.add({
target: '#content',
rule: '/',
Component: Scalar,
});
router.add({
target: '#content',
rule: '/scalars',
Component: Scalar,
});
<template>
<div class="visual-dl-page-charts">
<div class="visual-dl-chart-box" style="{{computedStyle}}">
</div>
<div class="visual-dl-chart-actions">
<san-button on-click="expandArea">
<san-icon size="20">settings_overscan</san-icon>
</san-button>
<ui-dropdown-menu
s-if="downloadLink"
stlye="width:100px;"
hintText="download type"
items="{{runsItems}}"
value="{=downloadType=}"
/>
<san-button
s-if="downloadLink"
on-click="handleDownLoad">
<san-icon size="20">file_download</san-icon>
</san-button>
</div>
</div>
</template>
<script>
// components
import Button from 'san-mui/Button';
import Icon from 'san-mui/Icon';
import DropDownMenu from '../../common/component/DropDownMenu';
// libs
import echarts from 'echarts';
import axios from 'axios';
import {isFinite, flatten, maxBy, minBy, sortBy, max, min} from 'lodash';
import {generateJsonAndDownload} from '../../common/util/downLoadFile';
import {quantile} from '../../common/util/index';
import moment from 'moment';
// service
import {getPluginScalarsScalars} from '../../service';
const originLinesOpacity = 0.3;
const defaultSmoothWeight = 0.6;
const lineWidth = 1.5;
const minQuantile = 0.05;
const maxQuantile = 0.95;
// the time to refresh chart data
const intervalTime = 15;
export default {
components: {
'ui-dropdown-menu': DropDownMenu,
'san-button': Button,
'san-icon': Icon
},
computed: {
computedStyle() {
let width = this.data.get('width');
let height = this.data.get('height');
return 'height:' + height + 'px;'
+ 'width:' + width + 'px;';
}
},
initData() {
return {
width: 400,
height: 300,
data: [
{
name: 'train',
value: []
}
],
// choose run type for download file
downloadType: ''
};
},
inited() {
this.watch('runsItems', val => {
this.initDownloadType();
});
this.watch('originData', originData => {
this.setChartData();
this.setChartsOutlier();
this.setChartHorizon();
});
this.watch('smoothing', smoothing => {
this.setChartData();
});
this.watch('outlier', outlier => {
// outlier
this.setChartsOutlier();
});
this.watch('horizontal', horizontal => {
this.setChartHorizon();
});
this.watch('runs', runs => {
this.setChartsRuns();
});
},
attached() {
let tagInfo = this.data.get('tagInfo');
this.initChart(tagInfo);
if (this.data.get('running')) {
this.startInterval();
}
this.watch('running', running => {
running ? this.startInterval() : this.stopInterval();
});
},
detached() {
this.stopInterval();
},
initDownloadType() {
let runsItems = this.data.get('runsItems');
if (runsItems.length === 0) {
return;
}
this.data.set('downloadType', runsItems[0].value);
},
// Create a Scalar Chart, initialize it with default settings, then load datas
initChart(tagInfo) {
this.createChart();
this.setChartsOptions(tagInfo);
this.getOriginChartData(tagInfo);
},
createChart() {
let el = this.el.getElementsByClassName('visual-dl-chart-box')[0];
this.myChart = echarts.init(el);
},
setChartsOptions({tagList, tag}) {
// Create two lines, one line is original, the other line is for smoothing
let seriesOption = tagList.map(item => [
{
name: item.run,
type: 'line',
showSymbol: false,
hoverAnimation: false,
z: 0,
data: [],
animationDuration: 100,
lineStyle: {
normal: {
opacity: originLinesOpacity,
width: lineWidth
}
}
},
{
name: item.run,
type: 'line',
showSymbol: false,
hoverAnimation: false,
z: 1,
data: [],
animationDuration: 100,
lineStyle: {
normal: {
width: lineWidth
}
}
}
]
);
seriesOption = flatten(seriesOption);
let legendOptions = tagList.map(item => item.run);
let that = this;
let option = {
color: [
'#c23531',
'#61a0a8',
'#d48265',
'#91c7ae',
'#749f83',
'#ca8622',
'#bda29a',
'#6e7074',
'#546570',
'#c4ccd3'
],
title: {
text: tag,
textStyle: {
fontSize: '12'
}
},
tooltip: {
trigger: 'axis',
axisPointer: {
animation: true
},
position: ['10%', '90%'],
formatter(params, ticket, callback) {
let data = that.getFormatterPoints(params[0].data);
return that.tansformFormatterData(data);
}
},
toolbox: {
show: true,
showTitle: true,
feature: {
dataZoom: {},
restore: {},
saveAsImage: {}
},
left: '10%',
top: '90%'
},
legend: {
data: legendOptions,
top: '10%'
},
grid: {
left: '10%',
top: '20%',
right: '10%',
bottom: '20%'
},
xAxis: {
type: 'value'
},
yAxis: {
type: 'value',
axisLabel: {
formatter(value) {
return value.toString().slice(0, 5);
}
}
},
series: seriesOption
};
this.myChart.setOption(option);
},
// Get origin data per 60 seconds
startInterval() {
this.getOringDataInterval = setInterval(() => {
let tagInfo = this.data.get('tagInfo');
this.getOriginChartData(tagInfo);
}, intervalTime * 1000);
},
stopInterval() {
clearInterval(this.getOringDataInterval);
},
getOriginChartData({tagList, tag}) {
let requestList = tagList.map(item => {
let params = {
run: item.run,
tag: tag
};
return getPluginScalarsScalars(params);
});
axios.all(requestList).then(resArray => {
if (resArray.every(res => res.status === 0)) {
this.data.set('originData', resArray.map(res => res.data));
}
});
},
setChartData() {
let originData = this.data.get('originData');
let seriesData = originData.map(lineData => {
// add the smoothed data
this.tansformDataset(lineData);
return [
{
data: lineData,
encode: {
// map 1 dimension to xAixs.
x: [1],
// map 2 dimension to yAixs.
y: [2]
}
},
{
data: lineData,
encode: {
// Map 1 dimension to xAixs.
x: [1],
// Map 3 dimension to yAixs,
// the third number is smoothed value.
y: [3]
}
}
];
});
this.myChart.setOption({
series: flatten(seriesData)
});
},
getChartOptions() {
return this.myChart.getOption() || {};
},
handleDownLoad() {
let options = this.getChartOptions();
let series = options.series || [];
let downloadType = this.data.get('downloadType');
let sery = series.find(item => item.name === downloadType) || {};
let tagInfo = this.data.get('tagInfo');
let fileName = tagInfo.tag.replace(/\//g, '-');
generateJsonAndDownload(sery.data, fileName);
},
tansformDataset(seriesData) {
let smoothing = this.data.get('smoothing');
// smooth
this.tansformData(seriesData, smoothing || defaultSmoothWeight);
},
/**
* @desc 1、add smooth data depend on smoothingWeight. see https://en.wikipedia.org/wiki/Moving_average for detail
* 2、add relative data
* @param {Object} echarts series Object
* @param {number} smoothingWeight smooth weight, between 0 ~ 1
*/
tansformData(seriesData, smoothingWeight) {
let data = seriesData;
let last = data.length > 0 ? 0 : NaN;
let numAccum = 0;
let startValue;
data.forEach((d, i) => {
let nextVal = d[2];
// second to millisecond.
let millisecond = Math.floor(d[0] * 1000);
if (i === 0) {
startValue = millisecond;
}
// Relative time, millisecond to hours.
d[4] = Math.floor(millisecond - startValue) / (60 * 60 * 1000);
if (!isFinite(nextVal)) {
d[3] = nextVal;
} else {
last = last * smoothingWeight + (1 - smoothingWeight) * nextVal;
numAccum++;
let debiasWeight = 1;
if (smoothingWeight !== 1.0) {
debiasWeight = 1.0 - Math.pow(smoothingWeight, numAccum);
}
d[3] = last / debiasWeight;
}
});
},
// Chart outlier options methods and functions ---- start.
// Compute Y domain from originData.
setChartsOutlier(seriesData) {
let outlier = this.data.get('outlier');
let originData = this.data.get('originData');
let domainRangeArray = originData.map(seriesData => this.computeDataRange(seriesData, outlier));
// Compare, get the best Y domain.
let flattenNumbers = flatten(domainRangeArray);
let finalMax = max(flattenNumbers);
let finalMin = min(flattenNumbers);
// Add padding.
let PaddedYDomain = this.paddedYDomain(finalMin, finalMax);
this.setChartOutlierOptions(PaddedYDomain);
// Store Y domain, if originData is not change, Y domain keep same.
},
// Compute max and min from array, if outlier is true, return quantile range.
computeDataRange(arr, isQuantile) {
// Get data range.
let max;
let min;
if (!isQuantile) {
// Get the orgin data range.
max = maxBy(arr, item => item[2])[2];
min = minBy(arr, item => item[2])[2];
}
else {
// Get the quantile range.
let sorted = sortBy(arr, [item => item[2]]);
min = quantile(sorted, minQuantile, item => item[2]);
max = quantile(arr, maxQuantile, item => item[2]);
}
return [min, max];
},
paddedYDomain(min, max) {
return {
max: max > 0 ? max * 1.1 : max * 0.9,
min: min > 0 ? min * 0.9 : min * 1.1
};
},
setChartOutlierOptions({min, max}) {
this.myChart.setOption({
yAxis: {
min,
max
}
});
},
// Chart horizontal options methods and functions ---- start.
setChartHorizon() {
let horizontal = this.data.get('horizontal');
let seriesOption = this.myChart.getOption().series;
let encodeSeries = val => {
return {
encode: {
x: [val]
}
};
};
let stepSeies = seriesOption.map(item => encodeSeries(1));
let relativeSeies = seriesOption.map(item => encodeSeries(4));
let wallSeries = seriesOption.map(item => encodeSeries(0));
let horizontalToxAxisOptions = {
step: {
xAxis: {
type: 'value'
},
series: stepSeies
},
relative: {
xAxis: {
type: 'value'
},
series: relativeSeies
},
wall: {
xAxis: {
type: 'time'
},
series: wallSeries
}
};
this.myChart.setOption(horizontalToxAxisOptions[horizontal]);
},
expandArea() {
let isExpand = this.data.get('isExpand');
let pageBoxWidth = document.getElementsByClassName('visual-dl-chart-page-box')[0].offsetWidth;
if (!isExpand) {
let el = this.el.getElementsByClassName('visual-dl-chart-box')[0];
el.style.width = pageBoxWidth + 'px';
el.style.height = '600px';
this.data.set('isExpand', true);
this.myChart.resize({
width: pageBoxWidth,
height: 600
});
}
else {
let el = this.el.getElementsByClassName('visual-dl-chart-box')[0];
el.style.width = '400px';
el.style.height = '300px';
this.data.set('isExpand', false);
this.myChart.resize({
width: 400,
height: 300
});
}
},
getFormatterPoints(data) {
let originData = this.data.get('originData');
let tagList = this.data.get('tagInfo.tagList');
let sortingMethod = this.data.get('sortingMethod');
// Can't know exactly the tigger runs.
// If the step is same, regard the point as the trigger point.
let [, step, triggerValue] = data;
let points = originData.map((series, index) => {
let nearestItem;
if (step === 0) {
nearestItem = series[0];
}
else {
for (let i = 0; i < series.length; i++) {
let item = series[i];
if (item[1] === step) {
nearestItem = item;
break;
}
if (item[1] > step) {
let index = i - 1;
nearestItem = series[index >= 0 ? index : 0];
break;
}
if (!nearestItem) {
nearestItem = series[series.length - 1];
}
}
}
return {
run: tagList[index].run,
item: nearestItem
};
});
if (sortingMethod === 'default' || !sortingMethod) {
return points;
}
let sortedPoints;
switch (sortingMethod) {
case 'desc':
sortedPoints = sortBy(points, one => one.item[3]);
sortedPoints.reverse();
break;
case 'asc':
sortedPoints = sortBy(points, one => one.item[3]);
break;
case 'nearest':
// Compare other ponts width the trigger point, caculate the nearest sort.
sortedPoints = sortBy(points, one => one.item[3] - triggerValue);
break;
default:
sortedPoints = points;
}
return sortedPoints;
},
tansformFormatterData(data) {
let indexPropMap = {
Time: 0,
Step: 1,
Value: 2,
Smoothed: 3,
Relative: 4
};
let widthPropMap = {
Run: 40,
Time: 90,
Step: 40,
Value: 50,
Smoothed: 50,
Relative: 40
};
let tranformedData = data.map(item => {
let data = item.item;
return {
Run: item.run,
// Keep six number for easy-read.
Smoothed: data[indexPropMap.Smoothed].toString().slice(0, 6),
Value: data[indexPropMap.Value].toString().slice(0, 6),
Step: data[indexPropMap.Step],
Time: moment(Math.floor(data[indexPropMap.Time] * 1000), 'x').format('YYYY-MM-DD HH:mm:ss'),
// Relative display value should take easy-read into consideration.
// Better to tranform data to 'day:hour', 'hour:minutes', 'minute: seconds' and second only.
Relative: Math.floor(data[indexPropMap.Relative] * 60 * 60) + 's'
};
});
let headerHtml = '<tr style="font-size:14px;">';
headerHtml += Object.keys(tranformedData[0]).map(key => {
return '<td style="padding: 0 4px; font-weight: bold; width:' + widthPropMap[key] + 'px;">' + key + '</td>';
}).join('');
headerHtml += '</tr>';
let content = tranformedData.map(item => {
let str = '<tr style="font-size:12px;">';
str += Object.keys(item).map(val => {
return '<td style="padding: 0 4px">' + item[val] + '</td>';
}).join('');
str += '</tr>';
return str;
}).join('');
return '<table style="text-align: left;table-layout: fixed;width: 480px;"><thead>' + headerHtml + '</thead>'
+ '<tbody>' + content + '</tbody><table>';
}
};
</script>
<style lang="stylus">
.visual-dl-page-charts
float left
margin 20px 30px 10px 0
background: #fff;
padding: 10px;
.visual-dl-chart-actions
height 50px
margin-left 10%
.sm-form-item
float left
width 100px
margin-top 0px
display block
.sm-button
float left
display block
height 20px
line-height 20px
margin-top 10px
padding 0 10px
</style>
<template>
<div class="visual-dl-chart-page">
<ui-expand-panel isShow="{{expand}}" info="{{tagList.length}}" title="{{title}}">
<div class="visual-dl-chart-page-box">
<ui-chart
s-for="tag in filteredTagList"
tagInfo="{{tag}}"
groupNameReg="{{config.groupNameReg}}"
smoothing="{{config.smoothing}}"
horizontal="{{config.horizontal}}"
sortingMethod="{{config.sortingMethod}}"
downloadLink="{{config.downloadLink}}"
outlier="{{config.outlier}}"
runs="{{config.runs}}"
running="{{config.running}}"
runsItems="{{runsItems}}"
></ui-chart>
</div>
<ui-pagination
s-if="total > pageSize"
on-pageChange="handlePageChange($event)"
current="{{currentPage}}"
pageSize="{{pageSize}}"
total="{{total}}"
showSizeChanger="{{false}}"
/>
</ui-expand-panel>
</div>
</template>
<script>
import ExpandPanel from '../../common/component/ExpandPanel';
import chart from './chart';
import Pagination from 'san-mui/Pagination';
import {cloneDeep} from 'lodash';
export default {
components: {
'ui-chart': chart,
'ui-expand-panel': ExpandPanel,
'ui-pagination': Pagination
},
computed: {
filteredRunsList() {
let tagList = this.data.get('tagList') || [];
let runs = this.data.get('config.runs') || [];
let list = cloneDeep(tagList);
return list.slice().map(item => {
item.tagList = item.tagList.filter(one => runs.includes(one.run));
return item;
});
},
filteredTagList() {
let tagList = this.data.get('filteredRunsList') || [];
let currentPage = this.data.get('currentPage');
let pageSize = this.data.get('pageSize');
return tagList.slice((currentPage - 1) * pageSize, currentPage * pageSize);
},
total() {
let tagList = this.data.get('tagList') || [];
return tagList.length;
}
},
initData() {
return {
// current page
currentPage: 1,
// item per page
pageSize: 8
};
},
handlePageChange({pageNum}) {
this.data.set('currentPage', pageNum);
}
};
</script>
<style lang="stylus">
@import '../../style/variables';
+prefix-classes('visual-dl-')
.chart-page
.chart-page-box:after
content: "";
clear: both;
display: block;
</style>
<template>
<div class="visual-dl-page-config-com">
<san-text-field
hintText="input a tag group name"
label="Group name RegExp"
inputValue="{=config.groupNameReg=}"
/>
<ui-slider
label="Smoothing"
value="{=config.smoothing=}"
min="{{0}}"
max="{{0.999}}"
step="{{0.001}}"
/>
<ui-radio-group
label="Horizontal"
value="{=config.horizontal=}"
items="{{horizontalItems}}"
/>
<ui-dropdown-menu
label="Tooltip sorting method"
items="{{sortingMethodItems}}"
value="{=config.sortingMethod=}"
/>
<ui-checkbox-group
value="{=config.downloadLink=}"
items="{{lnksItems}}"
/>
<ui-checkbox-group
value="{=config.outlier=}"
items="{{chartItems}}"
/>
<ui-checkbox-group
value="{=config.runs=}"
label="Runs"
items="{{runsItems}}"
/>
<san-button
class="visual-dl-page-run-toggle"
variants="raised {{config.running ? 'secondery' : 'primary'}}"
on-click="toggleAllRuns"
>
{{config.running ? 'Running' : 'Stopped'}}
</san-button>
</div>
</template>
<script>
import TextField from 'san-mui/TextField';
import Slider from '../../common/component/Slider';
import RadioGroup from '../../common/component/RadioGroup';
import DropDownMenu from '../../common/component/DropDownMenu';
import CheckBoxGroup from '../../common/component/CheckBoxGroup';
import Button from 'san-mui/Button';
export default {
components: {
'san-text-field': TextField,
'ui-slider': Slider,
'ui-radio-group': RadioGroup,
'ui-dropdown-menu': DropDownMenu,
'ui-checkbox-group': CheckBoxGroup,
'san-button': Button
},
initData() {
return {
config: {
groupNameReg: '.*',
smoothing: '0.6',
horizontal: 'step',
sortingMethod: 'default',
downloadLink: [],
outlier: [],
running: true
},
horizontalItems: [
{
name: 'Step',
value: 'step'
},
{
name: 'Relative',
value: 'relative'
},
{
name: 'Wall',
value: 'wall'
}
],
sortingMethodItems: [
{
name: 'default',
value: 'default'
},
{
name: 'descending',
value: 'desc'
},
{
name: 'ascending',
value: 'asc'
},
{
name: 'nearest',
value: 'nearest'
}
],
runsItems: [],
lnksItems: [
{
value: 'yes',
name: 'Show data download links'
}
],
chartItems: [
{
value: 'yes',
name: 'Ignore outliers in chart scaling'
}
]
};
},
toggleAllRuns() {
let running = this.data.get('config.running');
this.data.set('config.running', !running);
this.fire('runningChange', running);
}
};
</script>
<style lang="stylus">
@import '../../style/variables';
+prefix-classes('visual-dl-page-')
.config-com
width 90%
margin 20px auto
.run-toggle
width 100%
margin-top 20px
</style>
import {useRef, useEffect, useCallback} from 'react';
const useClickOutside = (callback: () => void) => {
const ref = useRef(null);
const escapeListener = useCallback(
(e: KeyboardEvent) => {
if (e.key === 'Escape') {
callback();
}
},
[callback]
);
const clickListener = useCallback(
(e: MouseEvent | TouchEvent) => {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
if (ref.current && !(ref.current! as Node).contains(e.target as Node)) {
callback();
}
},
[callback]
);
useEffect(() => {
if (process.browser) {
document.addEventListener('mousedown', clickListener);
document.addEventListener('touchstart', clickListener);
document.addEventListener('keyup', escapeListener);
return () => {
document.removeEventListener('mousedown', clickListener);
document.removeEventListener('touchstart', clickListener);
document.removeEventListener('keyup', escapeListener);
};
}
}, [clickListener, escapeListener]);
return ref;
};
export default useClickOutside;
import {useRef, useEffect, useCallback, MutableRefObject} from 'react';
import echarts, {ECharts} from 'echarts';
import {useTranslation} from '~/utils/i18n';
const useECharts = <T extends HTMLElement>(
loading: boolean
): [MutableRefObject<T | null>, MutableRefObject<ECharts | null>] => {
const {t} = useTranslation('common');
const ref = useRef(null);
const echart = useRef(null as ECharts | null);
const createChart = useCallback(() => {
echart.current = echarts.init((ref.current as unknown) as HTMLDivElement);
}, []);
const destroyChart = useCallback(() => {
echart.current?.dispose();
}, []);
useEffect(() => {
if (process.browser) {
createChart();
return () => destroyChart();
}
}, [createChart, destroyChart]);
useEffect(() => {
if (process.browser) {
if (loading) {
echart.current?.showLoading('default', {
text: t('loading'),
color: '#c23531',
textColor: '#000',
maskColor: 'rgba(255, 255, 255, 0.8)',
zlevel: 0
});
} else {
echart.current?.hideLoading();
}
}
}, [t, loading]);
return [ref, echart];
};
export default useECharts;
import {useReducer} from 'react';
import useSWR from 'swr';
import groupBy from 'lodash/groupBy';
import uniq from 'lodash/uniq';
import intersection from 'lodash/intersection';
import {NextPageContext} from 'next';
import {fetcher} from '~/utils/fetch';
import {Tag} from '~/types';
type Runs = string[];
type Tags = Record<string, string[]>;
const groupTags = (runs: Runs, tags?: Tags): Tag[] =>
Object.entries(
groupBy<{label: Tag['label']; run: Tag['runs'][number]}>(
runs
// get tags of selected runs
.filter(run => runs.includes(run))
// group by runs
.reduce((prev, run) => {
if (tags && tags[run]) {
Array.prototype.push.apply(
prev,
tags[run].map(label => ({label, run}))
);
}
return prev;
}, []),
tag => tag.label
)
).map(([label, tags]) => ({label, runs: tags.map(tag => tag.run)}));
type State = {
runs: Runs;
tags: Tag[];
filteredTags: Tag[];
};
enum ActionType {
setRuns,
setTags,
setFilteredTags
}
type ActionSetRuns = {
type: ActionType.setRuns;
payload: Runs;
};
type ActionSetTags = {
type: ActionType.setTags;
payload: Tag[];
};
type ActionSetFilteredTags = {
type: ActionType.setFilteredTags;
payload: Tag[];
};
type Action = ActionSetRuns | ActionSetTags | ActionSetFilteredTags;
type InitData = {
runs: Runs;
tags: Tags;
};
export type Props = {
tags: Tags;
runs: Runs;
selectedRuns: Runs;
};
export const defaultProps = {
tags: {},
runs: []
};
type GetInitialProps = (type: string, context: NextPageContext, f: typeof fetcher) => Promise<Props>;
export const getInitialProps: GetInitialProps = async (type, {query}, fetcher) => {
const [runs, tags] = await Promise.all([fetcher('/runs').then(uniq), fetcher(`/${type}/tags`)]);
return {
runs,
selectedRuns: query.runs
? intersection(uniq(Array.isArray(query.runs) ? query.runs : query.runs.split(',')), runs)
: runs,
tags
};
};
const useTagFilters = (type: string, selectedRuns: Runs, initData: InitData) => {
const {data: runs} = useSWR('/runs', {initialData: initData.runs});
const {data: tags} = useSWR(`/${type}/tags`, {initialData: initData.tags});
const reducer = (state: State, action: Action): State => {
switch (action.type) {
case ActionType.setRuns:
const newTags = groupTags(action.payload, tags);
return {
...state,
runs: action.payload,
tags: newTags,
filteredTags: newTags
};
case ActionType.setTags:
return {
...state,
tags: action.payload,
filteredTags: action.payload
};
case ActionType.setFilteredTags:
return {
...state,
filteredTags: action.payload
};
default:
throw Error();
}
};
const [state, dispatch] = useReducer(
reducer,
{
runs: selectedRuns,
tags: groupTags(selectedRuns, tags)
},
initArgs => ({...initArgs, filteredTags: initArgs.tags})
);
const onChangeRuns = (runs: Runs) => dispatch({type: ActionType.setRuns, payload: runs});
const onFilterTags = (tags: Tag[]) => dispatch({type: ActionType.setFilteredTags, payload: tags});
return {
runs,
tags: state.tags,
selectedRuns: state.runs,
selectedTags: state.filteredTags,
onChangeRuns,
onFilterTags
};
};
export default useTagFilters;
module.exports = {
'**/*.ts?(x)': () => ['tsc -p tsconfig.json --noEmit', 'eslint'],
'**/*.js?(x)': () => 'eslint'
};
# API
## runs
current runs
url: /data/runs
response:
```
["train", "test"]
```
## logdir
url: /data/logdir
response:
```
{
"logdir": "./tmp/tensorflow/mnist/logs/mnist_with_summaries/"
}
```
## data/plugins_listing
url: data/plugins_listing
/**
* get mock data
*
* @param {string} path request path
* @param {Object} queryParam query params
* @param {Object} postParam post params
* @return {Object}
*/
module.exports = function (path, queryParam, postParam) {
return {
// moock delay
_timeout: 0,
// mock http status
_status: 200,
// mock response data
_data: {
status: 0,
msg: 'SUCCESS',
data: [
{
"wall_time": 1512549785.061623,
"step": 60,
"query": "sample=0&index=0&tag=input_reshape%2Finput%2Faudio%2F0&run=test",
"width": 28,
"height": 28
},
{"wall_time": 1512886109.672786, "step": 60, "query": "sample=0&index=1&tag=input_reshape%2Finput%2Faudio%2F0&run=test"},
{"wall_time": 1512886124.266915, "step": 210, "query": "sample=0&index=2&tag=input_reshape%2Finput%2Faudio%2F0&run=test"},
{"wall_time": 1512886138.898628, "step": 330, "query": "sample=0&index=3&tag=input_reshape%2Finput%2Faudio%2F0&run=test"},
{"wall_time": 1512886139.883663, "step": 340, "query": "sample=0&index=4&tag=input_reshape%2Finput%2Faudio%2F0&run=test"},
{"wall_time": 1512886147.195567, "step": 410, "query": "sample=0&index=5&tag=input_reshape%2Finput%2Faudio%2F0&run=test"},
{"wall_time": 1512886156.47856, "step": 500, "query": "sample=0&index=6&tag=input_reshape%2Finput%2Faudio%2F0&run=test"},
{"wall_time": 1512886187.82793, "step": 810, "query": "sample=0&index=7&tag=input_reshape%2Finput%2Faudio%2F0&run=test"},
{"wall_time": 1512886200.386198, "step": 950, "query": "sample=0&index=8&tag=input_reshape%2Finput%2Faudio%2F0&run=test"},
{"wall_time": 1512886204.224405, "step": 990, "query": "sample=0&index=9&tag=input_reshape%2Finput%2Faudio%2F0&run=test"}
]
}
};
};
/**
* get mock data
*
* @param {string} path request path
* @param {Object} queryParam query params
* @param {Object} postParam post params
* @return {Object}
*/
module.exports = function (path, queryParam, postParam) {
return {
// moock delay
_timeout: 0,
// mock http status
_status: 200,
// mock response data
_data: {
status: 0,
msg: 'SUCCESS',
data: ''
}
};
};
/**
* get mock data
*
* @param {string} path request path
* @param {Object} queryParam query params
* @param {Object} postParam post params
* @return {Object}
*/
module.exports = function (path, queryParam, postParam) {
return {
// moock delay
_timeout: 0,
// mock http status
_status: 200,
// mock response data
_data: {
status: 0,
msg: 'SUCCESS',
data: {
"test": {
"input_reshape/input/audio/7": {
"displayName": "input_reshape/input/audio/7",
"description": "", "samples": 1
},
"input_reshape/input/audio/4": {
"displayName": "input_reshape/input/audio/4",
"description": "",
"samples": 1
},
"input_reshape/input/audio/5": {
"displayName": "input_reshape/input/audio/5",
"description": "", "samples": 1
}, "input_reshape/input/audio/2": {"displayName": "input_reshape/input/audio/2", "description": "", "samples": 1}, "input_reshape/input/audio/3": {"displayName": "input_reshape/input/audio/3", "description": "", "samples": 1}, "input_reshape/input/audio/0": {"displayName": "input_reshape/input/audio/0", "description": "", "samples": 1}, "input_reshape/input/audio/1": {"displayName": "input_reshape/input/audio/1", "description": "", "samples": 1}, "input_reshape/input/audio/8": {"displayName": "input_reshape/input/audio/8", "description": "", "samples": 1}, "input_reshape/input/audio/9": {"displayName": "input_reshape/input/audio/9", "description": "", "samples": 1}}, "train": {"input_reshape/input/audio/6": {"displayName": "input_reshape/input/audio/6", "description": "", "samples": 1}, "input_reshape/input/audio/7": {"displayName": "input_reshape/input/audio/7", "description": "", "samples": 1}, "input_reshape/input/audio/4": {"displayName": "input_reshape/input/audio/4", "description": "", "samples": 1}, "input_reshape/input/audio/5": {"displayName": "input_reshape/input/audio/5", "description": "", "samples": 1}, "input_reshape/input/audio/2": {"displayName": "input_reshape/input/audio/2", "description": "", "samples": 1}, "input_reshape/input/audio/3": {"displayName": "input_reshape/input/audio/3", "description": "", "samples": 1}, "input_reshape/input/audio/0": {"displayName": "input_reshape/input/audio/0", "description": "", "samples": 1}, "input_reshape/input/audio/1": {"displayName": "input_reshape/input/audio/1", "description": "", "samples": 1}, "input_reshape/input/audio/8": {"displayName": "input_reshape/input/audio/8", "description": "", "samples": 1}, "input_reshape/input/audio/9": {"displayName": "input_reshape/input/audio/9", "description": "", "samples": 1}}}
}
};
};
/**
* get mock data
*
* @param {string} path request path
* @param {Object} queryParam query params
* @param {Object} postParam post params
* @return {Object}
*/
module.exports = function(path, queryParam, postParam) {
if (queryParam.dimension === '3') {
return {
// moock delay
_timeout: 0,
// mock http status
_status: 200,
// mock response data
_data: {
status: 0,
msg: 'SUCCESS',
data: {
"embedding": [
[10.0, 8.04, 3],
[8.0, 6.95, 4],
[13.0, 7.58, 1],
[9.0, 8.81, 3],
[11.0, 8.33, 5],
[14.0, 9.96, 6],
[6.0, 7.24, 1],
[4.0, 4.26, 2],
[12.0, 10.84, 6],
[7.0, 4.8, 3],
[5.0, 5.68, 3]
],
"labels": [
"yellow",
"blue",
"red",
"king",
"queen",
"man",
"women",
"kid",
"adult",
"light",
"dark"
]
}
}
};
} else {
return {
// moock delay
_timeout: 0,
// mock http status
_status: 200,
// mock response data
_data: {
status: 0,
msg: 'SUCCESS',
data: {
"embedding": [
[10.0, 8.04],
[8.0, 6.95],
[13.0, 7.58],
[9.0, 8.81],
[11.0, 8.33],
[14.0, 9.96],
[6.0, 7.24],
[4.0, 4.26],
[12.0, 10.84],
[7.0, 4.8],
[5.0, 5.68]
],
"labels": [
"yellow",
"blue",
"red",
"king",
"queen",
"man",
"women",
"kid",
"adult",
"light",
"dark"
]
}
}
};
}
};
/**
* get mock data
*
* @param {string} path request path
* @param {Object} queryParam query params
* @param {Object} postParam post params
* @return {Object}
*/
module.exports = function (path, queryParam, postParam) {
return {
// moock delay
_timeout: 0,
// mock http status
_status: 200,
// mock response data
_data: {
status: 0,
msg: 'SUCCESS',
data: {
status: 0,
msg: 'SUCCESS',
// cifar10
data: {
"node":[
{
"attribute":[
{
"type":"INTS",
"name":"kernel_shape",
"ints":[
"5",
"5"
]
},
{
"type":"INTS",
"name":"strides",
"ints":[
"1",
"1"
]
},
{
"type":"INTS",
"name":"pads",
"ints":[
"0",
"0",
"0",
"0"
]
},
{
"type":"INTS",
"name":"dilations",
"ints":[
"1",
"1"
]
},
{
"i":"1",
"type":"INT",
"name":"group"
}
],
"opType":"Conv",
"output":[
"13"
],
"input":[
"1",
"2"
]
},
{
"attribute":[
{
"i":"1",
"type":"INT",
"name":"broadcast"
},
{
"i":"1",
"type":"INT",
"name":"axis"
}
],
"opType":"Add",
"output":[
"14"
],
"input":[
"13",
"3"
]
},
{
"input":[
"14"
],
"opType":"Relu",
"docString":"/usr/local/lib/python2.7/dist-packages/torch/nn/functional.py(583): relu\\ncifar10.py(82): forward\\n/usr/local/lib/python2.7/dist-packages/torch/nn/modules/module.py(325): __call__\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(236): traced_inner\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(259): wrapper\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(241): forward\\n/usr/local/lib/python2.7/dist-packages/torch/nn/modules/module.py(325): __call__\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(217): trace\\n/usr/local/lib/python2.7/dist-packages/torch/onnx/__init__.py(116): _export\\n/usr/local/lib/python2.7/dist-packages/torch/onnx/__init__.py(75): export\\ncifar10.py(130): <module>\\n",
"output":[
"15"
]
},
{
"attribute":[
{
"type":"INTS",
"name":"kernel_shape",
"ints":[
"2",
"2"
]
},
{
"type":"INTS",
"name":"pads",
"ints":[
"0",
"0"
]
},
{
"type":"INTS",
"name":"strides",
"ints":[
"2",
"2"
]
}
],
"output":[
"16"
],
"opType":"MaxPool",
"docString":"/usr/local/lib/python2.7/dist-packages/torch/nn/functional.py(334): max_pool2d\\n/usr/local/lib/python2.7/dist-packages/torch/nn/modules/pooling.py(143): forward\\n/usr/local/lib/python2.7/dist-packages/torch/nn/modules/module.py(325): __call__\\ncifar10.py(82): forward\\n/usr/local/lib/python2.7/dist-packages/torch/nn/modules/module.py(325): __call__\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(236): traced_inner\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(259): wrapper\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(241): forward\\n/usr/local/lib/python2.7/dist-packages/torch/nn/modules/module.py(325): __call__\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(217): trace\\n/usr/local/lib/python2.7/dist-packages/torch/onnx/__init__.py(116): _export\\n/usr/local/lib/python2.7/dist-packages/torch/onnx/__init__.py(75): export\\ncifar10.py(130): <module>\\n",
"input":[
"15"
]
},
{
"attribute":[
{
"type":"INTS",
"name":"kernel_shape",
"ints":[
"5",
"5"
]
},
{
"type":"INTS",
"name":"strides",
"ints":[
"1",
"1"
]
},
{
"type":"INTS",
"name":"pads",
"ints":[
"0",
"0",
"0",
"0"
]
},
{
"type":"INTS",
"name":"dilations",
"ints":[
"1",
"1"
]
},
{
"i":"1",
"type":"INT",
"name":"group"
}
],
"opType":"Conv",
"output":[
"18"
],
"input":[
"16",
"4"
]
},
{
"attribute":[
{
"i":"1",
"type":"INT",
"name":"broadcast"
},
{
"i":"1",
"type":"INT",
"name":"axis"
}
],
"opType":"Add",
"output":[
"19"
],
"input":[
"18",
"5"
]
},
{
"input":[
"19"
],
"opType":"Relu",
"docString":"/usr/local/lib/python2.7/dist-packages/torch/nn/functional.py(583): relu\\ncifar10.py(83): forward\\n/usr/local/lib/python2.7/dist-packages/torch/nn/modules/module.py(325): __call__\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(236): traced_inner\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(259): wrapper\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(241): forward\\n/usr/local/lib/python2.7/dist-packages/torch/nn/modules/module.py(325): __call__\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(217): trace\\n/usr/local/lib/python2.7/dist-packages/torch/onnx/__init__.py(116): _export\\n/usr/local/lib/python2.7/dist-packages/torch/onnx/__init__.py(75): export\\ncifar10.py(130): <module>\\n",
"output":[
"20"
]
},
{
"attribute":[
{
"type":"INTS",
"name":"kernel_shape",
"ints":[
"2",
"2"
]
},
{
"type":"INTS",
"name":"pads",
"ints":[
"0",
"0"
]
},
{
"type":"INTS",
"name":"strides",
"ints":[
"2",
"2"
]
}
],
"output":[
"21"
],
"opType":"MaxPool",
"docString":"/usr/local/lib/python2.7/dist-packages/torch/nn/functional.py(334): max_pool2d\\n/usr/local/lib/python2.7/dist-packages/torch/nn/modules/pooling.py(143): forward\\n/usr/local/lib/python2.7/dist-packages/torch/nn/modules/module.py(325): __call__\\ncifar10.py(83): forward\\n/usr/local/lib/python2.7/dist-packages/torch/nn/modules/module.py(325): __call__\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(236): traced_inner\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(259): wrapper\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(241): forward\\n/usr/local/lib/python2.7/dist-packages/torch/nn/modules/module.py(325): __call__\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(217): trace\\n/usr/local/lib/python2.7/dist-packages/torch/onnx/__init__.py(116): _export\\n/usr/local/lib/python2.7/dist-packages/torch/onnx/__init__.py(75): export\\ncifar10.py(130): <module>\\n",
"input":[
"20"
]
},
{
"attribute":[
{
"type":"INTS",
"name":"shape",
"ints":[
"-1",
"400"
]
}
],
"output":[
"22"
],
"opType":"Reshape",
"docString":"cifar10.py(84): forward\\n/usr/local/lib/python2.7/dist-packages/torch/nn/modules/module.py(325): __call__\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(236): traced_inner\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(259): wrapper\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(241): forward\\n/usr/local/lib/python2.7/dist-packages/torch/nn/modules/module.py(325): __call__\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(217): trace\\n/usr/local/lib/python2.7/dist-packages/torch/onnx/__init__.py(116): _export\\n/usr/local/lib/python2.7/dist-packages/torch/onnx/__init__.py(75): export\\ncifar10.py(130): <module>\\n",
"input":[
"21"
]
},
{
"attribute":[
{
"type":"FLOAT",
"name":"alpha",
"f":1.0
},
{
"type":"FLOAT",
"name":"beta",
"f":1.0
},
{
"i":"1",
"type":"INT",
"name":"broadcast"
},
{
"i":"1",
"type":"INT",
"name":"transB"
}
],
"output":[
"25"
],
"opType":"Gemm",
"docString":"/usr/local/lib/python2.7/dist-packages/torch/nn/functional.py(835): linear\\n/usr/local/lib/python2.7/dist-packages/torch/nn/modules/linear.py(55): forward\\n/usr/local/lib/python2.7/dist-packages/torch/nn/modules/module.py(325): __call__\\ncifar10.py(85): forward\\n/usr/local/lib/python2.7/dist-packages/torch/nn/modules/module.py(325): __call__\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(236): traced_inner\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(259): wrapper\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(241): forward\\n/usr/local/lib/python2.7/dist-packages/torch/nn/modules/module.py(325): __call__\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(217): trace\\n/usr/local/lib/python2.7/dist-packages/torch/onnx/__init__.py(116): _export\\n/usr/local/lib/python2.7/dist-packages/torch/onnx/__init__.py(75): export\\ncifar10.py(130): <module>\\n",
"input":[
"22",
"6",
"7"
]
},
{
"input":[
"25"
],
"opType":"Relu",
"docString":"/usr/local/lib/python2.7/dist-packages/torch/nn/functional.py(583): relu\\ncifar10.py(85): forward\\n/usr/local/lib/python2.7/dist-packages/torch/nn/modules/module.py(325): __call__\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(236): traced_inner\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(259): wrapper\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(241): forward\\n/usr/local/lib/python2.7/dist-packages/torch/nn/modules/module.py(325): __call__\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(217): trace\\n/usr/local/lib/python2.7/dist-packages/torch/onnx/__init__.py(116): _export\\n/usr/local/lib/python2.7/dist-packages/torch/onnx/__init__.py(75): export\\ncifar10.py(130): <module>\\n",
"output":[
"26"
]
},
{
"attribute":[
{
"type":"FLOAT",
"name":"alpha",
"f":1.0
},
{
"type":"FLOAT",
"name":"beta",
"f":1.0
},
{
"i":"1",
"type":"INT",
"name":"broadcast"
},
{
"i":"1",
"type":"INT",
"name":"transB"
}
],
"output":[
"29"
],
"opType":"Gemm",
"docString":"/usr/local/lib/python2.7/dist-packages/torch/nn/functional.py(835): linear\\n/usr/local/lib/python2.7/dist-packages/torch/nn/modules/linear.py(55): forward\\n/usr/local/lib/python2.7/dist-packages/torch/nn/modules/module.py(325): __call__\\ncifar10.py(86): forward\\n/usr/local/lib/python2.7/dist-packages/torch/nn/modules/module.py(325): __call__\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(236): traced_inner\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(259): wrapper\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(241): forward\\n/usr/local/lib/python2.7/dist-packages/torch/nn/modules/module.py(325): __call__\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(217): trace\\n/usr/local/lib/python2.7/dist-packages/torch/onnx/__init__.py(116): _export\\n/usr/local/lib/python2.7/dist-packages/torch/onnx/__init__.py(75): export\\ncifar10.py(130): <module>\\n",
"input":[
"26",
"8",
"9"
]
},
{
"input":[
"29"
],
"opType":"Relu",
"docString":"/usr/local/lib/python2.7/dist-packages/torch/nn/functional.py(583): relu\\ncifar10.py(86): forward\\n/usr/local/lib/python2.7/dist-packages/torch/nn/modules/module.py(325): __call__\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(236): traced_inner\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(259): wrapper\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(241): forward\\n/usr/local/lib/python2.7/dist-packages/torch/nn/modules/module.py(325): __call__\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(217): trace\\n/usr/local/lib/python2.7/dist-packages/torch/onnx/__init__.py(116): _export\\n/usr/local/lib/python2.7/dist-packages/torch/onnx/__init__.py(75): export\\ncifar10.py(130): <module>\\n",
"output":[
"30"
]
},
{
"attribute":[
{
"type":"FLOAT",
"name":"alpha",
"f":1.0
},
{
"type":"FLOAT",
"name":"beta",
"f":1.0
},
{
"i":"1",
"type":"INT",
"name":"broadcast"
},
{
"i":"1",
"type":"INT",
"name":"transB"
}
],
"output":[
"33"
],
"opType":"Gemm",
"docString":"/usr/local/lib/python2.7/dist-packages/torch/nn/functional.py(835): linear\\n/usr/local/lib/python2.7/dist-packages/torch/nn/modules/linear.py(55): forward\\n/usr/local/lib/python2.7/dist-packages/torch/nn/modules/module.py(325): __call__\\ncifar10.py(87): forward\\n/usr/local/lib/python2.7/dist-packages/torch/nn/modules/module.py(325): __call__\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(236): traced_inner\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(259): wrapper\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(241): forward\\n/usr/local/lib/python2.7/dist-packages/torch/nn/modules/module.py(325): __call__\\n/usr/local/lib/python2.7/dist-packages/torch/jit/__init__.py(217): trace\\n/usr/local/lib/python2.7/dist-packages/torch/onnx/__init__.py(116): _export\\n/usr/local/lib/python2.7/dist-packages/torch/onnx/__init__.py(75): export\\ncifar10.py(130): <module>\\n",
"input":[
"30",
"10",
"11"
]
}
],
"input":[
{
"shape":[
"4",
"3",
"32",
"32"
],
"name":"1",
"data_type":"FLOAT"
},
{
"shape":[
"6",
"3",
"5",
"5"
],
"name":"2",
"data_type":"FLOAT"
},
{
"shape":[
"6"
],
"name":"3",
"data_type":"FLOAT"
},
{
"shape":[
"16",
"6",
"5",
"5"
],
"name":"4",
"data_type":"FLOAT"
},
{
"shape":[
"16"
],
"name":"5",
"data_type":"FLOAT"
},
{
"shape":[
"120",
"400"
],
"name":"6",
"data_type":"FLOAT"
},
{
"shape":[
"120"
],
"name":"7",
"data_type":"FLOAT"
},
{
"shape":[
"84",
"120"
],
"name":"8",
"data_type":"FLOAT"
},
{
"shape":[
"84"
],
"name":"9",
"data_type":"FLOAT"
},
{
"shape":[
"10",
"84"
],
"name":"10",
"data_type":"FLOAT"
},
{
"shape":[
"10"
],
"name":"11",
"data_type":"FLOAT"
}
],
"edges":[
{
"source":"1",
"target":"node_0",
"label":"label_0"
},
{
"source":"2",
"target":"node_0",
"label":"label_1"
},
{
"source":"node_0",
"target":"13",
"label":"label_2"
},
{
"source":"13",
"target":"node_1",
"label":"label_3"
},
{
"source":"3",
"target":"node_1",
"label":"label_4"
},
{
"source":"node_1",
"target":"14",
"label":"label_5"
},
{
"source":"14",
"target":"node_2",
"label":"label_6"
},
{
"source":"node_2",
"target":"15",
"label":"label_7"
},
{
"source":"15",
"target":"node_3",
"label":"label_8"
},
{
"source":"node_3",
"target":"16",
"label":"label_9"
},
{
"source":"16",
"target":"node_4",
"label":"label_10"
},
{
"source":"4",
"target":"node_4",
"label":"label_11"
},
{
"source":"node_4",
"target":"18",
"label":"label_12"
},
{
"source":"18",
"target":"node_5",
"label":"label_13"
},
{
"source":"5",
"target":"node_5",
"label":"label_14"
},
{
"source":"node_5",
"target":"19",
"label":"label_15"
},
{
"source":"19",
"target":"node_6",
"label":"label_16"
},
{
"source":"node_6",
"target":"20",
"label":"label_17"
},
{
"source":"20",
"target":"node_7",
"label":"label_18"
},
{
"source":"node_7",
"target":"21",
"label":"label_19"
},
{
"source":"21",
"target":"node_8",
"label":"label_20"
},
{
"source":"node_8",
"target":"22",
"label":"label_21"
},
{
"source":"22",
"target":"node_9",
"label":"label_22"
},
{
"source":"6",
"target":"node_9",
"label":"label_23"
},
{
"source":"7",
"target":"node_9",
"label":"label_24"
},
{
"source":"node_9",
"target":"25",
"label":"label_25"
},
{
"source":"25",
"target":"node_10",
"label":"label_26"
},
{
"source":"node_10",
"target":"26",
"label":"label_27"
},
{
"source":"26",
"target":"node_11",
"label":"label_28"
},
{
"source":"8",
"target":"node_11",
"label":"label_29"
},
{
"source":"9",
"target":"node_11",
"label":"label_30"
},
{
"source":"node_11",
"target":"29",
"label":"label_31"
},
{
"source":"29",
"target":"node_12",
"label":"label_32"
},
{
"source":"node_12",
"target":"30",
"label":"label_33"
},
{
"source":"30",
"target":"node_13",
"label":"label_34"
},
{
"source":"10",
"target":"node_13",
"label":"label_35"
},
{
"source":"11",
"target":"node_13",
"label":"label_36"
},
{
"source":"node_13",
"target":"33",
"label":"label_37"
}
],
"name":"torch-jit-export",
"output":[
{
"shape":[
"4",
"10"
],
"name":"33",
"data_type":"FLOAT"
}
]
}
}
}
};
};
/**
* get mock data
*
* @param {string} path request path
* @param {Object} queryParam query params
* @param {Object} postParam post params
* @return {Object}
*/
module.exports = function (path, queryParam, postParam) {
return {
// mock delay
_timeout: 0,
// mock http status
_status: 200,
// mock response data
_data: {
status: 0,
msg: 'SUCCESS',
data: [
[1515224840.945252, 0, [
[-4.826786994934082, -5.099814079160488, 0.0],
[-5.099814079160488, -4.636194617418625, 1.0],
[-3.8315657995195243, -3.48324163592684, 125.0],
[-3.48324163592684, -3.1665833053880363, 436.0],
[-2.6170109961884593, -2.379100905625872, 5362.0],
[-2.379100905625872, -2.1628190051144287, 9589.0],
[-1.47723448201245, -1.3429404381931362, 54279.0],
[-1.3429404381931362, -1.220854943811942, 64480.0],
[-1.0089710279437536, -0.917246389039776, 89844.0],
[-0.917246389039776, -0.8338603536725235, 93854.0],
[-0.8338603536725235, -0.7580548669750213, 96552.0],
[-0.7580548669750213, -0.6891407881591103, 96980.0],
[-0.6891407881591103, -0.6264916255991911, 97035.0],
[-0.6264916255991911, -0.56953784145381, 94798.0],
[-1.316866795643118e-05, -1.1971516324028345e-05, 8.0],
[-1.1971516324028345e-05, -1.0883196658207586e-05, 1.0],
[-1.0883196658207586e-05, -9.893815143825077e-06, 1.0],
[-9.893815143825077e-06, -8.994377403477343e-06, 2.0],
[-8.994377403477343e-06, -8.176706730433948e-06, 2.0],
[-8.176706730433948e-06, -7.4333697549399525e-06, 2.0],
[-7.4333697549399525e-06, -6.757608868127229e-06, 1.0],
[-6.757608868127229e-06, -6.143280789206572e-06, 4.0],
[-6.143280789206572e-06, -5.077091561327744e-06, 0.0],
[-5.077091561327744e-06, -4.615537783025222e-06, 1.0],
[-4.615537783025222e-06, -4.1959434391138375e-06, 0.0],
[-4.1959434391138375e-06, -3.8144940355580335e-06, 2.0],
[-3.8144940355580335e-06, -3.467721850507303e-06, 1.0],
[-3.467721850507303e-06, -2.865885826865539e-06, 0.0],
[-2.865885826865539e-06, -2.605350751695944e-06, 1.0],
[-2.605350751695944e-06, -2.153182439418135e-06, 0.0],
[-1.2154153537011338e-06, -1.1049230488192125e-06, 1.0],
[-1.1049230488192125e-06, -5.670002325218022e-07, 0.0],
[2.5662008430919505e-05, 2.822820927401146e-05, 8.0],
[2.822820927401146e-05, 3.1051030201412604e-05, 4.0],
[3.1051030201412604e-05, 3.415613322155387e-05, 4.0],
[3.415613322155387e-05, 3.757174654370926e-05, 6.0],
[3.757174654370926e-05, 4.132892119808019e-05, 7.0],
[4.132892119808019e-05, 4.546181331788821e-05, 8.0],
[4.546181331788821e-05, 5.000799464967703e-05, 19.0],
[5.000799464967703e-05, 5.500879411464474e-05, 18.0],
[5.500879411464474e-05, 6.050967352610922e-05, 10.0],
[6.050967352610922e-05, 6.656064087872014e-05, 12.0],
[6.656064087872014e-05, 7.321670496659217e-05, 13.0],
[7.321670496659217e-05, 8.053837546325138e-05, 14.0],
[8.053837546325138e-05, 8.859221300957652e-05, 18.0],
[8.859221300957652e-05, 9.745143431053419e-05, 22.0],
[9.745143431053419e-05, 0.00010719657774158762, 23.0],
[0.00010719657774158762, 0.00011791623551574639, 34.0],
[0.917246389039776, 1.0089710279437536, 124200.0],
[1.0089710279437536, 1.109868130738129, 119511.0],
[1.109868130738129, 1.220854943811942, 111589.0],
[1.220854943811942, 1.3429404381931362, 101296.0],
[2.8787120958073054, 3.1665833053880363, 3382.0],
[3.1665833053880363, 3.48324163592684, 1351.0],
[3.48324163592684, 3.8315657995195243, 468.0],
[3.8315657995195243, 4.214722379471477, 105.0]
]
],
[1515224846.83122, 70, [
[-5.609264373779297, -5.609795487076537, 0.0],
[-5.609795487076537, -5.099814079160488, 5.0],
[-5.099814079160488, -4.636194617418625, 26.0],
[-4.636194617418625, -4.214722379471477, 114.0],
[-4.214722379471477, -3.8315657995195243, 379.0],
[-3.8315657995195243, -3.48324163592684, 1072.0],
[-3.48324163592684, -3.1665833053880363, 2542.0],
[-3.1665833053880363, -2.8787120958073054, 5260.0],
[-2.8787120958073054, -2.6170109961884593, 9568.0],
[-2.6170109961884593, -2.379100905625872, 15632.0],
[-2.379100905625872, -2.1628190051144287, 23154.0],
[-2.1628190051144287, -1.9661990955585713, 31489.0],
[-1.9661990955585713, -1.7874537232350647, 41367.0],
[-1.7874537232350647, -1.624957930213695, 50809.0],
[-0.052566063576589855, -0.04778733052417259, 10183.0],
[-0.04778733052417259, -0.043443027749247805, 9196.0],
[-0.01143990698806325, -0.010399915443693864, 2264.0],
[-0.010399915443693864, -0.00945446858517624, 2012.0],
[0.0007211649713244094, 0.0007932814684568504, 152.0],
[0.0007932814684568504, 0.0008726096153025355, 168.0],
[0.0008726096153025355, 0.0009598705768327891, 179.0],
[0.0009598705768327891, 0.001055857634516068, 198.0],
[0.47069243095356195, 0.5177616740489182, 96395.0],
[0.5177616740489182, 0.56953784145381, 103088.0],
[0.56953784145381, 0.6264916255991911, 110245.0],
[0.6264916255991911, 0.6891407881591103, 116777.0],
[0.6891407881591103, 0.7580548669750213, 123501.0],
[0.7580548669750213, 0.8338603536725235, 127806.0],
[0.8338603536725235, 0.917246389039776, 132276.0],
[0.917246389039776, 1.0089710279437536, 134169.0],
[1.0089710279437536, 1.109868130738129, 133209.0],
[1.109868130738129, 1.220854943811942, 129736.0],
[2.6170109961884593, 2.8787120958073054, 14814.0],
[2.8787120958073054, 3.1665833053880363, 8284.0],
[3.8315657995195243, 4.214722379471477, 699.0],
[4.214722379471477, 4.636194617418625, 245.0],
[4.636194617418625, 5.099814079160488, 64.0],
[5.099814079160488, 5.609795487076537, 22.0],
[5.609795487076537, 6.1707750357841915, 2.0],
[6.1707750357841915, 6.077327728271484, 0.0]
]
],
[1515224850.414384, 100, [
[-5.622415065765381, -6.1707750357841915, 0.0],
[-6.1707750357841915, -5.609795487076537, 1.0],
[-4.636194617418625, -4.214722379471477, 130.0],
[-4.214722379471477, -3.8315657995195243, 364.0],
[-3.8315657995195243, -3.48324163592684, 1063.0],
[-3.48324163592684, -3.1665833053880363, 2440.0],
[-2.6170109961884593, -2.379100905625872, 15079.0],
[-2.379100905625872, -2.1628190051144287, 22447.0],
[-1.0089710279437536, -0.917246389039776, 89632.0],
[-0.917246389039776, -0.8338603536725235, 91513.0],
[-0.8338603536725235, -0.7580548669750213, 91158.0],
[-0.7580548669750213, -0.6891407881591103, 89568.0],
[-0.6891407881591103, -0.6264916255991911, 88244.0],
[-0.6264916255991911, -0.56953784145381, 84929.0],
[-4.757441129747921e-08, 5.15454756838002e-07, 0.0],
[5.15454756838002e-07, 5.670002325218022e-07, 1.0],
[5.670002325218022e-07, 6.237002557739824e-07, 0.0],
[6.237002557739824e-07, 6.860702813513807e-07, 1.0],
[6.860702813513807e-07, 8.301450404351707e-07, 0.0],
[8.301450404351707e-07, 9.131595444786879e-07, 1.0],
[9.131595444786879e-07, 1.0044754989265568e-06, 1.0],
[1.0044754989265568e-06, 1.6177178357762093e-06, 0.0],
[6.757608868127229e-06, 7.4333697549399525e-06, 1.0],
[7.4333697549399525e-06, 8.176706730433948e-06, 2.0],
[8.176706730433948e-06, 8.994377403477343e-06, 1.0],
[8.994377403477343e-06, 9.893815143825077e-06, 0.0],
[9.893815143825077e-06, 1.0883196658207586e-05, 3.0],
[1.0883196658207586e-05, 1.1971516324028345e-05, 2.0],
[1.1971516324028345e-05, 1.316866795643118e-05, 3.0],
[1.316866795643118e-05, 1.44855347520743e-05, 4.0],
[3.757174654370926e-05, 4.132892119808019e-05, 8.0],
[4.132892119808019e-05, 4.546181331788821e-05, 8.0],
[4.546181331788821e-05, 5.000799464967703e-05, 7.0],
[5.000799464967703e-05, 5.500879411464474e-05, 10.0],
[5.500879411464474e-05, 6.050967352610922e-05, 13.0],
[6.050967352610922e-05, 6.656064087872014e-05, 11.0],
[6.656064087872014e-05, 7.321670496659217e-05, 15.0],
[7.321670496659217e-05, 8.053837546325138e-05, 16.0],
[8.053837546325138e-05, 8.859221300957652e-05, 27.0],
[8.859221300957652e-05, 9.745143431053419e-05, 17.0],
[0.8338603536725235, 0.917246389039776, 130481.0],
[0.917246389039776, 1.0089710279437536, 133238.0],
[1.0089710279437536, 1.109868130738129, 131855.0],
[1.109868130738129, 1.220854943811942, 129006.0],
[2.6170109961884593, 2.8787120958073054, 14697.0],
[2.8787120958073054, 3.1665833053880363, 8234.0],
[3.1665833053880363, 3.48324163592684, 4187.0],
[3.48324163592684, 3.8315657995195243, 1800.0],
[4.636194617418625, 5.099814079160488, 67.0],
[5.099814079160488, 5.609795487076537, 22.0],
[5.609795487076537, 6.1707750357841915, 3.0],
[6.1707750357841915, 6.0968852043151855, 0.0]
]
],
[1515224852.17382, 120, [
[-5.641714572906494, -6.1707750357841915, 0.0],
[-6.1707750357841915, -5.609795487076537, 1.0],
[-5.609795487076537, -5.099814079160488, 8.0],
[-5.099814079160488, -4.636194617418625, 23.0],
[-4.636194617418625, -4.214722379471477, 134.0],
[-4.214722379471477, -3.8315657995195243, 325.0],
[-3.8315657995195243, -3.48324163592684, 980.0],
[-3.48324163592684, -3.1665833053880363, 2241.0],
[-3.1665833053880363, -2.8787120958073054, 4732.0],
[-2.8787120958073054, -2.6170109961884593, 8511.0],
[-2.6170109961884593, -2.379100905625872, 14412.0],
[-2.379100905625872, -2.1628190051144287, 21324.0],
[-2.1628190051144287, -1.9661990955585713, 30265.0],
[-1.9661990955585713, -1.7874537232350647, 39939.0],
[-1.7874537232350647, -1.624957930213695, 49754.0],
[-1.624957930213695, -1.47723448201245, 59029.0],
[-1.47723448201245, -1.3429404381931362, 67624.0],
[-1.3429404381931362, -1.220854943811942, 75809.0],
[-1.220854943811942, -1.109868130738129, 82164.0],
[-1.109868130738129, -1.0089710279437536, 86962.0],
[-1.0089710279437536, -0.917246389039776, 90354.0],
[-0.917246389039776, -0.8338603536725235, 91382.0],
[-0.8338603536725235, -0.7580548669750213, 91667.0],
[-0.7580548669750213, -0.6891407881591103, 90086.0],
[-0.6891407881591103, -0.6264916255991911, 88401.0],
[-0.6264916255991911, -0.56953784145381, 85407.0],
[3.1051030201412604e-05, 3.415613322155387e-05, 8.0],
[8.053837546325138e-05, 8.859221300957652e-05, 11.0],
[0.012583897686869577, 0.013842287455556535, 2645.0],
[0.013842287455556535, 0.01522651620111219, 3037.0],
[0.01522651620111219, 0.01674916782122341, 3297.0],
[0.01674916782122341, 0.018424084603345752, 3686.0],
[0.018424084603345752, 0.02026649306368033, 3954.0],
[0.02026649306368033, 0.022293142370048362, 4388.0],
[0.022293142370048362, 0.0245224566070532, 4888.0],
[0.0245224566070532, 0.026974702267758523, 5350.0],
[0.026974702267758523, 0.02967217249453438, 5800.0],
[0.02967217249453438, 0.03263938974398782, 6459.0],
[0.03263938974398782, 0.035903328718386605, 7217.0],
[0.035903328718386605, 0.03949366159022527, 7816.0],
[0.03949366159022527, 0.043443027749247805, 8647.0],
[0.043443027749247805, 0.04778733052417259, 9398.0],
[0.04778733052417259, 0.052566063576589855, 10457.0],
[0.052566063576589855, 0.057822669934248845, 11420.0],
[0.057822669934248845, 0.06360493692767373, 12728.0],
[0.06360493692767373, 0.06996543062044111, 13975.0],
[0.06996543062044111, 0.07696197368248522, 15413.0],
[0.07696197368248522, 0.08465817105073375, 17143.0],
[0.08465817105073375, 0.09312398815580714, 19025.0],
[0.09312398815580714, 0.10243638697138786, 20509.0],
[0.10243638697138786, 0.11268002566852665, 22060.0],
[0.11268002566852665, 0.12394802823537933, 24938.0],
[0.12394802823537933, 0.13634283105891729, 27263.0],
[1.7874537232350647, 1.9661990955585713, 68215.0],
[1.9661990955585713, 2.1628190051144287, 51944.0],
[2.1628190051144287, 2.379100905625872, 36899.0],
[2.379100905625872, 2.6170109961884593, 23872.0],
[4.636194617418625, 5.099814079160488, 68.0],
[5.099814079160488, 5.609795487076537, 22.0],
[5.609795487076537, 6.1707750357841915, 3.0],
[6.1707750357841915, 6.084466934204102, 0.0]
]
],
]
}
};
};
/**
* get mock data
*
* @param {string} path request path
* @param {Object} queryParam query params
* @param {Object} postParam post params
* @return {Object}
*/
module.exports = function (path, queryParam, postParam) {
return {
// moock delay
_timeout: 0,
// mock http status
_status: 200,
// mock response data
_data: {
status: 0,
msg: 'SUCCESS',
data: {
"test": {
"layer1/Wx_plus_b/pre_activations":
{
"displayName": "layer1/Wx_plus_b/pre_activations",
"description": ""
},
"layer1/Wx_plus_b/pre_activations_1":
{
"displayName": "layer1/Wx_plus_b/pre_activations_1",
"description": ""
}
},
"train": {
"layer1/Wx_plus_b/pre_activations":
{
"displayName": "layer1/Wx_plus_b/pre_activations",
"description": ""
},
"layer1/Wx_plus_b/pre_activations_1":
{
"displayName": "layer1/Wx_plus_b/pre_activations_1",
"description": ""
}
}
}
}
};
};
/**
* get mock data
*
* @param {string} path request path
* @param {Object} queryParam query params
* @param {Object} postParam post params
* @return {Object}
*/
module.exports = function (path, queryParam, postParam) {
return {
// moock delay
_timeout: 0,
// mock http status
_status: 200,
// mock response data
_data: {
status: 0,
msg: 'SUCCESS',
data: [
{
"wall_time": 1512549785.061623,
"step": 60,
"query": "sample=0&index=0&tag=input_reshape%2Finput%2Fimage%2F0&run=test",
"width": 28,
"height": 28
},
{"wall_time": 1512886109.672786, "step": 60, "query": "sample=0&index=1&tag=input_reshape%2Finput%2Fimage%2F0&run=test", "width": 28, "height": 28},
{"wall_time": 1512886124.266915, "step": 210, "query": "sample=0&index=2&tag=input_reshape%2Finput%2Fimage%2F0&run=test", "width": 28, "height": 28},
{"wall_time": 1512886138.898628, "step": 330, "query": "sample=0&index=3&tag=input_reshape%2Finput%2Fimage%2F0&run=test", "width": 28, "height": 28},
{"wall_time": 1512886139.883663, "step": 340, "query": "sample=0&index=4&tag=input_reshape%2Finput%2Fimage%2F0&run=test", "width": 28, "height": 28},
{"wall_time": 1512886147.195567, "step": 410, "query": "sample=0&index=5&tag=input_reshape%2Finput%2Fimage%2F0&run=test", "width": 28, "height": 28},
{"wall_time": 1512886156.47856, "step": 500, "query": "sample=0&index=6&tag=input_reshape%2Finput%2Fimage%2F0&run=test", "width": 28, "height": 28},
{"wall_time": 1512886187.82793, "step": 810, "query": "sample=0&index=7&tag=input_reshape%2Finput%2Fimage%2F0&run=test", "width": 28, "height": 28},
{"wall_time": 1512886200.386198, "step": 950, "query": "sample=0&index=8&tag=input_reshape%2Finput%2Fimage%2F0&run=test", "width": 28, "height": 28},
{"wall_time": 1512886204.224405, "step": 990, "query": "sample=0&index=9&tag=input_reshape%2Finput%2Fimage%2F0&run=test", "width": 28, "height": 28}
]
}
};
};
/**
* get mock data
*
* @param {string} path request path
* @param {Object} queryParam query params
* @param {Object} postParam post params
* @return {Object}
*/
module.exports = function (path, queryParam, postParam) {
return {
// moock delay
_timeout: 0,
// mock http status
_status: 200,
// mock response data
_data: {
status: 0,
msg: 'SUCCESS',
data: ''
}
};
};
/**
* get mock data
*
* @param {string} path request path
* @param {Object} queryParam query params
* @param {Object} postParam post params
* @return {Object}
*/
module.exports = function (path, queryParam, postParam) {
return {
// moock delay
_timeout: 0,
// mock http status
_status: 200,
// mock response data
_data: {
status: 0,
msg: 'SUCCESS',
data: {
"test": {
"input_reshape/input/image/7": {
"displayName": "input_reshape/input/image/7",
"description": "", "samples": 1
},
"input_reshape/input/image/4": {
"displayName": "input_reshape/input/image/4",
"description": "",
"samples": 1
},
"input_reshape/input/image/5": {
"displayName": "input_reshape/input/image/5",
"description": "", "samples": 1
}, "input_reshape/input/image/2": {"displayName": "input_reshape/input/image/2", "description": "", "samples": 1}, "input_reshape/input/image/3": {"displayName": "input_reshape/input/image/3", "description": "", "samples": 1}, "input_reshape/input/image/0": {"displayName": "input_reshape/input/image/0", "description": "", "samples": 1}, "input_reshape/input/image/1": {"displayName": "input_reshape/input/image/1", "description": "", "samples": 1}, "input_reshape/input/image/8": {"displayName": "input_reshape/input/image/8", "description": "", "samples": 1}, "input_reshape/input/image/9": {"displayName": "input_reshape/input/image/9", "description": "", "samples": 1}}, "train": {"input_reshape/input/image/6": {"displayName": "input_reshape/input/image/6", "description": "", "samples": 1}, "input_reshape/input/image/7": {"displayName": "input_reshape/input/image/7", "description": "", "samples": 1}, "input_reshape/input/image/4": {"displayName": "input_reshape/input/image/4", "description": "", "samples": 1}, "input_reshape/input/image/5": {"displayName": "input_reshape/input/image/5", "description": "", "samples": 1}, "input_reshape/input/image/2": {"displayName": "input_reshape/input/image/2", "description": "", "samples": 1}, "input_reshape/input/image/3": {"displayName": "input_reshape/input/image/3", "description": "", "samples": 1}, "input_reshape/input/image/0": {"displayName": "input_reshape/input/image/0", "description": "", "samples": 1}, "input_reshape/input/image/1": {"displayName": "input_reshape/input/image/1", "description": "", "samples": 1}, "input_reshape/input/image/8": {"displayName": "input_reshape/input/image/8", "description": "", "samples": 1}, "input_reshape/input/image/9": {"displayName": "input_reshape/input/image/9", "description": "", "samples": 1}}}
}
};
};
/**
* get mock data
*
* @param {string} path request path
* @param {Object} queryParam query params
* @param {Object} postParam post params
* @return {Object}
*/
module.exports = function (path, queryParam, postParam) {
if (queryParam.run === 'train') {
return {
// moock delay
_timeout: 0,
// mock http status
_status: 200,
// mock response data
_data: {
status: 0,
msg: 'SUCCESS',
data: [[1511842145.705075, 1, 0.05000000074505806], [1511842145.7388, 2, 0.12999999523162842], [1511842145.774563, 3, 0.27000001072883606], [1511842145.806828, 4, 0.4399999976158142], [1511842145.838082, 5, 0.47999998927116394], [1511842145.868955, 6, 0.5899999737739563], [1511842145.899323, 7, 0.6100000143051147], [1511842145.930518, 8, 0.699999988079071], [1511842145.96089, 9, 0.6700000166893005], [1511842146.460557, 11, 0.6499999761581421], [1511842146.4952, 12, 0.7300000190734863], [1511842146.525936, 13, 0.6899999976158142], [1511842146.556059, 14, 0.75], [1511842146.648703, 15, 0.7099999785423279], [1511842146.683295, 16, 0.7900000214576721], [1511842146.719782, 17, 0.8299999833106995], [1511842146.752392, 18, 0.7900000214576721], [1511842146.786562, 19, 0.8299999833106995], [1511842147.296362, 21, 0.8199999928474426], [1511842147.329616, 22, 0.75], [1511842147.36413, 23, 0.800000011920929], [1511842147.394166, 24, 0.8700000047683716], [1511842147.426248, 25, 0.8500000238418579], [1511842147.455792, 26, 0.8799999952316284], [1511842147.486918, 27, 0.8600000143051147], [1511842147.516537, 28, 0.8399999737739563], [1511842147.545978, 29, 0.8999999761581421], [1511842148.059008, 31, 0.8299999833106995], [1511842148.093655, 32, 0.8500000238418579], [1511842148.126041, 33, 0.8799999952316284], [1511842148.156253, 34, 0.9100000262260437], [1511842148.189653, 35, 0.8700000047683716], [1511842148.221602, 36, 0.800000011920929], [1511842148.251149, 37, 0.7900000214576721], [1511842148.281332, 38, 0.8700000047683716], [1511842148.312354, 39, 0.8500000238418579], [1511842148.828949, 41, 0.8700000047683716], [1511842148.865255, 42, 0.8600000143051147], [1511842148.898558, 43, 0.8999999761581421], [1511842148.93859, 44, 0.8799999952316284], [1511842148.97468, 45, 0.8799999952316284], [1511842149.013585, 46, 0.8299999833106995], [1511842149.044709, 47, 0.8500000238418579], [1511842149.077821, 48, 0.8700000047683716], [1511842149.107665, 49, 0.8899999856948853], [1511842149.647978, 51, 0.8600000143051147], [1511842149.686268, 52, 0.8999999761581421], [1511842149.722652, 53, 0.8700000047683716], [1511842149.758858, 54, 0.8700000047683716], [1511842149.795508, 55, 0.8999999761581421], [1511842149.830682, 56, 0.8700000047683716], [1511842149.874498, 57, 0.8600000143051147], [1511842149.916357, 58, 0.8399999737739563], [1511842149.951223, 59, 0.8600000143051147], [1511842150.470112, 61, 0.8500000238418579], [1511842150.505811, 62, 0.9399999976158142], [1511842150.542528, 63, 0.8399999737739563], [1511842150.579082, 64, 0.8999999761581421], [1511842150.611267, 65, 0.8799999952316284], [1511842150.642279, 66, 0.8500000238418579], [1511842150.679586, 67, 0.9399999976158142], [1511842150.709423, 68, 0.8999999761581421], [1511842150.742542, 69, 0.9200000166893005], [1511842151.287115, 71, 0.8700000047683716], [1511842151.320888, 72, 0.9200000166893005], [1511842151.352388, 73, 0.8600000143051147], [1511842151.385154, 74, 0.8600000143051147], [1511842151.421342, 75, 0.8399999737739563], [1511842151.458697, 76, 0.8999999761581421], [1511842151.492929, 77, 0.8399999737739563], [1511842151.524682, 78, 0.9200000166893005], [1511842151.55707, 79, 0.8799999952316284], [1511842152.071344, 81, 0.8500000238418579], [1511842152.101479, 82, 0.949999988079071], [1511842152.132134, 83, 0.8999999761581421], [1511842152.165848, 84, 0.8799999952316284], [1511842152.195162, 85, 0.8899999856948853], [1511842152.224646, 86, 0.9399999976158142], [1511842152.255385, 87, 0.9300000071525574], [1511842152.28573, 88, 0.9100000262260437], [1511842152.315899, 89, 0.8999999761581421], [1511842152.834572, 91, 0.8899999856948853], [1511842152.872045, 92, 0.949999988079071], [1511842152.904879, 93, 0.9800000190734863], [1511842152.940016, 94, 0.8700000047683716], [1511842152.976859, 95, 0.8500000238418579], [1511842153.012571, 96, 0.8999999761581421], [1511842153.043776, 97, 0.8199999928474426], [1511842153.081662, 98, 0.8799999952316284], [1511842153.190446, 99, 0.8700000047683716], [1511842153.698591, 101, 0.9200000166893005], [1511842153.732005, 102, 0.9300000071525574], [1511842153.765796, 103, 0.8500000238418579], [1511842153.797352, 104, 0.9700000286102295], [1511842153.831314, 105, 0.9599999785423279], [1511842153.866427, 106, 0.9300000071525574], [1511842153.896475, 107, 0.8999999761581421], [1511842153.929657, 108, 0.9200000166893005], [1511842153.965421, 109, 0.949999988079071], [1511842154.485552, 111, 0.949999988079071], [1511842154.516489, 112, 0.9100000262260437], [1511842154.548223, 113, 0.8799999952316284], [1511842154.580801, 114, 0.9200000166893005], [1511842154.611307, 115, 0.9200000166893005], [1511842154.642873, 116, 0.9200000166893005], [1511842154.6751, 117, 0.9300000071525574], [1511842154.707684, 118, 0.8999999761581421], [1511842154.744283, 119, 0.9300000071525574], [1511842155.255668, 121, 0.9200000166893005], [1511842155.288454, 122, 0.8899999856948853], [1511842155.320779, 123, 0.9599999785423279], [1511842155.353925, 124, 0.9200000166893005], [1511842155.389438, 125, 0.8899999856948853], [1511842155.424823, 126, 0.9399999976158142], [1511842155.454526, 127, 0.9300000071525574], [1511842155.489204, 128, 0.9399999976158142], [1511842155.521019, 129, 0.9399999976158142], [1511842156.033606, 131, 0.8999999761581421], [1511842156.071066, 132, 0.9100000262260437], [1511842156.100447, 133, 0.8899999856948853], [1511842156.132395, 134, 0.9200000166893005], [1511842156.165163, 135, 0.8700000047683716], [1511842156.203128, 136, 0.8999999761581421], [1511842156.239275, 137, 0.8399999737739563], [1511842156.270908, 138, 0.9200000166893005], [1511842156.303224, 139, 0.9200000166893005], [1511842156.823475, 141, 0.9300000071525574], [1511842156.860178, 142, 0.8999999761581421], [1511842156.89245, 143, 0.8500000238418579], [1511842156.932155, 144, 0.9300000071525574], [1511842156.966936, 145, 0.8999999761581421], [1511842157.002507, 146, 0.9100000262260437], [1511842157.04046, 147, 0.949999988079071], [1511842157.075624, 148, 0.8799999952316284], [1511842157.113062, 149, 0.9100000262260437], [1511842157.610962, 151, 0.9200000166893005], [1511842157.644282, 152, 0.8899999856948853], [1511842157.674532, 153, 0.9399999976158142], [1511842157.704223, 154, 0.9700000286102295], [1511842157.734917, 155, 0.9100000262260437], [1511842157.766545, 156, 0.949999988079071], [1511842157.803228, 157, 0.9300000071525574], [1511842157.833582, 158, 0.9399999976158142], [1511842157.863983, 159, 0.9599999785423279], [1511842158.365138, 161, 0.9399999976158142], [1511842158.402051, 162, 0.8999999761581421], [1511842158.432824, 163, 0.9100000262260437], [1511842158.468544, 164, 0.9399999976158142], [1511842158.501693, 165, 0.9200000166893005], [1511842158.536712, 166, 0.9200000166893005], [1511842158.576052, 167, 0.9100000262260437], [1511842158.608077, 168, 0.9300000071525574], [1511842158.639638, 169, 0.9399999976158142], [1511842159.144704, 171, 0.949999988079071], [1511842159.175508, 172, 0.9200000166893005], [1511842159.206246, 173, 0.9399999976158142], [1511842159.236448, 174, 0.949999988079071], [1511842159.268592, 175, 0.8999999761581421], [1511842159.298385, 176, 0.8999999761581421], [1511842159.330691, 177, 0.9200000166893005], [1511842159.362888, 178, 0.949999988079071], [1511842159.394601, 179, 0.8899999856948853], [1511842159.917987, 181, 0.8500000238418579], [1511842159.949645, 182, 0.9800000190734863], [1511842159.980383, 183, 0.9399999976158142], [1511842160.011846, 184, 0.8999999761581421], [1511842160.043909, 185, 0.8999999761581421], [1511842160.082747, 186, 0.8999999761581421], [1511842160.116125, 187, 0.949999988079071], [1511842160.147119, 188, 0.9100000262260437], [1511842160.182338, 189, 0.9599999785423279], [1511842160.69661, 191, 0.9300000071525574], [1511842160.72888, 192, 0.8899999856948853], [1511842160.762084, 193, 0.9300000071525574], [1511842160.792814, 194, 0.9599999785423279], [1511842160.823444, 195, 0.9100000262260437], [1511842160.852744, 196, 0.9399999976158142], [1511842160.885255, 197, 0.9599999785423279], [1511842160.917985, 198, 0.8999999761581421], [1511842161.028077, 199, 0.949999988079071], [1511842161.548108, 201, 0.9300000071525574], [1511842161.580669, 202, 0.9100000262260437], [1511842161.613862, 203, 0.949999988079071], [1511842161.653309, 204, 0.8899999856948853], [1511842161.691085, 205, 0.9599999785423279], [1511842161.72533, 206, 0.9200000166893005], [1511842161.754774, 207, 0.9300000071525574], [1511842161.786702, 208, 0.9300000071525574], [1511842161.820508, 209, 0.8999999761581421], [1511842162.336378, 211, 0.949999988079071], [1511842162.373533, 212, 0.949999988079071], [1511842162.411207, 213, 0.8899999856948853], [1511842162.4438, 214, 0.9300000071525574], [1511842162.477444, 215, 0.949999988079071], [1511842162.509545, 216, 0.9399999976158142], [1511842162.543586, 217, 0.949999988079071], [1511842162.574829, 218, 0.9300000071525574], [1511842162.612825, 219, 0.9399999976158142], [1511842163.134331, 221, 0.9700000286102295], [1511842163.169464, 222, 0.9200000166893005], [1511842163.203311, 223, 0.9700000286102295], [1511842163.240668, 224, 0.9300000071525574], [1511842163.278642, 225, 0.9100000262260437], [1511842163.318872, 226, 0.9300000071525574], [1511842163.361079, 227, 0.9300000071525574], [1511842163.397876, 228, 0.9800000190734863], [1511842163.430826, 229, 0.9599999785423279], [1511842163.953991, 231, 0.9300000071525574], [1511842163.988582, 232, 0.9399999976158142], [1511842164.021841, 233, 0.949999988079071], [1511842164.052817, 234, 0.9300000071525574], [1511842164.090031, 235, 0.9399999976158142], [1511842164.121797, 236, 0.9100000262260437], [1511842164.158074, 237, 0.949999988079071], [1511842164.189932, 238, 0.9300000071525574], [1511842164.225797, 239, 0.9200000166893005], [1511842164.742692, 241, 0.949999988079071], [1511842164.773757, 242, 0.9800000190734863], [1511842164.810333, 243, 0.9300000071525574], [1511842164.840904, 244, 0.949999988079071], [1511842164.875269, 245, 0.949999988079071], [1511842164.907458, 246, 0.9700000286102295], [1511842164.940818, 247, 0.9200000166893005], [1511842165.032471, 248, 0.9399999976158142], [1511842165.06494, 249, 0.9399999976158142], [1511842165.711591, 251, 0.9200000166893005], [1511842165.742034, 252, 0.9399999976158142], [1511842165.776186, 253, 0.9100000262260437], [1511842165.80631, 254, 0.9300000071525574], [1511842165.841813, 255, 0.9700000286102295], [1511842165.88272, 256, 0.9100000262260437], [1511842165.914834, 257, 0.9399999976158142], [1511842165.944832, 258, 0.8999999761581421], [1511842165.977476, 259, 0.8999999761581421], [1511842166.49414, 261, 0.9300000071525574], [1511842166.530139, 262, 0.9300000071525574], [1511842166.582532, 263, 0.9200000166893005], [1511842166.624934, 264, 0.9399999976158142], [1511842166.65914, 265, 0.9200000166893005], [1511842166.708159, 266, 0.949999988079071], [1511842166.738785, 267, 0.8899999856948853], [1511842166.789074, 268, 0.9599999785423279], [1511842166.821725, 269, 0.949999988079071], [1511842167.351619, 271, 0.8899999856948853], [1511842167.383981, 272, 0.949999988079071], [1511842167.415674, 273, 0.9300000071525574], [1511842167.453889, 274, 0.9300000071525574], [1511842167.487546, 275, 0.9800000190734863], [1511842167.520855, 276, 0.8999999761581421], [1511842167.553859, 277, 0.949999988079071], [1511842167.591104, 278, 0.9800000190734863], [1511842167.627239, 279, 0.9100000262260437], [1511842168.151087, 281, 0.9599999785423279], [1511842168.185722, 282, 0.9300000071525574], [1511842168.225793, 283, 0.9399999976158142], [1511842168.265352, 284, 0.9200000166893005], [1511842168.297638, 285, 0.9599999785423279], [1511842168.331366, 286, 0.8899999856948853], [1511842168.367654, 287, 0.949999988079071], [1511842168.404366, 288, 0.9200000166893005], [1511842168.437306, 289, 0.9599999785423279], [1511842168.977181, 291, 0.9700000286102295], [1511842169.008927, 292, 0.8999999761581421], [1511842169.043079, 293, 0.8999999761581421], [1511842169.079313, 294, 0.9599999785423279], [1511842169.111267, 295, 0.8899999856948853], [1511842169.141979, 296, 0.9700000286102295], [1511842169.173568, 297, 0.9399999976158142], [1511842169.206784, 298, 0.9399999976158142], [1511842169.318883, 299, 0.9100000262260437], [1511842169.836233, 301, 0.949999988079071], [1511842169.869173, 302, 0.9300000071525574], [1511842169.899444, 303, 0.9599999785423279], [1511842169.93236, 304, 0.9399999976158142], [1511842169.964287, 305, 0.9200000166893005], [1511842169.999156, 306, 0.9399999976158142], [1511842170.04658, 307, 0.949999988079071], [1511842170.079765, 308, 0.9399999976158142], [1511842170.116286, 309, 0.9100000262260437], [1511842170.626257, 311, 0.9599999785423279], [1511842170.660356, 312, 0.9399999976158142], [1511842170.69418, 313, 0.9200000166893005], [1511842170.72758, 314, 0.8999999761581421], [1511842170.761281, 315, 0.9399999976158142], [1511842170.795563, 316, 0.9399999976158142], [1511842170.831212, 317, 0.949999988079071], [1511842170.865901, 318, 0.9200000166893005], [1511842170.900623, 319, 0.9100000262260437], [1511842171.442059, 321, 0.9200000166893005], [1511842171.474961, 322, 0.8999999761581421], [1511842171.506307, 323, 0.9399999976158142], [1511842171.539442, 324, 0.949999988079071], [1511842171.570183, 325, 0.9700000286102295], [1511842171.600969, 326, 0.9300000071525574], [1511842171.6316, 327, 0.949999988079071], [1511842171.665024, 328, 0.9399999976158142], [1511842171.697585, 329, 0.9399999976158142], [1511842172.226505, 331, 0.9300000071525574], [1511842172.261344, 332, 0.949999988079071], [1511842172.296245, 333, 0.9300000071525574], [1511842172.326279, 334, 0.9700000286102295], [1511842172.358168, 335, 0.9100000262260437], [1511842172.392341, 336, 0.9399999976158142], [1511842172.422466, 337, 0.9399999976158142], [1511842172.459868, 338, 0.9599999785423279], [1511842172.493555, 339, 0.949999988079071], [1511842173.033582, 341, 0.949999988079071], [1511842173.073034, 342, 0.9300000071525574], [1511842173.104858, 343, 0.9599999785423279], [1511842173.140056, 344, 0.8899999856948853], [1511842173.178958, 345, 0.9399999976158142], [1511842173.21675, 346, 0.9300000071525574], [1511842173.246909, 347, 0.9700000286102295], [1511842173.282099, 348, 0.9100000262260437], [1511842173.317242, 349, 0.9599999785423279], [1511842173.847353, 351, 0.9599999785423279], [1511842173.885366, 352, 0.9599999785423279], [1511842173.921206, 353, 0.8999999761581421], [1511842173.953769, 354, 0.9399999976158142], [1511842173.991128, 355, 0.9599999785423279], [1511842174.02312, 356, 0.8700000047683716], [1511842174.056031, 357, 0.9399999976158142], [1511842174.08923, 358, 0.9599999785423279], [1511842174.127158, 359, 0.9800000190734863], [1511842174.652944, 361, 0.9200000166893005], [1511842174.687431, 362, 0.9900000095367432], [1511842174.71948, 363, 0.9399999976158142], [1511842174.753943, 364, 0.9599999785423279], [1511842174.78847, 365, 0.9700000286102295], [1511842174.823361, 366, 0.8799999952316284], [1511842174.856826, 367, 0.9300000071525574], [1511842174.891638, 368, 0.8999999761581421], [1511842174.925622, 369, 0.9599999785423279], [1511842175.439573, 371, 0.9700000286102295], [1511842175.474021, 372, 0.9300000071525574], [1511842175.504075, 373, 0.9599999785423279], [1511842175.540268, 374, 0.9599999785423279], [1511842175.574921, 375, 0.9800000190734863], [1511842175.608212, 376, 0.949999988079071], [1511842175.64061, 377, 0.949999988079071], [1511842175.671253, 378, 0.9399999976158142], [1511842175.702623, 379, 0.949999988079071], [1511842176.214339, 381, 0.949999988079071], [1511842176.248076, 382, 0.8999999761581421], [1511842176.286246, 383, 0.949999988079071], [1511842176.319941, 384, 0.9300000071525574], [1511842176.357204, 385, 0.9100000262260437], [1511842176.388956, 386, 0.949999988079071], [1511842176.419332, 387, 0.9300000071525574], [1511842176.451727, 388, 0.9599999785423279], [1511842176.484456, 389, 0.9399999976158142], [1511842177.034638, 391, 0.9800000190734863], [1511842177.067667, 392, 0.9200000166893005], [1511842177.101138, 393, 0.9200000166893005], [1511842177.135038, 394, 0.9700000286102295], [1511842177.170068, 395, 0.9399999976158142], [1511842177.200651, 396, 0.949999988079071], [1511842177.23465, 397, 0.9599999785423279], [1511842177.269173, 398, 0.9700000286102295], [1511842177.379705, 399, 0.9300000071525574], [1511842177.930872, 401, 0.9700000286102295], [1511842177.964943, 402, 0.9200000166893005], [1511842177.999324, 403, 0.949999988079071], [1511842178.033477, 404, 0.9900000095367432], [1511842178.071781, 405, 0.949999988079071], [1511842178.105857, 406, 0.949999988079071], [1511842178.135511, 407, 0.9300000071525574], [1511842178.167634, 408, 0.9300000071525574], [1511842178.199537, 409, 0.9200000166893005], [1511842178.717725, 411, 0.9399999976158142], [1511842178.74796, 412, 0.9399999976158142], [1511842178.780912, 413, 0.949999988079071], [1511842178.811067, 414, 0.949999988079071], [1511842178.84161, 415, 0.9399999976158142], [1511842178.878333, 416, 0.949999988079071], [1511842178.914753, 417, 0.9100000262260437], [1511842178.947455, 418, 0.9800000190734863], [1511842178.979425, 419, 0.9700000286102295], [1511842179.503057, 421, 0.9200000166893005], [1511842179.540604, 422, 0.9300000071525574], [1511842179.573449, 423, 0.9300000071525574], [1511842179.608729, 424, 0.949999988079071], [1511842179.645117, 425, 0.949999988079071], [1511842179.678533, 426, 0.9599999785423279], [1511842179.725027, 427, 0.9100000262260437], [1511842179.758991, 428, 0.9700000286102295], [1511842179.78958, 429, 0.9300000071525574], [1511842180.311945, 431, 0.9700000286102295], [1511842180.342856, 432, 0.9800000190734863], [1511842180.372838, 433, 0.949999988079071], [1511842180.402146, 434, 0.9100000262260437], [1511842180.43488, 435, 0.9200000166893005], [1511842180.467817, 436, 0.8999999761581421], [1511842180.497947, 437, 0.9599999785423279], [1511842180.529357, 438, 0.9399999976158142], [1511842180.561293, 439, 0.949999988079071], [1511842181.077772, 441, 0.9399999976158142], [1511842181.108623, 442, 0.949999988079071], [1511842181.140136, 443, 0.9900000095367432], [1511842181.174364, 444, 0.9700000286102295], [1511842181.20535, 445, 0.9300000071525574], [1511842181.23487, 446, 0.9700000286102295], [1511842181.267768, 447, 0.9200000166893005], [1511842181.296881, 448, 0.9599999785423279], [1511842181.331577, 449, 0.9599999785423279], [1511842181.84731, 451, 0.9700000286102295], [1511842181.877643, 452, 0.949999988079071], [1511842181.90728, 453, 0.9200000166893005], [1511842181.937846, 454, 0.9599999785423279], [1511842181.971116, 455, 0.949999988079071], [1511842182.000763, 456, 0.949999988079071], [1511842182.037276, 457, 0.9399999976158142], [1511842182.06702, 458, 0.9399999976158142], [1511842182.096206, 459, 0.9300000071525574], [1511842182.611312, 461, 0.949999988079071], [1511842182.64513, 462, 0.9599999785423279], [1511842182.674909, 463, 0.9300000071525574], [1511842182.705437, 464, 0.9300000071525574], [1511842182.735784, 465, 1.0], [1511842182.767558, 466, 0.949999988079071], [1511842182.796914, 467, 0.949999988079071], [1511842182.826817, 468, 0.8999999761581421], [1511842182.857851, 469, 0.9800000190734863], [1511842183.352468, 471, 0.9800000190734863], [1511842183.384449, 472, 0.8799999952316284], [1511842183.420997, 473, 0.9300000071525574], [1511842183.452375, 474, 0.9399999976158142], [1511842183.483695, 475, 0.949999988079071], [1511842183.514538, 476, 0.949999988079071], [1511842183.547066, 477, 0.9599999785423279], [1511842183.577378, 478, 0.9399999976158142], [1511842183.613494, 479, 0.949999988079071], [1511842184.166345, 481, 0.9599999785423279], [1511842184.198856, 482, 0.9300000071525574], [1511842184.231571, 483, 0.9399999976158142], [1511842184.261741, 484, 0.949999988079071], [1511842184.291412, 485, 0.9599999785423279], [1511842184.321249, 486, 0.9900000095367432], [1511842184.351878, 487, 0.9300000071525574], [1511842184.381002, 488, 0.9399999976158142], [1511842184.410772, 489, 0.9700000286102295], [1511842184.908431, 491, 0.949999988079071], [1511842184.941166, 492, 0.949999988079071], [1511842184.978217, 493, 0.9700000286102295], [1511842185.008197, 494, 0.9399999976158142], [1511842185.039879, 495, 0.9800000190734863], [1511842185.070592, 496, 0.9599999785423279], [1511842185.10259, 497, 0.9599999785423279], [1511842185.133795, 498, 0.9900000095367432], [1511842185.243204, 499, 0.9599999785423279], [1511842185.856761, 501, 0.949999988079071], [1511842185.896018, 502, 0.9700000286102295], [1511842185.943021, 503, 0.949999988079071], [1511842185.981642, 504, 0.949999988079071], [1511842186.023147, 505, 0.9800000190734863], [1511842186.058391, 506, 0.949999988079071], [1511842186.092093, 507, 0.9599999785423279], [1511842186.134389, 508, 0.9200000166893005], [1511842186.168454, 509, 0.9300000071525574], [1511842186.73473, 511, 0.9399999976158142], [1511842186.765813, 512, 0.9399999976158142], [1511842186.798392, 513, 0.9599999785423279], [1511842186.832886, 514, 0.9700000286102295], [1511842186.869, 515, 0.9399999976158142], [1511842186.899931, 516, 0.9399999976158142], [1511842186.92933, 517, 0.9700000286102295], [1511842186.961637, 518, 0.949999988079071], [1511842186.993339, 519, 0.949999988079071], [1511842187.51295, 521, 0.949999988079071], [1511842187.542084, 522, 0.9300000071525574], [1511842187.571555, 523, 0.9800000190734863], [1511842187.600865, 524, 0.949999988079071], [1511842187.630905, 525, 0.9700000286102295], [1511842187.66434, 526, 0.9599999785423279], [1511842187.695883, 527, 0.9399999976158142], [1511842187.734118, 528, 0.949999988079071], [1511842187.768383, 529, 0.9399999976158142], [1511842188.2609, 531, 0.9599999785423279], [1511842188.291538, 532, 0.949999988079071], [1511842188.324743, 533, 0.949999988079071], [1511842188.359286, 534, 0.9399999976158142], [1511842188.392047, 535, 0.9300000071525574], [1511842188.421359, 536, 0.9399999976158142], [1511842188.454753, 537, 0.949999988079071], [1511842188.48794, 538, 0.9900000095367432], [1511842188.524741, 539, 0.9599999785423279], [1511842189.0112, 541, 0.949999988079071], [1511842189.043185, 542, 0.9300000071525574], [1511842189.074307, 543, 0.9700000286102295], [1511842189.106053, 544, 0.9399999976158142], [1511842189.135565, 545, 0.9700000286102295], [1511842189.168538, 546, 0.9599999785423279], [1511842189.201185, 547, 0.9399999976158142], [1511842189.235236, 548, 0.9900000095367432], [1511842189.26819, 549, 0.949999988079071], [1511842189.760432, 551, 0.9300000071525574], [1511842189.789696, 552, 0.9599999785423279], [1511842189.818744, 553, 0.9200000166893005], [1511842189.848042, 554, 0.949999988079071], [1511842189.877089, 555, 0.9399999976158142], [1511842189.907031, 556, 0.949999988079071], [1511842189.936881, 557, 0.9800000190734863], [1511842189.966071, 558, 0.9399999976158142], [1511842189.995653, 559, 0.9900000095367432], [1511842190.508212, 561, 0.9200000166893005], [1511842190.540299, 562, 0.9800000190734863], [1511842190.578574, 563, 0.9300000071525574], [1511842190.610377, 564, 0.949999988079071], [1511842190.643136, 565, 0.9399999976158142], [1511842190.672663, 566, 1.0], [1511842190.707029, 567, 0.9900000095367432], [1511842190.739414, 568, 0.949999988079071], [1511842190.77237, 569, 0.9599999785423279], [1511842191.31564, 571, 0.9300000071525574], [1511842191.348465, 572, 0.9900000095367432], [1511842191.382138, 573, 0.949999988079071], [1511842191.412707, 574, 0.9399999976158142], [1511842191.443585, 575, 0.9599999785423279], [1511842191.477383, 576, 0.9700000286102295], [1511842191.510109, 577, 0.9399999976158142], [1511842191.540084, 578, 0.9399999976158142], [1511842191.569611, 579, 0.9599999785423279], [1511842192.080061, 581, 0.949999988079071], [1511842192.114685, 582, 0.949999988079071], [1511842192.146026, 583, 0.9599999785423279], [1511842192.179577, 584, 0.9300000071525574], [1511842192.213491, 585, 0.949999988079071], [1511842192.247531, 586, 0.949999988079071], [1511842192.279046, 587, 0.9700000286102295], [1511842192.3092, 588, 0.9300000071525574], [1511842192.343594, 589, 0.9700000286102295], [1511842192.842748, 591, 0.9599999785423279], [1511842192.872712, 592, 0.9700000286102295], [1511842192.903806, 593, 0.9700000286102295], [1511842192.935047, 594, 0.949999988079071], [1511842192.966689, 595, 0.9300000071525574], [1511842192.996178, 596, 1.0], [1511842193.025323, 597, 0.9300000071525574], [1511842193.059378, 598, 0.949999988079071], [1511842193.161189, 599, 0.9599999785423279], [1511842193.658418, 601, 0.9900000095367432], [1511842193.688131, 602, 0.9399999976158142], [1511842193.720422, 603, 0.9800000190734863], [1511842193.752308, 604, 0.9599999785423279], [1511842193.782545, 605, 0.949999988079071], [1511842193.814567, 606, 0.9599999785423279], [1511842193.848188, 607, 0.9399999976158142], [1511842193.879656, 608, 0.9700000286102295], [1511842193.910992, 609, 0.9900000095367432], [1511842194.408775, 611, 0.949999988079071], [1511842194.557519, 612, 0.9900000095367432], [1511842194.59024, 613, 0.9700000286102295], [1511842194.62302, 614, 0.9399999976158142], [1511842194.656742, 615, 0.9599999785423279], [1511842194.68816, 616, 0.9900000095367432], [1511842194.720722, 617, 0.9300000071525574], [1511842194.752064, 618, 0.9800000190734863], [1511842194.784808, 619, 0.9100000262260437], [1511842195.290169, 621, 0.949999988079071], [1511842195.323044, 622, 0.9700000286102295], [1511842195.353092, 623, 0.9900000095367432], [1511842195.386405, 624, 0.949999988079071], [1511842195.417719, 625, 0.9700000286102295], [1511842195.471398, 626, 0.9800000190734863], [1511842195.508423, 627, 0.9599999785423279], [1511842195.543529, 628, 0.9700000286102295], [1511842195.582063, 629, 0.9700000286102295], [1511842196.143761, 631, 0.9700000286102295], [1511842196.182851, 632, 0.9700000286102295], [1511842196.214629, 633, 0.9700000286102295], [1511842196.253051, 634, 0.9700000286102295], [1511842196.287821, 635, 0.949999988079071], [1511842196.319766, 636, 0.9399999976158142], [1511842196.354184, 637, 0.9399999976158142], [1511842196.38808, 638, 0.9599999785423279], [1511842196.421604, 639, 0.949999988079071], [1511842196.947931, 641, 1.0], [1511842196.977982, 642, 0.949999988079071], [1511842197.013177, 643, 0.9599999785423279], [1511842197.053432, 644, 0.9599999785423279], [1511842197.089024, 645, 0.9700000286102295], [1511842197.120129, 646, 0.9599999785423279], [1511842197.150194, 647, 0.9300000071525574], [1511842197.18433, 648, 0.9700000286102295], [1511842197.214245, 649, 0.9599999785423279], [1511842197.734399, 651, 0.9599999785423279], [1511842197.765878, 652, 0.949999988079071], [1511842197.795536, 653, 0.9300000071525574], [1511842197.828955, 654, 0.949999988079071], [1511842197.858018, 655, 0.949999988079071], [1511842197.88918, 656, 0.9300000071525574], [1511842197.921247, 657, 0.9599999785423279], [1511842197.961132, 658, 0.9599999785423279], [1511842197.990723, 659, 0.949999988079071], [1511842198.489996, 661, 0.9700000286102295], [1511842198.520217, 662, 0.9900000095367432], [1511842198.550925, 663, 1.0], [1511842198.582604, 664, 0.9700000286102295], [1511842198.612304, 665, 0.9700000286102295], [1511842198.648211, 666, 0.9300000071525574], [1511842198.686078, 667, 0.9599999785423279], [1511842198.717921, 668, 0.949999988079071], [1511842198.750968, 669, 0.9599999785423279], [1511842199.258821, 671, 0.9399999976158142], [1511842199.291037, 672, 0.9800000190734863], [1511842199.320875, 673, 0.9700000286102295], [1511842199.352976, 674, 0.949999988079071], [1511842199.382681, 675, 0.9800000190734863], [1511842199.411833, 676, 0.949999988079071], [1511842199.443132, 677, 0.9700000286102295], [1511842199.475117, 678, 0.9700000286102295], [1511842199.505664, 679, 0.949999988079071], [1511842200.00445, 681, 0.949999988079071], [1511842200.037647, 682, 0.9900000095367432], [1511842200.073666, 683, 0.9200000166893005], [1511842200.104847, 684, 0.9200000166893005], [1511842200.137768, 685, 0.9300000071525574], [1511842200.170784, 686, 0.9800000190734863], [1511842200.204724, 687, 0.9800000190734863], [1511842200.240477, 688, 0.9800000190734863], [1511842200.275783, 689, 0.9900000095367432], [1511842200.81989, 691, 0.9700000286102295], [1511842200.858525, 692, 0.9300000071525574], [1511842200.890363, 693, 0.949999988079071], [1511842200.932829, 694, 0.9599999785423279], [1511842200.962743, 695, 0.9800000190734863], [1511842200.994843, 696, 0.9200000166893005], [1511842201.03947, 697, 0.9800000190734863], [1511842201.070836, 698, 0.9399999976158142], [1511842201.246026, 699, 0.9100000262260437], [1511842201.786404, 701, 0.9300000071525574], [1511842201.819202, 702, 0.9800000190734863], [1511842201.856957, 703, 0.9200000166893005], [1511842201.888767, 704, 1.0], [1511842201.92143, 705, 0.9399999976158142], [1511842201.961242, 706, 0.9700000286102295], [1511842201.996298, 707, 0.9200000166893005], [1511842202.032258, 708, 0.9800000190734863], [1511842202.069833, 709, 0.9300000071525574], [1511842202.5957, 711, 0.9800000190734863], [1511842202.632072, 712, 0.9800000190734863], [1511842202.664469, 713, 0.9700000286102295], [1511842202.696135, 714, 0.9300000071525574], [1511842202.72853, 715, 0.9700000286102295], [1511842202.759628, 716, 0.9800000190734863], [1511842202.794048, 717, 0.9800000190734863], [1511842202.827036, 718, 0.949999988079071], [1511842202.858473, 719, 0.9700000286102295], [1511842203.391985, 721, 0.9599999785423279], [1511842203.4215, 722, 0.9399999976158142], [1511842203.453421, 723, 0.9800000190734863], [1511842203.484233, 724, 0.9700000286102295], [1511842203.516743, 725, 0.9900000095367432], [1511842203.550632, 726, 0.9800000190734863], [1511842203.584461, 727, 0.9800000190734863], [1511842203.617915, 728, 0.9599999785423279], [1511842203.652398, 729, 0.9700000286102295], [1511842204.185468, 731, 0.9800000190734863], [1511842204.217265, 732, 0.9800000190734863], [1511842204.249281, 733, 1.0], [1511842204.282808, 734, 0.9700000286102295], [1511842204.314277, 735, 0.9700000286102295], [1511842204.345353, 736, 0.949999988079071], [1511842204.375898, 737, 0.9599999785423279], [1511842204.411013, 738, 0.9100000262260437], [1511842204.441207, 739, 0.9700000286102295], [1511842204.967109, 741, 0.9399999976158142], [1511842204.999614, 742, 0.9900000095367432], [1511842205.037706, 743, 0.9599999785423279], [1511842205.071398, 744, 0.9700000286102295], [1511842205.109827, 745, 0.9800000190734863], [1511842205.150377, 746, 0.9700000286102295], [1511842205.196859, 747, 0.9399999976158142], [1511842205.238587, 748, 0.9900000095367432], [1511842205.284592, 749, 0.9700000286102295], [1511842205.913203, 751, 0.9599999785423279], [1511842205.977628, 752, 0.9800000190734863], [1511842206.049908, 753, 0.9399999976158142], [1511842206.088929, 754, 0.9599999785423279], [1511842206.12656, 755, 0.9700000286102295], [1511842206.171609, 756, 0.9700000286102295], [1511842206.207161, 757, 0.9599999785423279], [1511842206.259537, 758, 0.9900000095367432], [1511842206.299124, 759, 0.9800000190734863], [1511842206.839902, 761, 0.9399999976158142], [1511842206.869605, 762, 0.9800000190734863], [1511842206.901015, 763, 0.9599999785423279], [1511842206.931029, 764, 0.9700000286102295], [1511842206.961387, 765, 0.9300000071525574], [1511842206.992158, 766, 0.9599999785423279], [1511842207.02291, 767, 0.9700000286102295], [1511842207.055302, 768, 0.9599999785423279], [1511842207.089098, 769, 0.9399999976158142], [1511842207.593272, 771, 0.9800000190734863], [1511842207.624582, 772, 0.949999988079071], [1511842207.654845, 773, 0.9599999785423279], [1511842207.688258, 774, 0.9800000190734863], [1511842207.718489, 775, 0.9700000286102295], [1511842207.747767, 776, 0.949999988079071], [1511842207.778593, 777, 0.9700000286102295], [1511842207.808232, 778, 0.9599999785423279], [1511842207.838551, 779, 0.9599999785423279], [1511842208.397092, 781, 0.9700000286102295], [1511842208.427281, 782, 0.949999988079071], [1511842208.458664, 783, 0.9800000190734863], [1511842208.488235, 784, 0.9599999785423279], [1511842208.519785, 785, 0.9599999785423279], [1511842208.554034, 786, 0.9800000190734863], [1511842208.586204, 787, 0.9800000190734863], [1511842208.619628, 788, 0.9700000286102295], [1511842208.654394, 789, 0.9800000190734863], [1511842209.194778, 791, 0.9800000190734863], [1511842209.226194, 792, 0.9599999785423279], [1511842209.266281, 793, 0.9599999785423279], [1511842209.295469, 794, 0.9800000190734863], [1511842209.327287, 795, 0.9800000190734863], [1511842209.364207, 796, 0.9599999785423279], [1511842209.395033, 797, 0.9599999785423279], [1511842209.429895, 798, 0.949999988079071], [1511842209.556844, 799, 0.949999988079071], [1511842210.130269, 801, 0.9700000286102295], [1511842210.160287, 802, 0.9700000286102295], [1511842210.193199, 803, 0.9700000286102295], [1511842210.22632, 804, 0.9399999976158142], [1511842210.26311, 805, 0.9800000190734863], [1511842210.309019, 806, 0.9599999785423279], [1511842210.347609, 807, 0.9800000190734863], [1511842210.390996, 808, 0.9900000095367432], [1511842210.439887, 809, 0.9200000166893005], [1511842211.003122, 811, 0.9599999785423279], [1511842211.037074, 812, 0.9599999785423279], [1511842211.067644, 813, 0.9399999976158142], [1511842211.101507, 814, 0.9599999785423279], [1511842211.140325, 815, 0.9599999785423279], [1511842211.174903, 816, 0.949999988079071], [1511842211.224003, 817, 0.9700000286102295], [1511842211.286801, 818, 0.9900000095367432], [1511842211.327776, 819, 0.9800000190734863], [1511842211.985095, 821, 0.9200000166893005], [1511842212.030882, 822, 0.9700000286102295], [1511842212.070569, 823, 0.9399999976158142], [1511842212.118181, 824, 0.9800000190734863], [1511842212.157094, 825, 0.9599999785423279], [1511842212.226286, 826, 0.9599999785423279], [1511842212.277023, 827, 0.9900000095367432], [1511842212.311592, 828, 1.0], [1511842212.348642, 829, 0.9599999785423279], [1511842212.91796, 831, 0.9900000095367432], [1511842212.950586, 832, 0.9800000190734863], [1511842212.996488, 833, 0.9599999785423279], [1511842213.027555, 834, 0.9800000190734863], [1511842213.058825, 835, 0.9800000190734863], [1511842213.091046, 836, 0.9599999785423279], [1511842213.125024, 837, 0.9599999785423279], [1511842213.160207, 838, 0.9399999976158142], [1511842213.191536, 839, 0.9700000286102295], [1511842213.728065, 841, 0.9700000286102295], [1511842213.762401, 842, 0.9700000286102295], [1511842213.799732, 843, 0.9700000286102295], [1511842213.833657, 844, 0.9800000190734863], [1511842213.866312, 845, 0.9800000190734863], [1511842213.902647, 846, 0.9599999785423279], [1511842213.942028, 847, 0.9700000286102295], [1511842213.983694, 848, 0.9599999785423279], [1511842214.017235, 849, 0.949999988079071], [1511842214.539192, 851, 0.9800000190734863], [1511842214.570802, 852, 0.9599999785423279], [1511842214.602371, 853, 0.9800000190734863], [1511842214.63469, 854, 0.9599999785423279], [1511842214.666527, 855, 0.9700000286102295], [1511842214.7013, 856, 0.949999988079071], [1511842214.736796, 857, 0.9700000286102295], [1511842214.773076, 858, 0.9900000095367432], [1511842214.804659, 859, 0.9900000095367432], [1511842215.333667, 861, 0.9700000286102295], [1511842215.36866, 862, 0.9800000190734863], [1511842215.408818, 863, 0.9800000190734863], [1511842215.446431, 864, 0.9900000095367432], [1511842215.484602, 865, 0.9399999976158142], [1511842215.520258, 866, 0.9800000190734863], [1511842215.555225, 867, 0.9800000190734863], [1511842215.592115, 868, 0.9599999785423279], [1511842215.630665, 869, 0.9700000286102295], [1511842216.128021, 871, 1.0], [1511842216.159525, 872, 0.9200000166893005], [1511842216.191044, 873, 0.9800000190734863], [1511842216.22625, 874, 0.949999988079071], [1511842216.264204, 875, 1.0], [1511842216.301708, 876, 0.9300000071525574], [1511842216.346822, 877, 0.949999988079071], [1511842216.387908, 878, 0.9900000095367432], [1511842216.431012, 879, 0.9399999976158142], [1511842216.948288, 881, 0.9800000190734863], [1511842216.980613, 882, 0.9599999785423279], [1511842217.01133, 883, 0.9700000286102295], [1511842217.042047, 884, 0.9900000095367432], [1511842217.073482, 885, 0.9300000071525574], [1511842217.108726, 886, 0.9599999785423279], [1511842217.14001, 887, 0.9800000190734863], [1511842217.171317, 888, 0.9599999785423279], [1511842217.203606, 889, 0.9800000190734863], [1511842217.753845, 891, 0.9399999976158142], [1511842217.789057, 892, 0.9599999785423279], [1511842217.830139, 893, 0.9800000190734863], [1511842217.864796, 894, 0.949999988079071], [1511842217.897203, 895, 0.9800000190734863], [1511842217.929849, 896, 0.949999988079071], [1511842217.963099, 897, 0.9800000190734863], [1511842217.996219, 898, 0.9599999785423279], [1511842218.111479, 899, 0.9599999785423279], [1511842218.683541, 901, 0.9700000286102295], [1511842218.714867, 902, 0.9900000095367432], [1511842218.745403, 903, 0.949999988079071], [1511842218.775027, 904, 0.9599999785423279], [1511842218.804858, 905, 0.9700000286102295], [1511842218.834642, 906, 0.9599999785423279], [1511842218.865326, 907, 0.9900000095367432], [1511842218.896291, 908, 0.9700000286102295], [1511842218.926799, 909, 0.9800000190734863], [1511842219.457638, 911, 0.949999988079071], [1511842219.489308, 912, 0.9700000286102295], [1511842219.524922, 913, 0.9100000262260437], [1511842219.55795, 914, 0.9900000095367432], [1511842219.595283, 915, 0.9900000095367432], [1511842219.687366, 916, 0.9900000095367432], [1511842219.727115, 917, 0.9800000190734863], [1511842219.768945, 918, 0.9599999785423279], [1511842219.801816, 919, 0.9800000190734863], [1511842220.390596, 921, 0.9900000095367432], [1511842220.43033, 922, 0.9700000286102295], [1511842220.469885, 923, 0.9700000286102295], [1511842220.501432, 924, 0.949999988079071], [1511842220.534336, 925, 0.949999988079071], [1511842220.577459, 926, 0.9800000190734863], [1511842220.634076, 927, 0.9700000286102295], [1511842220.668908, 928, 0.9599999785423279], [1511842220.7005, 929, 0.9900000095367432], [1511842221.287896, 931, 0.9800000190734863], [1511842221.319684, 932, 0.9599999785423279], [1511842221.355376, 933, 0.949999988079071], [1511842221.390386, 934, 0.9700000286102295], [1511842221.424849, 935, 0.9599999785423279], [1511842221.455576, 936, 0.9800000190734863], [1511842221.488522, 937, 0.9700000286102295], [1511842221.523331, 938, 0.949999988079071], [1511842221.562103, 939, 0.9800000190734863], [1511842222.11082, 941, 0.9399999976158142], [1511842222.144042, 942, 1.0], [1511842222.180893, 943, 0.9599999785423279], [1511842222.214718, 944, 0.9599999785423279], [1511842222.250779, 945, 0.9399999976158142], [1511842222.283768, 946, 0.9599999785423279], [1511842222.318964, 947, 0.949999988079071], [1511842222.351751, 948, 0.9599999785423279], [1511842222.382504, 949, 0.9800000190734863], [1511842222.889534, 951, 0.9800000190734863], [1511842222.921617, 952, 0.949999988079071], [1511842222.953747, 953, 0.9399999976158142], [1511842222.989928, 954, 0.9399999976158142], [1511842223.023551, 955, 0.9700000286102295], [1511842223.060438, 956, 0.9800000190734863], [1511842223.097254, 957, 0.9599999785423279], [1511842223.138771, 958, 0.9800000190734863], [1511842223.174054, 959, 0.9399999976158142], [1511842223.693137, 961, 0.949999988079071], [1511842223.723562, 962, 0.9800000190734863], [1511842223.755989, 963, 0.9700000286102295], [1511842223.790843, 964, 0.9900000095367432], [1511842223.822565, 965, 0.9800000190734863], [1511842223.853841, 966, 0.9900000095367432], [1511842223.892184, 967, 0.9399999976158142], [1511842223.928116, 968, 0.9800000190734863], [1511842223.961467, 969, 0.9700000286102295], [1511842224.536617, 971, 0.9900000095367432], [1511842224.577399, 972, 0.9599999785423279], [1511842224.617609, 973, 0.9700000286102295], [1511842224.655355, 974, 0.9599999785423279], [1511842224.689069, 975, 0.949999988079071], [1511842224.72824, 976, 0.9700000286102295], [1511842224.759455, 977, 0.949999988079071], [1511842224.793144, 978, 0.9599999785423279], [1511842224.824675, 979, 0.9700000286102295], [1511842225.342267, 981, 0.9599999785423279], [1511842225.374886, 982, 0.9700000286102295], [1511842225.407038, 983, 0.9800000190734863], [1511842225.438013, 984, 1.0], [1511842225.468219, 985, 0.9800000190734863], [1511842225.499246, 986, 0.9800000190734863], [1511842225.528987, 987, 0.949999988079071], [1511842225.56184, 988, 0.9599999785423279], [1511842225.596399, 989, 0.949999988079071], [1511842226.096082, 991, 0.9399999976158142], [1511842226.125964, 992, 0.9800000190734863], [1511842226.156644, 993, 0.9599999785423279], [1511842226.187556, 994, 0.9599999785423279], [1511842226.218394, 995, 0.9900000095367432], [1511842226.250693, 996, 0.9599999785423279], [1511842226.284415, 997, 0.9800000190734863], [1511842226.316085, 998, 0.9700000286102295], [1511842226.42392, 999, 0.9599999785423279]]
}
}
}
else {
return {
// moock delay
_timeout: 0,
// mock http status
_status: 200,
// mock response data
_data: {
status: 0,
msg: 'SUCCESS',
data: [[1511842145.514333, 0, 0.094200000166893], [1511842146.427384, 10, 0.7394000291824341], [1511842147.260405, 20, 0.8302000164985657], [1511842148.019018, 30, 0.8662999868392944], [1511842148.793569, 40, 0.8877999782562256], [1511842149.610228, 50, 0.8952000141143799], [1511842150.437095, 60, 0.9031000137329102], [1511842151.254679, 70, 0.9004999995231628], [1511842152.039353, 80, 0.9110000133514404], [1511842152.800043, 90, 0.9143000245094299], [1511842153.668115, 100, 0.9175000190734863], [1511842154.453025, 110, 0.9190000295639038], [1511842155.224028, 120, 0.9214000105857849], [1511842156.001674, 130, 0.9204999804496765], [1511842156.788682, 140, 0.9297999739646912], [1511842157.580495, 150, 0.9289000034332275], [1511842158.331122, 160, 0.9283999800682068], [1511842159.112936, 170, 0.9298999905586243], [1511842159.881351, 180, 0.9301000237464905], [1511842160.659058, 190, 0.9330999851226807], [1511842161.515267, 200, 0.9345999956130981], [1511842162.301136, 210, 0.9351000189781189], [1511842163.092769, 220, 0.9343000054359436], [1511842163.920516, 230, 0.9372000098228455], [1511842164.705352, 240, 0.9351999759674072], [1511842165.674882, 250, 0.9369999766349792], [1511842166.462909, 260, 0.9444000124931335], [1511842167.319383, 270, 0.9437000155448914], [1511842168.114944, 280, 0.9441999793052673], [1511842168.942822, 290, 0.9441999793052673], [1511842169.801691, 300, 0.9453999996185303], [1511842170.594651, 310, 0.9419000148773193], [1511842171.406169, 320, 0.9437000155448914], [1511842172.190729, 330, 0.9488999843597412], [1511842172.997593, 340, 0.9483000040054321], [1511842173.815758, 350, 0.9453999996185303], [1511842174.613314, 360, 0.9480000138282776], [1511842175.402401, 370, 0.9513999819755554], [1511842176.180888, 380, 0.9480999708175659], [1511842176.999133, 390, 0.9520000219345093], [1511842177.900425, 400, 0.954200029373169], [1511842178.682129, 410, 0.9490000009536743], [1511842179.471428, 420, 0.9534000158309937], [1511842180.272808, 430, 0.9549999833106995], [1511842181.044304, 440, 0.9545999765396118], [1511842181.814283, 450, 0.951200008392334], [1511842182.576814, 460, 0.9560999870300293], [1511842183.319649, 470, 0.9588000178337097], [1511842184.080669, 480, 0.9555000066757202], [1511842184.877782, 490, 0.955299973487854], [1511842185.816123, 500, 0.9545000195503235], [1511842186.704832, 510, 0.9559999704360962], [1511842187.475836, 520, 0.9563999772071838], [1511842188.231245, 530, 0.9596999883651733], [1511842188.981693, 540, 0.9562000036239624], [1511842189.72966, 550, 0.9553999900817871], [1511842190.468321, 560, 0.9580000042915344], [1511842191.281197, 570, 0.9575999975204468], [1511842192.046349, 580, 0.9589999914169312], [1511842192.808289, 590, 0.9599999785423279], [1511842193.623127, 600, 0.9603999853134155], [1511842194.371868, 610, 0.9605000019073486], [1511842195.257612, 620, 0.9606000185012817], [1511842196.113539, 630, 0.9559999704360962], [1511842196.914175, 640, 0.9610000252723694], [1511842197.701817, 650, 0.9621999859809875], [1511842198.457409, 660, 0.9599000215530396], [1511842199.228452, 670, 0.9620000123977661], [1511842199.973789, 680, 0.9628000259399414], [1511842200.786072, 690, 0.963699996471405], [1511842201.752806, 700, 0.963100016117096], [1511842202.55644, 710, 0.9632999897003174], [1511842203.355084, 720, 0.964900016784668], [1511842204.150081, 730, 0.9638000130653381], [1511842204.931775, 740, 0.9660000205039978], [1511842205.878417, 750, 0.9628000259399414], [1511842206.808438, 760, 0.9613000154495239], [1511842207.560386, 770, 0.9656000137329102], [1511842208.364481, 780, 0.9664000272750854], [1511842209.154627, 790, 0.9628000259399414], [1511842210.098208, 800, 0.9627000093460083], [1511842210.969653, 810, 0.9656999707221985], [1511842211.929992, 820, 0.9657999873161316], [1511842212.882522, 830, 0.9656000137329102], [1511842213.690861, 840, 0.9682000279426575], [1511842214.508996, 850, 0.9678999781608582], [1511842215.295672, 860, 0.968999981880188], [1511842216.096151, 870, 0.9682999849319458], [1511842216.910752, 880, 0.9661999940872192], [1511842217.718586, 890, 0.9648000001907349], [1511842218.653347, 900, 0.9678000211715698], [1511842219.421863, 910, 0.96670001745224], [1511842220.34967, 920, 0.9674000144004822], [1511842221.234565, 930, 0.9684000015258789], [1511842222.075741, 940, 0.9682000279426575], [1511842222.854794, 950, 0.9663000106811523], [1511842223.658847, 960, 0.9681000113487244], [1511842224.500655, 970, 0.9692999720573425], [1511842225.308939, 980, 0.9692000150680542], [1511842226.065685, 990, 0.9692000150680542]]
}
}
}
};
/**
* get mock data
*
* @param {string} path request path
* @param {Object} queryParam query params
* @param {Object} postParam post params
* @return {Object}
*/
module.exports = function (path, queryParam, postParam) {
return {
// moock delay
_timeout: 0,
// mock http status
_status: 200,
// mock response data
_data: {
status: 0,
msg: 'SUCCESS',
data: {
"test": {
"layer2/biases/summaries/mean": {
"displayName": "layer2/biases/summaries/mean",
"description": ""
}
},
"train": {
"layer2/biases/summaries/mean": {
"displayName": "layer2/biases/summaries/mean",
"description": ""
},
"layer2/biases/summaries/accuracy": {
"displayName": "layer2/biases/summaries/accuracy",
"description": ""
},
"layer2/biases/summaries/cost": {
"displayName": "layer2/biases/summaries/cost",
"description": ""
}
}
}
}
};
};
/**
* get mock data
*
* @param {string} path request path
* @param {Object} queryParam query params
* @param {Object} postParam post params
* @return {Object}
*/
module.exports = function (path, queryParam, postParam) {
return {
// moock delay
_timeout: 0,
// mock http status
_status: 200,
// mock response data
_data: {
status: 0,
msg: 'SUCCESS',
data: {
"test": {
"layer3/generated/animal": {
"displayName": "layer3/generated/animal",
"description": ""
}
},
"train": {
"layer3/generated/animal": {
"displayName": "layer3/generated/animal",
"description": ""
},
"layer3/generated/flower": {
"displayName": "layer3/generated/flower",
"description": ""
},
}
}
}
};
};
/**
* get mock data
*
* @param {string} path request path
* @param {Object} queryParam query params
* @param {Object} postParam post params
* @return {Object}
*/
module.exports = function (path, queryParam, postParam) {
if (queryParam.run === 'train') {
return {
// moock delay
_timeout: 0,
// mock http status
_status: 200,
// mock response data
_data: {
status: 0,
msg: 'SUCCESS',
data: [[1511842145.705075, 1, "Hello 1"], [1511842145.7388, 2, "Hello 2"], [1511842145.774563, 3, "Hello 3"], [1511842145.806828, 4, "Hello 4"], [1511842145.838082, 5, "Hello 5"], [1511842145.868955, 6, "Hello 6"], [1511842145.899323, 7, "Hello 7"], [1511842145.930518, 8, "Hello 8"], [1511842145.96089, 9, "Hello 7"], [1511842146.460557, 11, "Hello 11"], [1511842146.4952, 12, "Hello 12"], [1511842146.525936, 13, "Hello 13"], [1511842146.556059, 14, "Hello 14"], [1511842146.648703, 15, "Hello 15"], [1511842146.683295, 16, "Hello 16"], [1511842146.719782, 17, "Hello 17"], [1511842146.752392, 18, "Hello 18"]]
}
}
}
else {
return {
// moock delay
_timeout: 0,
// mock http status
_status: 200,
// mock response data
_data: {
status: 0,
msg: 'SUCCESS',
data: [[1511842145.514333, 0, "Hello 0"], [1511842146.427384, 10, "Hello 10"], [1511842147.260405, 20, "Hello 20"], [1511842148.019018, 30, "Hello 30 "], [1511842148.793569, 40, "Hello 40 "], [1511842149.610228, 50, "Hello 50 "], [1511842150.437095, 60, "Hello 60"], [1511842151.254679, 70, "Hello 70"], [1511842152.039353, 80, "Hello 80"], [1511842152.800043, 90, "Hello 90"]]
}
}
}
};
/**
* get mock data
*
* @param {string} path request path
* @param {Object} queryParam query params
* @param {Object} postParam post params
* @return {Object}
*/
module.exports = function (path, queryParam, postParam) {
return {
// moock delay
_timeout: 0,
// mock http status
_status: 200,
// mock response data
_data: {
status: 0,
msg: 'SUCCESS',
data: ["train", "test"]
}
};
};
import {Request} from 'express';
export default (req: Request) => {
if (req.query.dimension === '3') {
return {
embedding: [
[10.0, 8.04, 3],
[8.0, 6.95, 4],
[13.0, 7.58, 1],
[9.0, 8.81, 3],
[11.0, 8.33, 5],
[14.0, 9.96, 6],
[6.0, 7.24, 1],
[4.0, 4.26, 2],
[12.0, 10.84, 6],
[7.0, 4.8, 3],
[5.0, 5.68, 3]
],
labels: ['yellow', 'blue', 'red', 'king', 'queen', 'man', 'women', 'kid', 'adult', 'light', 'dark']
};
}
return {
embedding: [
[10.0, 8.04],
[8.0, 6.95],
[13.0, 7.58],
[9.0, 8.81],
[11.0, 8.33],
[14.0, 9.96],
[6.0, 7.24],
[4.0, 4.26],
[12.0, 10.84],
[7.0, 4.8],
[5.0, 5.68]
],
labels: ['yellow', 'blue', 'red', 'king', 'queen', 'man', 'women', 'kid', 'adult', 'light', 'dark']
};
};
export default {"status": 0, "msg": "", "data": {"data": {"node": [{"output": ["Parameter193"], "name": "Parameter193", "opType": "Constant", "attribute": [{"name": "value", "t": {"dims": ["16", "4", "4", "10"], "dataType": "FLOAT", "floatData": [0.09163288027048111, 0.12143590301275253, 0.0853506475687027, 0.12260685861110687, -0.09875397384166718, -0.1121244877576828, -0.03573284298181534, -0.09626211225986481, -0.14788731932640076, 0.03485893830657005, -0.048446524888277054, 0.136892631649971, 0.1460547000169754, -0.11976931244134903, 0.2080405354499817, -0.22713330388069153, 0.4233359098434448, 0.058677203953266144, -0.16731591522693634, -0.37082841992378235, -0.19223923981189728, 0.0943201333284378, 0.09369180351495743, -0.010435560718178749, 0.23059231042861938, -0.4524573087692261, 0.002500813687220216, -0.012435277923941612, 0.031778186559677124, -0.30429312586784363, 0.018025970086455345, 0.024281486868858337, 0.2873530089855194, 0.1709904670715332, -0.074394591152668, 0.01766752265393734, -0.10535763204097748, -0.08181136846542358, 0.05987928435206413, 0.00047348960652016103, -0.1535080373287201, 0.120629221200943, 0.10765989124774933, 0.09445933252573013, -0.06985045224428177, -0.025683380663394928, 0.10913115739822388, -0.08317743986845016, 0.08257905393838882, -0.1757078617811203, -0.168167844414711, 0.10513986647129059, -0.17431361973285675, -0.08228223025798798, 0.4647492468357086, 0.030260585248470306, -0.15933886170387268, 0.19958271086215973, -0.10104268789291382, -0.4945407509803772, 0.3295890688896179, 0.17750981450080872, 0.41138309240341187, 0.12326130270957947, -0.27575674653053284, -0.4662941098213196, -0.3712764084339142, -0.020994601771235466, -0.12800092995166779, 0.04856026917695999, 0.38166606426239014, -0.2319786101579666, 0.40788352489471436, 0.02265831269323826, 0.07786203920841217, -0.6701842546463013, -0.0611761249601841, 0.0467672273516655, -0.03293807432055473, 0.14224782586097717, -0.128555029630661, 0.025974348187446594, -0.008957884274423122, 0.17939205467700958, -0.0334603413939476, -0.027158400043845177, 0.13029633462429047, -0.045492373406887054, 0.05367948114871979, 0.021849706768989563, -0.0059657590463757515, -0.04966728389263153, -0.1589137762784958, 0.10884328186511993, -0.17006619274616241, 0.34957271814346313, -0.17430223524570465, 0.1654788851737976, -0.14037011563777924, -0.1737338900566101, -0.036601725965738297, 0.04010355472564697, 0.19195736944675446, 0.04251663759350777, -0.1638253629207611, 0.4419134557247162, 0.07696633040904999, -0.4376426637172699, 0.049478061497211456, -0.23576991260051727, -0.09825644642114639, -0.4054715037345886, -0.37302207946777344, 0.2436894327402115, -0.5215957760810852, 0.5668888092041016, 0.5552222728729248, -0.10442956537008286, 0.18002772331237793, -0.11376107484102249, -0.03965001553297043, -0.11214318126440048, -0.0023703111801296473, -0.003144004615023732, -0.10276811569929123, 0.019040677696466446, -0.07214156538248062, -0.06295154243707657, 0.08691363036632538, 0.059526339173316956, 0.18038588762283325, 0.10787897557020187, -0.19601596891880035, 0.008016468025743961, 0.06330039352178574, 0.014802279882133007, -0.07189273834228516, 0.10687673836946487, -0.24504677951335907, 0.015252113342285156, -0.335182249546051, -0.03278788924217224, -0.15907159447669983, 0.5842293500900269, -0.0735088586807251, 0.5157390236854553, 0.16114291548728943, -0.20041143894195557, 0.08611081540584564, -0.26673802733421326, -0.48252072930336, 0.04045981541275978, -0.025883780792355537, 0.2995097041130066, -0.21764476597309113, 0.08116388320922852, 0.2665603458881378, -0.2901787757873535, 0.2665983736515045, -0.20305156707763672, -0.12429767102003098, 0.005965419579297304, 0.2243628054857254, 0.13654103875160217, -0.028027368709445, -0.28091877698898315, 0.022815383970737457, 0.06510894000530243, -0.14604154229164124, 0.10212377458810806, -0.13724955916404724, 0.056102585047483444, -0.08111743628978729, 0.007112065330147743, -0.20668791234493256, 0.11320050060749054, -0.18013525009155273, 0.359819233417511, -0.2298140972852707, 0.007774946745485067, -0.21265363693237305, -0.10250820219516754, 0.09109640121459961, 0.2713518440723419, -0.14504371583461761, 0.08723330497741699, -0.07021252810955048, 0.13583463430404663, 0.11757422238588333, -0.006081802770495415, -0.0385749489068985, 0.0859772115945816, 0.0474117249250412, -0.036640118807554245, 0.0816631019115448, 0.08421722054481506, 0.1347440779209137, -0.06303027272224426, 0.0055456385016441345, 0.07729209959506989, -0.024022098630666733, -0.07385796308517456, 0.24266241490840912, 0.2002831995487213, -0.12752440571784973, -0.3758249878883362, -0.2573346495628357, 0.170244500041008, -0.07271948456764221, -0.00042671075789257884, -0.03506379574537277, 0.25228849053382874, 0.2963089048862457, 0.17691506445407867, -0.40711545944213867, -0.1792466640472412, -0.4868773818016052, 0.7461553812026978, -0.04348670691251755, -0.040731340646743774, 0.056606046855449677, -0.28346651792526245, 0.06753943115472794, -0.27477723360061646, -0.2953200042247772, 0.31945374608039856, -0.09977182000875473, 0.35889989137649536, -0.13710662722587585, -0.06071627885103226, 0.0891886055469513, -0.12389953434467316, -0.4814082086086273, -0.1209859848022461, -0.07548031955957413, 0.5070599913597107, 0.16170549392700195, 0.033460672944784164, -0.01295141875743866, 0.10999502241611481, -0.18118232488632202, -0.20907185971736908, 0.17070117592811584, 0.20845624804496765, 0.10394178330898285, 0.16494232416152954, -0.05194123461842537, 0.29782092571258545, -0.11981762945652008, -0.17728860676288605, -0.14260271191596985, -0.00290327868424356, -0.15693335235118866, -0.061181046068668365, 0.18368062376976013, 0.2737201750278473, -0.09010158479213715, -0.11838143318891525, 0.02725459448993206, 0.33432498574256897, -0.14430531859397888, -0.28883853554725647, -0.2550128102302551, -0.09727652370929718, 0.5777705907821655, -0.2912900447845459, 0.1857275366783142, -0.23318630456924438, 0.1816663146018982, -0.0103724654763937, -0.03815264254808426, -0.08915568888187408, 0.6465838551521301, 0.1674060970544815, 0.12680207192897797, -0.09792721271514893, 0.2141653299331665, 0.26453226804733276, 0.05386819317936897, -0.759514331817627, -0.20290550589561462, 0.34834200143814087, -0.13746915757656097, 0.2868601977825165, 0.21477994322776794, 0.09853070974349976, -0.24042019248008728, 0.15954174101352692, -0.2267710119485855, 0.01716097630560398, 0.011399302631616592, 0.17518985271453857, 0.04992486163973808, 0.07743320614099503, -0.045791998505592346, 0.02445896901190281, -0.05144383758306503, -0.48874711990356445, -0.0658048763871193, 0.10073553025722504, 0.2683431804180145, -0.039823323488235474, 0.0979309231042862, -0.03959166631102562, -0.07608389109373093, -0.00010426696826471016, 0.03268659859895706, -0.3119407296180725, 0.08907616138458252, -0.2897304594516754, -0.07899510115385056, 0.24833716452121735, 0.6559720635414124, -0.2895994186401367, 0.3463401794433594, -0.42760491371154785, -0.06253678351640701, 0.04139917343854904, -0.09482403844594955, -0.14266186952590942, 0.0364593043923378, -0.13176865875720978, 0.011298294179141521, -0.041946567595005035, -0.025355981662869453, -0.17728427052497864, 0.04871153458952904, 0.007119632791727781, -0.03515055775642395, -0.12065277248620987, 0.03831062093377113, -0.19670185446739197, 0.15221554040908813, 0.06654547899961472, 0.026643497869372368, -0.18223407864570618, -0.2007436752319336, 0.2476346790790558, 0.14272479712963104, -0.012629205361008644, 0.1260186731815338, -0.018152546137571335, -0.01157828513532877, 0.11374399811029434, -0.33338260650634766, -0.13109451532363892, -0.1446518898010254, 0.21875686943531036, 0.28940579295158386, 0.25008419156074524, 0.17396798729896545, 0.10197077691555023, -0.256145179271698, -0.11203703284263611, -0.05913129448890686, 0.03520730510354042, -0.04082378372550011, -0.08840140700340271, -0.017499366775155067, 0.03503291308879852, -0.10343275219202042, 0.06942393630743027, 0.2820097804069519, 0.06655175238847733, -0.16650205850601196, 0.06617830693721771, -0.16453854739665985, 0.40850934386253357, 0.06259692460298538, -0.06361491233110428, -0.2838923931121826, 0.18313315510749817, 0.49446889758110046, 0.29674839973449707, -0.2716815173625946, -0.007658152375370264, -0.49666067957878113, 0.343237966299057, 0.09508498013019562, -0.2770707309246063, 0.19309349358081818, -0.24312330782413483, 0.2228984385728836, 0.18062271177768707, -0.34044212102890015, 0.024597464129328728, -0.12014612555503845, 0.333555668592453, -0.23799657821655273, 0.030691465362906456, 0.020851705223321915, -0.057640593498945236, -0.012411107309162617, -0.25374025106430054, -0.3371070325374603, 0.4973212480545044, 0.4041796028614044, 0.022525912150740623, -0.223723366856575, 0.001989013748243451, -0.3189954459667206, 0.029870083555579185, 0.17537035048007965, 0.21442392468452454, 0.267106294631958, 0.10951993614435196, -0.2830830216407776, 0.32767611742019653, 0.2755309045314789, -0.37709763646125793, -0.6742045879364014, -0.4242328405380249, -0.17566432058811188, 0.22207844257354736, 0.5258628129959106, 0.4985211193561554, -0.7342137694358826, -0.07246284931898117, -0.03177037090063095, 0.6141102910041809, 0.27530428767204285, -0.1815706342458725, 0.010792283341288567, 0.2778345048427582, 0.04865288734436035, 0.1919439285993576, -0.1422531008720398, 0.09415336698293686, -0.14221195876598358, -0.04775889217853546, 0.13818661868572235, 0.11377434432506561, -0.0022223088890314102, 0.012142995372414589, -0.12801840901374817, 0.21084506809711456, 0.09857626259326935, -0.007353052031248808, -0.0913769006729126, -0.18609200417995453, 0.09367707371711731, 0.21986864507198334, 0.013781992718577385, 0.01853935606777668, 0.10021904110908508, 0.05750510096549988, 0.08740148693323135, -0.25919461250305176, 0.05117707699537277, 0.031620193272829056, 0.07561399042606354, -0.2155151516199112, -0.18499906361103058, 0.26917633414268494, -0.23229144513607025, 0.24011075496673584, 0.21374329924583435, -0.5332348942756653, -0.07875639200210571, 0.2117759883403778, 0.1705530434846878, 0.5362648963928223, -0.1995139867067337, -0.005656009074300528, -0.19522617757320404, -0.1240236833691597, 0.06757839024066925, -0.12189232558012009, 0.054548390209674835, -0.30103686451911926, -0.000548959884326905, 0.17150354385375977, 0.7702476382255554, -0.270901620388031, 0.058912355452775955, -0.14350523054599762, -0.023597054183483124, -0.022250233218073845, -0.23405173420906067, -0.2757638990879059, 0.1007445827126503, -0.1329796314239502, -0.13568520545959473, 0.15051181614398956, 0.1358998715877533, -0.0836479440331459, 0.14334900677204132, 0.10898629575967789, -0.1095767691731453, 0.004637917969375849, 0.08212459832429886, -0.05697902664542198, -0.032599519938230515, 0.16697385907173157, -0.11660593003034592, 0.13034111261367798, 0.11591079831123352, 0.08402854204177856, -0.13984470069408417, -0.004339132457971573, -0.07553751021623611, 0.07529407739639282, 0.14620235562324524, -0.07316114753484726, -0.16493269801139832, -0.04817352071404457, 0.11424325406551361, -0.16561166942119598, -0.09932099282741547, -0.17314133048057556, 0.098062664270401, 0.052351295948028564, 0.03586893901228905, 0.00025790484505705535, -0.1103641539812088, 0.07944493740797043, -0.014252503402531147, 0.044749870896339417, -0.0960293710231781, -0.06515513360500336, 0.018660664558410645, 0.10578678548336029, 0.11224555224180222, 0.1732243150472641, -0.06556550413370132, 0.032207805663347244, 0.06615697592496872, -0.10299636423587799, -0.04562302306294441, -0.09077974408864975, 0.08549204468727112, -0.06881946325302124, 0.32974880933761597, -0.13802692294120789, -0.06297125667333603, 0.1720268279314041, -0.057560257613658905, -0.13936729729175568, -0.2783893942832947, -0.0036408226005733013, -0.1684986650943756, 0.4008839726448059, 0.10527267307043076, -0.0300565417855978, -0.31405410170555115, -0.006559103261679411, -0.018896758556365967, -0.023097863420844078, -0.20794691145420074, 0.11639930307865143, -0.04596497863531113, 0.1214529275894165, 0.11801191419363022, 0.35721829533576965, -0.18851321935653687, -0.1327095776796341, 0.21601921319961548, -0.0711841806769371, -0.06027870252728462, -0.014308637008070946, 0.09809606522321701, -0.10807335376739502, 0.030968409031629562, -0.0976092740893364, 0.024996085092425346, -0.24101898074150085, 0.027350248768925667, 0.002106643049046397, 0.11929166316986084, 0.09693682938814163, 0.31900787353515625, -0.16620038449764252, 0.1639149785041809, -0.24900873005390167, 0.032387133687734604, 0.09503580629825592, 0.06371842324733734, 0.3932006061077118, -0.3992522060871124, -0.18966802954673767, -0.24347421526908875, 0.3726486265659332, -0.35335421562194824, 0.005322188138961792, -0.04494557902216911, 0.05848128721117973, -0.26220476627349854, -0.05913911014795303, -0.3559877872467041, 0.20696568489074707, 0.2702261805534363, 0.21548689901828766, -0.3574220538139343, -0.008915886282920837, -0.3990292251110077, 0.01371531281620264, 0.02647603303194046, 0.1421816349029541, -0.20252008736133575, 0.2786376476287842, -0.0004179552779532969, -0.19249746203422546, 0.15893307328224182, -0.023107875138521194, 0.028147293254733086, 0.11653110384941101, -0.017896151170134544, -0.056495871394872665, -0.08003103733062744, -0.07378257066011429, -0.10359156131744385, 0.04267094284296036, 0.3455430269241333, -0.3554867208003998, 0.06454678624868393, -0.09280721098184586, 0.11624147742986679, 0.21442848443984985, 0.28783032298088074, -0.36001425981521606, -0.3142940402030945, 0.08799482882022858, -0.40366727113723755, 0.0492858849465847, 0.26043832302093506, -0.0456053800880909, -0.08510875701904297, 0.3849102556705475, 0.25178590416908264, 0.03006647527217865, -0.19147968292236328, 0.010460179299116135, -0.1642722338438034, 0.10134069621562958, 0.07430271059274673, 0.07157307118177414, -0.13403825461864471, -0.19174471497535706, 0.004585821647197008, 0.012936335057020187, -0.016513358801603317, 0.002725588856264949, -0.009124319069087505, 0.11511059105396271, 0.06850532442331314, -0.10343107581138611, 0.11619291454553604, 0.015174216590821743, 0.027511922642588615, -0.02946728840470314, 0.08782140910625458, 0.17025546729564667, -0.10653657466173172, -0.11597806215286255, -0.13829486072063446, -0.01264076866209507, 0.10421432554721832, -0.07220742106437683, 0.042693838477134705, 0.08286269754171371, 0.016975056380033493, 0.2577604055404663, -0.11046063154935837, -0.14268110692501068, 0.08814547955989838, 0.23049873113632202, -0.04031062126159668, -0.07507094740867615, -0.3157734274864197, -0.022311316803097725, -0.14433537423610687, -0.0725242868065834, -0.15836475789546967, -0.1575719565153122, -0.06636432558298111, 0.3540959060192108, 0.006868716329336166, 0.037796322256326675, -0.28033024072647095, 0.018679393455386162, 0.0206664577126503, 0.06874176114797592, 0.2016603946685791, 0.09627377986907959, -0.11800261586904526, 0.12034659832715988, -0.017264321446418762, 0.050676003098487854, 0.10920056700706482, -0.04256569966673851, -0.028189225122332573, 0.22206032276153564, 0.13020053505897522, -0.052751574665308, 0.124635249376297, 0.08630852401256561, 0.049558911472558975, 0.1940731704235077, -0.3270353078842163, -0.2053120881319046, -0.2382669448852539, -0.2769091725349426, 0.060951318591833115, 0.19507752358913422, 0.07965121418237686, -0.14788250625133514, -0.2017786055803299, -0.07861172407865524, -0.021125325933098793, 0.6223727464675903, -0.12796884775161743, -0.09095203876495361, -0.1055283397436142, 0.29063162207603455, -0.05614039674401283, 0.05790459364652634, -0.08286868780851364, 0.019389694556593895, 0.3396531343460083, -0.041522618383169174, -0.1748998612165451, 0.13207004964351654, -0.014569399878382683, -0.11774333566427231, 0.06858433037996292, -0.04267200082540512, 0.14176085591316223, 0.06368128210306168, -0.1924912929534912, -0.11341242492198944, -0.012101749889552593, 0.10720602422952652, 0.30187278985977173, -0.12481964379549026, -0.03679987043142319, 0.29304084181785583, -0.26227569580078125, -0.053627096116542816, -0.08497927337884903, 0.12152071297168732, -0.007846342399716377, -0.2959749400615692, 0.08162492513656616, 0.3843308389186859, 0.08779431879520416, 0.06559973210096359, 0.14728093147277832, 0.12533937394618988, -0.055610451847314835, 0.2516423165798187, -0.0015343481209129095, -0.18029280006885529, -0.16464252769947052, -0.1175551638007164, -0.11583521962165833, -0.1070915088057518, 0.16618530452251434, 0.08879489451646805, 0.11461640149354935, -0.19360025227069855, -0.15142479538917542, 0.05598924309015274, 0.13593944907188416, -0.03091767057776451, -0.012382415123283863, 0.08237934112548828, 0.06515523046255112, -0.05971785634756088, -0.14912676811218262, 0.12891757488250732, 0.24418595433235168, -0.16759711503982544, 0.08927612006664276, 0.03573741018772125, -0.08931893855333328, -0.002873431658372283, -0.13407030701637268, -0.23093639314174652, 0.039058707654476166, -0.1672481745481491, 0.1786230504512787, -0.09433726221323013, -0.018776755779981613, 0.1370379626750946, -0.32226258516311646, 0.21761101484298706, 0.3319862484931946, -0.47562161087989807, 0.44754621386528015, -0.30787163972854614, -0.15269382297992706, 0.18217946588993073, -0.0888611301779747, 0.16506533324718475, 0.04154164344072342, 0.18264485895633698, 0.0028657126240432262, -0.30466267466545105, 0.15093721449375153, -0.06766299903392792, -0.16677311062812805, -0.13767512142658234, 0.08700795471668243, -0.040442097932100296, -0.03698461875319481, -0.18092450499534607, 0.04105095937848091, 0.12430304288864136, -0.04239628091454506, -0.06371389329433441, -0.1356329470872879, 0.09007593989372253, 0.14395377039909363, 0.19690565764904022, -0.030341407284140587, 0.045684002339839935, 0.06577257066965103, -0.0472409687936306, 0.0891195610165596, 0.04035165160894394, -0.05227403715252876, -0.15577834844589233, 0.1922885775566101, 0.13543137907981873, -0.011749576777219772, 0.06312236189842224, -0.0275140218436718, 0.019690584391355515, -0.07631327211856842, 0.040844131261110306, -0.033644527196884155, -0.07004953920841217, -0.04987196996808052, -0.14742253720760345, 0.05048427730798721, -0.015130467712879181, 0.10818115621805191, 0.09920626133680344, -0.13659435510635376, -0.04051431268453598, -0.09093411266803741, 0.23569150269031525, -0.2596786618232727, -0.04438869282603264, 0.028831075876951218, 0.051760755479335785, 0.003889303421601653, 0.15690290927886963, 0.10129068791866302, -0.20741795003414154, -0.09403233230113983, 0.25492313504219055, -0.151593878865242, -0.37808698415756226, 0.14954344928264618, 0.10286097973585129, -0.21811266243457794, -0.0008768771658651531, -0.11623913049697876, 0.09086018800735474, 0.5318314433097839, 0.1848234236240387, 0.15465310215950012, -0.07699967920780182, 0.07571322470903397, 0.23994295299053192, -0.45164182782173157, 0.0020482821855694056, -0.39811354875564575, -0.13066136837005615, -0.02498955838382244, 0.06897786259651184, -0.04159349575638771, 0.06566480547189713, -0.06346173584461212, 0.046806301921606064, -0.01255381852388382, -0.11576959490776062, -0.2331949770450592, -0.2768019735813141, -0.013630802743136883, -0.2924085259437561, -0.402077317237854, -0.3669428825378418, 0.3364390730857849, -0.050368160009384155, -0.04178308695554733, -0.25996798276901245, 0.2997923791408539, 0.4380180239677429, 0.05968686193227768, -0.007905100472271442, -0.38147321343421936, -0.21906282007694244, 0.25176504254341125, 0.17369648814201355, -0.17449451982975006, -0.15468837320804596, 0.1808316558599472, 0.35774892568588257, -0.04379989951848984, 0.37145715951919556, -0.4525375962257385, 0.1872825175523758, -0.01313698198646307, -0.14299286901950836, -0.5754454135894775, -0.12922726571559906, 0.17329920828342438, 0.38266071677207947, 0.1533488631248474, -0.15947268903255463, 0.03709738329052925, -0.01734403520822525, -0.03451868146657944, -0.17483440041542053, 0.10900341719388962, 0.0749971866607666, 0.15221449732780457, -0.04126245900988579, 0.06777593493461609, -0.1550237387418747, 0.16354630887508392, 0.22785420715808868, 0.04684881493449211, -0.029828466475009918, 0.10399839282035828, -0.18968293070793152, 0.13570716977119446, -0.0902256965637207, 0.26327604055404663, -0.2846408188343048, 0.6480950713157654, -0.13615000247955322, 0.06460057944059372, 0.03009645827114582, 0.2770584225654602, -0.22201181948184967, 0.16104179620742798, -0.23982785642147064, -0.22440768778324127, -0.014262770302593708, 0.45522406697273254, -0.014287739060819149, -0.19704768061637878, -0.27394959330558777, 0.17722734808921814, 0.07222182303667068, -0.1194758415222168, -0.07190455496311188, 0.10904071480035782, -0.17517201602458954, -0.08903846144676208, 0.17170043289661407, -0.05955890566110611, 0.11402436345815659, 0.16522061824798584, -0.35160520672798157, -0.034481167793273926, -0.11740123480558395, -0.1341399848461151, -0.16011583805084229, 0.2641150653362274, 0.10897932201623917, -0.0894259363412857, -0.17326205968856812, -0.05433197692036629, 0.045789893716573715, 0.08167993277311325, 0.0851130560040474, 0.08021274209022522, -0.24175073206424713, 0.3722534775733948, -0.10094456374645233, -0.1566823273897171, 0.0509134903550148, 0.19977764785289764, -0.24489189684391022, 0.13482235372066498, 0.0021940013393759727, -0.031168082728981972, 0.12135770916938782, -0.12688791751861572, -0.18958106637001038, 0.1666739135980606, 0.03047162853181362, 0.15504519641399384, -0.052737027406692505, 0.02627147175371647, -0.2274574190378189, -0.13437311351299286, 0.3057021200656891, -0.0929778516292572, -0.1847575455904007, 0.399563193321228, -0.22119897603988647, 0.17216287553310394, -0.029635321348905563, 0.10997044295072556, -0.09030432999134064, -0.003445087932050228, 0.14845050871372223, 0.051591478288173676, 0.17100530862808228, 0.020391153171658516, -0.2737419605255127, -0.2258184850215912, -0.14499276876449585, -0.050254352390766144, 0.25733503699302673, 0.1789223849773407, -0.41638413071632385, 0.023735329508781433, -0.17261525988578796, -0.5102411508560181, 0.12343695014715195, -0.30591854453086853, 0.037345319986343384, 0.19263741374015808, 0.47267165780067444, -0.1087423637509346, 0.0061024259775877, -0.046458132565021515, -0.48704057931900024, 0.04032278060913086, 0.08467965573072433, 0.5137514472007751, -0.06556256115436554, 0.15030834078788757, -0.0401739738881588, -0.21601969003677368, 0.24490106105804443, -0.13502101600170135, 0.10465565323829651, 0.7192519903182983, -0.12715119123458862, -0.26400426030158997, 0.12273196876049042, 0.003511932911351323, -0.6221611499786377, 0.0638633668422699, 0.029396679252386093, 0.3360448181629181, -0.029485199600458145, 0.10902433097362518, 0.11317962408065796, -0.20234441757202148, 0.24299386143684387, 0.10908794403076172, -0.3232010006904602, -0.1419249325990677, -0.06445199251174927, 0.19993530213832855, 0.033440060913562775, -0.011840429157018661, 0.023170193657279015, 0.03249383717775345, 0.09918065369129181, 0.008781714364886284, -0.4246515929698944, 0.12794847786426544, 0.3463687598705292, -0.2862425446510315, 0.26846349239349365, 0.20964421331882477, -0.19132165610790253, 0.3305538594722748, -0.30350014567375183, -0.0025937878526747227, -0.1251397728919983, 0.23763184249401093, 0.24581365287303925, 0.20030765235424042, -0.11234287172555923, -0.25250014662742615, -0.1133827418088913, -0.32861950993537903, -0.21313956379890442, -0.07529347389936447, 0.3853905200958252, -0.23673047125339508, 0.4138970971107483, -0.11850415170192719, 0.0405057929456234, 0.05868089571595192, 0.4284021854400635, -0.33250945806503296, -0.018637601286172867, -0.29963624477386475, -0.08990953862667084, -0.10388948768377304, 0.0031918510794639587, -0.12570688128471375, -0.038307785987854004, -0.4091474711894989, 0.023242607712745667, -0.17890839278697968, 0.3214879035949707, -0.2552642524242401, 0.1109834611415863, 0.10022710263729095, 0.12840622663497925, 0.0030893231742084026, 0.12838077545166016, -0.10303178429603577, 0.22976282238960266, -0.3123551607131958, 0.1463969498872757, 0.051804542541503906, 0.18107546865940094, -0.07624709606170654, 0.016001012176275253, -0.24331940710544586, 0.30368733406066895, -0.4261264503002167, 0.2724919319152832, 0.03811890259385109, 0.01578075811266899, 0.31527477502822876, -0.021301928907632828, 0.049029409885406494, -0.013109689578413963, 0.06902546435594559, 0.006003120448440313, -0.18253539502620697, 0.08975179493427277, 0.028871646150946617, -0.037357401102781296, 0.12274015694856644, 0.06220485270023346, 0.10932951420545578, -0.09101811051368713, 0.16965115070343018, -0.32301685214042664, -0.14145389199256897, 0.25746065378189087, 0.12483193725347519, -0.05370665714144707, 0.006776327732950449, 0.029081005603075027, -0.00832702312618494, 0.18339493870735168, 0.012635315768420696, -0.059541717171669006, 0.0070755924098193645, 0.1613999605178833, 0.05167313665151596, -0.03312039002776146, -0.14678755402565002, -0.041794199496507645, 0.024336209520697594, -0.04031798243522644, -0.07198493182659149, -0.06211192160844803, -0.09906855970621109, -0.07760624587535858, 0.12499915063381195, 0.05696330964565277, 0.08771709352731705, 0.12930439412593842, -0.002995092887431383, -0.10194438695907593, 0.0026786515954881907, -0.07013368606567383, 0.09556461125612259, 0.1567007154226303, 0.10396436601877213, 0.14370758831501007, -0.198551207780838, 0.20064552128314972, -0.24868379533290863, 0.017768235877156258, 0.10713237524032593, 0.4929283857345581, -0.26857101917266846, -0.12122423946857452, -0.1269984096288681, 0.052571892738342285, -0.26939892768859863, -0.10755529254674911, 0.19760534167289734, 0.20846694707870483, 0.18844573199748993, -0.11503980308771133, -0.30529141426086426, -0.11682813614606857, -0.34781256318092346, 0.5207266211509705, -0.4712638258934021, -0.23284949362277985, 0.15462812781333923, 0.2560245096683502, 0.18089650571346283, -0.3491568863391876, -0.0832585021853447, -0.08207681030035019, 0.20258057117462158, 0.17114199697971344, -0.17644831538200378, -0.173751562833786, 0.2703363299369812, -0.08097436279058456, 0.07127182185649872, -0.4510475695133209, 0.0683375746011734, -0.061998944729566574, 0.2676668167114258, -0.03474615514278412, 0.04513286426663399, 0.028333112597465515, -0.053918153047561646, 0.27216416597366333, 0.12015949189662933, -0.052361488342285156, 0.05582002177834511, 0.0011276945006102324, -0.09788046777248383, 0.08942519873380661, 0.24042055010795593, -0.1666560024023056, -0.16350886225700378, 0.1799515187740326, -0.008891127072274685, -0.028300389647483826, -0.1286436915397644, 0.03829898312687874, -0.007997912354767323, 0.41605329513549805, -0.2063947319984436, -0.12860269844532013, 0.13437971472740173, -0.0020448940340429544, -0.27876725792884827, -0.2895587682723999, -0.12267675995826721, -0.14330615103244781, 0.12025397270917892, -0.020110158249735832, 0.029675573110580444, -0.032737672328948975, 0.08538654446601868, -0.005821694619953632, 0.2769947350025177, -0.09291595965623856, 0.04073847457766533, -0.0648677721619606, 0.06735273450613022, -0.40732091665267944, 0.176787868142128, -0.05011263117194176, -0.44351816177368164, 0.13301397860050201, -0.0031333290971815586, -0.5690222382545471, 0.353231817483902, -0.15320757031440735, 0.07206130772829056, 0.34108296036720276, -0.015670016407966614, 0.019037077203392982, -0.11005114763975143, -0.14040493965148926, 0.08216293901205063, 0.315339058637619, 0.31822946667671204, -0.0022590586449950933, 0.03296921029686928, -0.07362024486064911, -0.23191256821155548, 0.08288105577230453, 0.33050337433815, -0.11705020070075989, -0.13865496218204498, 0.11741788685321808, -0.1185915470123291, 0.24399985373020172, 0.01046437956392765, -0.16304251551628113, -0.09938912093639374, -0.10205716639757156, -0.035569626837968826, -0.1990514099597931, 0.18492333590984344, 0.0006553978892043233, -0.011041722260415554, -0.046466778963804245, 0.1807551383972168, -0.20811247825622559, -0.010684726759791374, 0.11008577048778534, -0.3220294415950775, -0.05505755543708801, 0.29091495275497437, 0.20048213005065918, -0.29636889696121216, -0.0722438395023346, 0.19180257618427277, -0.48387813568115234, 0.28764960169792175, 0.14055180549621582, 0.2795824110507965, -0.036532964557409286, 0.08083942532539368, -0.17095451056957245, -0.12441227585077286, -0.2703731060028076, 0.3889428973197937, -0.35034751892089844, -0.09931854158639908, 0.40855515003204346, 0.1639467179775238, 0.2348717451095581, -0.0823296308517456, -0.2334691733121872, 0.24082490801811218, 0.05176466330885887, 0.26732632517814636, -0.09958333522081375, -0.14812098443508148, -0.15910203754901886, 0.04594074934720993, 0.1187119409441948, -0.24328404664993286, -0.14035339653491974, 0.20764797925949097, -0.18455490469932556, 0.15859569609165192, 0.12459331005811691, -0.02658882364630699, 0.050125814974308014, 0.020598595961928368, 0.057901062071323395, -0.06437429785728455, -0.015592400915920734, 0.14860665798187256, -0.10468282550573349, -0.12643377482891083, -0.16123637557029724, 0.028019972145557404, -0.1700768917798996, 0.15781885385513306, 0.12043140828609467, -0.16491831839084625, 0.36278823018074036, -0.26660239696502686, -0.14166858792304993, 0.09534836560487747, 0.06331297010183334, -0.4256412386894226, -0.09322820603847504, 0.06773596256971359, 0.1038305014371872, 0.35421863198280334, 0.010336420498788357, -0.08088551461696625, -0.05060804262757301, -0.2010881006717682, 0.021329276263713837, 0.1840088665485382, -0.16932892799377441, 0.0222773514688015, -0.10980163514614105, -0.07443203032016754, -0.5750479698181152, 0.3537646532058716, 0.12063731998205185, 0.2054765373468399, -0.03215046226978302, 0.13241805136203766, -0.2364823967218399, -0.09282831102609634, -0.12945803999900818, 0.10844548046588898, -0.47364747524261475, -0.04701530933380127, -0.24530808627605438, -0.1156986802816391, -0.18356169760227203, 1.1861310005187988, -0.21026891469955444, -0.13719399273395538, -0.08451486378908157, 0.40660810470581055, 0.16870488226413727, 0.11400485038757324, 0.12349721789360046, -0.3552941679954529, 0.19179904460906982, -0.1850225329399109, 0.06558170914649963, 0.2002565711736679, -0.08179304003715515, -0.19173672795295715, -0.08448340743780136, -0.08531129360198975, -0.0055637420155107975, -0.2091681957244873, 0.08557648211717606, 0.0032148510217666626, 0.03685230016708374, 0.037803005427122116, -0.12156190723180771, 0.10448916256427765, 0.023453611880540848, -0.1100384071469307, 0.05868661403656006, -0.05548909679055214, -0.0031452460680156946, -0.09814894199371338, 0.05643803998827934, -0.08316357433795929, -0.0712614357471466, -0.33011290431022644, 0.21189185976982117, -0.034644365310668945, 0.19138382375240326, 0.12992684543132782, 0.10623650252819061, -0.23683488368988037, 0.10848058015108109, -0.3113672137260437, 0.16969257593154907, -0.07752825319766998, 0.5105069875717163, 0.1177474856376648, 0.18304596841335297, -0.1715136021375656, 0.21025454998016357, -0.29864707589149475, 0.3801203668117523, -0.012968609109520912, 0.07246910780668259, -0.26793164014816284, 0.201850026845932, -0.047206707298755646, 0.1240856721997261, -0.06640107929706573, 0.06774567067623138, -0.06560380011796951, 0.056146081537008286, -0.03337770700454712, -0.04618610441684723, -0.11172571033239365, -0.005839026533067226, 0.011888879351317883, -0.020986517891287804, 0.2505110502243042, -0.10963255912065506, -0.008053852245211601, -0.23716501891613007, -0.00417969049885869, 0.21066942811012268, -0.10300850123167038, -0.08516135066747665, -0.05449817702174187, 0.17424049973487854, 0.2634599506855011, -0.15705397725105286, -0.013422468677163124, -0.13424603641033173, 0.017209967598319054, 0.10991669446229935, 0.12187641859054565, -0.1539606899023056, 0.11919951438903809, 0.040043748915195465, 0.21384088695049286, -0.1783691644668579, 0.08698581904172897, -0.24995124340057373, -0.05743696540594101, 0.048113759607076645, -0.028344716876745224, 0.03596768155694008, -0.05402682349085808, 0.03988547623157501, 0.19367027282714844, -0.08633040636777878, 0.09535384923219681, -0.08077926933765411, 0.1263255774974823, -0.10908278822898865, -0.2935137450695038, -0.07066411525011063, -0.11034257709980011, 0.32503363490104675, 0.10948950052261353, -0.042040541768074036, 0.1846393644809723, -0.08788450807332993, -0.051259737461805344, 0.09163495898246765, -0.07313388586044312, -0.10762644559144974, 0.2127339243888855, 0.21735820174217224, 0.0853695496916771, -0.24166391789913177, 0.015557408332824707, 0.14594785869121552, 0.25281521677970886, -0.09093687683343887, 0.15102308988571167, -0.04449621960520744, 0.13443465530872345, -0.12773896753787994, -0.195957750082016, 0.32714998722076416, -0.3709736466407776, -0.3606627881526947, 0.1639021635055542, -0.19797906279563904, -0.21479395031929016, 0.20640936493873596, -0.12935905158519745, -0.04810766130685806, 0.11872942000627518, -0.008912772871553898, 0.06727704405784607, -0.23403885960578918, 0.004117777105420828, -0.3485400676727295, -0.307677298784256, -0.12646032869815826, -0.017402198165655136, -0.04184497520327568, 0.40265971422195435, -0.17707951366901398, 0.26457467675209045, 0.17753338813781738, 0.0377577506005764, -0.04281865060329437, -0.23177896440029144, 0.059190891683101654, -0.15604664385318756, 0.012211055494844913, 0.08957357704639435, -0.17655152082443237, 0.05512037128210068, -0.16276082396507263, 0.08664463460445404, 0.407304048538208, -0.2962677776813507, -0.24978837370872498, 0.14562276005744934, 0.12931008636951447, -0.4197147786617279, 0.05457925796508789, -0.1537359356880188, 0.2251225709915161, 0.08317271620035172, -0.1624043583869934, -0.09045402705669403, 0.04738831892609596, 0.12446752935647964, -0.021907681599259377, -0.09075671434402466, -0.146789088845253, -0.09902244061231613, 0.1836661398410797, 0.07499725371599197, -0.24858562648296356, 0.2710239887237549, -0.03221258148550987, 0.1332555115222931, -0.060472261160612106, 0.07604660838842392, -0.17361874878406525, 0.1807483732700348, -0.3052387237548828, 0.10779628157615662, 0.007794092409312725, 0.08706516772508621, -0.28030669689178467, -0.14289571344852448, -0.5128602981567383, 0.22543589770793915, 0.12629014253616333, 0.27167996764183044, -0.042783282697200775, -0.7475414872169495, 0.048417821526527405, 0.17133012413978577, -0.2585906386375427, 0.7726876139640808, -0.3987360894680023, -0.38234850764274597, 0.5796756148338318, -0.25540217757225037, 0.7107363343238831, -0.2512716054916382, -0.08135175704956055, 0.12713563442230225, -0.06093304976820946, 0.23330548405647278, 0.028567597270011902, -0.0943719819188118, -0.1149260476231575, 0.033605147153139114, 0.19110143184661865, -0.06929178535938263, -0.04917209595441818, -0.06851105391979218, -0.05182645842432976, -0.17628557980060577, -0.18564371764659882, -0.08843103796243668, 0.15907913446426392, 0.03697087615728378, 0.08253259211778641, 0.044572506099939346, -0.026303235441446304, -0.07067366689443588, 0.10815569758415222, 0.008186123333871365, -0.17195309698581696, 0.16080370545387268, -0.07948866486549377, 0.05230630189180374, 0.22820840775966644, -0.30551737546920776, 0.10781540721654892, 0.05490799620747566, 0.4106053411960602, 0.012804289348423481, -0.1849522739648819, 0.10083245486021042, 0.02978093922138214, -0.22310878336429596, -0.10674408078193665, -0.2864815294742584, 0.0027282775845378637, -0.01875963993370533, 0.027877645567059517, -0.028210364282131195, 0.1770142912864685, -0.001138067920692265, -0.1693326085805893, 0.04564179852604866, -0.12622621655464172, -0.09707339107990265, -0.10689827054738998, 0.06370469927787781, -0.04921098053455353, -0.1335354596376419, -0.12757883965969086, 0.02395796775817871, 0.02175990864634514, 0.07789098471403122, -0.16637714207172394, 0.22396282851696014, 0.1878373920917511, -0.12122247368097305, 0.05983683839440346, -0.12599875032901764, -0.233385369181633, -0.0732240080833435, 0.0009943012846633792, -0.015200548805296421, -0.19849763810634613, -0.18918472528457642, 0.13618984818458557, 0.21157395839691162, -0.0220616664737463, -0.016799481585621834, 0.13569027185440063, 0.10037214308977127, 0.4547170102596283, -0.16371849179267883, -0.2288593351840973, 0.017500076442956924, -0.21339620649814606, -0.09750917553901672, 0.20197665691375732, 0.26100361347198486, 0.21527773141860962, 0.14448322355747223, 0.005367066245526075, 0.1222701147198677, -0.12429484724998474, 0.015985839068889618, -0.12777212262153625, 0.0850759819149971, -0.22391840815544128, 0.0850975289940834, -0.04477996751666069, -0.0412040650844574, -0.008552929386496544, -0.10770280659198761, -0.11422645300626755, -0.15896610915660858, 0.22284913063049316, -0.11556100845336914, -0.17280782759189606, -0.01871800795197487, -0.015931714326143265, 0.01257331483066082, 0.024434607475996017, 0.14841261506080627, 0.16672147810459137, -0.21141651272773743, 0.014692324213683605, -0.19379322230815887, -0.15269991755485535, 0.17062611877918243, 0.07471821457147598, -0.11901752650737762, -0.09921933710575104, 0.03650322183966637, 0.31105872988700867, -0.095945805311203, -0.10206720978021622, 0.44936010241508484, -0.1937129646539688, 0.23877239227294922, -0.1290832757949829, 0.026861069723963737, 0.25661391019821167, -0.1987503618001938, -0.12859177589416504, -0.031512659043073654, -0.10628928989171982, -0.03808625787496567, 0.032054152339696884, -0.06235811486840248, -0.08060873299837112, 0.13318294286727905, 0.08274532109498978, 0.08219254016876221, 0.031108645722270012, 0.01071149855852127, 0.030210349708795547, -0.4619043469429016, 0.183660626411438, 0.021655142307281494, -0.08007004112005234, 0.016972532495856285, -0.04425864666700363, 0.07582885026931763, 0.13842634856700897, 0.23412728309631348, -0.019941948354244232, 0.06732668727636337, -0.06974304467439651, 0.05040986090898514, 0.03805159404873848, -0.12216798216104507, -0.0871863067150116, -0.06372346729040146, 0.16974225640296936, -0.11044168472290039, 0.05904377996921539, 0.4589851498603821, -0.14396487176418304, 0.15211798250675201, 0.1446944624185562, -0.07633928954601288, -0.301066517829895, -0.05285453796386719, 0.23053640127182007, -0.22420048713684082, -0.10852871090173721, -0.04728035256266594, 0.1379842907190323, -0.25233691930770874, 0.15389811992645264, -0.08159181475639343, 0.17850467562675476, 0.23593822121620178, -0.1801925152540207, 0.056355565786361694, 0.1822410523891449, -0.06071987375617027, 0.03534381836652756, -0.08384084701538086, -0.00976612325757742, -0.10582179576158524, -0.10066009312868118, 0.07382789254188538, 0.16249482333660126, 0.16254375874996185, 0.07265857607126236, -0.2674592435359955, 0.06700117141008377, 0.19563879072666168, 0.1739630252122879, -0.3320904076099396, -0.21238672733306885, 0.021490084007382393, -0.04044990986585617, 0.08285176753997803, -0.04966937378048897, -0.04228868708014488, -0.0536111555993557, 0.23467934131622314, 0.27542030811309814, 0.037422649562358856, 0.23793713748455048, 0.01468587014824152, -0.10186164826154709, 0.08472035825252533, -0.05115465819835663, 0.025491489097476006, -0.3999477028846741, 0.3439120948314667, -0.07429708540439606, 0.09824683517217636, 0.1539658159017563, -0.22974321246147156, 0.18536338210105896, 0.05532529205083847, -0.027597852051258087, -0.09406723827123642, -0.11052313446998596, -0.08326128870248795, 0.16559477150440216, 0.1928194761276245, -0.1620512455701828, -0.2846093475818634, -0.0034706194419413805, -0.10936824977397919, 0.2654423713684082, -0.033143553882837296, -0.09331845492124557, -0.1388392150402069, 0.0708780586719513, 0.25986340641975403, 0.17230932414531708, -0.25502511858940125, -0.05669660493731499, 0.0731472298502922, -0.05990518257021904, -0.09204932302236557, -0.22543270885944366, -0.15445184707641602, -0.0011677690781652927, 0.2669079899787903, 0.12606631219387054, 0.32223689556121826, -0.12937554717063904, 0.04105887562036514, -0.15287844836711884, 0.4675813913345337, -0.2505764067173004, -0.08077554404735565, -0.14848989248275757, 0.07388019561767578, -0.3257356882095337, -0.06754890829324722, 0.007706445641815662, -0.015723468735814095, 0.23643121123313904, 0.4631030261516571, -0.27885568141937256, -0.1492631435394287, -0.0767640694975853, 0.23566347360610962, -0.051554158329963684, 0.5022464990615845, -0.5206839442253113, 0.009283848106861115, -0.010786342434585094, 0.3839424252510071, -0.15789054334163666, 0.02677026577293873, -0.2508058249950409, 0.13371799886226654, 0.01412013079971075, -0.22811226546764374, 0.38083457946777344, 0.08238974958658218, -0.05035298317670822, -0.2795805037021637, 0.14998027682304382, -0.12901055812835693, 0.10194721817970276, -0.0892038568854332, -0.08002103865146637, 0.006870552897453308, -0.14488966763019562, -0.11827981472015381, 0.0864274725317955, -0.1233612522482872, 0.390457421541214, 0.0030750755686312914, -0.04973769932985306, -0.21880492568016052, 0.15311329066753387, 0.13388670980930328, 0.115469790995121, -0.0321183018386364, -0.10503150522708893, 0.20968613028526306, -0.0288278479129076, -0.22620263695716858, 0.09677295386791229, -0.2204635739326477, 0.12297569215297699, -0.13909941911697388, 0.0429757684469223, -0.0989556834101677, 0.06527819484472275, 0.02929968200623989, 0.08586366474628448, -0.1973244994878769, 0.09793020039796829, -0.02709382213652134, -0.14886660873889923, -0.025338076055049896, 0.23911428451538086, -0.013518177904188633, -0.09968999773263931, -0.09116115421056747, 0.01607680693268776, 0.2772478461265564, -0.10512595623731613, -0.09591133892536163, 0.042364586144685745, -0.05058242008090019, -0.21266046166419983, 0.11773531138896942, 0.05306953564286232, -0.14792640507221222, -0.026770180091261864, 0.09337057173252106, -0.10149379819631577, -0.0242353193461895, 0.05025006830692291, -0.009657176211476326, 0.10595931112766266, 0.0803910568356514, -0.149536594748497, 0.0721006840467453, 0.08221825957298279, -0.09306750446557999, 0.09325151890516281, -0.27938002347946167, -0.009776020422577858, 0.162580206990242, 0.04543449357151985, -0.0019841354805976152, -0.068880096077919, -0.18597717583179474, 0.004596976097673178, -0.20701946318149567, 0.05681125819683075, 0.16298770904541016, -0.15762606263160706, -0.10010696202516556, 0.06836190074682236, -0.08382602035999298, 0.062018394470214844, -0.2608189582824707, -0.18282723426818848, -0.1546434611082077, 0.22141213715076447, 0.2976933717727661, 0.14205670356750488, 0.026995737105607986, -0.18853436410427094, -0.10416852682828903, 0.11187917739152908, 0.19259010255336761, 0.1210326999425888, 0.0038817846216261387, -0.041807178407907486, -0.12812112271785736, 0.006340083200484514, -0.1242712140083313, -0.05376539006829262, -0.059502746909856796, 0.03387151658535004, 0.27369076013565063, -0.006760495249181986, -0.09814820438623428, -0.03064030222594738, 0.10129426419734955, 0.069086454808712, -0.021286148577928543, -0.20684118568897247, 0.16031168401241302, 0.5048815608024597, 0.12490677833557129, -0.11521049588918686, -0.22555382549762726, -0.014399556443095207, 0.09113757312297821, -0.1552465260028839, -0.20916877686977386, -0.09535613656044006, -0.3157613277435303, 0.15782271325588226, -0.13757431507110596, 0.11036566644906998, 0.0007674915832467377, 0.17525681853294373, 0.2874178886413574, 0.16137345135211945, -0.18702073395252228, -0.08509460836648941, -0.25501564145088196, 0.10049008578062057, -0.08878795802593231, 0.01656375452876091, -0.06512349843978882, 0.13714613020420074, -0.25240448117256165, 0.2420269250869751, 0.2075420320034027, -0.043716225773096085, 0.2585706114768982, 0.17742082476615906, 0.13465921580791473, -0.3194114565849304, -0.024934323504567146, -0.24737225472927094, -0.22842465341091156, 0.2935566008090973, -0.15836350619792938, -0.004522630013525486, 0.07202397286891937, 0.32167965173721313, 0.07131728529930115, -0.002297147875651717, -0.10701901465654373, 0.16870470345020294, -0.000938170007430017, 0.2704542577266693, -0.10694101452827454, -0.2694871425628662, -0.09339971840381622, -0.3539048731327057, -0.30095797777175903, 0.3522149622440338, -0.06632636487483978, -0.3175421357154846, -0.22773690521717072, -0.05521746352314949, 0.47632256150245667, 0.3150201141834259, 0.0073163448832929134, -0.3858858346939087, -0.10069706290960312, 0.14946478605270386, 0.0311017744243145, 0.08539603650569916, 0.08982737362384796, -0.02532820589840412, -0.0979878380894661, 0.26106876134872437, 0.1970941424369812, -0.007667355239391327, 0.4941043555736542, -0.18313318490982056, 0.11132648587226868, -0.09027718007564545, 0.16763785481452942, -0.2332615852355957, -0.2187729924917221, -0.1979120969772339, 0.12164478003978729, 0.0678805410861969, 0.14465822279453278, -0.22007320821285248, -0.046480294317007065, -0.020698459818959236, 0.0012789309257641435, 0.14212997257709503, -0.2508954107761383, 0.015442886389791965, 0.34519049525260925, -0.3463636040687561, 0.020897381007671356, 0.308485209941864, 0.05864270403981209, 0.0465850830078125, 0.22139060497283936, -0.12406574189662933, -0.07770483940839767, -0.07477109134197235, -0.10737532377243042, -0.07447075098752975, -0.03775274381041527, 0.06398295611143112, 0.11340250074863434, -0.13752226531505585, 0.16645881533622742, 0.032555483281612396, 0.1076330617070198, -0.04083859547972679, -0.002472958993166685, 0.30685335397720337, -0.16834674775600433, -0.28403300046920776, 0.3573448061943054, 0.15544481575489044, 0.18260958790779114, 0.14618194103240967, -0.1803128570318222, -0.24402332305908203, -0.06737913191318512, 0.14641498029232025, -0.031270045787096024, -0.37890535593032837, 0.3647189438343048, 0.0882156640291214, -0.07255268096923828, -0.07019823044538498, 0.007762200199067593, -0.42886534333229065, -0.09201286733150482, 0.3917020559310913, -0.3115781843662262, -0.11496226489543915, 0.23937633633613586, 0.08160382509231567, 0.09224272519350052, -0.0802583396434784, -0.0678519532084465, -0.32147955894470215, 0.21147914230823517, -0.13341481983661652, -0.23506885766983032, -0.1792272925376892, 0.06087573245167732, -0.042891982942819595, 0.21714238822460175, -0.20626701414585114, 0.201058492064476, 0.08075398206710815, 0.22411735355854034, -0.5786503553390503, -0.04809611663222313, -0.23671020567417145, 0.3372442126274109, 0.1426411122083664, 0.2969563603401184, -0.26952123641967773, 0.05077838897705078, -0.014964457601308823, -0.13562652468681335, 0.01567445881664753, 0.0140603706240654, 0.5402702689170837, -0.4253346621990204, -0.25925618410110474, 0.05792998895049095, 0.2636577785015106, 0.0803728848695755, -0.2428169548511505, 0.12061206251382828, 0.08989693224430084, 0.48931244015693665, 0.1791509985923767, -0.06046198308467865, -0.6824105978012085, -0.26326984167099, -0.13821011781692505, 0.2801009714603424, 0.1360350400209427, 0.2786049246788025, -0.14275643229484558, -0.36448442935943604, 0.010670091956853867, -0.046446166932582855, -0.11217294633388519, 0.23060870170593262, -0.07024101167917252, 0.25122159719467163, 0.11865705251693726, 0.28948208689689636, -0.313789427280426, 0.11246306449174881, -0.5164400935173035, 0.35746052861213684, -0.19319528341293335, -0.176599383354187, -0.04791129007935524, 0.15526244044303894, 0.36664366722106934, -0.0984550416469574, -0.04675954580307007, 0.1959601491689682, -0.13349436223506927, -0.05451425537467003, -0.008563932031393051, -0.20475971698760986, -0.2049769014120102, -0.1733294427394867, 0.03330576792359352, -0.05876636877655983, -0.004854856990277767, -0.18974217772483826, 0.11875621229410172, -0.09086247533559799, 0.09426683932542801, 0.141457200050354, 0.22083529829978943, 0.027623698115348816, -0.056197039783000946, 0.15862946212291718, -0.14439880847930908, 0.16444502770900726, -0.15297940373420715, -0.16705329716205597, 0.0419013574719429, -0.09198348224163055, 0.09570011496543884, -0.026340976357460022, -0.04415898025035858, -0.17436644434928894, 0.28419384360313416, -0.48536404967308044, -0.2941833734512329, 0.26253727078437805, -0.08815394341945648, -0.21333570778369904, 0.44291430711746216, -0.10060562193393707, 0.3944021761417389, -0.5511215925216675, 0.0595761314034462, -0.15330703556537628, 0.1334509551525116, 0.4730198085308075, 0.045674946159124374, -0.18965916335582733, 0.5464207530021667, -0.34921783208847046, 0.5029051303863525, -0.26586171984672546, -0.07932215929031372, -0.38509365916252136, 0.306330144405365, 0.1669301688671112, 0.09887411445379257, -0.009195773862302303, 0.05586295947432518, 0.2254362851381302, 0.03526006266474724, -0.05456982180476189, -0.004949362948536873, -0.13237394392490387, -0.1019972413778305, 0.031114520505070686, -0.030299635604023933, -0.0845131129026413, -0.03793569654226303, -0.10391715914011002, -0.09681081026792526, -0.10136457532644272, 0.3237247169017792, -0.26862502098083496, 0.04975844919681549, 0.10625903308391571, 0.005191474687308073, -0.16198328137397766, 0.10068260878324509, -0.05405198410153389, -0.21035270392894745, 0.11951063573360443, 0.26177337765693665, -0.13579213619232178, 0.007991873659193516, 0.3645215630531311, -0.29055240750312805, 0.1512192189693451, 0.030905799940228462, 0.09095589071512222, -0.46284013986587524, -0.2177375853061676, -0.0051029580645263195, 0.1456194818019867, 0.21441659331321716, 0.20603126287460327, -0.14123064279556274, 0.15815362334251404, -0.008715899661183357, -0.09810589998960495, 0.07947159558534622, -0.1396624892950058, 0.06173152104020119, 0.06710177659988403, -0.0168836060911417, 0.09883078932762146, -0.055880848318338394, 0.015354502946138382, 0.1356501281261444, -0.12509557604789734, -0.03241462633013725, 0.06814441084861755, 0.05154133215546608, -0.0895727127790451, -0.1934402883052826, 0.0401373952627182, 0.1261255145072937, -0.020913315936923027, 0.038300253450870514, -0.2683873474597931, -0.16769985854625702, 0.1331944316625595, 0.19525298476219177, -0.027079153805971146, -0.013697702437639236, 0.14909052848815918, -0.110247902572155, -0.2676020860671997, 0.1705501526594162, -0.310339093208313, -0.13031157851219177, 0.049299806356430054, -0.15910914540290833, -0.015621941536664963, 0.051220934838056564, 0.1397838294506073, -0.10535258799791336, -0.1477993130683899, -0.16875022649765015, -0.07669683545827866, 0.2505059838294983, -0.003003362100571394, -0.17799164354801178, 0.012229104526340961, -0.057500436902046204, -0.11040540039539337, -0.025702932849526405, 0.07205810397863388, 0.12881679832935333, -0.10760212689638138, -0.03777306154370308, -0.14218011498451233, -0.014339782297611237, -0.11233339458703995, 0.37255966663360596, -0.20897512137889862, 0.13931065797805786, -0.10883304476737976, 0.20645785331726074, -0.13647018373012543, -0.02010585553944111, 0.053795989602804184, 0.11486411839723587, -0.05933515354990959, -0.28662779927253723, -0.19730667769908905, 0.25923246145248413, -0.04497561603784561, 0.12898068130016327, -0.03302007541060448, 0.10402760654687881, -0.10494498908519745, -0.3614307940006256, -0.4078723192214966, 0.5328720808029175, -0.44163015484809875, 0.47309404611587524, 0.23118089139461517, -0.3363891839981079, 0.4044477045536041, -0.15813294053077698, -0.09723250567913055, -0.05658591911196709, -0.08435302972793579, -0.07144183665513992, 0.15618644654750824, 0.18153110146522522, -0.1671576052904129, -0.09456442296504974, -0.12079601734876633, 0.018837355077266693, 0.16263948380947113, -0.06784000992774963, 0.058575745671987534, -0.043042536824941635, 0.14250025153160095, -0.1621142029762268, -0.18563970923423767, 0.0597509890794754, 0.2678234875202179, -0.027795419096946716, -0.13153494894504547, 0.17513103783130646, -0.1507090926170349, 0.13053220510482788, -0.17058800160884857, 0.0779305025935173, -0.28522345423698425, 0.12220115959644318, -0.09262830018997192, 0.13721340894699097, -0.2029872089624405, 0.003512923838570714, 0.1880211979150772, 0.02848992869257927, -0.009427144192159176, 0.022699449211359024, -0.09827877581119537, -0.1805722713470459, 0.46772533655166626, -0.1624213457107544, 0.10067939013242722, -0.019546231254935265, -0.07091809809207916, -0.04211652651429176, 0.007391056045889854, -0.052871450781822205, -0.1158294752240181, -0.12623220682144165, 0.05992994084954262, -0.14322011172771454, -0.10446105152368546, 0.04127275198698044, 0.11714762449264526, -0.12007235735654831, 0.1760271042585373, -0.17530688643455505, 0.2577372193336487, 0.1681281328201294, -0.019192496314644814, -0.19235984981060028, -0.1477588564157486, 0.14749203622341156, -0.23672394454479218, 0.10819783061742783, 0.0528017058968544, -0.25382426381111145, 0.3942755460739136, -0.007429537829011679, -0.12073516845703125, -0.1386883705854416, -0.09763137996196747, 0.048587799072265625, -0.17216959595680237, 0.05367553234100342, 0.06697092205286026, 0.02216830477118492, -0.00030509542557410896, -0.03204747661948204, -0.05957604944705963, 0.06665488332509995, 0.03787767142057419, -0.072029247879982, -0.014508004300296307, -0.09897033870220184, -0.0582190677523613, -0.06957041472196579, -0.06247461959719658, -0.10950496792793274, 0.13651923835277557, 0.10640163719654083, -0.16996562480926514, -0.19217419624328613, -0.31112247705459595, -0.06670261174440384, 0.26814502477645874, -0.18611367046833038, 0.39766421914100647, 0.02332381159067154, 0.05767787992954254, 0.21727587282657623, 0.26092052459716797, 0.0665898397564888, 0.0050725629553198814, -0.5116416811943054, -0.036236438900232315, 0.13016054034233093, 0.27805688977241516, 0.03227982670068741, -0.37316036224365234, 0.012584247626364231, -0.2893730700016022, 0.26432105898857117, -0.19136705994606018, 0.06407898664474487, 0.4371691048145294, -0.37601014971733093, -0.11794907599687576, 0.2714056074619293, 0.07839961349964142, -0.10618531703948975, 0.05727149546146393, -0.025094496086239815, -0.032552920281887054, -0.09845414012670517, -0.04288288578391075, 0.06692660599946976, 0.019280241802334785, 0.12945666909217834, -0.13146249949932098, 0.10157602280378342, 0.39481303095817566, -0.2198140174150467, -0.3305916488170624, -0.2594653069972992, -0.025741614401340485, -0.1876814216375351, 0.0401863195002079, 0.517649233341217, -0.03229093924164772, 0.03310152515769005, -0.06631464511156082, 0.3695562183856964, 0.08639432489871979, -0.21739579737186432, -0.32757076621055603, 0.20337849855422974, 0.04164079576730728, -0.037312284111976624, 0.2564018964767456, -0.2610512375831604, 0.29753121733665466, -0.13256239891052246, 0.3487018942832947, -0.4000661373138428, -0.023854920640587807, 0.1528821736574173, -0.35060834884643555, 0.4014970362186432, -0.005652683787047863, -0.255825936794281, -0.03075651079416275, -0.12134594470262527, -0.14143721759319305, 0.05910177528858185, -0.08720672130584717, 0.09060525894165039, 0.009084035642445087, 0.006501815747469664, 0.00593680702149868, -0.008353408426046371, -0.1778673529624939, 0.45000123977661133, -0.155264750123024, -0.2107311338186264, 0.06659012287855148, 0.16235144436359406, -0.06506900489330292, 0.0013953248271718621, -0.18484102189540863, -0.1127871423959732, -0.1005692258477211, 0.09815281629562378, -0.20032277703285217, 0.0055577936582267284, 0.3638778626918793, 0.11251764744520187, -0.4635980427265167, 0.061428215354681015, -0.37369653582572937, 0.518852174282074, 0.12878790497779846, -0.11820309609174728, -0.13900822401046753, 0.20781944692134857, -0.2720746695995331, 0.2698860466480255, -0.22185003757476807, 0.23510172963142395, -0.03656299039721489, 0.122023805975914]}, "type": "TENSOR"}], "docString": "", "domain": ""}, {"input": ["Parameter193"], "output": ["Parameter193_reshape1"], "name": "Times212_reshape1", "opType": "Reshape", "attribute": [{"name": "shape", "ints": ["256", "10"], "type": "INTS"}], "docString": "", "domain": ""}, {"output": ["Parameter6"], "name": "Parameter6", "opType": "Constant", "attribute": [{"name": "value", "t": {"dims": ["8"], "dataType": "FLOAT", "floatData": [-0.1615397185087204, -0.4338356554508209, 0.09164135903120041, -0.01685221679508686, -0.06502643972635269, -0.1317378729581833, 0.020417550578713417, -0.1211102306842804]}, "type": "TENSOR"}], "docString": "", "domain": ""}, {"output": ["Parameter5"], "name": "Parameter5", "opType": "Constant", "attribute": [{"name": "value", "t": {"dims": ["8", "1", "5", "5"], "dataType": "FLOAT", "floatData": [-0.008905669674277306, -0.23690743744373322, -0.5088216662406921, -0.06456177681684494, 0.14181184768676758, -0.5919761657714844, -0.4752853810787201, -0.049348145723342896, 0.7682155966758728, 0.26346519589424133, -0.4917634427547455, 0.05561765283346176, 1.0189645290374756, 0.5547041893005371, -0.4416643977165222, -0.15953698754310608, 0.5575414896011353, 0.5920912623405457, -0.2947413921356201, -0.6131798028945923, 0.03849884867668152, 0.22601930797100067, -0.21855629980564117, -0.47719430923461914, -0.2917049527168274, -0.039882346987724304, 0.2185998111963272, 0.49872705340385437, 0.42367178201675415, 0.048547789454460144, -0.10118173062801361, -0.2769094705581665, -0.004399026278406382, 0.5271722078323364, 0.40340957045555115, -0.15083789825439453, -0.32669755816459656, -0.15898573398590088, 0.35899585485458374, 0.3726355731487274, -0.5676766633987427, -0.38571643829345703, -0.1736956238746643, 0.22803734242916107, 0.33274900913238525, -0.38078179955482483, -0.2294795960187912, -0.06623970717191696, -0.01456076093018055, 0.2849120795726776, -0.023685239255428314, 0.10450534522533417, 0.253627210855484, 0.3617715537548065, 0.6909624934196472, 0.33491653203964233, 0.4169996976852417, 0.38482844829559326, 0.3294100761413574, 0.24301494657993317, -0.469070702791214, -0.07595888525247574, -0.1445249766111374, -0.17356260120868683, -0.24677062034606934, -0.9726812243461609, -0.7156173586845398, -0.5382127165794373, -0.6167798638343811, -0.44845151901245117, -0.19898280501365662, -0.3333558738231659, -0.3490765392780304, -0.14603577554225922, -0.06359775364398956, -0.29535022377967834, -0.33241569995880127, -0.32799458503723145, -0.0792078748345375, -0.22243107855319977, -0.4767628610134125, -0.21071620285511017, -0.05752904713153839, 0.16373887658119202, 0.16197435557842255, -0.39172589778900146, -0.02351396717131138, 0.12326627224683762, 0.042400017380714417, 0.22804906964302063, 0.09454049170017242, 0.3720371127128601, 0.2193872630596161, -0.011200291104614735, 0.18117614090442657, 0.3275194764137268, 0.3511163592338562, 0.029065223410725594, 0.20922230184078217, 0.3407168984413147, -0.21453875303268433, -0.12204788625240326, -0.002380508929491043, -0.22573916614055634, -0.16116438806056976, 0.08904799818992615, 0.2049759179353714, -0.15634816884994507, -0.22565391659736633, -0.5620983242988586, -0.06023457646369934, 0.4104316830635071, -0.014487497508525848, -0.47492480278015137, -0.5640554428100586, -0.11556227505207062, 0.1420968621969223, 0.27673882246017456, 0.04259895905852318, -0.01154940016567707, 0.009696257300674915, 0.24611404538154602, 0.625613272190094, 0.683263897895813, 0.23607052862644196, -0.16604582965373993, -0.3338145315647125, -0.19119441509246826, 0.05349813774228096, 0.14157480001449585, 0.18287110328674316, -0.5480813980102539, -0.7332809567451477, -0.58826744556427, -0.3842240273952484, 0.540283739566803, 0.3461269736289978, -0.25229349732398987, -0.3465349078178406, -0.21091517806053162, 0.22015060484409332, 0.6589154601097107, 0.3647841811180115, 0.12937375903129578, -0.10955952107906342, 0.060226935893297195, 0.3028530776500702, 0.23698604106903076, 0.46915197372436523, 0.22329305112361908, 0.09797149151563644, 0.5594847202301025, -0.21443209052085876, -0.4576771557331085, -0.2118259072303772, 0.36440980434417725, 0.48706260323524475, -0.4076792597770691, -0.4292023479938507, -0.2475433498620987, 0.4149287939071655, 0.30001330375671387, -0.45789340138435364, -0.30391550064086914, -0.08953923732042313, 0.2780548334121704, 0.11443112045526505, -0.17231403291225433, -0.3516780436038971, -0.15202881395816803, 0.34867072105407715, 0.185796856880188, 0.0708867609500885, 0.13417653739452362, -0.04618285596370697, -0.02208573743700981, -0.13200485706329346, 0.0916861891746521, 0.23160681128501892, 0.33974218368530273, 0.16504956781864166, 0.3764834702014923, 0.19502994418144226, 0.3151701092720032, 0.5671406984329224, -0.11800449341535568, 0.19598188996315002, 0.1325552612543106, 0.047790516167879105, 0.13364340364933014, 0.028376566246151924, -0.13915082812309265, -0.12077710032463074, -0.19753223657608032, -0.5022867918014526, -0.035823289304971695, -0.1898280829191208, -0.4275367856025696, -0.2847483158111572, -0.19034995138645172]}, "type": "TENSOR"}], "docString": "", "domain": ""}, {"input": ["Input3", "Parameter5"], "output": ["Convolution28_Output_0"], "name": "Convolution28", "opType": "Conv", "attribute": [{"name": "kernel_shape", "ints": ["5", "5"], "type": "INTS"}, {"name": "strides", "ints": ["1", "1"], "type": "INTS"}, {"name": "auto_pad", "s": "U0FNRV9VUFBFUg==", "type": "STRING"}, {"name": "group", "i": "1", "type": "INT"}, {"name": "dilations", "ints": ["1", "1"], "type": "INTS"}], "docString": "", "domain": ""}, {"input": ["Convolution28_Output_0", "Parameter6"], "output": ["Plus30_Output_0"], "name": "Plus30", "opType": "Add", "attribute": [{"name": "axis", "i": "1", "type": "INT"}, {"name": "broadcast", "i": "1", "type": "INT"}], "docString": "", "domain": ""}, {"input": ["Plus30_Output_0"], "output": ["ReLU32_Output_0"], "name": "ReLU32", "opType": "Relu", "docString": "", "domain": ""}, {"input": ["ReLU32_Output_0"], "output": ["Pooling66_Output_0"], "name": "Pooling66", "opType": "MaxPool", "attribute": [{"name": "kernel_shape", "ints": ["2", "2"], "type": "INTS"}, {"name": "strides", "ints": ["2", "2"], "type": "INTS"}, {"name": "pads", "ints": ["0", "0", "0", "0"], "type": "INTS"}], "docString": "", "domain": ""}, {"output": ["Parameter87"], "name": "Parameter87", "opType": "Constant", "attribute": [{"name": "value", "t": {"dims": ["16", "8", "5", "5"], "dataType": "FLOAT", "floatData": [-0.0485563650727272, -0.09101364016532898, -0.006567917298525572, -0.128403440117836, 0.10890022665262222, 0.08424150198698044, -0.1683894395828247, -0.27132806181907654, -0.019025469198822975, 0.0692625641822815, 0.039750680327415466, -0.011775517836213112, -0.06318891793489456, -0.15085993707180023, -0.11244388669729233, 0.06987237185239792, 0.0007687737816013396, 0.08335787802934647, -0.18104656040668488, -0.11850579082965851, 0.0033806723076850176, 0.2513008415699005, 0.19361533224582672, -0.05452343448996544, -0.12814028561115265, -0.4240483343601227, -0.2706243395805359, -0.2594493627548218, 0.08103776723146439, 0.08797059208154678, 0.00970472302287817, -0.229428231716156, -0.06401660293340683, 0.021817907691001892, -0.04962887242436409, 0.16946658492088318, 0.23561102151870728, -0.019434919580817223, -0.1350330263376236, -0.042808786034584045, -0.06604431569576263, 0.18613818287849426, 0.18148548901081085, -0.14488591253757477, 0.0301041416823864, -0.13984766602516174, 0.11360441893339157, 0.1050480380654335, 0.051293082535266876, 0.05778695270419121, -0.1550651639699936, -0.13397930562496185, 0.0788629949092865, 0.11649572849273682, -0.13530519604682922, -0.12452050298452377, -0.2071416676044464, -0.14239712059497833, -0.06145666539669037, -0.0848151445388794, -0.18943579494953156, -0.22062841057777405, -0.21656720340251923, -0.08668345212936401, 0.06490638852119446, -0.25929775834083557, -0.10393436998128891, -0.33296993374824524, -0.13464973866939545, -0.03164593502879143, 0.028283342719078064, 0.08956132084131241, -0.10871702432632446, -0.18743896484375, -0.22380830347537994, 0.10318344831466675, -0.04760589823126793, -0.026498841121792793, -0.021494023501873016, 0.02870049700140953, 0.047858599573373795, -0.0015511958627030253, 0.10386131703853607, -0.08803610503673553, -0.05492853373289108, 0.0767126977443695, 0.026416394859552383, -0.2577744424343109, -0.2845146059989929, -0.20862248539924622, 0.017891256138682365, 0.06780456006526947, -0.03435538709163666, -0.3046033978462219, -0.12663622200489044, -0.010425187647342682, 0.11742118000984192, 0.16988778114318848, -0.06706076860427856, 0.05505189672112465, 0.17483898997306824, -0.06551364064216614, -0.13898248970508575, -0.308615118265152, -0.1045035645365715, 0.09251601994037628, 0.2999582886695862, 0.06113322824239731, -0.2238905280828476, -0.21774233877658844, -0.0867142379283905, 0.03453875705599785, 0.12183117866516113, -0.14342059195041656, -0.14133720099925995, -0.42325878143310547, -0.035403620451688766, 0.05317186191678047, 0.024188712239265442, -0.016071122139692307, -0.12040923535823822, -0.1626027375459671, -0.09674572199583054, 0.03565060719847679, 0.01352375466376543, 0.1438552737236023, 0.019712625071406364, -0.33717676997184753, -0.22315596044063568, -0.16202999651432037, 0.16747891902923584, 0.45203301310539246, 0.2678220272064209, -0.12484310567378998, -0.2182544618844986, -0.14916153252124786, -0.07604195177555084, 0.25750207901000977, 0.1028762087225914, 0.065093033015728, -0.4209180474281311, -0.3114350140094757, -0.03601532801985741, 0.04679396376013756, 0.11451203376054764, -0.053237173706293106, -0.1361592710018158, -0.26634207367897034, -0.2130674421787262, -0.030975310131907463, 0.054346900433301926, -0.17052768170833588, -0.28975817561149597, -0.0414196215569973, -0.24664004147052765, 0.09930238872766495, 0.19524505734443665, -0.09816950559616089, -0.27048927545547485, -0.14976917207241058, -0.08557458221912384, 0.001977275824174285, 0.05408528447151184, 0.046747662127017975, -0.16107846796512604, 0.023279596120119095, 0.06521863490343094, 0.24592797458171844, 0.0606386698782444, 0.012831315398216248, -0.09471376985311508, -0.10581237822771072, 0.22934259474277496, 0.20430348813533783, -0.08989682048559189, -0.24754013121128082, 0.14427025616168976, 0.05195837840437889, -0.02395634539425373, 0.10000108927488327, -0.05712178349494934, -0.07585285604000092, -0.05744583159685135, 0.05116294324398041, 0.08658400177955627, 0.062275782227516174, -0.15449947118759155, -0.14051668345928192, 0.020217157900333405, 0.027638006955385208, -0.10162952542304993, 0.028731584548950195, -0.1280091404914856, -0.22699958086013794, -0.2687792479991913, 0.13324090838432312, 0.07806967943906784, -0.12345310300588608, -0.14539755880832672, -0.17290523648262024, 0.07490882277488708, 0.2147226631641388, -0.01865900307893753, -0.011617684736847878, -0.15776567161083221, -0.039294078946113586, -0.014340892434120178, -0.03494420647621155, 0.13751232624053955, 0.251747190952301, 0.04373861476778984, -0.3926660418510437, -0.07790732383728027, 0.14997632801532745, 0.2061816304922104, -0.14093178510665894, -0.1931440234184265, -0.04336024448275566, 0.09022607654333115, 0.21707259118556976, -0.08400165289640427, -0.20222805440425873, -0.13156744837760925, -0.09987356513738632, -0.0017187350895255804, -0.3674922287464142, -0.3101159930229187, -0.41247090697288513, -0.03239436820149422, -0.14428606629371643, -0.08322117477655411, -0.06490825861692429, -0.26588988304138184, -0.059059496968984604, -0.10231653600931168, 0.036359041929244995, 0.13712583482265472, -0.037482984364032745, -0.09332706034183502, 0.006899564526975155, 0.020245833322405815, 0.2299138307571411, -0.009017903357744217, -0.1711762398481369, -0.18040525913238525, 0.023168597370386124, -0.15403836965560913, -0.013067308813333511, -0.033201031386852264, -0.08521424978971481, -0.22192257642745972, -0.2521321773529053, -0.1847257763147354, -0.05622471496462822, 0.0955083891749382, -0.10368500649929047, -0.16978149116039276, -0.15736238658428192, 0.0018222701037302613, 0.006111889611929655, -0.005999081768095493, 0.20904089510440826, 0.06389889866113663, 0.16539031267166138, 0.2766287326812744, -0.057492636144161224, 0.08701781183481216, 0.14773015677928925, 0.13645263016223907, -0.009538683108985424, 0.1278182715177536, -0.01767723448574543, -0.07789589464664459, -0.03270944580435753, -0.15162914991378784, 0.13641193509101868, 0.03006272204220295, -0.07147711515426636, -0.15736185014247894, -0.0798630565404892, 0.02430896833539009, 0.006579856388270855, -0.138672336935997, 0.11343424767255783, 0.23744235932826996, -0.0670645534992218, -0.1272609829902649, -0.024227652698755264, 0.21766941249370575, 0.24051932990550995, -0.22820553183555603, -0.008572586812078953, -0.19617895781993866, -0.08930354565382004, -0.17843331396579742, -0.19912947714328766, -0.30946698784828186, -0.11069397628307343, -0.11934427917003632, 0.04169084504246712, 0.011480848304927349, -0.09059122949838638, -0.16148574650287628, -0.16161546111106873, -0.09363073855638504, 0.1012055054306984, 0.23056375980377197, 0.33410748839378357, -0.15872830152511597, -0.027987675741314888, 0.15227825939655304, 0.03316185995936394, 0.2040674388408661, 0.10759252309799194, 0.12716907262802124, 0.02643323689699173, -0.18552133440971375, -0.21519555151462555, -0.15143786370754242, -0.19436706602573395, -0.10167742520570755, -0.0668223649263382, -0.18159429728984833, -0.22546334564685822, -0.062224071472883224, -0.21034789085388184, -0.08713001757860184, -0.13168516755104065, -0.11911161243915558, -0.1495795100927353, 0.09994123876094818, 0.11954653263092041, 0.22844070196151733, -0.02858673594892025, 0.04422473534941673, 0.1575174331665039, 0.09188351035118103, 0.22744369506835938, -0.021807512268424034, 0.1916884034872055, 0.07369084656238556, 0.04892595484852791, -0.03920923173427582, -0.04705292358994484, -0.22891616821289062, -0.03614075854420662, 0.041426341980695724, -0.07762393355369568, -0.2611229121685028, -0.0912007987499237, -0.17292679846286774, -0.23834316432476044, 0.10433737188577652, -0.031183898448944092, -0.003995437640696764, -0.049886249005794525, 0.13645552098751068, 0.2172389030456543, -0.05016835778951645, -0.04197770729660988, -0.0634370818734169, -0.06891166418790817, 0.008541063405573368, 0.24360664188861847, 0.13791726529598236, -0.01115367840975523, -0.14292924106121063, 0.11151274293661118, 0.07313501089811325, -0.08778789639472961, 0.04911564663052559, -0.04676542803645134, -0.18753792345523834, -0.16639703512191772, -0.05079735442996025, -0.08475662767887115, 0.026826167479157448, -0.08649285137653351, -0.18647974729537964, 0.007361341267824173, -0.1363808959722519, -0.24112747609615326, -0.275541216135025, -0.10601148009300232, -0.0008207806968130171, -0.07741782814264297, 0.11260538548231125, 0.09809847176074982, -0.03961804136633873, 0.12805607914924622, 0.08752225339412689, 0.27042075991630554, 0.20268431305885315, 0.20752102136611938, 0.03979964554309845, -0.14928001165390015, -0.09358218312263489, -0.10785188525915146, -0.1947113275527954, -0.27080097794532776, -0.1566784381866455, -0.026621732860803604, 0.09703120589256287, -0.008688589558005333, -0.015095324255526066, -0.17963722348213196, -0.05860815942287445, -0.0791080892086029, -0.220678448677063, 0.1075926199555397, -0.5088579058647156, -0.309909462928772, -0.14241962134838104, 0.013917885720729828, -0.0332721546292305, -0.0611729770898819, -0.2279776781797409, -0.168904110789299, -0.11738067120313644, -0.09099238365888596, 0.06495463848114014, -0.2356211543083191, -0.016749761998653412, 0.029220901429653168, 0.2096763700246811, -0.1713377833366394, 0.3138743042945862, 0.22207890450954437, -0.23740322887897491, -0.1707688570022583, -0.2179967761039734, 0.19849348068237305, 0.168926402926445, 0.06156664341688156, -0.042811471968889236, -0.2683849334716797, 0.0663081556558609, 0.29191306233406067, 0.03754884749650955, 0.16733400523662567, -0.32384786009788513, -0.25886794924736023, -0.07261534035205841, -0.1953873336315155, 0.07085315883159637, 0.01921442337334156, -0.07297760248184204, -0.05503610521554947, -0.026403218507766724, -0.18798932433128357, 0.09289582073688507, -0.011830953881144524, -0.18425334990024567, -0.030384177342057228, -0.08106335997581482, 0.11830869317054749, 0.033954355865716934, -0.15159590542316437, -0.1246211901307106, 0.35987138748168945, 0.30385270714759827, 0.15977822244167328, 0.11741940677165985, 0.17384164035320282, 0.21723999083042145, -0.024622570723295212, -0.05187755823135376, -0.020101457834243774, 0.10644400119781494, -0.1154613047838211, 0.10250864923000336, -0.06351886689662933, -0.11650703102350235, -0.13352985680103302, -0.07271390408277512, 0.07817906141281128, 0.019656023010611534, 0.10619388520717621, 0.08268117904663086, 0.15436951816082, -0.29505619406700134, -0.19211812317371368, -0.07308638095855713, 0.047795411199331284, 0.20183216035366058, -0.221505269408226, -0.2858070731163025, -0.39411407709121704, -0.12909503281116486, -0.06852944940328598, 0.25425848364830017, 0.09744229167699814, -0.05849297717213631, -0.13732853531837463, -0.2529595196247101, 0.2653420567512512, 0.045385222882032394, 0.06224910169839859, 0.1795545071363449, 0.17525887489318848, 0.08852808177471161, 0.023113608360290527, -0.07702213525772095, 0.07809252291917801, -0.04656391963362694, -0.08425140380859375, -0.06461973488330841, -0.12551997601985931, -0.08405105769634247, 0.014204084873199463, 0.0354142040014267, -0.16464191675186157, -0.24463215470314026, -0.3694094121456146, -0.1805029958486557, 0.13938884437084198, 0.1029081717133522, -0.0999741330742836, -0.1553630232810974, -0.40147969126701355, 0.0801175907254219, 0.11636429280042648, 0.048825137317180634, 0.20691698789596558, 0.10473358631134033, -0.004640513565391302, 0.0037714543286710978, -0.188820481300354, 0.09153605997562408, -0.08869077265262604, -0.046445880085229874, -0.16173416376113892, -0.038405247032642365, -0.04863325506448746, -0.05188758298754692, 0.065911203622818, 0.021947888657450676, -0.1275767683982849, -0.1936386227607727, -0.27008572220802307, 0.09438394010066986, 0.22730889916419983, 0.09536141157150269, -0.040722887963056564, -0.23792697489261627, -0.1400575488805771, 0.0400947667658329, 0.2147902250289917, 0.06942731142044067, 0.30465835332870483, -0.06758856028318405, -0.06033667176961899, -0.01388031616806984, 0.22329550981521606, 0.12044026702642441, -0.0625072494149208, -0.07773168385028839, 0.004388993140310049, -0.06604526191949844, -0.3008423447608948, -0.13873329758644104, -0.22090953588485718, -0.16132496297359467, -0.27216678857803345, -0.28397229313850403, -0.2156323343515396, -0.07374999672174454, -0.19594880938529968, -0.27323150634765625, -0.262513667345047, -0.18629583716392517, 0.2254476249217987, 0.021181173622608185, 0.0008122368017211556, 0.011185912415385246, 0.06582364439964294, -0.03368503972887993, -0.20650511980056763, -0.20560866594314575, -0.2074623703956604, -0.019831780344247818, 0.05050733685493469, 0.00471616443246603, -0.050312675535678864, 0.23621651530265808, -0.06442952156066895, 0.053469669073820114, 0.2690306305885315, 0.3456336557865143, 0.20448674261569977, -0.4155077040195465, -0.24614383280277252, -0.10449036210775375, -0.04480655491352081, 0.02693212404847145, 0.08706800639629364, -0.22441278398036957, -0.2289963662624359, 0.00650830427184701, -0.018077388405799866, 0.336372047662735, 0.05157006159424782, -0.10236301273107529, -0.05782179534435272, -0.16025540232658386, -0.009699004702270031, -0.2092268466949463, 0.08736559748649597, -0.09876188635826111, -0.13653306663036346, -0.050851721316576004, -0.15948143601417542, 0.08124995976686478, 0.05858054757118225, -0.056563474237918854, -0.011578116565942764, -0.1257173717021942, 0.15367542207241058, -0.03538193926215172, -0.02044721692800522, -0.16568569839000702, -0.3309613764286041, -0.22421495616436005, 0.018195228651165962, -0.2279190868139267, 0.06933924555778503, 0.12477988004684448, 0.1241966113448143, -0.05020014941692352, 0.0014504591235890985, 0.09753495454788208, 0.26148828864097595, 0.04247131571173668, -0.09176084399223328, 0.26603856682777405, 0.012044012546539307, 0.06349027901887894, 0.2917325794696808, -0.20980994403362274, -0.08098441362380981, -0.1514623612165451, 0.01693526655435562, 0.026248710229992867, -0.28772059082984924, -0.15563209354877472, -0.11588084697723389, -0.16594025492668152, -0.04860479012131691, -0.09146153181791306, -0.3424217998981476, -0.08248615264892578, -0.14639954268932343, 0.06170615926384926, -0.06424456834793091, 0.10531934350728989, 0.03259674087166786, -0.04015224426984787, -0.04184994846582413, -0.14641475677490234, 0.04650091007351875, -0.19159215688705444, -0.09720258414745331, -0.026763247326016426, -0.008710562251508236, -0.1834431290626526, 0.032486774027347565, 0.054895903915166855, 0.05650826171040535, 0.09049119055271149, -0.07283502072095871, 0.040771208703517914, 0.01770399510860443, 0.023165585473179817, 0.08541125059127808, 0.07327347993850708, 0.07388172298669815, 0.19680674374103546, 0.13288091123104095, -0.08110922574996948, -0.09204757958650589, -0.02118545025587082, 0.0649576336145401, 0.01664741523563862, -0.19992229342460632, -0.39201831817626953, 0.05337882414460182, 0.14832061529159546, -0.015930501744151115, -0.04682142287492752, -0.1876724660396576, -0.03878039866685867, -0.09607725590467453, -0.24141086637973785, -0.11034749448299408, -0.1248227208852768, -0.1941799372434616, -0.21113526821136475, -0.08935874700546265, -0.11216948181390762, -0.1977689117193222, -0.11411645263433456, -0.05959547683596611, 0.09871963411569595, -0.0030470085330307484, 0.09484831988811493, -0.27617356181144714, -0.2762490510940552, 0.10739443451166153, 0.16690699756145477, -0.15530411899089813, -0.10048027336597443, -0.05641690269112587, -0.16939426958560944, 0.11060523986816406, -0.1286766529083252, -0.22765392065048218, -0.09630677103996277, -0.1019238829612732, -0.10251773148775101, -0.09103234857320786, -0.09878663718700409, -0.1266203671693802, -0.07014458626508713, -0.033576782792806625, -0.20395876467227936, -0.13930387794971466, -0.22477124631404877, -0.083558589220047, 0.023859236389398575, 0.1608676165342331, -0.15787112712860107, -0.23640334606170654, -0.18659746646881104, 0.08294444531202316, 0.007717343047261238, -0.18990717828273773, -0.0368315652012825, -0.1421593427658081, -0.04587904363870621, 0.03692972660064697, -0.2829573452472687, -0.16551727056503296, -0.18551060557365417, -0.2300465703010559, -0.044569652527570724, -0.2071906179189682, -0.06228456273674965, -0.026583096012473106, -0.09080245345830917, -0.01769099198281765, -0.2137795090675354, -0.16995050013065338, -0.05051632970571518, 0.16060075163841248, -0.10472562164068222, -0.18431325256824493, -0.0817534402012825, 0.02412394806742668, 0.3162372410297394, -0.020620400086045265, -0.037059236317873, -0.01589791290462017, 0.06975679844617844, 0.40803149342536926, 0.1922045648097992, -0.15207965672016144, -0.08055247366428375, 0.18993385136127472, 0.25558218359947205, 0.005665880162268877, -0.0635862797498703, -0.023513853549957275, 0.028532806783914566, -0.10798429697751999, -0.07838823646306992, 0.006924596149474382, -0.029963649809360504, 0.20361441373825073, 0.10302932560443878, 0.06137075647711754, -0.10591742396354675, 0.07669983804225922, 0.0010445468360558152, 0.1922081559896469, 0.058428023010492325, -0.20915839076042175, -0.11073622107505798, 0.1516658067703247, -0.03713640570640564, -0.054176099598407745, -0.0562775544822216, 0.16917124390602112, 0.17288422584533691, -0.07186485081911087, -0.15483108162879944, 0.09730042517185211, -0.08626920729875565, 0.037754155695438385, -0.12144140154123306, -0.17640529572963715, -0.03744393214583397, -0.1211773231625557, -0.06508835405111313, -0.011592800728976727, -0.1859850287437439, 0.17555756866931915, 0.22805985808372498, 0.11251313239336014, 0.08350186049938202, -0.12051472067832947, 0.17182858288288116, 0.2135157287120819, 0.05474758893251419, 0.2565140426158905, -0.04514119401574135, -0.0767223984003067, -0.029420606791973114, 0.38092151284217834, 0.11730678379535675, 0.015836525708436966, -0.17927579581737518, -0.0175944771617651, 0.1050080731511116, 0.007059205789119005, -0.05988568067550659, -0.004474120680242777, -0.14042404294013977, -0.06679479032754898, -0.19451801478862762, -0.04792727530002594, 0.014082209207117558, -0.05311235040426254, 0.09745048731565475, 0.18235157430171967, 0.27238303422927856, 0.1482742726802826, -0.10897787660360336, -0.006137829273939133, 0.014541476964950562, 0.02918483130633831, -0.042400360107421875, -0.1457047164440155, -0.2651108205318451, -0.20258715748786926, -0.23183348774909973, 0.19146016240119934, 0.1335183084011078, -0.15205053985118866, -0.22032365202903748, -0.2936010956764221, -0.0721922218799591, -0.05235185846686363, 0.070465587079525, 0.16709300875663757, 0.16302193701267242, -0.045340023934841156, -0.16536973416805267, -0.15742963552474976, -0.08623357862234116, -0.008763990364968777, -0.06531042605638504, -0.11710987240076065, -0.2890889048576355, -0.1423463076353073, -0.06993799656629562, -0.07339230179786682, 0.04702167958021164, 0.07068709284067154, 0.01164259109646082, 0.001530040637589991, 0.2679424285888672, 0.41476115584373474, 0.3318842351436615, 0.05309115722775459, -0.09126650542020798, -0.09105974435806274, -0.08052719384431839, -0.07754771411418915, -0.15218207240104675, -0.06944306194782257, -0.1597212851047516, 0.017591042444109917, 0.016774829477071762, -0.10425513982772827, -0.1507980078458786, -0.13542556762695312, -0.013737879693508148, -0.027242209762334824, 0.12156648933887482, -0.19823753833770752, -0.0260448157787323, 0.025637399405241013, -0.05903433635830879, 0.0035247579216957092, -0.09438861906528473, -0.13069668412208557, -0.2359791398048401, -0.10785036534070969, -0.26768311858177185, -0.06995970755815506, 0.027143465355038643, 0.2931978106498718, 0.24231164157390594, 0.11347775161266327, 0.09510540217161179, -0.004526076838374138, 0.06909330934286118, 0.0295697208493948, -0.032948583364486694, -0.08366659283638, -0.03908427804708481, 0.036163609474897385, -0.06011905521154404, 0.08593237400054932, -0.06908846646547318, 0.03778141364455223, 0.11311928927898407, -0.004552461672574282, -0.05190753936767578, -0.06595040112733841, -0.038535766303539276, -0.017827220261096954, -0.21660463511943817, -0.2647268772125244, -0.23418982326984406, -0.03451717272400856, 0.09788685292005539, 0.18291251361370087, 0.16025127470493317, 0.24531272053718567, 0.043764591217041016, 0.19735702872276306, 0.07365645468235016, 0.2242022603750229, -0.06002480909228325, -0.017072319984436035, -0.0968012884259224, -0.09551245719194412, 0.006014008074998856, -0.1255997121334076, 0.09679015725851059, 0.16055598855018616, -0.09497489780187607, -0.2649535536766052, -0.20399163663387299, 0.013760979287326336, 0.03815280646085739, -0.09369457513093948, -0.15725389122962952, -0.07138212025165558, -0.10705529153347015, -0.033424243330955505, 0.03713896498084068, -0.0902671217918396, -0.08425956964492798, -0.12584854662418365, -0.1511489450931549, 0.006971132941544056, 0.05209892615675926, 0.020854402333498, 0.11242306232452393, -0.10367371886968613, 0.03739583492279053, 0.06606831401586533, 0.027191419154405594, 0.013805653899908066, -0.11092380434274673, -0.23143675923347473, 0.04583947733044624, 0.082292340695858, -0.2254447191953659, -0.10254069417715073, -0.10895461589097977, -0.09785081446170807, -0.030701953917741776, 0.1891084462404251, 0.044401295483112335, -0.018865467980504036, -0.13528560101985931, -0.1711433380842209, 0.18068116903305054, 0.10807482153177261, -0.015967441722750664, -0.1361083984375, -0.21788561344146729, -0.11858073621988297, -0.08990351110696793, -0.12800705432891846, -0.06001388654112816, -0.0930866226553917, -0.16487400233745575, -0.06909117102622986, 0.05639393627643585, 0.08227597922086716, -0.12686052918434143, 0.07714255154132843, 0.32661935687065125, 0.15921442210674286, -0.04044591262936592, -0.12586498260498047, 0.2621592581272125, 0.32022663950920105, 0.11691885441541672, 0.29637154936790466, 0.4117778539657593, -0.06387952715158463, 0.09631044417619705, -0.10193310678005219, -0.07229720801115036, 0.017783701419830322, -0.1220608800649643, 0.06882794201374054, -0.3222334086894989, -0.44739943742752075, -0.2121708244085312, -0.04382479190826416, -0.2055710405111313, -0.201360285282135, -0.2263404130935669, -0.3250301480293274, -0.04634815454483032, -0.1532975137233734, -0.1776132583618164, -0.0890120267868042, -0.3261643350124359, 0.10592429339885712, 0.2931738495826721, 0.09220080822706223, -0.10742619633674622, -0.11680089682340622, 0.1118706464767456, 0.1606343388557434, 0.19108274579048157, -0.016946321353316307, -0.09085573256015778, 0.00866859219968319, -0.08802513033151627, 0.22110812366008759, 0.31805288791656494, -0.1386258602142334, 0.060469940304756165, 0.01004709955304861, 0.05625397711992264, 0.22364796698093414, 0.04092376306653023, -0.004037109203636646, 0.0007701382855884731, 0.2802278399467468, 0.029840026050806046, -0.03400858864188194, -0.20550419390201569, -0.21601001918315887, -0.4117316007614136, -0.19750390946865082, -0.21639364957809448, -0.13090138137340546, -0.22261102497577667, -0.25279468297958374, -0.06705359369516373, -0.1288449466228485, 0.02804957702755928, 0.06692557036876678, -0.02071668952703476, -0.0856904536485672, 0.16614267230033875, 0.13574251532554626, 0.05203128606081009, -0.1511194258928299, -0.17559345066547394, 0.20422761142253876, -0.05560991168022156, -0.1551693081855774, -0.2525765001773834, 0.044607698917388916, 0.16534742712974548, 0.3116951882839203, 0.011384028010070324, 0.06012119725346565, -0.1518121361732483, 0.027344848960638046, -0.0461873859167099, -0.09934677928686142, 0.09042976051568985, -0.1224156990647316, -0.0563633032143116, -0.09876688569784164, -0.02813403122127056, -0.09706991165876389, -0.00718895485624671, -0.1798936128616333, -0.06401971727609634, -0.027164127677679062, -0.2709146738052368, -0.18015383183956146, -0.37127357721328735, 0.015378309413790703, -0.2197401374578476, -0.018035758286714554, -0.1537073850631714, -0.16650912165641785, -0.12865965068340302, -0.2706142067909241, -0.04102994501590729, 0.15858601033687592, 0.1120070368051529, 0.08054431527853012, -0.19678574800491333, -0.355466365814209, 0.13648101687431335, 0.21813322603702545, 0.03019222617149353, -0.011387751437723637, -0.2274830937385559, -0.015775423496961594, 0.1691981554031372, 0.1536937803030014, 0.06293783336877823, -0.15644875168800354, 0.01270093210041523, 0.035062212496995926, -0.025814874097704887, -0.02413666807115078, -0.01132863387465477, 0.04051654040813446, 0.0078024109825491905, 0.10636173188686371, -0.16688115894794464, -0.3434835374355316, -0.07947812229394913, -0.06647878885269165, -0.005902669858187437, -0.16614937782287598, -0.37280553579330444, -0.21827982366085052, 0.12208424508571625, 0.07161525636911392, -0.1166985034942627, -0.26056259870529175, -0.11146153509616852, 0.335713267326355, 0.09522479772567749, 0.09288190305233002, -0.0013613420305773616, 0.04609062895178795, 0.10861741006374359, -0.06875447928905487, 0.07132304459810257, 0.03900471329689026, -0.016049660742282867, -0.03923631086945534, -0.1548767238855362, 0.12482482939958572, 0.20957456529140472, -0.008377982303500175, 0.01626286283135414, 0.1327681988477707, 0.06695391237735748, -0.1426796168088913, 0.04811171442270279, 0.1590464860200882, 0.1673273891210556, -0.11773747950792313, -0.14107142388820648, -0.06906991451978683, 0.1232963502407074, -0.10033141821622849, -0.03303530812263489, -0.07134335488080978, -0.051095329225063324, -0.2152068167924881, -0.15770451724529266, 0.1170814260840416, 0.00016185354616027325, 0.14732231199741364, -0.01444218773394823, 0.0770399197936058, -0.00817920919507742, -0.09513308852910995, -0.020986804738640785, 0.12352730333805084, 0.13023440539836884, 0.07731342315673828, 0.08898136019706726, 0.05387340858578682, 0.04946614056825638, -0.051570042967796326, 0.04020273685455322, 0.06020360440015793, 0.08013579249382019, 0.19994878768920898, 0.1845567375421524, -0.0632992684841156, -0.01516373734921217, 0.0989835262298584, 0.20225705206394196, -0.09517420828342438, -0.16016104817390442, -0.2306392341852188, -0.068105049431324, -0.07609310001134872, 0.07609765231609344, 0.04369436949491501, -0.06016815826296806, -0.215978741645813, -0.1534215211868286, 0.04961172863841057, 0.013782075606286526, -0.13848954439163208, 0.12541504204273224, 0.09149223566055298, -0.08470294624567032, -0.07492679357528687, 0.023261770606040955, 0.28689634799957275, 0.290023535490036, -0.09855242073535919, -0.09918238967657089, 0.1926700621843338, -0.015411085449159145, 0.06880120187997818, -0.1779782921075821, 0.013996596448123455, -0.009337572380900383, -0.40401268005371094, -0.36349788308143616, 0.024537181481719017, -0.11701644957065582, -0.19684094190597534, -0.24279186129570007, -0.2949340045452118, -0.09546900540590286, -0.29880863428115845, -0.2091635912656784, -0.06454624235630035, -0.09352410584688187, -0.13063128292560577, -0.07719530910253525, -0.015509634278714657, -0.13318678736686707, 0.1005655825138092, -0.18421754240989685, 0.11681082099676132, 0.13888637721538544, -0.13101647794246674, 0.0208098366856575, 0.011934978887438774, 0.016694866120815277, -0.1232849508523941, -0.17336785793304443, 0.10684994608163834, -0.20629042387008667, -0.0025521425995975733, -0.08022551983594894, -0.015917537733912468, 0.2180190533399582, -0.19791017472743988, -0.1673593968153, -0.06403307616710663, -0.1271553635597229, 0.13218767940998077, -0.14962318539619446, -0.10590993613004684, -0.06556273996829987, 0.09608038514852524, 0.4399641156196594, -0.11545287072658539, -0.1913483887910843, -0.16551128029823303, -0.1300518810749054, -0.05926847830414772, -0.20521223545074463, -0.3004314601421356, -0.14050377905368805, 0.01287066750228405, 0.16172394156455994, 0.056493405252695084, -0.21612891554832458, -0.142697274684906, -0.04841594025492668, 0.06498148292303085, -0.024837186560034752, -0.2095622569322586, -0.1327848583459854, 0.2082269936800003, 0.29817140102386475, -0.3958395719528198, 0.0012315640924498439, 0.1606300324201584, 0.14921563863754272, -0.1719454526901245, -0.22417625784873962, -0.1224074736237526, 0.03075721487402916, -0.08543993532657623, -0.24014495313167572, -0.20720459520816803, -0.1129094809293747, -0.0777837485074997, -0.4912426471710205, -0.2607001066207886, 0.09397679567337036, -0.06037205085158348, -0.17194807529449463, -0.09484104812145233, 0.235667422413826, 0.0298997163772583, -0.13375046849250793, -0.11678595840930939, 0.06369614601135254, 0.19389821588993073, 0.01822228915989399, -0.11250792443752289, -0.09005735069513321, -0.0037346198223531246, -0.04151574522256851, 0.0276777446269989, -0.06704837828874588, -0.10807409882545471, 0.07279594242572784, 0.00037549223634414375, 0.1374470591545105, -0.07971636205911636, 0.050221994519233704, -0.07456394284963608, 0.03628600388765335, 0.0672714114189148, 0.019621342420578003, -0.007040363736450672, -0.0024584163911640644, 0.14657947421073914, -0.09013102203607559, -0.017205234616994858, -0.0029734582640230656, 0.04067029803991318, 0.133265420794487, -0.19262701272964478, 0.03851403668522835, 0.07597807794809341, -0.03894009813666344, 0.20365791022777557, -0.05458710715174675, -0.13279679417610168, -0.17076259851455688, 0.08308213204145432, 0.03594811260700226, 0.13195179402828217, 0.05662524700164795, -0.1479339748620987, -0.05142957344651222, 0.024911096319556236, 0.09497301280498505, 0.08771537244319916, -0.18450738489627838, -0.3274580240249634, -0.1723305881023407, 0.24972666800022125, 0.11131858080625534, -0.12225835025310516, -0.2666175365447998, -0.05561603605747223, 0.3384305536746979, -0.010742263868451118, -0.13553713262081146, -0.023337947204709053, -0.1585884541273117, 0.13291393220424652, -0.1665944755077362, 0.03664242476224899, 0.36329415440559387, -0.0052890595979988575, -0.08935342729091644, -0.16782966256141663, 0.4154664874076843, 0.08401496708393097, -0.005490325856953859, -0.17276214063167572, -0.1776987910270691, -0.2543099522590637, -0.1918422132730484, -0.21491499245166779, 0.030371496453881264, -0.30694225430488586, -0.14748217165470123, -0.16316969692707062, -0.022662123665213585, -0.1589118242263794, -0.34499117732048035, 0.016575947403907776, 0.25546497106552124, 0.41956639289855957, -0.17676687240600586, -0.16295258700847626, 0.14946916699409485, 0.0504726804792881, 0.042421575635671616, -0.32634153962135315, -0.01980431191623211, 0.0863298699259758, 0.011281110346317291, -0.043400608003139496, 0.026077648624777794, 0.09223547577857971, -0.008472481742501259, -0.02289782464504242, -0.10938775539398193, 0.047743603587150574, 0.08632590621709824, -0.0869782343506813, -0.10349399596452713, -0.2371327430009842, 0.015206682495772839, 0.3043708801269531, 0.033185843378305435, -0.1677403748035431, 0.10788559913635254, 0.14289642870426178, 0.15832926332950592, -0.10159981995820999, 0.2257034331560135, 0.07633709162473679, 0.035476990044116974, -0.008995553478598595, 0.2448979616165161, 0.043584953993558884, 0.13270224630832672, -0.11642137169837952, 0.046961747109889984, -0.12562842667102814, -0.13045519590377808, 0.2589865028858185, 0.1462501436471939, 0.01396910473704338, -0.18083925545215607, -0.12266993522644043, 0.21669164299964905, 0.13043315708637238, -0.24795007705688477, -0.07755236327648163, 0.1058027446269989, 0.34534886479377747, 0.15230344235897064, -0.18038444221019745, 0.07628408819437027, -0.040477361530065536, 0.3155892789363861, -0.23563548922538757, -0.0987670049071312, -0.020773520693182945, 0.12866266071796417, 0.007795214187353849, -0.05567863583564758, -0.04069242998957634, 0.018100405111908913, 0.07602665573358536, -0.03709479421377182, -0.19376583397388458, -0.27393051981925964, 0.05864730849862099, 0.004962973762303591, -0.09719419479370117, -0.19667363166809082, -0.07698346674442291, 0.05539616942405701, -0.03639049455523491, -0.25636056065559387, 0.14271746575832367, 0.06827230006456375, -0.03436293080449104, -0.21579091250896454, -0.20046265423297882, 0.17429880797863007, -0.009857657365500927, -0.17309468984603882, 0.015864823013544083, -0.03480299934744835, 0.07328956574201584, 0.1482413113117218, 0.22561264038085938, 0.0938318520784378, 0.024868855252861977, 0.026193756610155106, 0.04698070138692856, 0.011032504960894585, -0.11348801851272583, 0.13010556995868683, 0.029541634023189545, 0.08172206580638885, -0.17626126110553741, -0.25558170676231384, 0.10013291984796524, -0.11286602914333344, -0.22774262726306915, -0.2565389573574066, 0.19728107750415802, 0.2971039116382599, -0.1352369636297226, -0.17027194797992706, -0.18491968512535095, 0.0592418871819973, 0.08274230360984802, -0.12228108942508698, 0.11720985919237137, 0.24419665336608887, 0.33953657746315, -0.010053749196231365, -0.20573386549949646, -0.10988809913396835, -0.01599220559000969, -0.08630041778087616, -0.21884240210056305, -0.0011970468331128359, -0.09690215438604355, -0.2860567569732666, -0.25249359011650085, -0.29506269097328186, -0.19878682494163513, -0.24717573821544647, -0.25962597131729126, -0.10596401989459991, -0.15180177986621857, -0.13266345858573914, -0.3476365804672241, -0.35321348905563354, -0.02693963795900345, -0.04517204314470291, 0.1347474753856659, 0.06551877409219742, 0.11732611060142517, 0.18416205048561096, 0.20452354848384857, -0.1555970311164856, -0.13807807862758636, -0.04630351811647415, 0.06374285370111465, 0.04937514290213585, -0.1808212846517563, -0.06056109443306923, -0.22906593978405, -0.11109992116689682, -0.2703650891780853, -0.08327022194862366, -0.17854630947113037, -0.2751132845878601, -0.17374996840953827, -0.05754399672150612, -0.25563299655914307, -0.3444579839706421, -0.33209237456321716, -0.13241371512413025, -0.1507311314344406, -0.0458599254488945, -0.18026690185070038, -0.019549662247300148, 0.09280002862215042, 0.019341707229614258, -0.21084073185920715, 0.02286013960838318, -0.033520955592393875, -0.13988149166107178, -0.06956855207681656, -0.17530623078346252, 0.12899141013622284, 0.09517482668161392, -0.0026444685645401478, -0.13921429216861725, -0.0973266065120697, 0.149188831448555, 0.07800910621881485, -0.06366381794214249, -0.03144282102584839, -0.2004280537366867, 0.06225169450044632, -0.15379448235034943, 0.1399761587381363, 0.03578062355518341, -0.2833864986896515, 0.07853612303733826, 0.03281057998538017, 0.018781501799821854, -0.12333155423402786, -0.07429515570402145, 0.16664953529834747, 0.17738287150859833, 0.150464728474617, -0.17904020845890045, 0.07333499938249588, 0.1420428305864334, -0.009978152811527252, -0.21358545124530792, -0.04897414892911911, 0.18912136554718018, -0.0005015463684685528, -0.2428470104932785, -0.14563654363155365, -0.0332910381257534, 0.10580228269100189, -0.3154694437980652, -0.15101458132266998, 0.003219667822122574, 0.1480933427810669, -0.2241315394639969, -0.06325744092464447, -0.21262209117412567, 0.042552441358566284, 0.0912562757730484, -0.16822083294391632, -0.007077492773532867, -0.30059608817100525, -0.23668603599071503, -0.1888251006603241, -0.06178611144423485, 0.06518077850341797, -0.3113889992237091, -0.1671891063451767, -0.22406916320323944, -0.09401162713766098, -0.09444310516119003, 0.20701704919338226, 0.5326575636863708, 0.10293186455965042, -0.008675266988575459, 0.22253666818141937, 0.3854483664035797, 0.06323060393333435, 0.04686513915657997, -0.2395608127117157, 0.14906015992164612, 0.06470972299575806, 0.18507567048072815, 0.08771529048681259, -0.0172132458537817, -0.10631972551345825, 0.14580826461315155, 0.28898191452026367, 0.10936245322227478, -0.02717692404985428, -0.021016471087932587, -0.06662363559007645, 0.23331642150878906, 0.15135277807712555, -0.1883697807788849, -0.017400898039340973, 0.10591831803321838, -0.2700497806072235, -0.08066635578870773, 0.10556872934103012, -0.044582583010196686, -0.26075512170791626, -0.18242688477039337, 0.10925643891096115, -0.16166967153549194, 0.044285356998443604, 0.10129479318857193, 0.09576630592346191, -0.012398604303598404, -0.110832579433918, -0.06110904738306999, 0.018988952040672302, -0.0959567129611969, -0.37198057770729065, 0.12065266072750092, 0.1575903296470642, 0.18612925708293915, -0.20687498152256012, -0.1998114436864853, 0.202619731426239, 0.10698894411325455, -0.1453993320465088, -0.26998311281204224, -0.18321824073791504, -0.0760231614112854, -0.10328815132379532, -0.30033671855926514, -0.2437833547592163, -0.15383674204349518, -0.2155226618051529, 0.009679398499429226, 0.04777821898460388, -0.00957147404551506, -0.14839990437030792, -0.17442941665649414, -0.051215045154094696, 0.02868163213133812, -0.009464219212532043, -0.175765722990036, -0.08997268974781036, -0.09946141391992569, -0.02009236253798008, -0.06404496729373932, -0.003384033218026161, -0.1904933601617813, 0.0073551274836063385, 0.05200555548071861, 0.1879449039697647, 0.37624815106391907, 0.13103502988815308, 0.23060502111911774, 0.27454715967178345, 0.19146886467933655, -0.07663280516862869, -0.0206294022500515, 0.10298444330692291, -0.006697640288621187, -0.027158547192811966, 0.2872070074081421, -0.03663591295480728, 0.2246231585741043, 0.18238131701946259, -0.15988504886627197, 0.06547840684652328, -0.1046198308467865, -0.18605074286460876, -0.0730196163058281, -0.042811069637537, 0.0838024914264679, -0.32359328866004944, 0.09644073992967606, -0.13041187822818756, 0.042708754539489746, -0.14140568673610687, -0.054851338267326355, -0.06686735153198242, -0.0436120443046093, -0.011483201757073402, -0.10973489284515381, -0.020457692444324493, -0.0011978113325312734, -0.02466648817062378, -0.07471144944429398, 0.31381815671920776, -0.025728747248649597, 0.17295633256435394, 0.16908086836338043, 0.0544915534555912, 0.23368261754512787, 0.05139593034982681, -0.08165951073169708, -0.0049301194958388805, -0.1043921411037445, -0.09103207290172577, -0.13038723170757294, 0.024682585150003433, 0.09280980378389359, -0.08965624868869781, -0.2173289805650711, -0.11851079016923904, 0.0836050882935524, -0.1445498913526535, -0.2996372580528259, -0.05894472822546959, 0.2071380764245987, -0.007876926101744175, 0.1546112596988678, 0.008365999907255173, 0.07036849856376648, -0.1071542277932167, -0.04873289912939072, -0.01628076285123825, 0.11483966559171677, 0.0471089631319046, -0.08725746721029282, -0.24715320765972137, -0.3144981563091278, -0.21280460059642792, -0.01670234091579914, -0.41751110553741455, -0.3320493996143341, -0.47275543212890625, -0.4394574761390686, -0.2902557849884033, -0.3440623879432678, -0.3676583766937256, -0.3230421841144562, -0.10271696001291275, 0.11769703775644302, -0.1984442174434662, -0.09053533524274826, -0.0142294242978096, -0.08133108913898468, -0.03549562767148018, -0.09528719633817673, -0.05626038834452629, 0.08650588989257812, -0.14065606892108917, -0.10357911139726639, 0.1517326980829239, 0.16220185160636902, -0.10313296318054199, -0.08603596687316895, -0.1982647329568863, -0.02469531260430813, -0.06589321047067642, 0.05010022595524788, 0.1030510887503624, 0.15548637509346008, -0.19065749645233154, -0.10342811793088913, 0.14710229635238647, 0.09911081194877625, 0.026040056720376015, -0.2385258972644806, -0.02202725224196911, -0.2781979739665985, -0.15072456002235413, 0.16351141035556793, 0.0903412476181984, 0.05495467036962509, -0.21249951422214508, 0.043895818293094635, 0.21818752586841583, 0.14050047099590302, 0.002930961549282074, -0.10563881695270538, 0.12919515371322632, 0.011017071083188057, 0.24015453457832336, -0.33231496810913086, -0.09003341943025589, -0.14618422091007233, -0.21795699000358582, 0.01837809942662716, -0.09987379610538483, -0.3663826882839203, -0.4173044264316559, -0.11637169122695923, -0.020905762910842896, 0.11880181729793549, 0.17549486458301544, 0.03912606090307236, -0.1807737499475479, 0.006064896937459707, -0.0630958154797554, 0.11843215674161911, 0.41298454999923706, -0.1091005727648735, 0.10295723378658295, -0.1581384539604187, 0.14200490713119507, 0.29805049300193787, 0.022545920684933662, -0.15240342915058136, -0.00491176825016737, 0.13014067709445953, 0.45092645287513733, 0.07225018739700317, -0.13036979734897614, -0.13428206741809845, 0.0034701437689363956, 0.20728935301303864, 0.009152990765869617, 0.10160040855407715, -0.017770782113075256, -0.10279397666454315, -0.06607762724161148, -0.08658703416585922, 0.1220579519867897, 0.19294346868991852, -0.025889908894896507, -0.01841019280254841, -0.17648042738437653, -0.08403707295656204, -0.029459312558174133, -0.19456534087657928, -0.12360013276338577, -0.36285629868507385, -0.11465441435575485, -0.10222556442022324, -0.09279078990221024, 0.1495802253484726, -0.15256500244140625, -0.22689108550548553, -0.146629199385643, -0.14952827990055084, 0.09984276443719864, 0.018248051404953003, 0.23495875298976898, 0.10801473259925842, -0.03429274260997772, -0.05211322754621506, -0.06912677735090256, 0.13573074340820312, 0.16471682488918304, -0.19381144642829895, 0.11798721551895142, -0.08782480657100677, 0.04675177112221718, -0.15473148226737976, -0.12090275436639786, 0.019765134900808334, -0.1646607518196106, 0.03201333060860634, -0.2862144708633423, -0.25593292713165283, 0.02036255970597267, -0.11477534472942352, -0.05171440169215202, -0.2082870751619339, -0.0500066801905632, -0.06700050085783005, -0.26217031478881836, 0.04017994925379753, -0.17876966297626495, -0.09571023285388947, -0.09712506085634232, -0.06483881920576096, 0.050782375037670135, 0.08086526393890381, -0.14124174416065216, -0.1476992666721344, 0.10607345402240753, -0.11617141216993332, -0.0950997993350029, -0.27055782079696655, -0.02927429974079132, 0.17202182114124298, -0.08933133631944656, -0.11667614430189133, -0.14691874384880066, -0.015447476878762245, 0.3727625012397766, -0.10610129684209824, -0.07311651110649109, -0.013537811115384102, 0.023837575688958168, 0.1392187774181366, 0.0890526995062828, -0.0032879847567528486, -0.30976781249046326, -0.20187105238437653, -0.12630799412727356, 0.11445321887731552, 0.029607923701405525, -0.053274139761924744, -0.27743834257125854, -0.04893269017338753, -0.0879630520939827, -0.1052839457988739, -0.07318087667226791, -0.20961572229862213, -0.15003490447998047, 0.011706658639013767, -0.13202907145023346, -0.14036430418491364, -0.14057491719722748, 0.11583326756954193, -0.03035786934196949, -0.18036633729934692, -0.102110855281353, 0.06427764147520065, 0.18574032187461853, -0.20340421795845032, -0.2226450890302658, -0.3532222509384155, -0.17690040171146393, 0.24420857429504395, -0.09712269902229309, -0.013423288241028786, -0.05223367363214493, -0.06324184685945511, 0.2915133535861969, -0.03807725012302399, 0.1592804193496704, 0.010391289368271828, 0.07036372274160385, 0.32067209482192993, 0.10205161571502686, 0.29072636365890503, 0.1460496485233307, 0.15928137302398682, 0.3670864999294281, 0.18808019161224365, 0.0704004243016243, 0.09752059727907181, -0.08419856429100037, 0.017799165099859238, 0.09501618146896362, -0.05567554011940956, 0.09105060249567032, 0.033384159207344055, 0.043803803622722626, -0.04768095538020134, 0.21684065461158752, -0.015350324101746082, -0.14381882548332214, 0.01870122365653515, 0.1213555857539177, 0.043534114956855774, -0.004041086416691542, -0.003919785842299461, -0.1874760091304779, 0.07643667608499527, -0.21807533502578735, -0.12455408275127411, 0.17523805797100067, -0.1797899752855301, -0.03259379789233208, -0.32365861535072327, -0.21219541132450104, -0.1662071943283081, 0.004090193193405867, 0.060685403645038605, 0.07820228487253189, -0.0368727371096611, -0.014137346297502518, -0.10795308649539948, 0.10761340707540512, 0.15035666525363922, -0.15893007814884186, -0.09580163657665253, -0.0700661763548851, -0.04883328452706337, -0.127066969871521, 0.02467939630150795, 0.02719433605670929, -0.030211621895432472, -0.2106005698442459, 0.02645151875913143, 0.13456374406814575, 0.11560872942209244, -0.048604816198349, 0.03730705380439758, 0.26786699891090393, 0.10168687254190445, 0.15440720319747925, 0.333089143037796, 0.019061286002397537, -0.06913160532712936, -0.08926842361688614, -0.13829170167446136, -0.049724891781806946, 0.06774496287107468, -0.1507083922624588, -0.005107280798256397, 0.015856213867664337, -0.044023074209690094, 0.10370689630508423, -0.23135975003242493, -0.09763240069150925, -0.0742754265666008, 0.0592571422457695, 0.17990727722644806, -0.020424913614988327, 0.05212269723415375, 0.07666853815317154, -0.07569599151611328, 0.12268605828285217, 0.04598599299788475, 0.11218740046024323, 0.16469424962997437, -0.003150396514683962, -0.08560936152935028, -0.1714411824941635, -0.18154288828372955, -0.19995787739753723, -0.027544889599084854, -0.10454297065734863, -0.1574077308177948, -0.07835753262042999, -0.0537114143371582, 0.017605124041438103, -0.0450231209397316, -0.02547929808497429, -0.061385318636894226, 0.021292470395565033, 0.06567129492759705, -0.12805694341659546, 0.07723911851644516, 0.16545958817005157, 0.03636464849114418, -0.23016110062599182, 0.14191795885562897, 0.22819748520851135, 0.31870847940444946, -0.18707342445850372, -0.39112693071365356, -0.0002914036449510604, -0.05006469413638115, -0.11482483893632889, -0.12156588584184647, 0.12397248297929764, 0.004818559158593416, -0.039556872099637985, -0.04269751161336899, 0.0704243928194046, -0.010953606106340885, 0.0584075041115284, -0.024163249880075455, 0.08746067434549332, 0.029075266793370247, 0.09364321082830429, -0.08153349906206131, 0.024203576147556305, -0.05363624170422554, -0.0708167552947998, -0.0593719445168972, -0.2417459785938263, -0.13787615299224854, -0.2537054121494293, -0.10379768908023834, 0.09051993489265442, -0.006841186434030533, -0.18749172985553741, -0.22089523077011108, -0.09179354459047318, -0.0036450019106268883, -0.20024706423282623, -0.12908129394054413, -0.09465787559747696, 0.0025590502191334963, 0.009588697925209999, 0.04907683655619621, 0.25999459624290466, 0.03137040138244629, -0.06768953055143356, -0.05741386488080025, 0.18991616368293762, 0.012778333388268948, -0.13399361073970795, -0.20112550258636475, -0.11014849692583084, -0.15951122343540192, -0.0500679537653923, -0.24756480753421783, -0.16328373551368713, 0.05914198234677315, -0.047905709594488144, -0.01943720318377018, -0.16938409209251404, 0.00566032575443387, -0.07564867287874222, -0.16811136901378632, -0.08813551068305969, -0.16604609787464142, -0.11029907315969467, -0.03788130730390549, 0.16822099685668945, 0.21191082894802094, 0.05789146572351456, -0.034764617681503296, -0.10285808891057968, 0.10685564577579498, 0.04687060788273811, -0.04785851016640663, -0.19113384187221527, -0.11736606061458588, -0.19135688245296478, -0.13008107244968414, -0.16139189898967743, -0.27423498034477234, -0.1139947697520256, -0.002299768151715398, -0.03363873437047005, -0.010529465973377228, -0.1614876091480255, -0.03366705775260925, 0.012305823154747486, 0.03186067193746567, 0.11308486014604568, -0.0743972659111023, -0.035192061215639114, -0.027682624757289886, 0.13673707842826843, -0.003986587282270193, -0.11996402591466904, 0.0031558224000036716, 0.049582589417696, -0.03423725441098213, -0.06419599056243896, -0.09960241615772247, -0.07921914756298065, -0.09984888136386871, -0.022778134793043137, 0.0328502431511879, -0.07681623101234436, 0.06328267604112625, -0.09261514246463776, -0.23364153504371643, -0.17584896087646484, -0.12131179869174957, 0.11819427460432053, 9.840578422881663e-05, -0.16914008557796478, -0.14319154620170593, -0.0889936164021492, -0.09342923015356064, -0.09051921963691711, -0.07507352530956268, -0.08036774396896362, -0.024037620052695274, -0.02825877070426941, 0.019431335851550102, 0.19084477424621582, 0.20427902042865753, 0.001147413277067244, -0.11692720651626587, 0.23554106056690216, 0.22103194892406464, 0.08759090304374695, -0.25354382395744324, -0.07971490174531937, -0.2396189570426941, 0.13963869214057922, 0.22888055443763733, -0.17719906568527222, -0.06413081288337708, -0.17226392030715942, -0.04852486029267311, -0.1257057934999466, -0.07671749591827393, -0.06737338751554489, -0.1216805949807167, -0.06046278029680252, 0.07491951435804367, -0.0836677998304367, -0.16019511222839355, 0.09679513424634933, 0.02615419402718544, -0.02895020693540573, 0.11257169395685196, 0.021143218502402306, 0.2357875555753708, 0.13821323215961456, -0.172121062874794, 0.2564495801925659, 0.15030646324157715, -0.15401922166347504, -0.005129547324031591, -0.10490493476390839, 0.031676847487688065, -0.12825359404087067, 0.016066234558820724, -0.10008502006530762, 0.0408390648663044, 0.08540340512990952, -0.2527438998222351, 0.018851736560463905, -0.0036638150922954082, -0.020703274756669998, -0.03762085363268852, 0.08971523493528366, -0.12017375230789185, -0.06834498047828674, -0.07595597207546234, 0.006653539836406708, 0.12468481063842773, -0.03157215937972069, -0.2784830629825592, 0.08835187554359436, 0.09326324611902237, 0.05165494978427887, 0.204855814576149, 0.28688502311706543, 0.04115425795316696, -0.16958419978618622, 0.022188352420926094, -0.034609731286764145, 0.07781386375427246, 0.030051985755562782, -0.11765152215957642, -0.12999142706394196, 0.03514641895890236, 0.06215678155422211, 0.12592512369155884, -0.10368996113538742, -0.23787249624729156, 0.00823953840881586, 0.059710558503866196, 0.1965235471725464, 0.014912329614162445, -0.05145514756441116, 0.008298621512949467, 0.02400660328567028, -0.1534443348646164, -0.227367103099823, -0.17465926706790924, -0.087058886885643, -0.0819503515958786, 0.02512240596115589, -0.19902090728282928, -0.31067028641700745, -0.26244238018989563, -0.20822332799434662, -0.12655338644981384, -0.023556945845484734, -0.15583258867263794, -0.1472005844116211, -0.10240335762500763, 0.10180413722991943, 0.039840150624513626, 0.16503837704658508, -0.05531330034136772, -0.03939545899629593, 0.11107568442821503, 0.0584467351436615, 0.39487364888191223, 0.03639357164502144, 0.02545267343521118, 0.13117626309394836, 0.4097166359424591, 0.4704922139644623, -0.0075064185075461864, 0.027232155203819275, 0.02421271987259388, -0.026749441400170326, -0.12744025886058807, 0.006767702754586935, 0.09552627056837082, 0.060782019048929214, -0.08731986582279205, 0.027963491156697273, -0.10893512517213821, 0.08074875921010971, 0.01342702005058527, 0.03775434568524361, 0.24610066413879395, -2.284697075083386e-05, -0.08442918956279755, -0.05321495980024338, -0.06211590766906738, 0.09092846512794495, 0.009333260357379913, 0.042374394834041595, -0.16055887937545776, -0.010524691082537174, -0.05229874700307846, 0.17351892590522766, 0.05016486719250679, -0.10062311589717865, -0.01245815958827734, 0.04912189766764641, -0.15517102181911469, 0.05551593750715256, 0.09836620092391968, -0.13195830583572388, 0.02613997645676136, 0.020531892776489258, 0.07372374087572098, 0.12314315885305405, -0.04075516015291214, 0.12312952429056168, 0.017657192423939705, -0.09388758987188339, 0.04298393800854683, 0.0376976914703846, -0.10657943785190582, -0.014692269265651703, 0.028644101694226265, -0.0012099439045414329, -0.13629987835884094, -0.37033939361572266, 0.13997939229011536, -0.07149897515773773, 0.19163021445274353, 0.2112896740436554, -0.007434510625898838, 0.08748137950897217, 0.035120345652103424, 0.017099518328905106, 0.014196478761732578, 0.041091177612543106, -0.05924266204237938, -0.013525492511689663, -0.09961263090372086, -0.13462430238723755, -0.05352376773953438, 0.052685417234897614, -0.13710661232471466, -0.12186338007450104, -0.12708264589309692, -0.12692058086395264, 0.10882620513439178, 0.0906781256198883, -0.05861654877662659, -0.07500675320625305, -0.10414785146713257, 0.2119355946779251, 0.21172338724136353, 0.06868530809879303, -0.2540980279445648, -0.16105949878692627, 0.01724047213792801, 0.04296639561653137, 0.10826094448566437, -0.16289924085140228, -0.24944673478603363, 0.0012548284139484167, -0.09175790846347809, -0.07098469883203506, -0.10132147371768951, -0.21263112127780914, 0.05744437500834465, 0.013898895122110844, -0.0008237772271968424, -0.1316782534122467, -0.21643297374248505, 0.02665071375668049, -0.039899468421936035, -0.20941269397735596, -0.12282302230596542, 0.025393960997462273, 0.03791604936122894, 0.11752580106258392, -0.11997079104185104, -0.17006425559520721, -0.0974060446023941, 0.2040930837392807, 0.18937800824642181, -0.04156796634197235, 0.04682784900069237, -0.05478455126285553, -0.07522128522396088, -0.07960820198059082, -0.10860631614923477, -0.13048386573791504, -0.01907430961728096, -0.20847836136817932, -0.12601810693740845, -0.05182056128978729, -0.1340228170156479, -0.2559832036495209, -0.04736020416021347, 0.038704849779605865, -0.16174907982349396, -0.18938277661800385, -0.23769408464431763, 0.09377532452344894, 0.0316203348338604, 0.17238400876522064, 0.15128959715366364, 0.06676064431667328, 0.01735650561749935, -0.24847467243671417, 0.06912048906087875, 0.08293496072292328, 0.14625200629234314, 0.14844031631946564, -0.1716056615114212, -0.09441854059696198, 0.003140414599329233, 0.04708539694547653, 0.03722015395760536, -0.0891025960445404, 0.03273649141192436, -0.17332570254802704, -0.12498585879802704, 0.12006985396146774, -0.008997735567390919, 0.005789116956293583, -0.20669680833816528, 0.07063423097133636, -0.0045884838327765465, -0.08422159403562546, 0.047885648906230927, 0.013271360658109188, 0.04124471917748451, -0.07766992598772049, 0.04437686875462532, 0.07709188759326935, -0.003952840343117714, 0.011193477548658848, 0.2308434247970581, 0.0352470688521862, -0.14262109994888306, -0.006152662448585033, 0.11057950556278229, 0.15979771316051483, -0.0875079557299614, -0.19825321435928345, -0.049622949212789536, -0.0015058054123073816, -0.0384463295340538, -0.03928394615650177, 0.017626123502850533, 0.0032545679714530706, -0.18658564984798431, 0.259381502866745, 0.007519046775996685, -0.2376730889081955, -0.20677244663238525, 0.049227409064769745, 0.11393087357282639, -0.14944511651992798, -0.2871221899986267, -0.18484020233154297, -0.02631327509880066, -0.2249223291873932, -0.13892489671707153, -0.20621660351753235, -0.1390407681465149, -0.07978161424398422, -0.18970906734466553, -0.13464243710041046, -0.14555296301841736, -0.05649721994996071, -0.14710566401481628, 0.04794403538107872, 0.05822640284895897, -0.021077953279018402, 0.01606758125126362, 0.18601414561271667, 0.05376607924699783, 0.01687629334628582, -0.10760953277349472, 0.002376855816692114, -0.16628874838352203, -0.02771289087831974, -0.07196903228759766, -0.1462544947862625, -0.1989220380783081, 0.009861456230282784, -0.03116292878985405, -0.0843893438577652, -0.056947972625494, 0.030412355437874794, -0.14734292030334473, -0.015280810184776783, 0.04345068708062172, -0.09911275655031204, 0.06721687316894531, -0.1371580809354782, -0.07826177030801773, 0.06090272590517998, 0.029655463993549347, 0.08085127174854279, 0.21955598890781403, 0.007791598327457905, -0.17671631276607513, -0.009461888112127781, -0.01337971817702055, -0.05811981111764908, -0.21824118494987488, -0.04433790594339371, -0.03396182507276535, -0.17719145119190216, 0.004158083815127611, -0.06344307214021683, 0.09530612081289291, -0.05958188325166702, -0.04285247623920441, -0.032206129282712936, -0.01752249151468277, 0.0136181078851223, 0.04746931046247482, -0.04476536437869072, -0.13436146080493927, -0.04273949936032295, -0.03315950557589531, -0.04112407565116882, 0.029338540509343147, 0.24079091846942902, -0.20155911147594452, -0.004041842184960842, 0.15413641929626465, -0.17833857238292694, -0.0029308595694601536, -0.014963881112635136, 0.19375060498714447, 0.03481123223900795, -0.06549357622861862, 0.05228158086538315, 0.25178393721580505, 0.15584157407283783, -0.11138920485973358, -0.06900258362293243, -0.1286614090204239, -0.06771023571491241, -0.22163213789463043, -0.07439027726650238, 0.030526040121912956, -0.2030724138021469, -0.22259250283241272, -0.11553328484296799, -0.10924137383699417, 0.17891861498355865, 0.19344545900821686, 0.07368660718202591, 0.22504501044750214, -0.06462597101926804, 0.025440169498324394, 0.08109414577484131, 0.2586511969566345, 0.13528364896774292, -0.007965746335685253, 0.01224359031766653, 0.10130314528942108, 0.23459261655807495, -0.0972885712981224, -0.26341134309768677, -0.07255029678344727, 0.06163343787193298, -0.09539055824279785, -0.18845432996749878, -0.1160246729850769, -0.15175916254520416, -0.07703544199466705, -0.08954305201768875, 0.018136778846383095, -0.02451903373003006, -0.10092924535274506, -0.2096453309059143, 0.09329509735107422, -0.03888171166181564, -0.20742550492286682, -0.19547367095947266, -0.17629767954349518, -0.11726798862218857, 0.1620369851589203, -0.1793665885925293, -0.2218245267868042, 0.057226505130529404, -0.07165323197841644, 0.00649593910202384, 0.20411331951618195, 0.5647211670875549, 0.19953320920467377, -0.13235674798488617, 0.29019400477409363, 0.2693951427936554, 0.313791960477829, 0.11655484884977341, 0.10399580001831055, 0.07897382974624634, 0.2602117359638214, 0.161493182182312, -0.04899950698018074, -0.09173513203859329, -0.05643380805850029, -0.1242508590221405, -0.26255157589912415, -0.1404028981924057, 0.03324513137340546, -0.06115133687853813, 0.009860995225608349, 0.2364950031042099, -0.1986180543899536, 0.06706178933382034, 0.032096657902002335, 0.3241947889328003, 0.1504427045583725, -0.017628170549869537, 0.19966517388820648, -0.17567095160484314, 0.1566508412361145, -0.11615198105573654, -0.1709584891796112, 0.0034051937982439995, -0.11347205191850662, 0.03153498098254204, -0.13322797417640686, -0.20983107388019562, 0.008155489340424538, -0.018315648660063744, -0.03628380969166756, -0.14723460376262665, -0.22431613504886627, 0.12160255759954453, 0.09395760297775269, 0.03802406042814255, -0.07208721339702606, -0.30288660526275635, 0.09381438046693802, 0.129303976893425, -0.11919524520635605, -0.20404502749443054, -0.10019979625940323, 0.08316077291965485, -0.29207178950309753, -0.32461950182914734, -0.1375880241394043, 0.07741624861955643, 0.05675008147954941, 0.048212870955467224, -0.16695570945739746, -0.16831110417842865, -0.2571466267108917, 0.022004347294569016, 0.09018582105636597, 0.09696881473064423, 0.09034634381532669, -0.1292535364627838, 0.004232535604387522, -0.0361546166241169, 0.016906339675188065, -0.17100994288921356, -0.12802155315876007, 0.002461853204295039, -0.12794269621372223, -0.26542770862579346, -0.2275809943675995, -0.050402626395225525, 0.048668306320905685, -0.04898228496313095, 0.13361530005931854, 0.08174533396959305, -0.07200723141431808, 0.09268345683813095, 0.05294530466198921, 0.1024443507194519, 0.010859944857656956, -0.117163747549057, 0.012810362502932549, 0.13470156490802765, 0.11545589566230774, -0.18238921463489532, -0.07483283430337906, 0.14451947808265686, 0.04795333370566368, -0.08783704787492752, -0.16123518347740173, -0.035415589809417725, 0.006858181674033403, -0.2047734558582306, -0.0845630019903183, -0.023606058210134506, -0.0935060977935791, -0.06924706697463989, -0.13980109989643097, -0.10452355444431305, 0.116352379322052, 0.08454099297523499, 0.01485222764313221, -0.132890522480011, -0.041142191737890244, 0.13448728621006012, 0.026495829224586487, 0.010445990599691868, 0.12186530977487564, 0.12172020971775055, -0.06771471351385117, 0.04841993749141693, 0.11444833874702454, 0.0736367329955101, 0.04923733323812485, -0.08311907947063446, -0.11450047045946121, -0.012753566727042198, -0.12205453217029572, -0.08805416524410248, 0.16590599715709686, -0.12613283097743988, 0.15344344079494476, -0.10184058547019958, -0.2849140465259552, -0.1972079873085022, 0.145134836435318, -0.11697839200496674, -0.15852832794189453, -0.23581789433956146, -0.1428460329771042, 0.08243904262781143, 0.0062004635110497475, 0.030994925647974014, -0.2091696560382843, -0.19504885375499725, -0.03647194057703018, -0.15777380764484406, -0.19751423597335815, -0.32161587476730347, -0.23731712996959686, 0.030523812398314476, -0.3122556209564209, -0.3323538899421692, -0.3562094271183014, 0.07318214327096939, 0.20391343533992767, -0.16811995208263397, -0.2475641369819641, -0.21656933426856995, 0.2908965051174164, 0.39868035912513733, -0.12157081067562103, 0.04372075945138931, 0.32752954959869385, 0.36171799898147583, -0.2521674633026123, 0.10686428099870682, -0.02736382558941841, -0.19672268629074097, -0.2012820541858673, -0.2544558644294739, 0.09724858403205872, 0.23113957047462463, 0.07206568121910095, 0.12388995289802551, 0.11896011233329773, 0.15748290717601776, 0.030156834051012993, -0.0882047787308693, 0.1707567274570465, 0.1586868166923523, -0.12648992240428925, -0.20787328481674194, -0.050144344568252563, 0.10365675389766693, -0.14081212878227234, 0.14581237733364105, -0.07897355407476425, -0.09284720569849014, -0.030984580516815186, -0.08686868846416473, 0.21250396966934204, 0.06007371470332146, 0.07954876869916916, -0.048412397503852844, -0.028884807601571083, -0.03859134018421173, -0.02472190000116825, -0.11523935943841934, 0.03985869139432907, -0.031945936381816864, -0.2382495105266571, -0.034580882638692856, -0.09721174836158752, 0.06683377921581268, -0.016985073685646057, 0.10067277401685715, -0.1049547865986824, -0.13881389796733856, -0.14210717380046844, -0.2768247425556183, 0.3137509822845459, -0.04183318465948105, -0.21355649828910828, -0.0411934033036232, -0.12977243959903717, -0.06019407883286476, 0.04811530187726021, 0.08899696916341782, 0.1068376824259758, 0.232931986451149, -0.16326867043972015, -0.23055557906627655, -0.15439842641353607, -0.07647205144166946, -0.004677221644669771, 0.055177390575408936, -0.07482249289751053, -0.025068696588277817, 0.16921831667423248, 0.08354384452104568, 0.17827296257019043, 0.05370161682367325, 0.030275115743279457, 0.14360961318016052, 0.09926435351371765, 0.2643301784992218, 0.033600907772779465, 0.008439828641712666, 0.27800285816192627, 0.21687322854995728, -0.0752246230840683, 0.13471324741840363, 0.07948550581932068, 0.21037662029266357, 0.2200196087360382, -0.09812972694635391, -0.06310079991817474, -0.009932506829500198, -0.1807117611169815, -0.1958836317062378, -0.18373388051986694, -0.10958927124738693, 0.01903403177857399, 0.14254017174243927, 0.1662747710943222, -0.03602447733283043, -0.10233362019062042, -0.059397969394922256, -0.044369928538799286, 0.005768158473074436, -0.031363047659397125, -0.13877004384994507, -0.20925423502922058, -0.27202555537223816, -0.181751549243927, -0.09620437771081924, 0.04155270382761955, 0.0002717328316066414, -0.09034977108240128, -0.0892462208867073, 0.08479072153568268, -0.02221817523241043, -0.09679907560348511, 0.007331250701099634, 0.04291274771094322, -0.14118272066116333, -0.17924050986766815, -0.1893685907125473, -0.07861194759607315, 0.12131419032812119, 0.02166990377008915, -0.07661392539739609, -0.2798451781272888, -0.09635965526103973, 0.24392525851726532, 0.1828036606311798, -0.01877511478960514, -0.2502667009830475, -0.014575309120118618, 0.11755242943763733, -0.294646292924881, -0.017945528030395508, -0.047251924872398376, -0.16415968537330627, -0.06664136052131653, 0.07301001995801926, -0.04651498422026634, -0.10898774862289429, 0.003970691002905369, 0.08528124541044235, 0.04211319610476494, 0.18762603402137756, -0.19994805753231049, -0.14850379526615143, -0.02457486093044281, -0.2107260823249817, 0.08899848163127899, 0.05454479157924652, -0.11118531972169876, 0.17667894065380096, -0.07545655965805054, 0.048310551792383194, -0.21471673250198364, -0.09871657192707062, 0.18537060916423798, -0.18458177149295807, -0.08262211829423904, -0.026693256571888924, -0.10781820863485336, -0.10106638073921204, 0.053038205951452255, -0.15798625349998474, -0.06392887234687805, 0.09861180186271667, 0.029901163652539253, 0.001519288052804768, 0.26066046953201294, 0.05618865415453911, -0.23252789676189423, 0.0048353346064686775, -0.17480142414569855, 0.19722984731197357, 0.06807364523410797, 0.0010178566444665194, 0.06233600899577141, -0.12367811053991318, -0.14416956901550293, -0.14910942316055298, -0.18400131165981293, 0.1462024450302124, -0.18691189587116241, -0.1743750274181366, 0.004131439607590437, -0.13937342166900635, -0.0542483776807785, 0.02287149429321289, -0.05463290959596634, 0.011019124649465084, -0.12462515383958817, -0.04046550393104553, 0.2129766196012497, 0.09828410297632217, 0.0839545726776123, -0.06253013759851456, -0.10529949516057968, 0.0007133163162507117, 0.290810227394104, 0.09346265345811844, -0.046142395585775375, 0.021029504016041756, 0.07995675504207611, 0.3741243779659271, 0.052287135273218155, -0.1683509647846222, 0.0817892849445343, 0.11373836547136307, 0.15297241508960724, 0.23521210253238678, 0.18708638846874237, 0.13726967573165894, -0.11583950370550156, -0.12688139081001282, -0.21673327684402466, -0.1633685678243637, -0.22900572419166565, -0.19121961295604706, -0.097773477435112, -0.04152447730302811, -0.05148942396044731, -0.02906440757215023, -0.09864502400159836, -0.09059233963489532, -0.1979944407939911, -0.06620555371046066, -0.11525478214025497, 0.08191221952438354, 0.037804488092660904, -0.2439771592617035, -0.15621019899845123, -0.03560324013233185, -0.26549574732780457, -0.026013031601905823, 0.03324810788035393, -0.14629940688610077, 0.038986269384622574, -0.3180956244468689, 0.141331747174263, 0.21758069097995758, -0.02337529882788658, -0.19773052632808685, -0.12990990281105042, 0.1723267138004303, 0.1737419217824936, -0.026691852137446404, -0.059743013232946396, 0.1508241891860962, 0.17710275948047638, -0.05646875500679016, -0.19448880851268768, -0.1125706136226654, 0.102003313601017, 0.06413102149963379, 0.022393103688955307, -0.0486660897731781, -0.06719961762428284, -0.1603998988866806, 0.2988450527191162, 0.09396980702877045, -0.05188735947012901, -0.20511776208877563, -0.0674038901925087, 0.37601208686828613, 0.0710567906498909, -0.08999726176261902, -0.08873164653778076, 0.10997025668621063, 0.3110874593257904, -0.039821118116378784, -0.17280615866184235, -0.08821404725313187, 0.08216695487499237, 0.17704299092292786, -0.01785420812666416, -0.26170045137405396, -0.040617506951093674, 0.13885964453220367, -0.0629393607378006, -0.23392893373966217, -0.16718319058418274, -0.06548523902893066, -0.08285006880760193, 0.012885474599897861, 0.030689295381307602, -0.17983876168727875, 0.015564031898975372, 0.050101060420274734, -0.10828489810228348, -0.18234165012836456, -0.04937426373362541, 0.11945352703332901, -0.2450055330991745, -0.17728891968727112, -0.25745889544487, -0.1269768625497818, 0.10940859466791153, -0.19667373597621918, -0.18263570964336395, -0.12250763177871704, -0.1221049427986145, -0.19130270183086395, -0.3059132993221283, -0.09151965379714966, -0.05769868940114975, 0.008145126514136791, -0.1192246600985527, -0.32970860600471497, 0.047232598066329956, 0.06317702680826187, 0.051146265119314194, -0.13449865579605103, -0.08313160389661789, 0.1207214742898941, 0.10196544229984283, -0.23894789814949036, -0.0980876088142395, -0.031556058675050735, 0.30378907918930054, 0.0798535943031311, -0.23975811898708344, -0.17803440988063812, -0.017718646675348282, 0.2528759241104126, 0.0009659613133408129, -0.27992352843284607, -0.08374585211277008, 0.29411810636520386, 0.014804522506892681, -0.1062842309474945, -0.23746807873249054, -0.016262857243418694, -0.3478291928768158, -0.4175308346748352, -0.03429028019309044, -0.030044136568903923, -0.1615401655435562, -0.2813355624675751, -0.1474749892950058, 0.06117721647024155, 0.0072184475138783455, -0.21263828873634338, -0.05274982005357742, 0.03300371766090393, 0.05101073160767555, -0.08903712034225464, -0.07652730494737625, -0.1430962234735489, 0.044749319553375244, 0.03963678330183029, -0.12862099707126617, -0.019345849752426147, -0.08805625140666962, 0.032519835978746414, -0.1121276468038559, 0.013764279894530773, -0.18477843701839447, -0.22862376272678375, -0.3146893382072449, -0.31722402572631836, -0.09822338819503784, 0.012015719898045063, -0.08609748631715775, -0.2498539388179779, -0.02578314207494259, -0.15795856714248657, 0.010197232477366924, 0.015698887407779694, 0.043517667800188065, -0.014383804984390736, 0.02584853582084179, 0.14021894335746765, -0.17387813329696655, -0.008749159052968025, -0.11152090132236481, 0.1136445626616478, -0.06834572553634644, -0.25240716338157654, -0.06570333242416382, -0.11186471581459045, -0.10149776935577393, -0.14316894114017487, -0.12045606970787048, -0.22813014686107635, -0.24143242835998535, -0.08770299702882767, -0.13444285094738007, 0.005942130461335182, -0.307727187871933, -0.01332571730017662, 0.03267451003193855, -0.02363727241754532, 0.09723944962024689, -0.20495210587978363, 0.042783498764038086, 0.1427505761384964, 0.09182456880807877, -0.18678048253059387, 0.1467844545841217, 0.16653329133987427, 0.13158179819583893, 0.009870793670415878, -0.16178305447101593, 0.3640344440937042, 0.20362819731235504, 0.09525342285633087, -0.003482609521597624, -0.14667150378227234, 0.007529497612267733, 0.06498174369335175, 0.05966806784272194, 0.06855358183383942, -0.30848249793052673, -0.24865518510341644, 0.014578567817807198, 0.13278897106647491, 0.19720420241355896, -0.4323715567588806, 0.06938602775335312, -0.06515297293663025, -0.14105871319770813, -0.09422450512647629, -0.10208545625209808, -0.005929190199822187, -0.0017513337079435587, -0.2089109718799591, -0.09509705752134323, -0.2085665911436081, 0.05150070786476135, -0.14073416590690613, 0.01365603692829609, -0.11389368772506714]}, "type": "TENSOR"}], "docString": "", "domain": ""}, {"input": ["Pooling66_Output_0", "Parameter87"], "output": ["Convolution110_Output_0"], "name": "Convolution110", "opType": "Conv", "attribute": [{"name": "kernel_shape", "ints": ["5", "5"], "type": "INTS"}, {"name": "strides", "ints": ["1", "1"], "type": "INTS"}, {"name": "auto_pad", "s": "U0FNRV9VUFBFUg==", "type": "STRING"}, {"name": "group", "i": "1", "type": "INT"}, {"name": "dilations", "ints": ["1", "1"], "type": "INTS"}], "docString": "", "domain": ""}, {"output": ["Parameter88"], "name": "Parameter88", "opType": "Constant", "attribute": [{"name": "value", "t": {"dims": ["16"], "dataType": "FLOAT", "floatData": [-0.08224882185459137, -0.10886877775192261, -0.14103959500789642, -0.20486916601657867, -0.17913565039634705, -0.2154383808374405, -0.1338050663471222, -0.19572456181049347, -0.26825064420700073, -0.25821220874786377, -0.07615606486797333, 0.01328414585441351, -0.004444644320756197, -0.41474083065986633, -0.17879115045070648, -0.03865588828921318]}, "type": "TENSOR"}], "docString": "", "domain": ""}, {"input": ["Convolution110_Output_0", "Parameter88"], "output": ["Plus112_Output_0"], "name": "Plus112", "opType": "Add", "attribute": [{"name": "axis", "i": "1", "type": "INT"}, {"name": "broadcast", "i": "1", "type": "INT"}], "docString": "", "domain": ""}, {"input": ["Plus112_Output_0"], "output": ["ReLU114_Output_0"], "name": "ReLU114", "opType": "Relu", "docString": "", "domain": ""}, {"input": ["ReLU114_Output_0"], "output": ["Pooling160_Output_0"], "name": "Pooling160", "opType": "MaxPool", "attribute": [{"name": "kernel_shape", "ints": ["3", "3"], "type": "INTS"}, {"name": "strides", "ints": ["3", "3"], "type": "INTS"}, {"name": "pads", "ints": ["0", "0", "0", "0"], "type": "INTS"}], "docString": "", "domain": ""}, {"input": ["Pooling160_Output_0"], "output": ["Pooling160_Output_0_reshape0"], "name": "Times212_reshape0", "opType": "Reshape", "attribute": [{"name": "shape", "ints": ["1", "256"], "type": "INTS"}], "docString": "", "domain": ""}, {"input": ["Pooling160_Output_0_reshape0", "Parameter193_reshape1"], "output": ["Times212_Output_0"], "name": "Times212", "opType": "MatMul", "docString": "", "domain": ""}, {"output": ["Parameter194"], "name": "Parameter194", "opType": "Constant", "attribute": [{"name": "value", "t": {"dims": ["1", "10"], "dataType": "FLOAT", "floatData": [-0.04485602676868439, 0.007791661191731691, 0.06810081750154495, 0.02999374084174633, -0.1264096349477768, 0.14021874964237213, -0.055284902453422546, -0.04938381537795067, 0.08432205021381378, -0.05454041436314583]}, "type": "TENSOR"}], "docString": "", "domain": ""}, {"input": ["Times212_Output_0", "Parameter194"], "output": ["Plus214_Output_0"], "name": "Plus214", "opType": "Add", "attribute": [{"name": "broadcast", "i": "0", "type": "INT"}], "docString": "", "domain": ""}], "name": "CNTKGraph", "input": [{"name": "Input3", "data_type": "FLOAT", "shape": ["1", "1", "28", "28"]}], "output": [{"name": "Plus214_Output_0", "data_type": "FLOAT", "shape": ["1", "10"]}], "valueInfo": [{"name": "Parameter5", "type": {"tensorType": {"elemType": "FLOAT", "shape": {"dim": [{"dimValue": "8"}, {"dimValue": "1"}, {"dimValue": "5"}, {"dimValue": "5"}]}}}}, {"name": "Convolution28_Output_0", "type": {"tensorType": {"elemType": "FLOAT", "shape": {"dim": [{"dimValue": "1"}, {"dimValue": "8"}, {"dimValue": "28"}, {"dimValue": "28"}]}}}}, {"name": "Parameter6", "type": {"tensorType": {"elemType": "FLOAT", "shape": {"dim": [{"dimValue": "8"}]}}}}, {"name": "Plus30_Output_0", "type": {"tensorType": {"elemType": "FLOAT", "shape": {"dim": [{"dimValue": "1"}, {"dimValue": "8"}, {"dimValue": "28"}, {"dimValue": "28"}]}}}}, {"name": "ReLU32_Output_0", "type": {"tensorType": {"elemType": "FLOAT", "shape": {"dim": [{"dimValue": "1"}, {"dimValue": "8"}, {"dimValue": "28"}, {"dimValue": "28"}]}}}}, {"name": "Pooling66_Output_0", "type": {"tensorType": {"elemType": "FLOAT", "shape": {"dim": [{"dimValue": "1"}, {"dimValue": "8"}, {"dimValue": "14"}, {"dimValue": "14"}]}}}}, {"name": "Parameter87", "type": {"tensorType": {"elemType": "FLOAT", "shape": {"dim": [{"dimValue": "16"}, {"dimValue": "8"}, {"dimValue": "5"}, {"dimValue": "5"}]}}}}, {"name": "Convolution110_Output_0", "type": {"tensorType": {"elemType": "FLOAT", "shape": {"dim": [{"dimValue": "1"}, {"dimValue": "16"}, {"dimValue": "14"}, {"dimValue": "14"}]}}}}, {"name": "Parameter88", "type": {"tensorType": {"elemType": "FLOAT", "shape": {"dim": [{"dimValue": "16"}]}}}}, {"name": "Plus112_Output_0", "type": {"tensorType": {"elemType": "FLOAT", "shape": {"dim": [{"dimValue": "1"}, {"dimValue": "16"}, {"dimValue": "14"}, {"dimValue": "14"}]}}}}, {"name": "ReLU114_Output_0", "type": {"tensorType": {"elemType": "FLOAT", "shape": {"dim": [{"dimValue": "1"}, {"dimValue": "16"}, {"dimValue": "14"}, {"dimValue": "14"}]}}}}, {"name": "Pooling160_Output_0", "type": {"tensorType": {"elemType": "FLOAT", "shape": {"dim": [{"dimValue": "1"}, {"dimValue": "16"}, {"dimValue": "4"}, {"dimValue": "4"}]}}}}, {"name": "Parameter193", "type": {"tensorType": {"elemType": "FLOAT", "shape": {"dim": [{"dimValue": "16"}, {"dimValue": "4"}, {"dimValue": "4"}, {"dimValue": "10"}]}}}}, {"name": "Pooling160_Output_0_reshape0", "type": {"tensorType": {"elemType": "FLOAT", "shape": {"dim": [{"dimValue": "1"}, {"dimValue": "256"}]}}}}, {"name": "Parameter193_reshape1", "type": {"tensorType": {"elemType": "FLOAT", "shape": {"dim": [{"dimValue": "256"}, {"dimValue": "10"}]}}}}, {"name": "Times212_Output_0", "type": {"tensorType": {"elemType": "FLOAT", "shape": {"dim": [{"dimValue": "1"}, {"dimValue": "10"}]}}}}, {"name": "Parameter194", "type": {"tensorType": {"elemType": "FLOAT", "shape": {"dim": [{"dimValue": "1"}, {"dimValue": "10"}]}}}}], "edges": [{"source": "node_0", "target": "Parameter193", "label": "label_0"}, {"source": "Parameter193", "target": "node_1", "label": "label_1"}, {"source": "node_1", "target": "Parameter193_reshape1", "label": "label_2"}, {"source": "node_2", "target": "Parameter6", "label": "label_3"}, {"source": "node_3", "target": "Parameter5", "label": "label_4"}, {"source": "Input3", "target": "node_4", "label": "label_5"}, {"source": "Parameter5", "target": "node_4", "label": "label_6"}, {"source": "node_4", "target": "Convolution28_Output_0", "label": "label_7"}, {"source": "Convolution28_Output_0", "target": "node_5", "label": "label_8"}, {"source": "Parameter6", "target": "node_5", "label": "label_9"}, {"source": "node_5", "target": "Plus30_Output_0", "label": "label_10"}, {"source": "Plus30_Output_0", "target": "node_6", "label": "label_11"}, {"source": "node_6", "target": "ReLU32_Output_0", "label": "label_12"}, {"source": "ReLU32_Output_0", "target": "node_7", "label": "label_13"}, {"source": "node_7", "target": "Pooling66_Output_0", "label": "label_14"}, {"source": "node_8", "target": "Parameter87", "label": "label_15"}, {"source": "Pooling66_Output_0", "target": "node_9", "label": "label_16"}, {"source": "Parameter87", "target": "node_9", "label": "label_17"}, {"source": "node_9", "target": "Convolution110_Output_0", "label": "label_18"}, {"source": "node_10", "target": "Parameter88", "label": "label_19"}, {"source": "Convolution110_Output_0", "target": "node_11", "label": "label_20"}, {"source": "Parameter88", "target": "node_11", "label": "label_21"}, {"source": "node_11", "target": "Plus112_Output_0", "label": "label_22"}, {"source": "Plus112_Output_0", "target": "node_12", "label": "label_23"}, {"source": "node_12", "target": "ReLU114_Output_0", "label": "label_24"}, {"source": "ReLU114_Output_0", "target": "node_13", "label": "label_25"}, {"source": "node_13", "target": "Pooling160_Output_0", "label": "label_26"}, {"source": "Pooling160_Output_0", "target": "node_14", "label": "label_27"}, {"source": "node_14", "target": "Pooling160_Output_0_reshape0", "label": "label_28"}, {"source": "Pooling160_Output_0_reshape0", "target": "node_15", "label": "label_29"}, {"source": "Parameter193_reshape1", "target": "node_15", "label": "label_30"}, {"source": "node_15", "target": "Times212_Output_0", "label": "label_31"}, {"source": "node_16", "target": "Parameter194", "label": "label_32"}, {"source": "Times212_Output_0", "target": "node_17", "label": "label_33"}, {"source": "Parameter194", "target": "node_17", "label": "label_34"}, {"source": "node_17", "target": "Plus214_Output_0", "label": "label_35"}]}}};
export default [
{
wallTime: 1512549785.061623,
step: 60
},
{
wallTime: 1512886109.672786,
step: 60
},
{
wallTime: 1512886124.266915,
step: 210
},
{
wallTime: 1512886138.898628,
step: 330
},
{
wallTime: 1512886139.883663,
step: 340
},
{
wallTime: 1512886147.195567,
step: 410
},
{
wallTime: 1512886156.47856,
step: 500
},
{
wallTime: 1512886187.82793,
step: 810
},
{
wallTime: 1512886200.386198,
step: 950
},
{
wallTime: 1512886204.224405,
step: 990
}
];
import fetch from 'isomorphic-unfetch';
import {Request, Response} from 'express';
const images = [
'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1582885214651&di=77163884e9a374391b4302d8bdd4fa1d&imgtype=0&src=http%3A%2F%2Fhbimg.b0.upaiyun.com%2F50124b1944e8887b95154598f8b5212886ddf03641f19-GbcSBV_fw658',
'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1582889403799&di=bb4db115c1227e081852bbb95336150b&imgtype=0&src=http%3A%2F%2Fres.hpoi.net.cn%2Fgk%2Fcover%2Fn%2F2015%2F02%2Fff897b88ccd5417f91d4159a8ea343a6.jpg%3Fdate%3D1464606291000',
'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1582889975692&di=cd91e6c70d07ef496bfcca20597eb5af&imgtype=0&src=http%3A%2F%2Fimg3.duitang.com%2Fuploads%2Fitem%2F201411%2F28%2F20141128211355_HPfYT.thumb.224_0.gif',
'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1582890006236&di=9f030009422b91e8753f8c476426fc39&imgtype=0&src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201812%2F22%2F20181222172346_ykcdh.thumb.224_0.gif',
'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1582890018944&di=d79e0ce4cef39f0ef81cb38c440ca858&imgtype=0&src=http%3A%2F%2Fgss3.bdstatic.com%2F7Po3dSag_xI4khGkpoWK1HF6hhy%2Fbaike%2Fw%3D150%2Fsign%3D074ebdb2367adab43dd01f46bbd5b36b%2F42166d224f4a20a4b974325d90529822730ed0c6.jpg'
];
export default async (req: Request, res: Response) => {
const index = (req.query.index ?? 0) % images.length;
const result = await fetch(images[index]);
if (result.headers.has('Content-Type')) {
res.type(result.headers.get('Content-Type') as string);
}
return result.arrayBuffer();
};
export default {
test: [
'input_reshape/input/image/7',
'input_reshape/input/image/4',
'input_reshape/input/image/5',
'input_reshape/input/image/2',
'input_reshape/input/image/3',
'input_reshape/input/image/0',
'input_reshape/input/image/1',
'input_reshape/input/image/8',
'input_reshape/input/image/9'
],
train: [
'input_reshape/input/image/6',
'input_reshape/input/image/7',
'input_reshape/input/image/4',
'input_reshape/input/image/5',
'input_reshape/input/image/2',
'input_reshape/input/image/3',
'input_reshape/input/image/0',
'input_reshape/input/image/1',
'input_reshape/input/image/8',
'input_reshape/input/image/9'
]
};
export default ['train', 'test'];
import {Request} from 'express';
export default (request: Request) => {
if (request.query.run === 'train') {
return [
[1511842145.705075, 1, 0.05000000074505806],
[1511842145.7388, 2, 0.12999999523162842],
[1511842145.774563, 3, 0.27000001072883606],
[1511842145.806828, 4, 0.4399999976158142],
[1511842145.838082, 5, 0.47999998927116394],
[1511842145.868955, 6, 0.5899999737739563],
[1511842145.899323, 7, 0.6100000143051147],
[1511842145.930518, 8, 0.699999988079071],
[1511842145.96089, 9, 0.6700000166893005],
[1511842146.460557, 11, 0.6499999761581421],
[1511842146.4952, 12, 0.7300000190734863],
[1511842146.525936, 13, 0.6899999976158142],
[1511842146.556059, 14, 0.75],
[1511842146.648703, 15, 0.7099999785423279],
[1511842146.683295, 16, 0.7900000214576721],
[1511842146.719782, 17, 0.8299999833106995],
[1511842146.752392, 18, 0.7900000214576721],
[1511842146.786562, 19, 0.8299999833106995],
[1511842147.296362, 21, 0.8199999928474426],
[1511842147.329616, 22, 0.75],
[1511842147.36413, 23, 0.800000011920929],
[1511842147.394166, 24, 0.8700000047683716],
[1511842147.426248, 25, 0.8500000238418579],
[1511842147.455792, 26, 0.8799999952316284],
[1511842147.486918, 27, 0.8600000143051147],
[1511842147.516537, 28, 0.8399999737739563],
[1511842147.545978, 29, 0.8999999761581421],
[1511842148.059008, 31, 0.8299999833106995],
[1511842148.093655, 32, 0.8500000238418579],
[1511842148.126041, 33, 0.8799999952316284],
[1511842148.156253, 34, 0.9100000262260437],
[1511842148.189653, 35, 0.8700000047683716],
[1511842148.221602, 36, 0.800000011920929],
[1511842148.251149, 37, 0.7900000214576721],
[1511842148.281332, 38, 0.8700000047683716],
[1511842148.312354, 39, 0.8500000238418579],
[1511842148.828949, 41, 0.8700000047683716],
[1511842148.865255, 42, 0.8600000143051147],
[1511842148.898558, 43, 0.8999999761581421],
[1511842148.93859, 44, 0.8799999952316284],
[1511842148.97468, 45, 0.8799999952316284],
[1511842149.013585, 46, 0.8299999833106995],
[1511842149.044709, 47, 0.8500000238418579],
[1511842149.077821, 48, 0.8700000047683716],
[1511842149.107665, 49, 0.8899999856948853],
[1511842149.647978, 51, 0.8600000143051147],
[1511842149.686268, 52, 0.8999999761581421],
[1511842149.722652, 53, 0.8700000047683716],
[1511842149.758858, 54, 0.8700000047683716],
[1511842149.795508, 55, 0.8999999761581421],
[1511842149.830682, 56, 0.8700000047683716],
[1511842149.874498, 57, 0.8600000143051147],
[1511842149.916357, 58, 0.8399999737739563],
[1511842149.951223, 59, 0.8600000143051147],
[1511842150.470112, 61, 0.8500000238418579],
[1511842150.505811, 62, 0.9399999976158142],
[1511842150.542528, 63, 0.8399999737739563],
[1511842150.579082, 64, 0.8999999761581421],
[1511842150.611267, 65, 0.8799999952316284],
[1511842150.642279, 66, 0.8500000238418579],
[1511842150.679586, 67, 0.9399999976158142],
[1511842150.709423, 68, 0.8999999761581421],
[1511842150.742542, 69, 0.9200000166893005],
[1511842151.287115, 71, 0.8700000047683716],
[1511842151.320888, 72, 0.9200000166893005],
[1511842151.352388, 73, 0.8600000143051147],
[1511842151.385154, 74, 0.8600000143051147],
[1511842151.421342, 75, 0.8399999737739563],
[1511842151.458697, 76, 0.8999999761581421],
[1511842151.492929, 77, 0.8399999737739563],
[1511842151.524682, 78, 0.9200000166893005],
[1511842151.55707, 79, 0.8799999952316284],
[1511842152.071344, 81, 0.8500000238418579],
[1511842152.101479, 82, 0.949999988079071],
[1511842152.132134, 83, 0.8999999761581421],
[1511842152.165848, 84, 0.8799999952316284],
[1511842152.195162, 85, 0.8899999856948853],
[1511842152.224646, 86, 0.9399999976158142],
[1511842152.255385, 87, 0.9300000071525574],
[1511842152.28573, 88, 0.9100000262260437],
[1511842152.315899, 89, 0.8999999761581421],
[1511842152.834572, 91, 0.8899999856948853],
[1511842152.872045, 92, 0.949999988079071],
[1511842152.904879, 93, 0.9800000190734863],
[1511842152.940016, 94, 0.8700000047683716],
[1511842152.976859, 95, 0.8500000238418579],
[1511842153.012571, 96, 0.8999999761581421],
[1511842153.043776, 97, 0.8199999928474426],
[1511842153.081662, 98, 0.8799999952316284],
[1511842153.190446, 99, 0.8700000047683716],
[1511842153.698591, 101, 0.9200000166893005],
[1511842153.732005, 102, 0.9300000071525574],
[1511842153.765796, 103, 0.8500000238418579],
[1511842153.797352, 104, 0.9700000286102295],
[1511842153.831314, 105, 0.9599999785423279],
[1511842153.866427, 106, 0.9300000071525574],
[1511842153.896475, 107, 0.8999999761581421],
[1511842153.929657, 108, 0.9200000166893005],
[1511842153.965421, 109, 0.949999988079071],
[1511842154.485552, 111, 0.949999988079071],
[1511842154.516489, 112, 0.9100000262260437],
[1511842154.548223, 113, 0.8799999952316284],
[1511842154.580801, 114, 0.9200000166893005],
[1511842154.611307, 115, 0.9200000166893005],
[1511842154.642873, 116, 0.9200000166893005],
[1511842154.6751, 117, 0.9300000071525574],
[1511842154.707684, 118, 0.8999999761581421],
[1511842154.744283, 119, 0.9300000071525574],
[1511842155.255668, 121, 0.9200000166893005],
[1511842155.288454, 122, 0.8899999856948853],
[1511842155.320779, 123, 0.9599999785423279],
[1511842155.353925, 124, 0.9200000166893005],
[1511842155.389438, 125, 0.8899999856948853],
[1511842155.424823, 126, 0.9399999976158142],
[1511842155.454526, 127, 0.9300000071525574],
[1511842155.489204, 128, 0.9399999976158142],
[1511842155.521019, 129, 0.9399999976158142],
[1511842156.033606, 131, 0.8999999761581421],
[1511842156.071066, 132, 0.9100000262260437],
[1511842156.100447, 133, 0.8899999856948853],
[1511842156.132395, 134, 0.9200000166893005],
[1511842156.165163, 135, 0.8700000047683716],
[1511842156.203128, 136, 0.8999999761581421],
[1511842156.239275, 137, 0.8399999737739563],
[1511842156.270908, 138, 0.9200000166893005],
[1511842156.303224, 139, 0.9200000166893005],
[1511842156.823475, 141, 0.9300000071525574],
[1511842156.860178, 142, 0.8999999761581421],
[1511842156.89245, 143, 0.8500000238418579],
[1511842156.932155, 144, 0.9300000071525574],
[1511842156.966936, 145, 0.8999999761581421],
[1511842157.002507, 146, 0.9100000262260437],
[1511842157.04046, 147, 0.949999988079071],
[1511842157.075624, 148, 0.8799999952316284],
[1511842157.113062, 149, 0.9100000262260437],
[1511842157.610962, 151, 0.9200000166893005],
[1511842157.644282, 152, 0.8899999856948853],
[1511842157.674532, 153, 0.9399999976158142],
[1511842157.704223, 154, 0.9700000286102295],
[1511842157.734917, 155, 0.9100000262260437],
[1511842157.766545, 156, 0.949999988079071],
[1511842157.803228, 157, 0.9300000071525574],
[1511842157.833582, 158, 0.9399999976158142],
[1511842157.863983, 159, 0.9599999785423279],
[1511842158.365138, 161, 0.9399999976158142],
[1511842158.402051, 162, 0.8999999761581421],
[1511842158.432824, 163, 0.9100000262260437],
[1511842158.468544, 164, 0.9399999976158142],
[1511842158.501693, 165, 0.9200000166893005],
[1511842158.536712, 166, 0.9200000166893005],
[1511842158.576052, 167, 0.9100000262260437],
[1511842158.608077, 168, 0.9300000071525574],
[1511842158.639638, 169, 0.9399999976158142],
[1511842159.144704, 171, 0.949999988079071],
[1511842159.175508, 172, 0.9200000166893005],
[1511842159.206246, 173, 0.9399999976158142],
[1511842159.236448, 174, 0.949999988079071],
[1511842159.268592, 175, 0.8999999761581421],
[1511842159.298385, 176, 0.8999999761581421],
[1511842159.330691, 177, 0.9200000166893005],
[1511842159.362888, 178, 0.949999988079071],
[1511842159.394601, 179, 0.8899999856948853],
[1511842159.917987, 181, 0.8500000238418579],
[1511842159.949645, 182, 0.9800000190734863],
[1511842159.980383, 183, 0.9399999976158142],
[1511842160.011846, 184, 0.8999999761581421],
[1511842160.043909, 185, 0.8999999761581421],
[1511842160.082747, 186, 0.8999999761581421],
[1511842160.116125, 187, 0.949999988079071],
[1511842160.147119, 188, 0.9100000262260437],
[1511842160.182338, 189, 0.9599999785423279],
[1511842160.69661, 191, 0.9300000071525574],
[1511842160.72888, 192, 0.8899999856948853],
[1511842160.762084, 193, 0.9300000071525574],
[1511842160.792814, 194, 0.9599999785423279],
[1511842160.823444, 195, 0.9100000262260437],
[1511842160.852744, 196, 0.9399999976158142],
[1511842160.885255, 197, 0.9599999785423279],
[1511842160.917985, 198, 0.8999999761581421],
[1511842161.028077, 199, 0.949999988079071],
[1511842161.548108, 201, 0.9300000071525574],
[1511842161.580669, 202, 0.9100000262260437],
[1511842161.613862, 203, 0.949999988079071],
[1511842161.653309, 204, 0.8899999856948853],
[1511842161.691085, 205, 0.9599999785423279],
[1511842161.72533, 206, 0.9200000166893005],
[1511842161.754774, 207, 0.9300000071525574],
[1511842161.786702, 208, 0.9300000071525574],
[1511842161.820508, 209, 0.8999999761581421],
[1511842162.336378, 211, 0.949999988079071],
[1511842162.373533, 212, 0.949999988079071],
[1511842162.411207, 213, 0.8899999856948853],
[1511842162.4438, 214, 0.9300000071525574],
[1511842162.477444, 215, 0.949999988079071],
[1511842162.509545, 216, 0.9399999976158142],
[1511842162.543586, 217, 0.949999988079071],
[1511842162.574829, 218, 0.9300000071525574],
[1511842162.612825, 219, 0.9399999976158142],
[1511842163.134331, 221, 0.9700000286102295],
[1511842163.169464, 222, 0.9200000166893005],
[1511842163.203311, 223, 0.9700000286102295],
[1511842163.240668, 224, 0.9300000071525574],
[1511842163.278642, 225, 0.9100000262260437],
[1511842163.318872, 226, 0.9300000071525574],
[1511842163.361079, 227, 0.9300000071525574],
[1511842163.397876, 228, 0.9800000190734863],
[1511842163.430826, 229, 0.9599999785423279],
[1511842163.953991, 231, 0.9300000071525574],
[1511842163.988582, 232, 0.9399999976158142],
[1511842164.021841, 233, 0.949999988079071],
[1511842164.052817, 234, 0.9300000071525574],
[1511842164.090031, 235, 0.9399999976158142],
[1511842164.121797, 236, 0.9100000262260437],
[1511842164.158074, 237, 0.949999988079071],
[1511842164.189932, 238, 0.9300000071525574],
[1511842164.225797, 239, 0.9200000166893005],
[1511842164.742692, 241, 0.949999988079071],
[1511842164.773757, 242, 0.9800000190734863],
[1511842164.810333, 243, 0.9300000071525574],
[1511842164.840904, 244, 0.949999988079071],
[1511842164.875269, 245, 0.949999988079071],
[1511842164.907458, 246, 0.9700000286102295],
[1511842164.940818, 247, 0.9200000166893005],
[1511842165.032471, 248, 0.9399999976158142],
[1511842165.06494, 249, 0.9399999976158142],
[1511842165.711591, 251, 0.9200000166893005],
[1511842165.742034, 252, 0.9399999976158142],
[1511842165.776186, 253, 0.9100000262260437],
[1511842165.80631, 254, 0.9300000071525574],
[1511842165.841813, 255, 0.9700000286102295],
[1511842165.88272, 256, 0.9100000262260437],
[1511842165.914834, 257, 0.9399999976158142],
[1511842165.944832, 258, 0.8999999761581421],
[1511842165.977476, 259, 0.8999999761581421],
[1511842166.49414, 261, 0.9300000071525574],
[1511842166.530139, 262, 0.9300000071525574],
[1511842166.582532, 263, 0.9200000166893005],
[1511842166.624934, 264, 0.9399999976158142],
[1511842166.65914, 265, 0.9200000166893005],
[1511842166.708159, 266, 0.949999988079071],
[1511842166.738785, 267, 0.8899999856948853],
[1511842166.789074, 268, 0.9599999785423279],
[1511842166.821725, 269, 0.949999988079071],
[1511842167.351619, 271, 0.8899999856948853],
[1511842167.383981, 272, 0.949999988079071],
[1511842167.415674, 273, 0.9300000071525574],
[1511842167.453889, 274, 0.9300000071525574],
[1511842167.487546, 275, 0.9800000190734863],
[1511842167.520855, 276, 0.8999999761581421],
[1511842167.553859, 277, 0.949999988079071],
[1511842167.591104, 278, 0.9800000190734863],
[1511842167.627239, 279, 0.9100000262260437],
[1511842168.151087, 281, 0.9599999785423279],
[1511842168.185722, 282, 0.9300000071525574],
[1511842168.225793, 283, 0.9399999976158142],
[1511842168.265352, 284, 0.9200000166893005],
[1511842168.297638, 285, 0.9599999785423279],
[1511842168.331366, 286, 0.8899999856948853],
[1511842168.367654, 287, 0.949999988079071],
[1511842168.404366, 288, 0.9200000166893005],
[1511842168.437306, 289, 0.9599999785423279],
[1511842168.977181, 291, 0.9700000286102295],
[1511842169.008927, 292, 0.8999999761581421],
[1511842169.043079, 293, 0.8999999761581421],
[1511842169.079313, 294, 0.9599999785423279],
[1511842169.111267, 295, 0.8899999856948853],
[1511842169.141979, 296, 0.9700000286102295],
[1511842169.173568, 297, 0.9399999976158142],
[1511842169.206784, 298, 0.9399999976158142],
[1511842169.318883, 299, 0.9100000262260437],
[1511842169.836233, 301, 0.949999988079071],
[1511842169.869173, 302, 0.9300000071525574],
[1511842169.899444, 303, 0.9599999785423279],
[1511842169.93236, 304, 0.9399999976158142],
[1511842169.964287, 305, 0.9200000166893005],
[1511842169.999156, 306, 0.9399999976158142],
[1511842170.04658, 307, 0.949999988079071],
[1511842170.079765, 308, 0.9399999976158142],
[1511842170.116286, 309, 0.9100000262260437],
[1511842170.626257, 311, 0.9599999785423279],
[1511842170.660356, 312, 0.9399999976158142],
[1511842170.69418, 313, 0.9200000166893005],
[1511842170.72758, 314, 0.8999999761581421],
[1511842170.761281, 315, 0.9399999976158142],
[1511842170.795563, 316, 0.9399999976158142],
[1511842170.831212, 317, 0.949999988079071],
[1511842170.865901, 318, 0.9200000166893005],
[1511842170.900623, 319, 0.9100000262260437],
[1511842171.442059, 321, 0.9200000166893005],
[1511842171.474961, 322, 0.8999999761581421],
[1511842171.506307, 323, 0.9399999976158142],
[1511842171.539442, 324, 0.949999988079071],
[1511842171.570183, 325, 0.9700000286102295],
[1511842171.600969, 326, 0.9300000071525574],
[1511842171.6316, 327, 0.949999988079071],
[1511842171.665024, 328, 0.9399999976158142],
[1511842171.697585, 329, 0.9399999976158142],
[1511842172.226505, 331, 0.9300000071525574],
[1511842172.261344, 332, 0.949999988079071],
[1511842172.296245, 333, 0.9300000071525574],
[1511842172.326279, 334, 0.9700000286102295],
[1511842172.358168, 335, 0.9100000262260437],
[1511842172.392341, 336, 0.9399999976158142],
[1511842172.422466, 337, 0.9399999976158142],
[1511842172.459868, 338, 0.9599999785423279],
[1511842172.493555, 339, 0.949999988079071],
[1511842173.033582, 341, 0.949999988079071],
[1511842173.073034, 342, 0.9300000071525574],
[1511842173.104858, 343, 0.9599999785423279],
[1511842173.140056, 344, 0.8899999856948853],
[1511842173.178958, 345, 0.9399999976158142],
[1511842173.21675, 346, 0.9300000071525574],
[1511842173.246909, 347, 0.9700000286102295],
[1511842173.282099, 348, 0.9100000262260437],
[1511842173.317242, 349, 0.9599999785423279],
[1511842173.847353, 351, 0.9599999785423279],
[1511842173.885366, 352, 0.9599999785423279],
[1511842173.921206, 353, 0.8999999761581421],
[1511842173.953769, 354, 0.9399999976158142],
[1511842173.991128, 355, 0.9599999785423279],
[1511842174.02312, 356, 0.8700000047683716],
[1511842174.056031, 357, 0.9399999976158142],
[1511842174.08923, 358, 0.9599999785423279],
[1511842174.127158, 359, 0.9800000190734863],
[1511842174.652944, 361, 0.9200000166893005],
[1511842174.687431, 362, 0.9900000095367432],
[1511842174.71948, 363, 0.9399999976158142],
[1511842174.753943, 364, 0.9599999785423279],
[1511842174.78847, 365, 0.9700000286102295],
[1511842174.823361, 366, 0.8799999952316284],
[1511842174.856826, 367, 0.9300000071525574],
[1511842174.891638, 368, 0.8999999761581421],
[1511842174.925622, 369, 0.9599999785423279],
[1511842175.439573, 371, 0.9700000286102295],
[1511842175.474021, 372, 0.9300000071525574],
[1511842175.504075, 373, 0.9599999785423279],
[1511842175.540268, 374, 0.9599999785423279],
[1511842175.574921, 375, 0.9800000190734863],
[1511842175.608212, 376, 0.949999988079071],
[1511842175.64061, 377, 0.949999988079071],
[1511842175.671253, 378, 0.9399999976158142],
[1511842175.702623, 379, 0.949999988079071],
[1511842176.214339, 381, 0.949999988079071],
[1511842176.248076, 382, 0.8999999761581421],
[1511842176.286246, 383, 0.949999988079071],
[1511842176.319941, 384, 0.9300000071525574],
[1511842176.357204, 385, 0.9100000262260437],
[1511842176.388956, 386, 0.949999988079071],
[1511842176.419332, 387, 0.9300000071525574],
[1511842176.451727, 388, 0.9599999785423279],
[1511842176.484456, 389, 0.9399999976158142],
[1511842177.034638, 391, 0.9800000190734863],
[1511842177.067667, 392, 0.9200000166893005],
[1511842177.101138, 393, 0.9200000166893005],
[1511842177.135038, 394, 0.9700000286102295],
[1511842177.170068, 395, 0.9399999976158142],
[1511842177.200651, 396, 0.949999988079071],
[1511842177.23465, 397, 0.9599999785423279],
[1511842177.269173, 398, 0.9700000286102295],
[1511842177.379705, 399, 0.9300000071525574],
[1511842177.930872, 401, 0.9700000286102295],
[1511842177.964943, 402, 0.9200000166893005],
[1511842177.999324, 403, 0.949999988079071],
[1511842178.033477, 404, 0.9900000095367432],
[1511842178.071781, 405, 0.949999988079071],
[1511842178.105857, 406, 0.949999988079071],
[1511842178.135511, 407, 0.9300000071525574],
[1511842178.167634, 408, 0.9300000071525574],
[1511842178.199537, 409, 0.9200000166893005],
[1511842178.717725, 411, 0.9399999976158142],
[1511842178.74796, 412, 0.9399999976158142],
[1511842178.780912, 413, 0.949999988079071],
[1511842178.811067, 414, 0.949999988079071],
[1511842178.84161, 415, 0.9399999976158142],
[1511842178.878333, 416, 0.949999988079071],
[1511842178.914753, 417, 0.9100000262260437],
[1511842178.947455, 418, 0.9800000190734863],
[1511842178.979425, 419, 0.9700000286102295],
[1511842179.503057, 421, 0.9200000166893005],
[1511842179.540604, 422, 0.9300000071525574],
[1511842179.573449, 423, 0.9300000071525574],
[1511842179.608729, 424, 0.949999988079071],
[1511842179.645117, 425, 0.949999988079071],
[1511842179.678533, 426, 0.9599999785423279],
[1511842179.725027, 427, 0.9100000262260437],
[1511842179.758991, 428, 0.9700000286102295],
[1511842179.78958, 429, 0.9300000071525574],
[1511842180.311945, 431, 0.9700000286102295],
[1511842180.342856, 432, 0.9800000190734863],
[1511842180.372838, 433, 0.949999988079071],
[1511842180.402146, 434, 0.9100000262260437],
[1511842180.43488, 435, 0.9200000166893005],
[1511842180.467817, 436, 0.8999999761581421],
[1511842180.497947, 437, 0.9599999785423279],
[1511842180.529357, 438, 0.9399999976158142],
[1511842180.561293, 439, 0.949999988079071],
[1511842181.077772, 441, 0.9399999976158142],
[1511842181.108623, 442, 0.949999988079071],
[1511842181.140136, 443, 0.9900000095367432],
[1511842181.174364, 444, 0.9700000286102295],
[1511842181.20535, 445, 0.9300000071525574],
[1511842181.23487, 446, 0.9700000286102295],
[1511842181.267768, 447, 0.9200000166893005],
[1511842181.296881, 448, 0.9599999785423279],
[1511842181.331577, 449, 0.9599999785423279],
[1511842181.84731, 451, 0.9700000286102295],
[1511842181.877643, 452, 0.949999988079071],
[1511842181.90728, 453, 0.9200000166893005],
[1511842181.937846, 454, 0.9599999785423279],
[1511842181.971116, 455, 0.949999988079071],
[1511842182.000763, 456, 0.949999988079071],
[1511842182.037276, 457, 0.9399999976158142],
[1511842182.06702, 458, 0.9399999976158142],
[1511842182.096206, 459, 0.9300000071525574],
[1511842182.611312, 461, 0.949999988079071],
[1511842182.64513, 462, 0.9599999785423279],
[1511842182.674909, 463, 0.9300000071525574],
[1511842182.705437, 464, 0.9300000071525574],
[1511842182.735784, 465, 1.0],
[1511842182.767558, 466, 0.949999988079071],
[1511842182.796914, 467, 0.949999988079071],
[1511842182.826817, 468, 0.8999999761581421],
[1511842182.857851, 469, 0.9800000190734863],
[1511842183.352468, 471, 0.9800000190734863],
[1511842183.384449, 472, 0.8799999952316284],
[1511842183.420997, 473, 0.9300000071525574],
[1511842183.452375, 474, 0.9399999976158142],
[1511842183.483695, 475, 0.949999988079071],
[1511842183.514538, 476, 0.949999988079071],
[1511842183.547066, 477, 0.9599999785423279],
[1511842183.577378, 478, 0.9399999976158142],
[1511842183.613494, 479, 0.949999988079071],
[1511842184.166345, 481, 0.9599999785423279],
[1511842184.198856, 482, 0.9300000071525574],
[1511842184.231571, 483, 0.9399999976158142],
[1511842184.261741, 484, 0.949999988079071],
[1511842184.291412, 485, 0.9599999785423279],
[1511842184.321249, 486, 0.9900000095367432],
[1511842184.351878, 487, 0.9300000071525574],
[1511842184.381002, 488, 0.9399999976158142],
[1511842184.410772, 489, 0.9700000286102295],
[1511842184.908431, 491, 0.949999988079071],
[1511842184.941166, 492, 0.949999988079071],
[1511842184.978217, 493, 0.9700000286102295],
[1511842185.008197, 494, 0.9399999976158142],
[1511842185.039879, 495, 0.9800000190734863],
[1511842185.070592, 496, 0.9599999785423279],
[1511842185.10259, 497, 0.9599999785423279],
[1511842185.133795, 498, 0.9900000095367432],
[1511842185.243204, 499, 0.9599999785423279],
[1511842185.856761, 501, 0.949999988079071],
[1511842185.896018, 502, 0.9700000286102295],
[1511842185.943021, 503, 0.949999988079071],
[1511842185.981642, 504, 0.949999988079071],
[1511842186.023147, 505, 0.9800000190734863],
[1511842186.058391, 506, 0.949999988079071],
[1511842186.092093, 507, 0.9599999785423279],
[1511842186.134389, 508, 0.9200000166893005],
[1511842186.168454, 509, 0.9300000071525574],
[1511842186.73473, 511, 0.9399999976158142],
[1511842186.765813, 512, 0.9399999976158142],
[1511842186.798392, 513, 0.9599999785423279],
[1511842186.832886, 514, 0.9700000286102295],
[1511842186.869, 515, 0.9399999976158142],
[1511842186.899931, 516, 0.9399999976158142],
[1511842186.92933, 517, 0.9700000286102295],
[1511842186.961637, 518, 0.949999988079071],
[1511842186.993339, 519, 0.949999988079071],
[1511842187.51295, 521, 0.949999988079071],
[1511842187.542084, 522, 0.9300000071525574],
[1511842187.571555, 523, 0.9800000190734863],
[1511842187.600865, 524, 0.949999988079071],
[1511842187.630905, 525, 0.9700000286102295],
[1511842187.66434, 526, 0.9599999785423279],
[1511842187.695883, 527, 0.9399999976158142],
[1511842187.734118, 528, 0.949999988079071],
[1511842187.768383, 529, 0.9399999976158142],
[1511842188.2609, 531, 0.9599999785423279],
[1511842188.291538, 532, 0.949999988079071],
[1511842188.324743, 533, 0.949999988079071],
[1511842188.359286, 534, 0.9399999976158142],
[1511842188.392047, 535, 0.9300000071525574],
[1511842188.421359, 536, 0.9399999976158142],
[1511842188.454753, 537, 0.949999988079071],
[1511842188.48794, 538, 0.9900000095367432],
[1511842188.524741, 539, 0.9599999785423279],
[1511842189.0112, 541, 0.949999988079071],
[1511842189.043185, 542, 0.9300000071525574],
[1511842189.074307, 543, 0.9700000286102295],
[1511842189.106053, 544, 0.9399999976158142],
[1511842189.135565, 545, 0.9700000286102295],
[1511842189.168538, 546, 0.9599999785423279],
[1511842189.201185, 547, 0.9399999976158142],
[1511842189.235236, 548, 0.9900000095367432],
[1511842189.26819, 549, 0.949999988079071],
[1511842189.760432, 551, 0.9300000071525574],
[1511842189.789696, 552, 0.9599999785423279],
[1511842189.818744, 553, 0.9200000166893005],
[1511842189.848042, 554, 0.949999988079071],
[1511842189.877089, 555, 0.9399999976158142],
[1511842189.907031, 556, 0.949999988079071],
[1511842189.936881, 557, 0.9800000190734863],
[1511842189.966071, 558, 0.9399999976158142],
[1511842189.995653, 559, 0.9900000095367432],
[1511842190.508212, 561, 0.9200000166893005],
[1511842190.540299, 562, 0.9800000190734863],
[1511842190.578574, 563, 0.9300000071525574],
[1511842190.610377, 564, 0.949999988079071],
[1511842190.643136, 565, 0.9399999976158142],
[1511842190.672663, 566, 1.0],
[1511842190.707029, 567, 0.9900000095367432],
[1511842190.739414, 568, 0.949999988079071],
[1511842190.77237, 569, 0.9599999785423279],
[1511842191.31564, 571, 0.9300000071525574],
[1511842191.348465, 572, 0.9900000095367432],
[1511842191.382138, 573, 0.949999988079071],
[1511842191.412707, 574, 0.9399999976158142],
[1511842191.443585, 575, 0.9599999785423279],
[1511842191.477383, 576, 0.9700000286102295],
[1511842191.510109, 577, 0.9399999976158142],
[1511842191.540084, 578, 0.9399999976158142],
[1511842191.569611, 579, 0.9599999785423279],
[1511842192.080061, 581, 0.949999988079071],
[1511842192.114685, 582, 0.949999988079071],
[1511842192.146026, 583, 0.9599999785423279],
[1511842192.179577, 584, 0.9300000071525574],
[1511842192.213491, 585, 0.949999988079071],
[1511842192.247531, 586, 0.949999988079071],
[1511842192.279046, 587, 0.9700000286102295],
[1511842192.3092, 588, 0.9300000071525574],
[1511842192.343594, 589, 0.9700000286102295],
[1511842192.842748, 591, 0.9599999785423279],
[1511842192.872712, 592, 0.9700000286102295],
[1511842192.903806, 593, 0.9700000286102295],
[1511842192.935047, 594, 0.949999988079071],
[1511842192.966689, 595, 0.9300000071525574],
[1511842192.996178, 596, 1.0],
[1511842193.025323, 597, 0.9300000071525574],
[1511842193.059378, 598, 0.949999988079071],
[1511842193.161189, 599, 0.9599999785423279],
[1511842193.658418, 601, 0.9900000095367432],
[1511842193.688131, 602, 0.9399999976158142],
[1511842193.720422, 603, 0.9800000190734863],
[1511842193.752308, 604, 0.9599999785423279],
[1511842193.782545, 605, 0.949999988079071],
[1511842193.814567, 606, 0.9599999785423279],
[1511842193.848188, 607, 0.9399999976158142],
[1511842193.879656, 608, 0.9700000286102295],
[1511842193.910992, 609, 0.9900000095367432],
[1511842194.408775, 611, 0.949999988079071],
[1511842194.557519, 612, 0.9900000095367432],
[1511842194.59024, 613, 0.9700000286102295],
[1511842194.62302, 614, 0.9399999976158142],
[1511842194.656742, 615, 0.9599999785423279],
[1511842194.68816, 616, 0.9900000095367432],
[1511842194.720722, 617, 0.9300000071525574],
[1511842194.752064, 618, 0.9800000190734863],
[1511842194.784808, 619, 0.9100000262260437],
[1511842195.290169, 621, 0.949999988079071],
[1511842195.323044, 622, 0.9700000286102295],
[1511842195.353092, 623, 0.9900000095367432],
[1511842195.386405, 624, 0.949999988079071],
[1511842195.417719, 625, 0.9700000286102295],
[1511842195.471398, 626, 0.9800000190734863],
[1511842195.508423, 627, 0.9599999785423279],
[1511842195.543529, 628, 0.9700000286102295],
[1511842195.582063, 629, 0.9700000286102295],
[1511842196.143761, 631, 0.9700000286102295],
[1511842196.182851, 632, 0.9700000286102295],
[1511842196.214629, 633, 0.9700000286102295],
[1511842196.253051, 634, 0.9700000286102295],
[1511842196.287821, 635, 0.949999988079071],
[1511842196.319766, 636, 0.9399999976158142],
[1511842196.354184, 637, 0.9399999976158142],
[1511842196.38808, 638, 0.9599999785423279],
[1511842196.421604, 639, 0.949999988079071],
[1511842196.947931, 641, 1.0],
[1511842196.977982, 642, 0.949999988079071],
[1511842197.013177, 643, 0.9599999785423279],
[1511842197.053432, 644, 0.9599999785423279],
[1511842197.089024, 645, 0.9700000286102295],
[1511842197.120129, 646, 0.9599999785423279],
[1511842197.150194, 647, 0.9300000071525574],
[1511842197.18433, 648, 0.9700000286102295],
[1511842197.214245, 649, 0.9599999785423279],
[1511842197.734399, 651, 0.9599999785423279],
[1511842197.765878, 652, 0.949999988079071],
[1511842197.795536, 653, 0.9300000071525574],
[1511842197.828955, 654, 0.949999988079071],
[1511842197.858018, 655, 0.949999988079071],
[1511842197.88918, 656, 0.9300000071525574],
[1511842197.921247, 657, 0.9599999785423279],
[1511842197.961132, 658, 0.9599999785423279],
[1511842197.990723, 659, 0.949999988079071],
[1511842198.489996, 661, 0.9700000286102295],
[1511842198.520217, 662, 0.9900000095367432],
[1511842198.550925, 663, 1.0],
[1511842198.582604, 664, 0.9700000286102295],
[1511842198.612304, 665, 0.9700000286102295],
[1511842198.648211, 666, 0.9300000071525574],
[1511842198.686078, 667, 0.9599999785423279],
[1511842198.717921, 668, 0.949999988079071],
[1511842198.750968, 669, 0.9599999785423279],
[1511842199.258821, 671, 0.9399999976158142],
[1511842199.291037, 672, 0.9800000190734863],
[1511842199.320875, 673, 0.9700000286102295],
[1511842199.352976, 674, 0.949999988079071],
[1511842199.382681, 675, 0.9800000190734863],
[1511842199.411833, 676, 0.949999988079071],
[1511842199.443132, 677, 0.9700000286102295],
[1511842199.475117, 678, 0.9700000286102295],
[1511842199.505664, 679, 0.949999988079071],
[1511842200.00445, 681, 0.949999988079071],
[1511842200.037647, 682, 0.9900000095367432],
[1511842200.073666, 683, 0.9200000166893005],
[1511842200.104847, 684, 0.9200000166893005],
[1511842200.137768, 685, 0.9300000071525574],
[1511842200.170784, 686, 0.9800000190734863],
[1511842200.204724, 687, 0.9800000190734863],
[1511842200.240477, 688, 0.9800000190734863],
[1511842200.275783, 689, 0.9900000095367432],
[1511842200.81989, 691, 0.9700000286102295],
[1511842200.858525, 692, 0.9300000071525574],
[1511842200.890363, 693, 0.949999988079071],
[1511842200.932829, 694, 0.9599999785423279],
[1511842200.962743, 695, 0.9800000190734863],
[1511842200.994843, 696, 0.9200000166893005],
[1511842201.03947, 697, 0.9800000190734863],
[1511842201.070836, 698, 0.9399999976158142],
[1511842201.246026, 699, 0.9100000262260437],
[1511842201.786404, 701, 0.9300000071525574],
[1511842201.819202, 702, 0.9800000190734863],
[1511842201.856957, 703, 0.9200000166893005],
[1511842201.888767, 704, 1.0],
[1511842201.92143, 705, 0.9399999976158142],
[1511842201.961242, 706, 0.9700000286102295],
[1511842201.996298, 707, 0.9200000166893005],
[1511842202.032258, 708, 0.9800000190734863],
[1511842202.069833, 709, 0.9300000071525574],
[1511842202.5957, 711, 0.9800000190734863],
[1511842202.632072, 712, 0.9800000190734863],
[1511842202.664469, 713, 0.9700000286102295],
[1511842202.696135, 714, 0.9300000071525574],
[1511842202.72853, 715, 0.9700000286102295],
[1511842202.759628, 716, 0.9800000190734863],
[1511842202.794048, 717, 0.9800000190734863],
[1511842202.827036, 718, 0.949999988079071],
[1511842202.858473, 719, 0.9700000286102295],
[1511842203.391985, 721, 0.9599999785423279],
[1511842203.4215, 722, 0.9399999976158142],
[1511842203.453421, 723, 0.9800000190734863],
[1511842203.484233, 724, 0.9700000286102295],
[1511842203.516743, 725, 0.9900000095367432],
[1511842203.550632, 726, 0.9800000190734863],
[1511842203.584461, 727, 0.9800000190734863],
[1511842203.617915, 728, 0.9599999785423279],
[1511842203.652398, 729, 0.9700000286102295],
[1511842204.185468, 731, 0.9800000190734863],
[1511842204.217265, 732, 0.9800000190734863],
[1511842204.249281, 733, 1.0],
[1511842204.282808, 734, 0.9700000286102295],
[1511842204.314277, 735, 0.9700000286102295],
[1511842204.345353, 736, 0.949999988079071],
[1511842204.375898, 737, 0.9599999785423279],
[1511842204.411013, 738, 0.9100000262260437],
[1511842204.441207, 739, 0.9700000286102295],
[1511842204.967109, 741, 0.9399999976158142],
[1511842204.999614, 742, 0.9900000095367432],
[1511842205.037706, 743, 0.9599999785423279],
[1511842205.071398, 744, 0.9700000286102295],
[1511842205.109827, 745, 0.9800000190734863],
[1511842205.150377, 746, 0.9700000286102295],
[1511842205.196859, 747, 0.9399999976158142],
[1511842205.238587, 748, 0.9900000095367432],
[1511842205.284592, 749, 0.9700000286102295],
[1511842205.913203, 751, 0.9599999785423279],
[1511842205.977628, 752, 0.9800000190734863],
[1511842206.049908, 753, 0.9399999976158142],
[1511842206.088929, 754, 0.9599999785423279],
[1511842206.12656, 755, 0.9700000286102295],
[1511842206.171609, 756, 0.9700000286102295],
[1511842206.207161, 757, 0.9599999785423279],
[1511842206.259537, 758, 0.9900000095367432],
[1511842206.299124, 759, 0.9800000190734863],
[1511842206.839902, 761, 0.9399999976158142],
[1511842206.869605, 762, 0.9800000190734863],
[1511842206.901015, 763, 0.9599999785423279],
[1511842206.931029, 764, 0.9700000286102295],
[1511842206.961387, 765, 0.9300000071525574],
[1511842206.992158, 766, 0.9599999785423279],
[1511842207.02291, 767, 0.9700000286102295],
[1511842207.055302, 768, 0.9599999785423279],
[1511842207.089098, 769, 0.9399999976158142],
[1511842207.593272, 771, 0.9800000190734863],
[1511842207.624582, 772, 0.949999988079071],
[1511842207.654845, 773, 0.9599999785423279],
[1511842207.688258, 774, 0.9800000190734863],
[1511842207.718489, 775, 0.9700000286102295],
[1511842207.747767, 776, 0.949999988079071],
[1511842207.778593, 777, 0.9700000286102295],
[1511842207.808232, 778, 0.9599999785423279],
[1511842207.838551, 779, 0.9599999785423279],
[1511842208.397092, 781, 0.9700000286102295],
[1511842208.427281, 782, 0.949999988079071],
[1511842208.458664, 783, 0.9800000190734863],
[1511842208.488235, 784, 0.9599999785423279],
[1511842208.519785, 785, 0.9599999785423279],
[1511842208.554034, 786, 0.9800000190734863],
[1511842208.586204, 787, 0.9800000190734863],
[1511842208.619628, 788, 0.9700000286102295],
[1511842208.654394, 789, 0.9800000190734863],
[1511842209.194778, 791, 0.9800000190734863],
[1511842209.226194, 792, 0.9599999785423279],
[1511842209.266281, 793, 0.9599999785423279],
[1511842209.295469, 794, 0.9800000190734863],
[1511842209.327287, 795, 0.9800000190734863],
[1511842209.364207, 796, 0.9599999785423279],
[1511842209.395033, 797, 0.9599999785423279],
[1511842209.429895, 798, 0.949999988079071],
[1511842209.556844, 799, 0.949999988079071],
[1511842210.130269, 801, 0.9700000286102295],
[1511842210.160287, 802, 0.9700000286102295],
[1511842210.193199, 803, 0.9700000286102295],
[1511842210.22632, 804, 0.9399999976158142],
[1511842210.26311, 805, 0.9800000190734863],
[1511842210.309019, 806, 0.9599999785423279],
[1511842210.347609, 807, 0.9800000190734863],
[1511842210.390996, 808, 0.9900000095367432],
[1511842210.439887, 809, 0.9200000166893005],
[1511842211.003122, 811, 0.9599999785423279],
[1511842211.037074, 812, 0.9599999785423279],
[1511842211.067644, 813, 0.9399999976158142],
[1511842211.101507, 814, 0.9599999785423279],
[1511842211.140325, 815, 0.9599999785423279],
[1511842211.174903, 816, 0.949999988079071],
[1511842211.224003, 817, 0.9700000286102295],
[1511842211.286801, 818, 0.9900000095367432],
[1511842211.327776, 819, 0.9800000190734863],
[1511842211.985095, 821, 0.9200000166893005],
[1511842212.030882, 822, 0.9700000286102295],
[1511842212.070569, 823, 0.9399999976158142],
[1511842212.118181, 824, 0.9800000190734863],
[1511842212.157094, 825, 0.9599999785423279],
[1511842212.226286, 826, 0.9599999785423279],
[1511842212.277023, 827, 0.9900000095367432],
[1511842212.311592, 828, 1.0],
[1511842212.348642, 829, 0.9599999785423279],
[1511842212.91796, 831, 0.9900000095367432],
[1511842212.950586, 832, 0.9800000190734863],
[1511842212.996488, 833, 0.9599999785423279],
[1511842213.027555, 834, 0.9800000190734863],
[1511842213.058825, 835, 0.9800000190734863],
[1511842213.091046, 836, 0.9599999785423279],
[1511842213.125024, 837, 0.9599999785423279],
[1511842213.160207, 838, 0.9399999976158142],
[1511842213.191536, 839, 0.9700000286102295],
[1511842213.728065, 841, 0.9700000286102295],
[1511842213.762401, 842, 0.9700000286102295],
[1511842213.799732, 843, 0.9700000286102295],
[1511842213.833657, 844, 0.9800000190734863],
[1511842213.866312, 845, 0.9800000190734863],
[1511842213.902647, 846, 0.9599999785423279],
[1511842213.942028, 847, 0.9700000286102295],
[1511842213.983694, 848, 0.9599999785423279],
[1511842214.017235, 849, 0.949999988079071],
[1511842214.539192, 851, 0.9800000190734863],
[1511842214.570802, 852, 0.9599999785423279],
[1511842214.602371, 853, 0.9800000190734863],
[1511842214.63469, 854, 0.9599999785423279],
[1511842214.666527, 855, 0.9700000286102295],
[1511842214.7013, 856, 0.949999988079071],
[1511842214.736796, 857, 0.9700000286102295],
[1511842214.773076, 858, 0.9900000095367432],
[1511842214.804659, 859, 0.9900000095367432],
[1511842215.333667, 861, 0.9700000286102295],
[1511842215.36866, 862, 0.9800000190734863],
[1511842215.408818, 863, 0.9800000190734863],
[1511842215.446431, 864, 0.9900000095367432],
[1511842215.484602, 865, 0.9399999976158142],
[1511842215.520258, 866, 0.9800000190734863],
[1511842215.555225, 867, 0.9800000190734863],
[1511842215.592115, 868, 0.9599999785423279],
[1511842215.630665, 869, 0.9700000286102295],
[1511842216.128021, 871, 1.0],
[1511842216.159525, 872, 0.9200000166893005],
[1511842216.191044, 873, 0.9800000190734863],
[1511842216.22625, 874, 0.949999988079071],
[1511842216.264204, 875, 1.0],
[1511842216.301708, 876, 0.9300000071525574],
[1511842216.346822, 877, 0.949999988079071],
[1511842216.387908, 878, 0.9900000095367432],
[1511842216.431012, 879, 0.9399999976158142],
[1511842216.948288, 881, 0.9800000190734863],
[1511842216.980613, 882, 0.9599999785423279],
[1511842217.01133, 883, 0.9700000286102295],
[1511842217.042047, 884, 0.9900000095367432],
[1511842217.073482, 885, 0.9300000071525574],
[1511842217.108726, 886, 0.9599999785423279],
[1511842217.14001, 887, 0.9800000190734863],
[1511842217.171317, 888, 0.9599999785423279],
[1511842217.203606, 889, 0.9800000190734863],
[1511842217.753845, 891, 0.9399999976158142],
[1511842217.789057, 892, 0.9599999785423279],
[1511842217.830139, 893, 0.9800000190734863],
[1511842217.864796, 894, 0.949999988079071],
[1511842217.897203, 895, 0.9800000190734863],
[1511842217.929849, 896, 0.949999988079071],
[1511842217.963099, 897, 0.9800000190734863],
[1511842217.996219, 898, 0.9599999785423279],
[1511842218.111479, 899, 0.9599999785423279],
[1511842218.683541, 901, 0.9700000286102295],
[1511842218.714867, 902, 0.9900000095367432],
[1511842218.745403, 903, 0.949999988079071],
[1511842218.775027, 904, 0.9599999785423279],
[1511842218.804858, 905, 0.9700000286102295],
[1511842218.834642, 906, 0.9599999785423279],
[1511842218.865326, 907, 0.9900000095367432],
[1511842218.896291, 908, 0.9700000286102295],
[1511842218.926799, 909, 0.9800000190734863],
[1511842219.457638, 911, 0.949999988079071],
[1511842219.489308, 912, 0.9700000286102295],
[1511842219.524922, 913, 0.9100000262260437],
[1511842219.55795, 914, 0.9900000095367432],
[1511842219.595283, 915, 0.9900000095367432],
[1511842219.687366, 916, 0.9900000095367432],
[1511842219.727115, 917, 0.9800000190734863],
[1511842219.768945, 918, 0.9599999785423279],
[1511842219.801816, 919, 0.9800000190734863],
[1511842220.390596, 921, 0.9900000095367432],
[1511842220.43033, 922, 0.9700000286102295],
[1511842220.469885, 923, 0.9700000286102295],
[1511842220.501432, 924, 0.949999988079071],
[1511842220.534336, 925, 0.949999988079071],
[1511842220.577459, 926, 0.9800000190734863],
[1511842220.634076, 927, 0.9700000286102295],
[1511842220.668908, 928, 0.9599999785423279],
[1511842220.7005, 929, 0.9900000095367432],
[1511842221.287896, 931, 0.9800000190734863],
[1511842221.319684, 932, 0.9599999785423279],
[1511842221.355376, 933, 0.949999988079071],
[1511842221.390386, 934, 0.9700000286102295],
[1511842221.424849, 935, 0.9599999785423279],
[1511842221.455576, 936, 0.9800000190734863],
[1511842221.488522, 937, 0.9700000286102295],
[1511842221.523331, 938, 0.949999988079071],
[1511842221.562103, 939, 0.9800000190734863],
[1511842222.11082, 941, 0.9399999976158142],
[1511842222.144042, 942, 1.0],
[1511842222.180893, 943, 0.9599999785423279],
[1511842222.214718, 944, 0.9599999785423279],
[1511842222.250779, 945, 0.9399999976158142],
[1511842222.283768, 946, 0.9599999785423279],
[1511842222.318964, 947, 0.949999988079071],
[1511842222.351751, 948, 0.9599999785423279],
[1511842222.382504, 949, 0.9800000190734863],
[1511842222.889534, 951, 0.9800000190734863],
[1511842222.921617, 952, 0.949999988079071],
[1511842222.953747, 953, 0.9399999976158142],
[1511842222.989928, 954, 0.9399999976158142],
[1511842223.023551, 955, 0.9700000286102295],
[1511842223.060438, 956, 0.9800000190734863],
[1511842223.097254, 957, 0.9599999785423279],
[1511842223.138771, 958, 0.9800000190734863],
[1511842223.174054, 959, 0.9399999976158142],
[1511842223.693137, 961, 0.949999988079071],
[1511842223.723562, 962, 0.9800000190734863],
[1511842223.755989, 963, 0.9700000286102295],
[1511842223.790843, 964, 0.9900000095367432],
[1511842223.822565, 965, 0.9800000190734863],
[1511842223.853841, 966, 0.9900000095367432],
[1511842223.892184, 967, 0.9399999976158142],
[1511842223.928116, 968, 0.9800000190734863],
[1511842223.961467, 969, 0.9700000286102295],
[1511842224.536617, 971, 0.9900000095367432],
[1511842224.577399, 972, 0.9599999785423279],
[1511842224.617609, 973, 0.9700000286102295],
[1511842224.655355, 974, 0.9599999785423279],
[1511842224.689069, 975, 0.949999988079071],
[1511842224.72824, 976, 0.9700000286102295],
[1511842224.759455, 977, 0.949999988079071],
[1511842224.793144, 978, 0.9599999785423279],
[1511842224.824675, 979, 0.9700000286102295],
[1511842225.342267, 981, 0.9599999785423279],
[1511842225.374886, 982, 0.9700000286102295],
[1511842225.407038, 983, 0.9800000190734863],
[1511842225.438013, 984, 1.0],
[1511842225.468219, 985, 0.9800000190734863],
[1511842225.499246, 986, 0.9800000190734863],
[1511842225.528987, 987, 0.949999988079071],
[1511842225.56184, 988, 0.9599999785423279],
[1511842225.596399, 989, 0.949999988079071],
[1511842226.096082, 991, 0.9399999976158142],
[1511842226.125964, 992, 0.9800000190734863],
[1511842226.156644, 993, 0.9599999785423279],
[1511842226.187556, 994, 0.9599999785423279],
[1511842226.218394, 995, 0.9900000095367432],
[1511842226.250693, 996, 0.9599999785423279],
[1511842226.284415, 997, 0.9800000190734863],
[1511842226.316085, 998, 0.9700000286102295],
[1511842226.42392, 999, 0.9599999785423279]
];
}
return [
[1511842145.514333, 0, 0.094200000166893],
[1511842146.427384, 10, 0.7394000291824341],
[1511842147.260405, 20, 0.8302000164985657],
[1511842148.019018, 30, 0.8662999868392944],
[1511842148.793569, 40, 0.8877999782562256],
[1511842149.610228, 50, 0.8952000141143799],
[1511842150.437095, 60, 0.9031000137329102],
[1511842151.254679, 70, 0.9004999995231628],
[1511842152.039353, 80, 0.9110000133514404],
[1511842152.800043, 90, 0.9143000245094299],
[1511842153.668115, 100, 0.9175000190734863],
[1511842154.453025, 110, 0.9190000295639038],
[1511842155.224028, 120, 0.9214000105857849],
[1511842156.001674, 130, 0.9204999804496765],
[1511842156.788682, 140, 0.9297999739646912],
[1511842157.580495, 150, 0.9289000034332275],
[1511842158.331122, 160, 0.9283999800682068],
[1511842159.112936, 170, 0.9298999905586243],
[1511842159.881351, 180, 0.9301000237464905],
[1511842160.659058, 190, 0.9330999851226807],
[1511842161.515267, 200, 0.9345999956130981],
[1511842162.301136, 210, 0.9351000189781189],
[1511842163.092769, 220, 0.9343000054359436],
[1511842163.920516, 230, 0.9372000098228455],
[1511842164.705352, 240, 0.9351999759674072],
[1511842165.674882, 250, 0.9369999766349792],
[1511842166.462909, 260, 0.9444000124931335],
[1511842167.319383, 270, 0.9437000155448914],
[1511842168.114944, 280, 0.9441999793052673],
[1511842168.942822, 290, 0.9441999793052673],
[1511842169.801691, 300, 0.9453999996185303],
[1511842170.594651, 310, 0.9419000148773193],
[1511842171.406169, 320, 0.9437000155448914],
[1511842172.190729, 330, 0.9488999843597412],
[1511842172.997593, 340, 0.9483000040054321],
[1511842173.815758, 350, 0.9453999996185303],
[1511842174.613314, 360, 0.9480000138282776],
[1511842175.402401, 370, 0.9513999819755554],
[1511842176.180888, 380, 0.9480999708175659],
[1511842176.999133, 390, 0.9520000219345093],
[1511842177.900425, 400, 0.954200029373169],
[1511842178.682129, 410, 0.9490000009536743],
[1511842179.471428, 420, 0.9534000158309937],
[1511842180.272808, 430, 0.9549999833106995],
[1511842181.044304, 440, 0.9545999765396118],
[1511842181.814283, 450, 0.951200008392334],
[1511842182.576814, 460, 0.9560999870300293],
[1511842183.319649, 470, 0.9588000178337097],
[1511842184.080669, 480, 0.9555000066757202],
[1511842184.877782, 490, 0.955299973487854],
[1511842185.816123, 500, 0.9545000195503235],
[1511842186.704832, 510, 0.9559999704360962],
[1511842187.475836, 520, 0.9563999772071838],
[1511842188.231245, 530, 0.9596999883651733],
[1511842188.981693, 540, 0.9562000036239624],
[1511842189.72966, 550, 0.9553999900817871],
[1511842190.468321, 560, 0.9580000042915344],
[1511842191.281197, 570, 0.9575999975204468],
[1511842192.046349, 580, 0.9589999914169312],
[1511842192.808289, 590, 0.9599999785423279],
[1511842193.623127, 600, 0.9603999853134155],
[1511842194.371868, 610, 0.9605000019073486],
[1511842195.257612, 620, 0.9606000185012817],
[1511842196.113539, 630, 0.9559999704360962],
[1511842196.914175, 640, 0.9610000252723694],
[1511842197.701817, 650, 0.9621999859809875],
[1511842198.457409, 660, 0.9599000215530396],
[1511842199.228452, 670, 0.9620000123977661],
[1511842199.973789, 680, 0.9628000259399414],
[1511842200.786072, 690, 0.963699996471405],
[1511842201.752806, 700, 0.963100016117096],
[1511842202.55644, 710, 0.9632999897003174],
[1511842203.355084, 720, 0.964900016784668],
[1511842204.150081, 730, 0.9638000130653381],
[1511842204.931775, 740, 0.9660000205039978],
[1511842205.878417, 750, 0.9628000259399414],
[1511842206.808438, 760, 0.9613000154495239],
[1511842207.560386, 770, 0.9656000137329102],
[1511842208.364481, 780, 0.9664000272750854],
[1511842209.154627, 790, 0.9628000259399414],
[1511842210.098208, 800, 0.9627000093460083],
[1511842210.969653, 810, 0.9656999707221985],
[1511842211.929992, 820, 0.9657999873161316],
[1511842212.882522, 830, 0.9656000137329102],
[1511842213.690861, 840, 0.9682000279426575],
[1511842214.508996, 850, 0.9678999781608582],
[1511842215.295672, 860, 0.968999981880188],
[1511842216.096151, 870, 0.9682999849319458],
[1511842216.910752, 880, 0.9661999940872192],
[1511842217.718586, 890, 0.9648000001907349],
[1511842218.653347, 900, 0.9678000211715698],
[1511842219.421863, 910, 0.96670001745224],
[1511842220.34967, 920, 0.9674000144004822],
[1511842221.234565, 930, 0.9684000015258789],
[1511842222.075741, 940, 0.9682000279426575],
[1511842222.854794, 950, 0.9663000106811523],
[1511842223.658847, 960, 0.9681000113487244],
[1511842224.500655, 970, 0.9692999720573425],
[1511842225.308939, 980, 0.9692000150680542],
[1511842226.065685, 990, 0.9692000150680542]
];
};
export default {
test: ['layer2/biases/summaries/mean'],
train: ['layer2/biases/summaries/mean', 'layer2/biases/summaries/accuracy', 'layer2/biases/summaries/cost']
};
/// <reference types="next" />
/// <reference types="next/types/global" />
/* eslint-disable @typescript-eslint/no-var-requires */
const path = require('path');
const pkg = require('./package.json');
const publicPath = process.env.PUBLIC_PATH || '';
const apiUrl = process.env.API_URL || '/api';
const APP = {
name: pkg.name,
version: pkg.version,
title: pkg.title,
description: pkg.description,
author: pkg.author,
keywords: pkg.keywords.join(',')
};
module.exports = {
assetPrefix: publicPath,
distDir: 'dist',
poweredByHeader: false,
env: {
...APP,
PUBLIC_PATH: publicPath,
API_URL: apiUrl
},
webpack: config => {
config.resolve = config.resolve || {};
config.resolve.alias = config.resolve.alias || {};
config.resolve.alias['~'] = path.resolve(__dirname);
return config;
}
};
{ {
"name": "VisualDL", "name": "visual-dl",
"version": "1.0.0", "version": "2.0.0-beta",
"description": "Visualization toolkit for deep learning", "title": "VisualDL",
"scripts": { "description": "A platform to visualize the deep learning process and result.",
"release": "cross-env NODE_ENV=production node ./tool/build.js", "keywords": [
"build": "cross-env NODE_ENV=dev node ./tool/build.js", "visualdl",
"dev": "cross-env NODE_ENV=dev node tool/dev-server.js", "paddlepaddle",
"demo": "cross-env NODE_ENV=demo node tool/demo-server.js", "visualization",
"lint": "./node_modules/fecs/bin/fecs --rule" "deep learning"
}, ],
"engines": { "homepage": "https://github.com/PaddlePaddle/VisualDL",
"node": ">= 6.4.0" "bugs": {
}, "url": "https://github.com/PaddlePaddle/VisualDL/issues"
"dependencies": { },
"axios": "^0.16.1", "license": "Apache-2.0",
"csshint": "^0.3.3", "author": "PeterPanZH <littlepanzh@gmail.com> (https://github.com/PeterPanZH)",
"d3": "^4.7.4", "contributors": [
"d3-format": "^1.2.1", "Niandalu <littlepanzh@gmail.com> (https://github.com/Niandalu)"
"dagre": "^0.8.2", ],
"echarts": "^4.0.0", "repository": {
"echarts-gl": "^1.1.0", "type": "git",
"file-saver": "^1.3.3", "url": "https://github.com/PaddlePaddle/VisualDL.git",
"graphlib": "^1.0.5", "directory": "frontend"
"htmlcs": "^0.4.1", },
"lesslint": "^1.0.2", "scripts": {
"lodash": "^4.17.4", "dev": "cross-env NODE_ENV=development nodemon --watch server --ext ts --exec \"ts-node --project=tsconfig.server.json\" server/index.ts",
"normalize.css": "^6.0.0", "build:next": "next build",
"qs": "^6.5.1", "build:server": "tsc --project tsconfig.server.json",
"vue": "^2.5.2", "start": "NODE_ENV=production node dist/server/index.js",
"vue-router": "^3.0.1", "lint": "tsc --noEmit && eslint --ext .tsx,.jsx.ts,.js --ignore-path .gitignore .",
"vue-i18n": ">=7.0.0", "format": "prettier --write \"**/*.ts\" \"**/*.tsx\" \"**/*.js\" \"**/*.jsx\"",
"vuetify": "^0.17.7", "test": "echo \"Error: no test specified\" && exit 0"
"xlsx": "^0.11.3" },
}, "dependencies": {
"devDependencies": { "dagre-d3": "0.6.4",
"autoprefixer": "^6.7.7", "echarts": "4.6.0",
"autoresponse": "^0.2.0", "echarts-gl": "1.1.1",
"babel-core": "^6.25.0", "express": "4.17.1",
"babel-loader": "^6.2.7", "isomorphic-unfetch": "3.0.0",
"babel-plugin-transform-class-properties": "^6.19.0", "lodash": "4.17.15",
"babel-plugin-transform-runtime": "^6.23.0", "moment": "2.24.0",
"babel-preset-es2015": "^6.18.0", "next": "9.2.2",
"babel-preset-stage-0": "^6.16.0", "next-i18next": "4.2.0",
"babel-register": "^6.0.0", "nprogress": "0.2.0",
"babel-runtime": "^6.26.0", "polished": "3.4.4",
"case-sensitive-paths-webpack-plugin": "^2.1.1", "react": "16.13.0",
"chalk": "^1.1.3", "react-dom": "16.13.0",
"copy-webpack-plugin": "^4.0.1", "react-input-range": "1.3.0",
"cross-env": "^4.0.0", "react-is": "16.13.0",
"css-loader": "^0.28.0", "save-svg-as-png": "1.4.17",
"eslint": "^4.19.1", "styled-components": "5.0.1",
"eslint-config-google": "^0.9.1", "swr": "0.1.18"
"eslint-plugin-vue": "^4.4.0", },
"express": "^4.16.2", "devDependencies": {
"extract-text-webpack-plugin": "^2.1.0", "@babel/core": "7.8.6",
"fecs": "1.5.2", "@types/d3": "5.7.2",
"file-loader": "^0.11.1", "@types/dagre": "0.7.42",
"friendly-errors-webpack-plugin": "^1.6.1", "@types/echarts": "4.4.3",
"glob": "^7.1.1", "@types/express": "4.17.2",
"html-loader": "^0.4.4", "@types/faker": "4.1.10",
"html-webpack-plugin": "^2.28.0", "@types/lodash": "4.14.149",
"http-proxy-middleware": "^0.17.4", "@types/node": "13.7.7",
"interactjs": "^1.3.2", "@types/nprogress": "0.2.0",
"json-loader": "^0.5.4", "@types/react": "16.9.23",
"opn": "^5.1.0", "@types/react-dom": "16.9.5",
"optimize-css-assets-webpack-plugin": "^1.3.2", "@types/styled-components": "5.0.1",
"ora": "^1.1.0", "@types/webpack": "4.41.7",
"postcss-loader": "^1.3.3", "@typescript-eslint/eslint-plugin": "2.21.0",
"raw-loader": "^0.5.1", "@typescript-eslint/parser": "2.21.0",
"rimraf": "^2.6.2", "babel-plugin-styled-components": "1.10.7",
"style-loader": "^0.16.1", "babel-plugin-typescript-to-proptypes": "1.2.1",
"stylus": "^0.54.5", "cross-env": "7.0.0",
"stylus-loader": "^3.0.1", "eslint": "6.8.0",
"url-loader": "^0.5.8", "eslint-config-prettier": "6.10.0",
"vue-eslint-parser": "^2.0.3", "eslint-plugin-prettier": "3.1.2",
"vue-jest": "^1.0.2", "eslint-plugin-react": "7.18.3",
"vue-loader": "^13.3.0", "eslint-plugin-react-hooks": "2.5.0",
"vue-style-loader": "^3.0.1", "faker": "4.1.0",
"vue-template-compiler": "^2.5.2", "husky": "4.2.3",
"webpack": "^2.7.0", "lint-staged": "10.0.8",
"webpack-dev-middleware": "^1.12.1", "nodemon": "2.0.2",
"webpack-dev-server": "^2.4.2", "prettier": "1.19.1",
"webpack-hot-middleware": "^2.19.1", "ts-node": "8.6.2",
"webpack-merge": "^4.1.0", "typescript": "3.8.3"
"yargs": "^8.0.2" },
} "engines": {
"node": ">=10",
"npm": ">=6"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
}
} }
import '~/public/style/vdl-icon.css';
import React from 'react';
import {NextComponentType, NextPageContext} from 'next';
import App from 'next/app';
import Head from 'next/head';
import NProgress from 'nprogress';
import {SWRConfig} from 'swr';
import {fetcher} from '~/utils/fetch';
import {Router, appWithTranslation} from '~/utils/i18n';
import {GlobalStyle} from '~/utils/style';
import Title from '~/components/Title';
import Layout from '~/components/Layout';
Router.events.on('routeChangeStart', () => NProgress.start());
Router.events.on('routeChangeComplete', () => NProgress.done());
Router.events.on('routeChangeError', () => NProgress.done());
type AppProps<P = {}> = {
// eslint-disable-next-line
Component: {title?: string} & NextComponentType<NextPageContext, any, P>;
};
class VDLApp extends App<AppProps> {
render() {
const {Component, pageProps} = this.props;
return (
<>
<Head>
<title>{process.env.title}</title>
<link rel="shortcut icon" href="/favicon.ico" />
<meta
name="viewport"
content="width=device-width,minimum-scale=1,maximum-scale=1,initial-scale=1,user-scalable=no,shrink-to-fit=no"
/>
<meta name="description" content={process.env.description} />
<meta name="keywords" content={process.env.keywords} />
<meta name="author" content={process.env.author} />
</Head>
<Title>{Component.title}</Title>
<GlobalStyle />
<SWRConfig
value={{
fetcher,
revalidateOnFocus: false,
revalidateOnReconnect: false
}}
>
<Layout>
<Component {...pageProps} />
</Layout>
</SWRConfig>
</>
);
}
}
export default appWithTranslation(VDLApp);
import Document, {Head, Main, NextScript, DocumentContext, DocumentProps} from 'next/document';
import {ServerStyleSheet} from '~/utils/style';
interface VDLDocumentProps extends DocumentProps {
languageDirection: string;
language: string;
}
export default class VDLDocument extends Document<VDLDocumentProps> {
static async getInitialProps(ctx: DocumentContext) {
// https://github.com/zeit/next.js/blob/canary/examples/with-typescript-styled-components/pages/_document.tsx
const sheet = new ServerStyleSheet();
const originalRenderPage = ctx.renderPage;
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: App => props => sheet.collectStyles(<App {...props} />)
});
const initialProps = await Document.getInitialProps(ctx);
// stealed from https://github.com/isaachinman/next-i18next/issues/20#issuecomment-558799264
// FIXME: https://github.com/i18next/i18next-express-middleware/blob/master/src/index.js#L23-L26
// eslint-disable-next-line
const {locals} = ctx.res as any;
const additionalProps = {
languageDirection: locals.languageDirection as string,
language: locals.language as string
};
return {
...initialProps,
...additionalProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
)
};
} finally {
sheet.seal();
}
}
render() {
const {languageDirection, language} = this.props;
return (
<html lang={language} dir={languageDirection}>
<Head />
<body>
<Main />
<NextScript />
</body>
</html>
);
}
}
import React from 'react';
import {useTranslation, NextI18NextPage} from '~/utils/i18n';
interface ErrorProps {
statusCode?: number | null;
}
const Error: NextI18NextPage<ErrorProps> = ({statusCode}) => {
const {t} = useTranslation('errors');
return <p>{statusCode ? t('error-with-status', {statusCode}) : t('error-without-status')}</p>;
};
Error.getInitialProps = ({res, err}) => {
let statusCode = null;
if (res) {
({statusCode} = res);
} else if (err) {
({statusCode} = err);
}
return {
namespacesRequired: ['errors'],
statusCode
};
};
export default Error;
import React, {useState, useEffect, useMemo} from 'react';
import useSWR from 'swr';
import styled from 'styled-components';
import RawButton from '~/components/Button';
import RawRangeSlider from '~/components/RangeSlider';
import Content from '~/components/Content';
import Title from '~/components/Title';
import Field from '~/components/Field';
import {useTranslation, NextI18NextPage} from '~/utils/i18n';
import {rem} from '~/utils/style';
import {fetcher} from '~/utils/fetch';
import NodeInfo, {NodeInfoProps} from '~/components/GraphPage/NodeInfo';
import {Graph, collectDagFacts} from '~/resource/graph';
import {saveSvgAsPng} from 'save-svg-as-png';
const dumbFn = () => {};
const SubSection = styled.div`
margin-bottom: ${rem(30)};
`;
const Button = styled(RawButton)`
width: 100%;
text-transform: uppercase;
& + & {
margin-top: ${rem(20)};
}
`;
const RangeSlider = styled(RawRangeSlider)`
width: 100%;
`;
const GraphSvg = styled('svg')`
width: 100%;
cursor: grab;
&.grabbing {
cursor: grabbing;
}
.node {
cursor: pointer;
}
.edgePath path.path {
stroke: #333;
stroke-width: 1.5px;
}
`;
const loadDagLibs = [import('d3'), import('dagre-d3')] as const;
const MIN_SCALE = 0.1;
const MAX_SCALE = 4;
const useDag = (graph?: Graph) => {
const [displaySwitch, setDisplaySwitch] = useState({
detail: true,
input: true,
output: true
});
const facts = useMemo(() => collectDagFacts(graph), [graph]);
const dagInfo = useMemo(() => {
const {inputLayer, outputLayer, briefLayer, detailLayer, findNode} = facts;
const availableLayers = displaySwitch.detail ? [detailLayer] : [briefLayer];
if (displaySwitch.input) {
availableLayers.push(inputLayer);
}
if (displaySwitch.output) {
availableLayers.push(outputLayer);
}
return {
...availableLayers.reduce(
(memo, {nodes, edges}) => ({
nodes: memo.nodes.concat(nodes),
edges: memo.edges.concat(edges)
}),
{
nodes: [],
edges: []
}
),
findNode
};
}, [facts, displaySwitch]);
return {
dagInfo,
displaySwitch,
setDisplaySwitch
};
};
const useDagreD3 = (graph: Graph | undefined) => {
const [currentNode, setCurrentNode] = useState<NodeInfoProps['node']>(undefined);
const {dagInfo, displaySwitch, setDisplaySwitch} = useDag(graph);
const [downloadImage, setDownloadImageFn] = useState<() => void>(() => dumbFn);
const [fitScreen, setFitScreenFn] = useState<() => void>(() => dumbFn);
const [scale, setScaleValue] = useState(1);
const [setScale, setScaleFn] = useState<(n: number) => void>(() => dumbFn);
useEffect(() => {
Promise.all(loadDagLibs).then(([d3, {default: dagre}]) => {
if (!dagInfo.nodes.length || !dagInfo.edges.length) {
return;
}
const g = new dagre.graphlib.Graph();
g.setGraph({}).setDefaultEdgeLabel(() => ({}));
dagInfo.nodes.forEach(n => g.setNode(n.key, n));
dagInfo.edges.forEach(e => g.setEdge(e[0], e[1]));
const render = new dagre.render();
const svg = d3.select<HTMLElement, any>('svg');
const inner = svg.select('svg g');
render(inner, g);
const {width, height} = g.graph();
const scaleFactor = 1;
svg.attr('height', Math.max(640, window.innerHeight + 40));
var zoom = d3
.zoom<HTMLElement, any>()
.scaleExtent([MIN_SCALE, MAX_SCALE])
.on('zoom', function() {
setScaleValue(d3.event.transform.k / scaleFactor);
inner.attr('transform', d3.event.transform);
})
.on('start', () => svg.classed('grabbing', true))
.on('end', () => svg.classed('grabbing', false));
svg.call(zoom);
// install event listeners
svg.selectAll('g.node').on('click', v => {
const uid = v as string;
const {type} = g.node(uid);
const dagNode = dagInfo.findNode(type, uid);
if (!dagNode) {
setCurrentNode({type: 'unknown', guessType: type, msg: uid});
return;
}
setCurrentNode({...dagNode, type});
});
const fitScreen = () => {
if (!svg) {
return;
}
const parent = svg.node()?.parentElement;
if (!parent) {
return;
}
const {width: parentWidth} = parent.getBoundingClientRect();
svg.call(
zoom.transform,
d3.zoomIdentity.translate((parentWidth - (width ?? 0) * scaleFactor) / 2, 20).scale(scaleFactor)
);
};
fitScreen();
setFitScreenFn(() => fitScreen);
setDownloadImageFn(() => {
let processing = false;
return async () => {
if (processing) {
return;
}
processing = true;
fitScreen();
const svgNode = svg.node();
if (!svgNode) {
return;
}
const originalHeight = +svg.attr('height');
svg.attr('height', (height ?? 0) + 40);
await saveSvgAsPng(svgNode, 'graph.png');
svg.attr('height', originalHeight);
processing = false;
};
});
setScaleFn(() => (n: number) => {
zoom.scaleTo(svg, scaleFactor * n);
setScaleValue(n);
});
});
}, [dagInfo]);
return {currentNode, displaySwitch, setDisplaySwitch, downloadImage, fitScreen, scale, setScale};
};
interface GraphsProps {}
const Graphs: NextI18NextPage<GraphsProps> = () => {
const {t} = useTranslation(['graphs', 'common']);
const {data: graph} = useSWR<{data: Graph}>('/graphs/graph', fetcher);
const {currentNode, downloadImage, fitScreen, scale, setScale} = useDagreD3(graph ? graph.data : undefined);
const aside = (
<section>
<SubSection>
<Button icon="download" onClick={downloadImage}>
{t('common:download-image')}
</Button>
<Button icon="revert" onClick={fitScreen}>
{t('common:restore-image')}
</Button>
</SubSection>
<SubSection>
<Field label={`${t('common:scale')}:`}>
<RangeSlider min={MIN_SCALE} max={MAX_SCALE} step={0.1} value={scale} onChange={setScale} />
</Field>
</SubSection>
<SubSection>
<Field label={`${t('common:node-info')}:`}></Field>
<NodeInfo node={currentNode}></NodeInfo>
</SubSection>
</section>
);
return (
<>
<Title>{t('common:graphs')}</Title>
<Content aside={aside}>
<GraphSvg>
<g></g>
</GraphSvg>
</Content>
</>
);
};
Graphs.getInitialProps = () => {
return {
namespacesRequired: ['graphs', 'common']
};
};
export default Graphs;
import React, {useState} from 'react';
import styled from 'styled-components';
import uniq from 'lodash/uniq';
import useSWR from 'swr';
import {withFetcher} from '~/utils/fetch';
import {rem, em} from '~/utils/style';
import {useTranslation, NextI18NextPage} from '~/utils/i18n';
import Title from '~/components/Title';
import Content from '~/components/Content';
import SearchInput from '~/components/SearchInput';
import Icon from '~/components/Icon';
import Field from '~/components/Field';
import Checkbox from '~/components/Checkbox';
import RadioGroup from '~/components/RadioGroup';
import RadioButton from '~/components/RadioButton';
import RunningToggle from '~/components/RunningToggle';
import ScatterChart from '~/components/ScatterChart';
import Select, {SelectValueType} from '~/components/Select';
import AsideDivider from '~/components/AsideDivider';
import {Dimension} from '~/types';
const dimensions = ['2d', '3d'];
const reductions = ['pca', 'tsne'];
const StyledIcon = styled(Icon)`
margin-right: ${em(4)};
vertical-align: middle;
`;
const AsideTitle = styled.div`
font-size: ${rem(16)};
line-height: ${rem(16)};
font-weight: 700;
margin-bottom: ${rem(10)};
`;
const StyledScatterChart = styled(ScatterChart)`
height: ${rem(600)};
`;
type Data = {
embedding: ([number, number] | [number, number, number])[];
labels: string[];
};
type HighDimensionalProps = {
runs: string[];
selectedRun: string;
};
const HighDimensional: NextI18NextPage<HighDimensionalProps> = ({runs, selectedRun}) => {
const {t} = useTranslation(['high-dimensional', 'common']);
const [run, setRun] = useState(selectedRun);
const [search, setSearch] = useState('');
const [dimension, setDimension] = useState(dimensions[0] as Dimension);
const [reduction, setReduction] = useState(reductions[0]);
const [running, setRunning] = useState(true);
const {data, error} = useSWR<Data>(
`/embeddings/embeddings?run=${encodeURIComponent(run)}&dimension=${Number.parseInt(
dimension
)}&reduction=${reduction}`,
{
refreshInterval: running ? 15 * 1000 : 0
}
);
const aside = (
<section>
<AsideTitle>{t('common:select-runs')}</AsideTitle>
<Select
list={runs}
value={run}
onChange={(value: SelectValueType | SelectValueType[]) => setRun(value as string)}
/>
<AsideDivider />
<Field>
<SearchInput placeholder={t('common:search')} value={search} onChange={setSearch} />
</Field>
<Field>
<Checkbox>{t('display-all-label')}</Checkbox>
</Field>
<AsideDivider />
<AsideTitle>
<StyledIcon type="dimension" />
{t('dimension')}
</AsideTitle>
<Field>
<RadioGroup value={dimension} onChange={value => setDimension(value as Dimension)}>
{dimensions.map(item => (
<RadioButton key={item} value={item}>
{t(item)}
</RadioButton>
))}
</RadioGroup>
</Field>
<AsideDivider />
<AsideTitle>
<StyledIcon type="reduction" />
{t('reduction-method')}
</AsideTitle>
<Field>
<RadioGroup value={reduction} onChange={value => setReduction(value as string)}>
{reductions.map(item => (
<RadioButton key={item} value={item}>
{t(item)}
</RadioButton>
))}
</RadioGroup>
</Field>
<RunningToggle running={running} onToggle={setRunning} />
</section>
);
return (
<>
<Title>{t('common:high-dimensional')}</Title>
<Content aside={aside}>
<StyledScatterChart
data={data?.embedding}
labels={data?.labels}
dimension={dimension}
loading={!data && !error}
/>
</Content>
</>
);
};
HighDimensional.defaultProps = {
runs: []
};
HighDimensional.getInitialProps = withFetcher(async ({query}, fetcher) => {
const runs = await fetcher('/runs').then(uniq);
return {
runs,
selectedRun: runs.includes(query.run) ? query.run : runs[0],
namespacesRequired: ['high-dimensional', 'common']
};
});
export default HighDimensional;
import Title from '~/components/Title';
import Content from '~/components/Content';
import {useTranslation} from '~/utils/i18n';
const HighDimension = () => {
const {t} = useTranslation(['highDimension', 'common']);
const aside = <section></section>;
return (
<>
<Title>{t('common:highDimension')}</Title>
<Content aside={aside}></Content>
</>
);
};
HighDimension.getInitialProps = () => {
return {
namespacesRequired: ['highDimension', 'common']
};
};
export default HighDimension;
import {useEffect} from 'react';
import {NextI18NextPage, Router} from '~/utils/i18n';
const Index: NextI18NextPage = () => {
useEffect(() => {
Router.replace('/scalars');
}, []);
return null;
};
Index.getInitialProps = () => {
return {
namespacesRequired: []
};
};
export default Index;
import React, {useState, useCallback, useMemo} from 'react';
import styled from 'styled-components';
import {rem, em} from '~/utils/style';
import {useTranslation, NextI18NextPage} from '~/utils/i18n';
import useTagFilter, {
getInitialProps as getTagFilterInitialProps,
defaultProps as defaultTagFilterProps,
Props as TagFilterProps
} from '~/hooks/useTagFilter';
import {withFetcher} from '~/utils/fetch';
import Title from '~/components/Title';
import Content from '~/components/Content';
import RunSelect from '~/components/RunSelect';
import TagFilter from '~/components/TagFilter';
import Icon from '~/components/Icon';
import Field from '~/components/Field';
import Checkbox from '~/components/Checkbox';
import RunningToggle from '~/components/RunningToggle';
import AsideDivider from '~/components/AsideDivider';
import ChartPage from '~/components/ChartPage';
import SampleChart from '~/components/SampleChart';
const StyledIcon = styled(Icon)`
font-size: ${rem(16)};
margin-left: ${em(6)};
margin-right: ${em(4)};
vertical-align: middle;
`;
const CheckboxTitle = styled.span`
font-size: ${rem(16)};
font-weight: 700;
vertical-align: text-top;
`;
const SubField = styled(Field)`
margin-left: ${rem(26)};
`;
type Item = {
run: string;
label: string;
};
type SamplesProps = TagFilterProps & {};
const Samples: NextI18NextPage<SamplesProps> = ({tags: propTags, runs: propRuns, selectedRuns: propSelectedRuns}) => {
const {t} = useTranslation(['samples', 'common']);
const {runs, tags, selectedRuns, selectedTags, onChangeRuns, onFilterTags} = useTagFilter(
'images',
propSelectedRuns,
{
runs: propRuns,
tags: propTags
}
);
const ungroupedSelectedTags = useMemo(
() =>
selectedTags.reduce((prev, {runs, ...item}) => {
Array.prototype.push.apply(
prev,
runs.map(run => ({...item, run}))
);
return prev;
}, [] as Item[]),
[selectedTags]
);
const [showImage, setShowImage] = useState(true);
// const [showAudio, setShowAudio] = useState(true);
// const [showText, setShowText] = useState(true);
const [showActualSize, setShowActualSize] = useState(false);
const [running, setRunning] = useState(true);
const aside = (
<section>
<RunSelect runs={runs} value={selectedRuns} onChange={onChangeRuns} />
<AsideDivider />
<Field>
<Checkbox value={showImage} onChange={setShowImage} disabled>
<StyledIcon type="image" />
<CheckboxTitle>{t('image')}</CheckboxTitle>
</Checkbox>
</Field>
{showImage && (
<SubField>
<Checkbox value={showActualSize} onChange={setShowActualSize}>
{t('show-actual-size')}
</Checkbox>
</SubField>
)}
{/* <AsideDivider />
<Field>
<Checkbox value={showAudio} onChange={setShowAudio}>
<StyledIcon type="audio" />
<CheckboxTitle>{t('audio')}</CheckboxTitle>
</Checkbox>
</Field>
<AsideDivider />
<Field>
<Checkbox value={showText} onChange={setShowText}>
<StyledIcon type="text" />
<CheckboxTitle>{t('text')}</CheckboxTitle>
</Checkbox>
</Field> */}
<RunningToggle running={running} onToggle={setRunning} />
</section>
);
const withChart = useCallback(
({run, label}: Item) => <SampleChart run={run} tag={label} fit={!showActualSize} running={running} />,
[showActualSize, running]
);
return (
<>
<Title>{t('common:samples')}</Title>
<Content aside={aside}>
<TagFilter tags={tags} onChange={onFilterTags} />
<ChartPage items={ungroupedSelectedTags} withChart={withChart} />
</Content>
</>
);
};
Samples.defaultProps = {
...defaultTagFilterProps
};
Samples.getInitialProps = withFetcher(async (context, fetcher) => {
return {
...(await getTagFilterInitialProps('images', context, fetcher)),
namespacesRequired: ['samples', 'common']
};
});
export default Samples;
import React, {useState, useCallback} from 'react';
import {useTranslation, NextI18NextPage} from '~/utils/i18n';
import useTagFilter, {
getInitialProps as getTagFilterInitialProps,
defaultProps as defaultTagFilterProps,
Props as TagFilterProps
} from '~/hooks/useTagFilter';
import {withFetcher} from '~/utils/fetch';
import Title from '~/components/Title';
import Content from '~/components/Content';
import RunSelect from '~/components/RunSelect';
import TagFilter from '~/components/TagFilter';
import Select, {SelectValueType} from '~/components/Select';
import Field from '~/components/Field';
import Checkbox from '~/components/Checkbox';
import SmoothingSlider from '~/components/SmoothingSlider';
import RunningToggle from '~/components/RunningToggle';
import AsideDivider from '~/components/AsideDivider';
import ChartPage from '~/components/ChartPage';
import ScalarChart, {xAxisMap, sortingMethodMap} from '~/components/ScalarChart';
import {Tag} from '~/types';
type XAxis = keyof typeof xAxisMap;
const xAxisValues = ['step', 'relative', 'wall'];
type TooltiopSorting = keyof typeof sortingMethodMap;
const toolTipSortingValues = ['default', 'descending', 'ascending', 'nearest'];
type ScalarsProps = TagFilterProps & {};
const Scalars: NextI18NextPage<ScalarsProps> = ({tags: propTags, runs: propRuns, selectedRuns: propSelectedRuns}) => {
const {t} = useTranslation(['scalars', 'common']);
const {runs, tags, selectedRuns, selectedTags, onChangeRuns, onFilterTags} = useTagFilter(
'scalars',
propSelectedRuns,
{
runs: propRuns,
tags: propTags
}
);
const [smoothing, setSmoothing] = useState(0.6);
const [xAxis, setXAxis] = useState(xAxisValues[0] as XAxis);
const onChangeXAxis = (value: SelectValueType | SelectValueType[]) => setXAxis(value as XAxis);
const [tooltipSorting, setTooltipSorting] = useState(toolTipSortingValues[0] as TooltiopSorting);
const onChangeTooltipSorting = (value: SelectValueType | SelectValueType[]) =>
setTooltipSorting(value as TooltiopSorting);
const [ignoreOutliers, setIgnoreOutliers] = useState(false);
const [running, setRunning] = useState(true);
const aside = (
<section>
<RunSelect runs={runs} value={selectedRuns} onChange={onChangeRuns} />
<AsideDivider />
<SmoothingSlider value={smoothing} onChange={setSmoothing} />
<Field label={t('x-axis')}>
<Select
list={xAxisValues.map(value => ({label: t(`x-axis-value.${value}`), value}))}
value={xAxis}
onChange={onChangeXAxis}
></Select>
</Field>
<Field label={t('tooltip-sorting')}>
<Select
list={toolTipSortingValues.map(value => ({label: t(`tooltip-sorting-value.${value}`), value}))}
value={tooltipSorting}
onChange={onChangeTooltipSorting}
/>
</Field>
<Field>
<Checkbox value={ignoreOutliers} onChange={setIgnoreOutliers}>
{t('ignore-outliers')}
</Checkbox>
</Field>
<RunningToggle running={running} onToggle={setRunning} />
</section>
);
const withChart = useCallback(
(item: Tag) => (
<ScalarChart
runs={item.runs}
tag={item.label}
smoothing={smoothing}
xAxis={xAxis}
sortingMethod={tooltipSorting}
outlier={ignoreOutliers}
running={running}
/>
),
[smoothing, xAxis, tooltipSorting, ignoreOutliers, running]
);
return (
<>
<Title>{t('common:scalars')}</Title>
<Content aside={aside}>
<TagFilter tags={tags} onChange={onFilterTags} />
<ChartPage items={selectedTags} withChart={withChart} />
</Content>
</>
);
};
Scalars.defaultProps = {
...defaultTagFilterProps
};
Scalars.getInitialProps = withFetcher(async (context, fetcher) => {
return {
...(await getTagFilterInitialProps('scalars', context, fetcher)),
namespacesRequired: ['scalars', 'common']
};
});
export default Scalars;
module.exports = {
arrowParens: 'avoid',
bracketSpacing: false,
endOfLine: 'lf',
printWidth: 120,
semi: true,
singleQuote: true,
tabWidth: 4,
trailingComma: 'none',
useTabs: false,
quoteProps: 'as-needed',
jsxSingleQuote: false,
jsxBracketSameLine: false
};
<svg height="31" viewBox="0 0 97 31" width="97" xmlns="http://www.w3.org/2000/svg"><g fill="#fff" fill-rule="evenodd" transform="translate(0 .0625)"><path d="m2.446115.0742695c-1.32588958 0-2.40434375 1.0740707-2.40434375 2.39411403s1.07845417 2.39382156 2.40434375 2.39382156 2.40434375-1.07377823 2.40434375-2.39382156-1.07845417-2.39411403-2.40434375-2.39411403" transform="translate(23.010417 .023203)"/><path d="m.23204292 23.3006269h3.46595625c.06922708 0 .13199166-.0401668.16068125-.1029517l10.45446458-22.89241762c.0531687-.1163081-.0322146-.24831243-.1605833-.24831243h-3.4659563c-.0691292 0-.1318937.04026424-.1605833.10295168l-10.45456252 22.89241757c-.05307083.1163081.0323125.2483125.16058334.2483125" transform="translate(24.0875 6.652667)"/><path d="m2.48757292.0742695c-1.32588959 0-2.40434375 1.0740707-2.40434375 2.39411403s1.07845416 2.39382156 2.40434375 2.39382156c1.32588958 0 2.40434375-1.07377823 2.40434375-2.39382156s-1.07845417-2.39411403-2.40434375-2.39411403" transform="translate(43.866667 .023203)"/><path d="m17.4206283.05694515h-3.4659562c-.0691292 0-.1318938.04026424-.1605834.10304917l-4.08253745 8.93954011h-8.13765833c-.1075125 0-.2050375.06278493-.24900209.16047204l-1.31139791 2.91052983c-.04513959.1002219.02849375.2135077.13884583.2135077h8.05922708l-4.87203958 10.6682704c-.05307083.1163081.0323125.2483125.16058333.2483125h3.46595625c.06922709 0 .13199167-.0401668.16058334-.1029517l10.45456253-22.89241762c.0531687-.1163081-.0322146-.24831243-.1605834-.24831243" transform="translate(0 6.652667)"/><path d="m88.2453102 16.6856012h-2.3656667c-.057575 0-.1042812.0503059-.1042812.1123109v.4521685c0 .0620049-.1053583.1121159-.1629333.1121159h-8.1528355c-.057575 0-.1042812.0504034-.1042812.1125059v2.0085327c0 .062005.0467062.1123109.1042812.1123109h8.1528355c.057575 0 .1629333.0502085.1629333.1123109v6.5331421c0 .0619075.0467062.1123109.1042812.1123109h2.3656667c.057575 0 .1040854-.0504034.1040854-.1123109v-6.6217624c0-.0621025.0468042-.1125059.1043792-.1125059h8.2350854c.057575 0 .1041833-.050111.1041833-.1121159v-1.9199124c0-.0621025-.0466083-.1125059-.1041833-.1125059h-8.2350854c-.057575 0-.1043792-.050111-.1043792-.1121159v-.4521685c0-.062005-.0465104-.1123109-.1040854-.1123109"/><path d="m96.684219 26.1518075c-3.9578896-.1114765-6.2973146-2.7413265-7.5708188-5.4024715-.0359354-.0748739.0162542-.1641767.0944896-.1641767h2.5724667c.0362291 0 .0694229.0209608.0878312.0544981 1.0067792 1.8302196 2.4509521 2.9112122 4.8307188 3.1399288.0532666.0050696.0941958.0526457.0941958.1102636l-.0000979 2.1481414c0 .0633698-.0497417.1155281-.1087854.1138163"/><path d="m77.4642446 26.1518075c3.9577916-.1114765 6.2973146-2.7413265 7.5708187-5.4024715.0359355-.0748739-.0162541-.1641767-.0944896-.1641767h-2.5724666c-.0362292 0-.0694229.0209608-.0878313.0544981-1.0067791 1.8302196-2.4509521 2.9112122-4.8308166 3.1399288-.0531688.0050696-.094098.0526457-.094098.1102636v2.1481414c0 .0633698.0497417.1155281.1088834.1138163"/><path d="m82.2474346 11.0463936.0828375.0187185-.0570854.0674645c-.8224021.9556178-2.8349813 2.2483634-4.7713813 2.6626074-.0483708.0104316-.0827396.055278-.0827396.1085087v2.2131687c0 .0722416.0621771.1255698.1275854.1094836.6848292-.1683689 3.0546084-.8443792 4.860975-2.3903118l.0785292-.0670746v2.375493c0 .062005.0466083.1122135.1041833.1122135h2.1235188c.057575 0 .1042813-.0502085.1042813-.1122135v-10.0640142c0-.0619075-.0467063-.11231092-.1042813-.11231092h-2.1235188c-.057575 0-.1041833.05040342-.1041833.11231092v2.62409795l-.0613937-.01842601c-.9334396-.28009486-2.0094459-1.10546317-2.8149084-2.72188255-.0179187-.0358771-.0526791-.05908022-.090475-.05908022h-2.299475c-.0741229 0-.1263125.07994354-.0976229.15355009.6211833 1.5938987 2.3375646 4.37115674 5.1251542 4.98769694"/><path d="m66.6262894 10.9951713h-1.2381563c-.0401458 0-.0768646.0233981-.0953708.0606401l-1.1418063 2.3095883c-.0370125.0747765.0148834.1638843.0953709.1638843h2.3630229c4.9453792 0 6.1433896-2.7184704 7.2068625-5.14543923.5133771-1.17175781.8783125-2.03846278.9769146-2.33006171.0247729-.0731191-.0274167-.14867549-.1016375-.14867549h-2.4150167c-.0422021 0-.0803896.02573792-.0978187.06580718l-.8186813 1.87340862c-.9938542 2.18587083-1.8460229 3.15084793-4.7336833 3.15084793"/><path d="m73.1139344 21.4007394h.9736833c.0593375 0 .1074146-.0503059.1074146-.1122134v-2.2473884c0-.0621025-.0480771-.112311-.1074146-.112311h-.7099937c-4.6595605-.1208902-6.7445-3.6464978-6.9835146-4.1677882-.0179188-.0389968-.0545396-.0617125-.0957625-.0617125h-2.5366292c-.0804875 0-.1279771.0864755-.0954687.1634943.7714854 1.8228102 3.1349 6.2135629 9.4476854 6.5379192"/><path d="m92.0818419 12.0709188c-1.1624667-.5661367-2.2028313-1.8381164-2.4761167-2.17787649-.0329979-.04094669-.0879292-.04923352-.130425-.02027836-.6883542.46776725-1.4961667.88191375-1.7924625 1.02922435-.0601208.0297351-.0785292.1133833-.0389708.1705137 1.0811958 1.5644561 2.0699583 2.1849934 2.2465021 2.2879451.0188.0108216.0390687.0144289.059925.0118941l1.8079333-.223452c.0393625-.0048746.0726542-.0332448.0860687-.0732166l.2924771-.8662175c.0185063-.0549855-.0054833-.1144557-.0549312-.1385363"/><path d="m10.5225265 1.01053509h-5.78139171l.04690209-.07984605c.13884583-.23661338.2637875-.47927127.37296458-.72436646.03329166-.07458148-.01919167-.16105699-.09586042-.16105699h-2.29722291c-.03857917 0-.07333959.0234956-.09096459.06044512-.46148125.96614693-1.14650625 1.67530462-2.52781666 2.21346113-.04102709.01598871-.06961876.05791032-.06961876.10480403v2.09003611c0 .07477646.06854167.12937205.13522292.10850873 1.53699792-.47975873 2.33100417-1.19232865 2.496875-1.32950006.01850625-.01520877.0405375-.02330062.06364584-.02330062h5.36661666c.11417083.00526457.19769375.04182412.25017708.10928867.05385417.06902442.07314376.16719899.05796667.29159894-1.57342291 4.06103433-6.41452083 4.47869058-8.27307708 4.56623851-.05591042.00263228-.09742709.05176831-.09742709.11201844v1.98571951c0 .0633699.04974167.1146508.10868751.1131256 9.2807375-.2467873 10.92231037-5.87871216 10.92231037-8.39449637v-.5753985c0-.24616761-.1243541-.46727974-.5879895-.46727974" transform="translate(85.775 5.677746)"/><path d="m59.1702779 23.0532504c-.2743625-.4648425.0102813-1.2022729.3589625-1.9300516l6.715125-14.4215221c.1452104-.29871586.2348042-.66382386-.4236854-.66382386h-10.1527833c-.0591417 0-.1072188.05020845-.1072188.11221343v2.22584264c0 .06210248.0480771.11231092.1072188.11231092h6.2318083c.0588479.00175486.2004354.01676865.2765167.12050027.0483708.06590467.0609041.15247767.0371104.25747669l-.0036229.01082163-5.8071438 12.74602248c-.5315896 1.2901133-.5565583 2.4795172-.069325 3.2543846.4908563.7800344 1.4662042 1.1756575 2.8992146 1.1756575h14.8945937c.0592396 0 .1074146-.050306.1074146-.1124085v-2.2947695c0-.0621025-.048175-.112311-.1074146-.112311h-13.627552c-.7035313 0-1.1384771-.1572547-1.3292188-.4803436"/><path d="m29.3354319 12.1665001c-.3381063-2.99856519-2.8049209-5.35027016-5.8800917-5.45507419-.0279062-.00107241-.0550292.00302226-.0813687.00887179-.0140021-.0049721-.0284938-.00887179-.0441605-.00887179h-2.1002145c-.0522875 0-.0995813.03032005-.121123.07779872l-1.2130895 2.67576877c-.0396563.08754793.0247729.18679491.1211229.18679491h2.1414375c.4538437-.00653197.7861729.02330061 1.1568854.08062598 1.7253896.26693343 2.7979687 1.52672661 2.7732937 3.19686421-.0235 1.5783974-1.3395979 2.8354608-2.9250645 2.8354608h-7.669225c-.1306209 0-.2491.0760439-.3029542.1943018l-1.2729167 2.7896396c-.0615896.1347341.0376.2880892.1863354.2880892h8.9637813c3.7159375 0 6.6818333-3.1934519 6.2673521-6.8702698"/><path d="m50.1567746 12.1665001c-.3381063-2.99856519-2.8049209-5.35027016-5.8801896-5.45507419-.0279063-.00107241-.0549313.00302226-.0813688.00887179-.0139041-.0049721-.0283958-.00887179-.0440625-.00887179h-2.1003125c-.0521895 0-.0995812.03032005-.1211229.07779872l-1.2130896 2.67576877c-.0395583.08754793.024675.18679491.1212209.18679491h2.1413396c.4539416-.00653197.7862708.02330061 1.1569833.08062598 1.7252917.26693343 2.7978708 1.52672661 2.7731958 3.19686421-.0235 1.5783974-1.3395979 2.8354608-2.9250646 2.8354608h-7.669127c-.1306209 0-.2491.0760439-.3030521.1943018l-1.2729167 2.7896396c-.0614916.1347341.0376979.2880892.1863354.2880892h8.9638792c3.7158396 0 6.6817354-3.1934519 6.2673521-6.8702698"/></g></svg>
\ No newline at end of file
{
"scalars": "Scalars",
"samples": "Samples",
"graphs": "Graphs",
"high-dimensional": "High Dimensional",
"search": "Search",
"searchTagPlaceholder": "Search tags in RegExp",
"all": "ALL",
"empty": "Empty",
"select": "Please Select",
"runs": "Runs",
"select-runs": "Select Runs",
"scale": "Scale",
"download-image": "Download Image",
"restore-image": "Restore Image",
"node-info": "Node Info",
"running": "Running",
"stopped": "Stopped",
"loading": "Loading"
}
{
"error-with-status": "A {{statusCode}} error occurred on server",
"error-without-status": "An error occurred on the server"
}
{
"node-type": "Node Type",
"node-name": "Node Name",
"node-data-shape": "Shape",
"input": "Input",
"output": "Output",
"op-type": "Operator Type",
"node-data-type": "Data Type",
"click-node": "Click a node to display"
}
{
"display-all-label": "Display All Labels",
"dimension": "Dimension",
"2d": "2D",
"3d": "3D",
"reduction-method": "Reduction Method",
"pca": "PCA",
"tsne": "T-SNE"
}
{
"image": "Image",
"audio": "Audio",
"text": "Text",
"show-actual-size": "Show Actual Image Size",
"step": "Step"
}
{
"smoothing": "Smoothing",
"x-axis": "X-Axis",
"x-axis-value": {
"step": "Step",
"relative": "Relative",
"wall": "Wall Time"
},
"tooltip-sorting": "Tooltip Sorting",
"tooltip-sorting-value": {
"default": "Default",
"descending": "Descending",
"ascending": "Ascending",
"nearest": "Nearest"
},
"ignore-outliers": "Ignore outliers in chart scaling"
}
{
"scalars": "标量数据",
"samples": "样本数据",
"graphs": "网络结构",
"high-dimensional": "高维数据映射",
"search": "搜索",
"searchTagPlaceholder": "搜索标签(支持正则)",
"all": "全部",
"empty": "空空如也",
"select": "请选择",
"runs": "数据流",
"select-runs": "选择数据流",
"running": "运行中",
"stopped": "已停止",
"loading": "载入中"
}
{
"error-with-status": "服务器发生了一个 {{statusCode}} 错误",
"error-without-status": "服务器发生了一个错误"
}
{
"display-all-label": "展示所有标签",
"dimension": "维度",
"2d": "二维",
"3d": "三维",
"reduction-method": "降维方法",
"pca": "PCA",
"tsne": "T-SNE"
}
{
"image": "图片",
"audio": "音频",
"text": "文本",
"show-actual-size": "按真实大小展示",
"step": "步"
}
{
"smoothing": "平滑度",
"x-axis": "X轴",
"x-axis-value": {
"step": "步",
"relative": "相对值",
"wall": "时间"
},
"tooltip-sorting": "标签排序方法",
"tooltip-sorting-value": {
"default": "默认",
"descending": "降序",
"ascending": "升序",
"nearest": "最近"
},
"ignore-outliers": "图表缩放时忽略极端值",
"mode": "模式",
"mode-value": {
"overlay": "概览",
"offset": "偏移"
}
}
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Generated by IcoMoon</metadata>
<defs>
<font id="vdl-icon" horiz-adv-x="1024">
<font-face units-per-em="1024" ascent="960" descent="-64" />
<missing-glyph horiz-adv-x="1024" />
<glyph unicode="&#x20;" horiz-adv-x="512" d="" />
<glyph unicode="&#xe900;" glyph-name="reduction" d="M34.133 960v0c20.48 0 34.133-13.653 34.133-34.133v-955.733c0-20.48-13.653-34.133-34.133-34.133v0c-20.48 0-34.133 13.653-34.133 34.133v955.733c0 20.48 13.653 34.133 34.133 34.133zM1024-29.867v0c0-20.48-13.653-34.133-34.133-34.133h-955.733c-20.48 0-34.133 13.653-34.133 34.133v0c0 20.48 13.653 34.133 34.133 34.133h955.733c20.48 0 34.133-13.653 34.133-34.133zM839.68 202.24c-13.653 0-20.48 6.827-27.307 13.653l-279.893 477.867h-273.067c-20.48 0-34.133 13.653-34.133 34.133s13.653 34.133 34.133 34.133h286.72c13.653 0 20.48-6.827 27.307-13.653l293.547-498.347c6.827-13.653 6.827-34.133-13.653-47.787 0 0-6.827 0-13.653 0zM887.467 407.040v0c20.48-6.827 27.307-20.48 27.307-40.96l-34.133-129.707c-6.827-20.48-20.48-27.307-40.96-27.307v0c-20.48 6.827-27.307 20.48-27.307 40.96l34.133 129.707c0 20.48 20.48 34.133 40.96 27.307zM662.187 270.507v0c0-20.48 6.827-34.133 27.307-40.96l136.533-20.48c20.48 0 34.133 6.827 40.96 27.307v0c0 20.48-6.827 34.133-27.307 40.96l-136.533 20.48c-20.48 0-34.133-6.827-40.96-27.307z" />
<glyph unicode="&#xe901;" glyph-name="dimension" d="M34.133 960v0c20.48 0 34.133-13.653 34.133-34.133v-955.733c0-20.48-13.653-34.133-34.133-34.133v0c-20.48 0-34.133 13.653-34.133 34.133v955.733c0 20.48 13.653 34.133 34.133 34.133zM1024-29.867v0c0-20.48-13.653-34.133-34.133-34.133h-955.733c-20.48 0-34.133 13.653-34.133 34.133v0c0 20.48 13.653 34.133 34.133 34.133h955.733c20.48 0 34.133-13.653 34.133-34.133zM204.8 311.467c-6.827 0-13.653 0-20.48 6.827-13.653 13.653-20.48 34.133-6.827 47.787l225.28 273.067c6.827 6.827 20.48 13.653 27.307 13.653s20.48-6.827 27.307-13.653l204.8-238.933 197.973 238.933c13.653 13.653 34.133 13.653 47.787 6.827 13.653-13.653 13.653-34.133 6.827-47.787l-225.28-273.067c-6.827-6.827-13.653-13.653-27.307-13.653-6.827 0-20.48 6.827-27.307 13.653l-204.8 238.933-197.973-238.933c-6.827-6.827-20.48-13.653-27.307-13.653z" />
<glyph unicode="&#xe902;" glyph-name="revert" horiz-adv-x="887" d="M859.087 483.656c-11.921 4.52-25.325 2.275-35.162-5.888s-14.614-21.005-12.53-33.687c3.17-19.030 4.776-39.808 4.776-60.289 0.28-99.752-38.983-195.47-109.037-265.816-69.71-70.718-164.555-110.329-263.379-109.996-98.83-0.282-193.666 39.356-263.379 110.081-70.054 70.38-109.316 166.125-109.037 265.902 0 100.396 38.712 194.903 109.037 265.902 69.719 70.71 164.555 110.332 263.379 110.039 4.142 0 8.326-0.085 12.467-0.213l-81.017-81.708c-6.702-6.741-10.47-15.899-10.47-25.451s3.767-18.71 10.47-25.451c13.947-14.080 36.557-14.080 50.419 0l134.521 135.809c6.702 6.741 10.47 15.899 10.47 25.451s-3.767 18.71-10.47 25.451l-134.563 135.639c-6.677 6.767-15.749 10.57-25.209 10.57s-18.532-3.804-25.209-10.57c-6.702-6.741-10.47-15.899-10.47-25.451s3.767-18.71 10.47-25.451l66.056-66.518c-116.785-0.569-228.611-47.731-311.093-131.201-83.413-83.924-130.245-197.956-130.126-316.846-0.16-118.839 46.611-232.841 129.957-316.761 83.145-84.139 196.075-131.356 313.798-131.202 59.928 0 117.954 11.819 172.726 35.201 52.73 22.409 100.632 54.973 141.029 95.873 40.497 40.79 72.788 89.111 95.090 142.295 23.202 55.211 34.866 113.921 34.866 174.423 0 24.662-1.986 48.982-5.747 72.107-2.084 12.64-10.711 23.237-22.632 27.756z" />
<glyph unicode="&#xe903;" glyph-name="download" d="M987.004 9.948h-950.089c-20.388 0-36.915-16.54-36.915-36.992 0-20.419 16.558-36.956 36.915-36.956h950.16c20.399 0 36.924 16.537 36.924 36.956 0 20.452-16.525 36.992-36.924 36.992h-0.072zM511.231 77.702c10.54 0 20.026 4.306 26.85 11.32l385.738 386.248c6.898 6.864 11.244 16.364 11.268 26.841 0 20.927-17.071 37.877-37.856 37.877-10.513 0.030-19.961-4.276-26.784-11.143l-321.387-321.794v714.965c0 21.005-16.931 37.984-37.787 37.984-20.913 0-37.838-16.977-37.838-37.91l0.036-715.001-321.351 321.794c-6.827 6.864-16.343 11.131-26.781 11.102-20.904 0.030-37.829-16.947-37.903-37.802 0-10.519 4.301-20.090 11.2-26.883l385.672-386.314c6.892-6.942 16.379-11.284 26.925-11.284z" />
<glyph unicode="&#xe904;" glyph-name="text" d="M320 704h384v-64h-384v64zM256 192h512v-64h-512v64zM256 768h64v-192h-64v192zM704 768h64v-192h-64v192zM480 672h64v-384h-64v384zM960-64h-896c-38.4 0-64 25.6-64 64v896c0 38.4 25.6 64 64 64h896c38.4 0 64-25.6 64-64v-896c0-38.4-25.6-64-64-64zM64 896v-896h896v896h-896zM64 928v-32c0 0 0 0 0 0v32z" />
<glyph unicode="&#xe905;" glyph-name="audio" d="M276.105 608.971c-10.665 0-20.892-4.496-28.433-12.498s-11.777-18.855-11.777-30.172v-337.314c0-23.584 18.017-42.703 40.242-42.703s40.242 19.119 40.242 42.703v337.247c0.017 11.34-4.221 22.22-11.777 30.238s-17.81 12.515-28.496 12.498zM512 960c-10.665 0-20.892-4.496-28.433-12.498s-11.777-18.855-11.777-30.172v-938.661c0-23.566 18.003-42.669 40.211-42.669s40.211 19.104 40.211 42.669v938.661c0 11.317-4.236 22.17-11.777 30.172s-17.769 12.498-28.433 12.498zM983.789 518.994c-10.686 0.018-20.939-4.479-28.496-12.498s-11.794-18.899-11.777-30.238v-184.724c0-23.584 18.017-42.703 40.242-42.703s40.242 19.119 40.242 42.703v184.79c0.017 11.328-4.213 22.198-11.755 30.215s-17.78 12.521-28.455 12.521v-0.066zM40.211 518.994c-10.675 0-20.913-4.505-28.455-12.521s-11.772-18.887-11.755-30.215v-184.724c0-23.584 18.017-42.703 40.242-42.703s40.242 19.119 40.242 42.703v184.79c0.017 11.34-4.221 22.22-11.777 30.238s-17.81 12.515-28.496 12.498v-0.066zM747.895 790.184c-10.686 0.018-20.939-4.479-28.496-12.498s-11.794-18.899-11.777-30.238v-643.619c0-23.602 18.031-42.736 40.273-42.736s40.273 19.133 40.273 42.736v643.619c0.017 11.34-4.221 22.22-11.777 30.238s-17.81 12.515-28.496 12.498z" />
<glyph unicode="&#xe906;" glyph-name="scalar" d="M928-64h-832c-51.2 0-96 44.8-96 96v832c0 51.2 44.8 96 96 96h832c51.2 0 96-44.8 96-96v-832c0-51.2-44.8-96-96-96zM96 896c-19.2 0-32-12.8-32-32v-832c0-19.2 12.8-32 32-32h832c19.2 0 32 12.8 32 32v832c0 19.2-12.8 32-32 32h-832zM192 288c-6.4 0-12.8 0-19.2 6.4-12.8 12.8-12.8 32-6.4 44.8l211.2 256c6.4 6.4 19.2 12.8 25.6 12.8s19.2-6.4 25.6-12.8l192-224 185.6 224c12.8 12.8 32 12.8 44.8 6.4 12.8-12.8 12.8-32 6.4-44.8l-211.2-256c-6.4-6.4-12.8-12.8-25.6-12.8-6.4 0-19.2 6.4-25.6 12.8l-192 224-185.6-224c-6.4-6.4-19.2-12.8-25.6-12.8z" />
<glyph unicode="&#xe907;" glyph-name="histogram" d="M25.6 57.6h966.4c12.8 0 25.6-12.8 25.6-32s-12.8-32-25.6-32h-966.4c-12.8 0-25.6 12.8-25.6 32s12.8 32 25.6 32zM160 198.4c-51.2 0-96 44.8-96 96v211.2c0 51.2 44.8 96 96 96s96-44.8 96-96v-211.2c0-57.6-44.8-96-96-96zM160 537.6c-19.2 0-32-19.2-32-32v-211.2c0-19.2 12.8-32 32-32s32 12.8 32 32v211.2c0 12.8-12.8 32-32 32zM864 198.4c-51.2 0-96 44.8-96 96v409.6c0 51.2 44.8 96 96 96s96-44.8 96-96v-409.6c0-57.6-44.8-96-96-96zM864 736c-19.2 0-32-12.8-32-32v-409.6c0-19.2 12.8-32 32-32s32 12.8 32 32v409.6c0 19.2-12.8 32-32 32zM512 198.4c-51.2 0-96 44.8-96 96v544c0 51.2 44.8 96 96 96s96-44.8 96-96v-544c0-57.6-44.8-96-96-96zM512 870.4c-19.2 0-32-12.8-32-32v-544c0-19.2 12.8-32 32-32s32 12.8 32 32v544c0 19.2-12.8 32-32 32z" />
<glyph unicode="&#xe908;" glyph-name="search" d="M969.387-57.173l-177.493 177.493c-88.747-75.093-197.973-116.053-314.027-116.053-266.24 0-477.867 211.627-477.867 477.867s211.627 477.867 477.867 477.867c266.24 0 477.867-211.627 477.867-477.867 0-116.053-40.96-225.28-116.053-314.027l177.493-177.493-47.787-47.787zM477.867 891.733c-225.28 0-409.6-184.32-409.6-409.6s184.32-409.6 409.6-409.6c95.573 0 191.147 34.133 266.24 102.4l40.96 40.96c68.267 75.093 102.4 170.667 102.4 266.24 0 225.28-184.32 409.6-409.6 409.6z" />
<glyph unicode="&#xe909;" glyph-name="image" horiz-adv-x="1092" d="M989.867-64h-887.467c-54.613 0-102.4 47.787-102.4 102.4v819.2c0 54.613 47.787 102.4 102.4 102.4h887.467c54.613 0 102.4-47.787 102.4-102.4v-819.2c0-54.613-47.787-102.4-102.4-102.4zM102.4 891.733c-20.48 0-34.133-13.653-34.133-34.133v-819.2c0-20.48 13.653-34.133 34.133-34.133h887.467c20.48 0 34.133 13.653 34.133 34.133v819.2c0 20.48-13.653 34.133-34.133 34.133h-887.467zM785.067 516.267c-75.093 0-136.533 61.44-136.533 136.533s61.44 136.533 136.533 136.533 136.533-61.44 136.533-136.533-61.44-136.533-136.533-136.533zM785.067 721.067c-40.96 0-68.267-27.307-68.267-68.267s27.307-68.267 68.267-68.267 68.267 27.307 68.267 68.267-27.307 68.267-68.267 68.267zM1003.52-43.52l-273.067 341.333-191.147-197.973-204.8 314.027-238.933-436.907-61.44 34.133 293.547 532.48 225.28-334.507 177.493 197.973 327.68-409.6z" />
<glyph unicode="&#xe90a;" glyph-name="chevron-down" d="M512.001 294.4l-438.858 460.8-73.143-76.8 512-537.6 512 537.6-73.143 76.8z" />
<glyph unicode="&#xe90b;" glyph-name="check-mark" horiz-adv-x="1408" d="M571.176-25.367l-475.176 475.176 118.794 118.794 356.337-356.337 712.809 712.718 118.794-118.794z" />
</font></defs></svg>
@font-face {
font-family: 'vdl-icon';
src: url('/style/fonts/vdl-icon.ttf?5sp5gl') format('truetype'),
url('/style/fonts/vdl-icon.woff?5sp5gl') format('woff'),
url('/style/fonts/vdl-icon.svg?5sp5gl#vdl-icon') format('svg');
font-weight: normal;
font-style: normal;
font-display: block;
}
.vdl-icon {
/* use !important to prevent issues with browser extensions that change fonts */
font-family: 'vdl-icon' !important;
speak: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
/* Better Font Rendering =========== */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-chevron-down:before {
content: '\e90a';
}
.icon-reduction:before {
content: '\e900';
}
.icon-dimension:before {
content: '\e901';
}
.icon-revert:before {
content: '\e902';
}
.icon-download:before {
content: '\e903';
}
.icon-text:before {
content: '\e904';
}
.icon-audio:before {
content: '\e905';
}
.icon-scalar:before {
content: '\e906';
}
.icon-histogram:before {
content: '\e907';
}
.icon-search:before {
content: '\e908';
}
.icon-image:before {
content: '\e909';
}
.icon-check-mark:before {
content: '\e90b';
}
import {Graph, Node, NodeUID, InputNode, NodeType} from './types';
import {OpNodeStyle, OutputNodeStyle, InputNodeStyle} from './style';
interface DagNode {
key: string;
type: NodeType;
label: string;
shape: string;
class: string;
style: string;
}
type DagEdge = [string, string];
interface NodeRelation {
input: NodeUID[];
output: NodeUID[];
}
interface NodeRelationMapping {
[nodeUID: string]: NodeRelation;
}
type WithUID<T> = T & {uid: NodeUID};
type WithUIDMap<T> = T extends (infer U)[] ? WithUID<U>[] : WithUID<T>;
type NodeFinder = (type: NodeType, uid: NodeUID) => undefined | Node;
const OP_NODE_PREFIX = 'opNode_';
/* misc */
const genNodeUID = (type: NodeType, id: number | string) => {
switch (type) {
case NodeType.Op:
return `${OP_NODE_PREFIX}${id}`;
case NodeType.Input:
case NodeType.Output:
return `${id}`;
}
};
const assignNodeUID = <T extends Node>(type: NodeType, node: T[]): WithUID<T>[] => {
const process = (node: T, i: number) => {
const uid = genNodeUID(type, i);
return {...node, uid};
};
return node.map(process);
};
const createNodeFinder = (graph?: Graph) => {
if (!graph) {
return () => undefined;
}
const reverseInputIdx = graph.input.reduce<{[k: string]: number}>((memo, input, i) => {
memo[genNodeUID(NodeType.Input, input.name)] = i;
return memo;
}, {});
const reverseOutputIdx = graph.output.reduce<{[k: string]: number}>((memo, input, i) => {
memo[genNodeUID(NodeType.Output, input.name)] = i;
return memo;
}, {});
return (type: NodeType, nodeUID: NodeUID) => {
switch (type) {
case NodeType.Input: {
const idx = reverseInputIdx[nodeUID];
return idx == undefined ? undefined : graph.input[idx];
}
case NodeType.Output: {
const idx = reverseOutputIdx[nodeUID];
return idx == undefined ? undefined : graph.output[idx];
}
case NodeType.Op: {
const idx = +nodeUID.replace(OP_NODE_PREFIX, '');
return graph.node[idx];
}
}
};
};
const relationPush = (
nodeRelationMapping: NodeRelationMapping,
nodeUID: NodeUID,
key: keyof NodeRelation,
value: NodeUID
) => {
const leaf = nodeRelationMapping[nodeUID] || {input: [], output: []};
leaf[key].push(value);
nodeRelationMapping[nodeUID] = leaf;
};
const traverseRelation = (
nodeMapping: NodeRelationMapping,
process: (bridge: NodeUID, inputTo: NodeUID, outputTo: NodeUID) => void
) => {
for (const [nodeUID, relations] of Object.entries(nodeMapping)) {
const {input, output} = relations;
input.forEach(inputTo => {
output.forEach(outputTo => {
process(nodeUID, inputTo, outputTo);
});
});
}
};
const buildNodeRelationMapping = (nodeList: WithUIDMap<Graph['node']>) => {
return nodeList.reduce<NodeRelationMapping>((memo, node) => {
const uid = node.uid;
// reverse
(node.output || []).forEach(v => relationPush(memo, v, 'input', uid));
(node.input || []).forEach(v => relationPush(memo, v, 'output', uid));
return memo;
}, {});
};
const expandRelations = (nodeMapping: NodeRelationMapping) => {
const briefLayer: {nodes: DagNode[]; edges: DagEdge[]} = {nodes: [], edges: []};
// a tmp node the middle man between input & output
const detailLayer: {nodes: DagNode[]; edges: DagEdge[]} = {nodes: [], edges: []};
traverseRelation(nodeMapping, (bridge, inputTo, outputTo) => {
detailLayer.nodes.push({
key: bridge,
label: bridge,
shape: 'diamond',
class: 'output',
type: NodeType.Output,
style: OutputNodeStyle
});
detailLayer.edges.push([inputTo, bridge]);
detailLayer.edges.push([bridge, outputTo]);
briefLayer.edges.push([inputTo, outputTo]);
});
return {
briefLayer,
detailLayer
};
};
const extractInputLayer = (nodeRelationMapping: NodeRelationMapping, findNode: NodeFinder) => {
const nodes: DagNode[] = [];
const edges: DagEdge[] = [];
for (const [nodeUID, relations] of Object.entries(nodeRelationMapping)) {
if (relations.input.length !== 0) {
continue;
}
const sepIdx = nodeUID.indexOf('@');
const inputNodeUID = sepIdx > 0 ? nodeUID.slice(0, sepIdx) : nodeUID;
const inputNode = findNode(NodeType.Input, inputNodeUID) as InputNode;
nodes.push({
key: inputNodeUID,
type: NodeType.Input,
label: `
id: ${inputNode.name}
type: ${inputNode.data_type}
dims: ${inputNode.shape.join(' × ')}
`,
shape: 'rect',
class: 'input',
style: InputNodeStyle
});
relations.output.forEach(o => edges.push([inputNodeUID, o]));
}
return {nodes, edges};
};
const extractOutputLayer = (nodeRelationMapping: NodeRelationMapping) => {
const nodes: DagNode[] = [];
const edges: DagEdge[] = [];
for (const [nodeUID, relations] of Object.entries(nodeRelationMapping)) {
if (relations.output.length !== 0) {
continue;
}
nodes.push({
key: nodeUID,
type: NodeType.Output,
label: nodeUID,
shape: 'diamond',
class: 'output',
style: OutputNodeStyle
});
for (const inputNode of relations.input) {
edges.push([nodeUID, inputNode]);
}
}
return {
nodes,
edges
};
};
export const collectDagFacts = (graph?: Graph) => {
const findNode = createNodeFinder(graph);
const nodeList = assignNodeUID(NodeType.Op, graph ? graph.node : []);
const nodeRelationMapping = buildNodeRelationMapping(nodeList);
const inputLayer = extractInputLayer(nodeRelationMapping, findNode);
const outputLayer = extractOutputLayer(nodeRelationMapping);
const backboneNodes = nodeList.map(n => ({
key: n.uid,
type: NodeType.Op,
label: n.opType,
shape: 'rect',
class: 'operator',
style: OpNodeStyle
}));
const {briefLayer: bl, detailLayer: dl} = expandRelations(nodeRelationMapping);
const briefLayer = {nodes: backboneNodes, edges: bl.edges};
const detailLayer = {nodes: briefLayer.nodes.concat(dl.nodes), edges: dl.edges};
return {
briefLayer,
detailLayer,
inputLayer,
outputLayer,
findNode
};
};
export * from './types';
export * from './collectDagFacts';
export const OpNodeStyle = `
stroke-width: 3px;
opacity: 0.1;
rx: 10;
ry: 10;
stroke: #333;
stroke-color: #41b3a3;
fill: #008c99;
`;
export const OutputNodeStyle = `
opacity: 0.1;
stroke-width: 3px;
stroke-dasharray: 5, 5;
stroke: #333;
stroke-color: #41b3a3;
fill: #015249;
`;
export const InputNodeStyle = `
opacity: 0.1;
stroke-width: 3px;
stroke: #333;
stroke-color: #41b3a3;
fill: #6c648b;
`;
export type NodeUID = string;
export enum NodeType {
Input,
Output,
Op
}
export type InputNode = {
data_type: string;
name: string;
shape: string[];
};
export type OutputNode = {
data_type: string;
name: string;
shape: string[];
};
export type OpNode = {
input: NodeUID[];
output: NodeUID[];
opType: string;
};
export type Node = InputNode | OutputNode | OpNode;
export type TypedNode =
| (InputNode & {type: NodeType.Input})
| (OutputNode & {type: NodeType.Output})
| (OpNode & {type: NodeType.Op});
export type Edge = {
source: string;
target: string;
label: string;
};
export interface Graph {
input: InputNode[];
output: OutputNode[];
name: string;
node: OpNode[];
edges: Edge[];
}
#!/bin/bash
set -e
WORKING_PATH=`pwd`
DIST_DIR='dist'
DIST_PATH="$WORKING_PATH/$DIST_DIR"
# generate dist
rm -rf $DIST_PATH
mkdir -p $DIST_PATH
yarn
# next build
yarn build:next
# server build
yarn build:server
# move static files
cp next.config.js $DIST_PATH
cp package.json $DIST_PATH
import path from 'path';
import express from 'express';
import next from 'next';
import {setConfig} from 'next/config';
import nextI18NextMiddleware from 'next-i18next/middleware';
import config from '../next.config';
import nextI18next from '../utils/i18n';
import mock from '../utils/mock';
const isDev = process.env.NODE_ENV !== 'production';
setConfig(config);
const port = process.env.PORT || 8999;
const app = next({dev: isDev, conf: config});
const handle = app.getRequestHandler();
(async () => {
await app.prepare();
const server = express();
if (isDev) {
server.use(config.env.API_URL, mock({path: path.resolve(__dirname, '../mock')}));
}
await nextI18next.initPromise;
server.use(nextI18NextMiddleware(nextI18next));
server.get('*', (req, res) => handle(req, res));
server.listen(port);
console.log(`> Ready on http://localhost:${port}`); // eslint-disable-line no-console
})();
<template>
<div id="app">
<v-app>
<AppMenu :initial-route="initialRoute"/>
<router-view/>
</v-app>
</div>
</template>
<script>
import AppMenu from './common/component/AppMenu';
import {getLanguage} from './service';
export default {
name: 'App',
components: {
AppMenu,
},
data() {
return {
initialRoute: 'metrics',
};
},
created() {
getLanguage().then(({errno, data}) => {
this.$i18n.locale = data;
});
if (location.hash && location.hash != '#/') {
this.initialRoute = /(\#\/)(\w*)([?|&]{0,1})/.exec(location.hash)[2];
} else {
location.hash = '#/metrics';
}
},
};
</script>
<style lang="stylus">
@import '~style/variables';
@import '../style/main';
@import url('https://fonts.googleapis.com/css?family=Merriweather+Sans:400,700');
#app {
font-family: 'Merriweather Sans', Helvetica, Arial, sans-serif;
font-weight: regular;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: $-content-text-color;
}
+prefix-classes('visual-dl-page-')
.container
padding-right 300px
position relative
background $-left-background-color
.left
width 100%
overflow scroll
border solid 1px $-left-border-color
background $-left-border-color
min-height 300px
padding 2% 0% 2% 2%
box-sizing border-box
.right
overflow scroll
width 300px
min-height 300px
position absolute
right 0
top 0
box-sizing border-box
font-size 14px
font-weight normal
.config-com
color $-right-font-color
</style>
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" baseProfile="full" width="76" height="76" viewBox="0 0 76.00 76.00" enable-background="new 0 0 76.00 76.00" xml:space="preserve">
<path fill="#999999" fill-opacity="1" stroke-width="0.2" stroke-linejoin="round" d="M 25,52L 51,52L 51,57L 25,57L 25,52 Z M 35,16L 41,16L 41,36.5L 49,27L 49,36.5L 38,49L 27,36.5L 27,27L 35,36.5L 35,16 Z "/>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" baseProfile="full" width="76" height="76" viewBox="0 0 76.00 76.00" enable-background="new 0 0 76.00 76.00" xml:space="preserve">
<path fill="#999999" fill-opacity="1" stroke-width="0.2" stroke-linejoin="round" d="M 44.5,19L 58,19L 58,32.75L 53,37.5L 53,28L 37.75,43.25L 34,39.5L 49.5,24L 39.5,24L 44.5,19 Z M 20,27L 42.5,27L 37.5,32L 25,32L 25,52L 45,52L 45,40.5L 50,35.5L 50,57L 20,57L 20,27 Z "/>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" baseProfile="full" width="76" height="76" viewBox="0 0 76.00 76.00" enable-background="new 0 0 76.00 76.00" xml:space="preserve">
<path fill="#008c99" fill-opacity="1" stroke-width="0.2" stroke-linejoin="round" d="M 44.5,19L 58,19L 58,32.75L 53,37.5L 53,28L 37.75,43.25L 34,39.5L 49.5,24L 39.5,24L 44.5,19 Z M 20,27L 42.5,27L 37.5,32L 25,32L 25,52L 45,52L 45,40.5L 50,35.5L 50,57L 20,57L 20,27 Z "/>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 150 24"><defs><style>.cls-1,.cls-2,.cls-3{fill:#fff;}.cls-2{opacity:0.85;}.cls-3{opacity:0.65;}</style></defs><title>logo</title><path class="cls-1" d="M50.85,21.48,45,3.33h4L51.71,12l1.43,5.7h.08L54.6,12l2.7-8.71h3.88l-5.9,18.15Z"/><path class="cls-1" d="M61.72,4.47V3.9C61.72,2.81,62.4,2,64,2s2.24.81,2.24,1.9v.57c0,1.09-.68,1.9-2.24,1.9S61.72,5.56,61.72,4.47ZM62,7.83h3.85V21.48H62Z"/><path class="cls-1" d="M67.05,19.35l2.26-2.29a4.75,4.75,0,0,0,3.62,1.74c1.51,0,2-.49,2-1.3s-.42-1-1.38-1.14l-1.48-.18C69,15.78,67.5,14.43,67.5,12c0-2.63,2.05-4.45,5.31-4.45a6.86,6.86,0,0,1,5.57,2.13l-2.21,2.26A4.56,4.56,0,0,0,73,10.5c-1.3,0-1.82.47-1.82,1.14s.31,1.12,1.43,1.27l1.53.21c3,.39,4.5,1.74,4.5,4.11,0,2.63-2.34,4.55-5.85,4.55A7.13,7.13,0,0,1,67.05,19.35Z"/><path class="cls-1" d="M88,19.19h-.13a3.71,3.71,0,0,1-3.82,2.6c-2.78,0-4.27-2-4.27-5.38V7.83h3.85v8.24c0,1.66.55,2.6,2,2.6a2.17,2.17,0,0,0,2.42-2V7.83h3.85V21.48H88Z"/><path class="cls-1" d="M104.27,21.48a2.6,2.6,0,0,1-2.6-2.39h-.16c-.42,1.77-1.92,2.7-4,2.7-2.73,0-4.24-1.61-4.24-4,0-2.89,2.24-4.27,5.85-4.27h2.16v-.86c0-1.33-.65-2.16-2.26-2.16a3.37,3.37,0,0,0-2.94,1.61l-2.29-2c1.09-1.61,2.65-2.6,5.51-2.6,3.85,0,5.83,1.77,5.83,5v6h1.27v3Zm-3-4.14V15.73H99.41c-1.48,0-2.26.55-2.26,1.53v.39c0,1,.65,1.46,1.79,1.46S101.28,18.59,101.28,17.34Z"/><path class="cls-1" d="M111.5,21.48c-2.63,0-3.82-1.33-3.82-3.75V2.23h3.85V18.49h1.72v3Z"/><path class="cls-1" d="M119.3,3.33h6.84c4.81,0,8,3,8,9.08s-3.17,9.08-8,9.08H119.3ZM126.14,18c2.34,0,3.8-1.27,3.8-4.16V11c0-2.89-1.46-4.16-3.8-4.16h-2.89V18Z"/><path class="cls-1" d="M136.13,21.48V3.33h4V18H147v3.51Z"/><circle class="cls-1" cx="19.58" cy="4.33" r="2.05"/><circle class="cls-2" cx="19.58" cy="9.69" r="2.05"/><circle class="cls-2" cx="19.58" cy="15.04" r="2.05"/><circle class="cls-1" cx="24.58" cy="7.03" r="2.05"/><circle class="cls-2" cx="24.58" cy="12.39" r="2.05"/><circle class="cls-3" cx="19.58" cy="20.38" r="2.05"/><circle class="cls-3" cx="24.58" cy="17.67" r="2.05"/><circle class="cls-1" cx="29.59" cy="9.69" r="2.05"/><circle class="cls-3" cx="29.6" cy="15.04" r="2.05"/><circle class="cls-1" cx="34.88" cy="12.39" r="2.05"/><circle class="cls-3" cx="14.43" cy="17.8" r="2.05"/><circle class="cls-1" cx="9.56" cy="9.73" r="2.05"/><circle class="cls-1" cx="14.43" cy="7.03" r="2.05"/><circle class="cls-3" cx="9.43" cy="15.15" r="2.05"/><circle class="cls-1" cx="4.14" cy="12.45" r="2.05"/></svg>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" baseProfile="full" width="76.0106" height="76.0106" viewBox="0 0 76.01 76.01" enable-background="new 0 0 76.01 76.01" xml:space="preserve">
<path fill="#999999" fill-opacity="1" stroke-width="0.2" stroke-linejoin="round" d="M 25.3362,20.5864L 25.3348,29.2137C 28.5107,25.8499 33.0116,23.7507 38.0029,23.7507C 47.6232,23.7507 55.422,31.5494 55.422,41.1698C 55.422,45.9799 53.4723,50.3347 50.32,53.4869L 46.401,49.5679C 48.5503,47.4187 49.8796,44.4495 49.8796,41.1699C 49.8796,34.6106 44.5623,29.2932 38.003,29.2932C 34.4855,29.2932 31.3251,30.8224 29.1504,33.2522L 38.0029,33.2531L 33.2529,38.0031L 20.5862,38.0031L 20.5862,25.3364L 25.3362,20.5864 Z "/>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" baseProfile="full" width="76" height="76" viewBox="0 0 76.00 76.00" enable-background="new 0 0 76.00 76.00" xml:space="preserve">
<path fill="#999999" fill-opacity="1" stroke-width="0.2" stroke-linejoin="round" d="M 17.4167,53.8333L 17.4167,49.0833L 22.1667,49.0833L 22.1667,28.5L 17.4167,28.5L 17.4167,23.75L 22.1667,23.75L 22.1667,19L 26.9167,19L 26.9167,23.75L 48.6875,23.75L 53.4375,19L 57,22.5625L 52.25,27.3125L 52.25,49.0833L 57,49.0833L 57,53.8333L 52.25,53.8333L 52.25,58.5833L 47.5,58.5833L 47.5,53.8333L 26.9167,53.8333L 26.9167,58.5833L 22.1667,58.5833L 22.1667,53.8333L 17.4167,53.8333 Z M 30.4792,49.0833L 47.5,49.0833L 47.5,32.0625L 30.4792,49.0833 Z M 26.9167,45.5208L 43.9375,28.5L 26.9167,28.5L 26.9167,45.5208 Z "/>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" baseProfile="full" width="76" height="76" viewBox="0 0 76.00 76.00" enable-background="new 0 0 76.00 76.00" xml:space="preserve">
<path fill="#008c99" fill-opacity="1" stroke-width="0.2" stroke-linejoin="round" d="M 17.4167,53.8333L 17.4167,49.0833L 22.1667,49.0833L 22.1667,28.5L 17.4167,28.5L 17.4167,23.75L 22.1667,23.75L 22.1667,19L 26.9167,19L 26.9167,23.75L 48.6875,23.75L 53.4375,19L 57,22.5625L 52.25,27.3125L 52.25,49.0833L 57,49.0833L 57,53.8333L 52.25,53.8333L 52.25,58.5833L 47.5,58.5833L 47.5,53.8333L 26.9167,53.8333L 26.9167,58.5833L 22.1667,58.5833L 22.1667,53.8333L 17.4167,53.8333 Z M 30.4792,49.0833L 47.5,49.0833L 47.5,32.0625L 30.4792,49.0833 Z M 26.9167,45.5208L 43.9375,28.5L 26.9167,28.5L 26.9167,45.5208 Z "/>
</svg>
{
"lang": {
"runs": "Runs",
"notRunsSelect": "None selected",
"metrics": "metrics",
"samples": "samples",
"graphs": "graphs",
"HighDimensional": "HighDimensional",
"text": "Text",
"image": "Image",
"audio": "Audio",
"showActualImageSize": "Show actual image size",
"startRunning": "Running",
"stopRunning": "Stopped",
"searchTagInReg": "Search tags in RegExp",
"scalars": "Scalars",
"smoothing": "Smoothing",
"xAxis": "X-axis",
"toolTipSorting": "Tooltip sorting",
"ignoreOutliers": "Ignore outliers in chart scaling",
"histogram": "Histogram",
"mode": "Mode",
"step": "Step",
"relative": "Relative",
"wall": "Wall Time",
"default": "default",
"descending": "descending",
"ascending": "ascending",
"nearest": "nearest",
"overlay": "Overlay",
"offset": "Offset",
"downloadImage": "Download image",
"restoreImage": "Restore image",
"scale": "Scale",
"nodeInfo": "Node Info",
"nodeName": "Name",
"nodeType": "Node Type",
"dataShape": "Shape",
"dataType": "Data Type",
"input": "Input",
"output": "Output",
"opType": "Operator Type",
"search": "Search",
"searchByLabel": "Search by label",
"dimension": "Dimension",
"2D": "2D",
"3D": "3D",
"displayAllLabel": "Display All Labels",
"reductionMethod": "Reduction Method",
"downloadDataInJson": "Download data in JSON",
"all": "All"
}
}
{
"lang": {
"runs": "数据流",
"notRunsSelect": "未选中任何数据",
"metrics": "度量数据",
"samples": "样本数据",
"graphs": "网络结构",
"HighDimensional": "高维数据映射",
"text": "文本",
"image": "图片",
"audio": "音频",
"showActualImageSize": "按真实大小显示",
"startRunning": "运行",
"stopRunning": "停止",
"searchTagInReg": "搜索标签(支持正则)",
"scalars": "标量",
"smoothing": "平滑度",
"xAxis": "x轴",
"toolTipSorting": "标签排序方法",
"ignoreOutliers": "图表缩放时忽略极端值",
"histogram": "直方图",
"mode": "模式",
"step": "步",
"relative": "相对值",
"wall": "时间",
"default": "默认",
"descending": "降序",
"ascending": "升序",
"nearest": "最近",
"overlay": "概览",
"offset": "偏移",
"downloadImage": "下载图片",
"restoreImage": "还原图片",
"scale": "比例",
"nodeInfo": "节点信息",
"nodeName": "节点名称",
"nodeType": "节点类型",
"dataShape": "数据形状",
"dataType": "数据类型",
"input": "输入",
"output": "输出",
"opType": "算子类型",
"search": "搜索",
"searchByLabel": "通过标签搜索",
"dimension": "维度",
"2D": "二维",
"3D": "三维",
"displayAllLabel": "展示所有标签",
"reductionMethod": "降维方法",
"downloadDataInJson": "下载数据(json格式)",
"all": "全部"
}
}
<template>
<div class="visual-dl-page-container">
<div class="visual-dl-page-left">
<ui-audio-container
:expand="true"
:config="filteredConfig"
:tag-list="filteredTagsList"
:title="'Tags matching ' + config.groupNameReg"
/>
<ui-audio-container
v-for="item in groupedTags"
:key="item.group"
:config="filteredConfig"
:tag-list="item.tags"
:title="item.group"
/>
</div>
<div class="visual-dl-page-right">
<div class="visual-dl-page-config-container">
<ui-config
:config="config"
/>
</div>
</div>
</div>
</template>
<script>
import {getPluginAudioTags} from '../service';
import {flatten, uniq} from 'lodash';
import autoAdjustHeight from '../common/util/autoAdjustHeight';
import Config from './ui/Config';
import AudioPanelContainer from './ui/AudioPanelContainer';
export default {
name: 'Audio',
components: {
'ui-config': Config,
'ui-audio-container': AudioPanelContainer,
},
props: {
runs: {
type: Array,
required: true,
},
},
data() {
return {
tags: [],
config: {
groupNameReg: '.*',
isActualImageSize: false,
runs: [],
running: true,
},
filteredTagsList: [],
};
},
computed: {
tagsList() {
let tags = this.tags;
let runs = Object.keys(tags);
let tagsArray = runs.map((run) => Object.keys(tags[run]));
let allUniqTags = uniq(flatten(tagsArray));
// get the data for every chart
return allUniqTags.map((tag) => {
let tagList = runs.map((run) => {
return {
run,
tag: tags[run][tag],
};
}).filter((item) => item.tag !== undefined);
return {
tagList,
tag,
group: tag.split('/')[0],
};
});
},
groupedTags() {
let tagsList = this.tagsList || [];
// put data in group
let groupData = {};
tagsList.forEach((item) => {
let group = item.group;
if (groupData[group] === undefined) {
groupData[group] = [];
groupData[group].push(item);
} else {
groupData[group].push(item);
}
});
// to array
let groups = Object.keys(groupData);
return groups.map((group) => {
return {
group,
tags: groupData[group],
};
});
},
filteredConfig() {
let config = this.config || {};
let filteredConfig = {};
Object.keys(config).forEach((key) => {
let val = config[key];
filteredConfig[key] = val;
});
return filteredConfig;
},
},
created() {
getPluginAudioTags().then(({errno, data}) => {
this.tags = data;
// filter when inited
let groupNameReg = this.config.groupNameReg;
this.filterTagsList(groupNameReg);
});
this.config.runs = this.runs;
},
mounted() {
autoAdjustHeight();
},
watch: {
'config.groupNameReg': function(val) {
this.throttledFilterTagsList();
},
runs: function(val) {
this.config.runs = val;
}
},
methods: {
filterTagsList(groupNameReg) {
if (!groupNameReg) {
this.filteredTagsList = [];
return;
}
let tagsList = this.tagsList || [];
let regExp = new RegExp(groupNameReg);
this.filteredTagsList = tagsList.filter((item) => regExp.test(item.tag));
},
throttledFilterTagsList: _.debounce(
function() {
this.filterTagsList(this.config.groupNameReg);
}, 300
),
},
};
</script>
<style lang="stylus">
</style>
<template>
<v-card
hover
class="visual-dl-audio">
<h3 class="visual-dl-audio-title">{{ tagInfo.tag.displayName }}
<span class="visual-dl-audio-run-icon">{{ tagInfo.run }}</span>
</h3>
<p>
<span>Step:</span>
<span>{{ audioData.step }}</span>
<span class="visual-del-audio-time">{{ audioData.wallTime | formatTime }}</span>
</p>
<v-slider
:max="steps"
:min="slider.min"
:step="1"
v-model="currentIndex"
/>
<audio
controls
:src="audioData.audioSrc">
Your browser does not support the audio element.
</audio>
</v-card>
</template>
<script>
import {getPluginAudioAudio} from '../../service';
// the time to refresh chart data
const intervalTime = 30;
export default {
props: {
tagInfo: {
type: Object,
required: true,
},
runs: {
type: Array,
required: true,
},
running: {
type: Boolean,
required: true,
},
},
computed: {
steps() {
let data = this.data || [];
return data.length - 1;
},
},
filters: {
formatTime: function(value) {
if (!value) {
return;
}
// The value was made in seconds, must convert it to milliseconds
let time = new Date(value * 1000);
let options = {
weekday: 'short', year: 'numeric', month: 'short',
day: 'numeric', hour: '2-digit', minute: '2-digit', second: '2-digit',
};
return time.toLocaleDateString('en-US', options);
},
},
data() {
return {
currentIndex: 0,
slider: {
value: '0',
label: '',
min: 0,
step: 1,
},
audioData: {},
data: [],
isDemo: process.env.NODE_ENV === 'demo',
};
},
created() {
this.getOriginAudioData();
},
mounted() {
if (this.running && !this.isDemo) {
this.startInterval();
}
},
beforeDestroy() {
this.stopInterval();
},
watch: {
running: function(val) {
(val && !this.isDemo) ? this.startInterval() : this.stopInterval();
},
currentIndex: function(index) {
if (this.data && this.data[index]) {
let currentAudioInfo = this.data ? this.data[index] : {};
let {query, step, wallTime} = currentAudioInfo;
let url = '/data/plugin/audio/individualAudio?ts=' + wallTime;
let audioSrc = [url, query].join('&');
this.audioData = {
audioSrc,
step,
wallTime,
};
}
},
},
methods: {
stopInterval() {
clearInterval(this.getOringDataInterval);
},
// get origin data per {{intervalTime}} seconds
startInterval() {
this.getOringDataInterval = setInterval(() => {
this.getOriginAudioData();
}, intervalTime * 1000);
},
getOriginAudioData() {
// let {run, tag} = this.tagInfo;
let run = this.tagInfo.run;
let tag = this.tagInfo.tag;
let {displayName, samples} = tag;
let params = {
run,
tag: displayName,
samples,
};
getPluginAudioAudio(params).then(({status, data}) => {
if (status === 0) {
this.data = data;
this.currentIndex = data.length - 1;
}
});
},
},
};
</script>
<style lang="stylus">
.visual-dl-audio
font-size 12px
width 420px
float left
margin 20px 30px 10px 0
background #fff
padding 10px
.visual-dl-audio-title
font-size 14px
line-height 30px
.visual-dl-audio-run-icon
background #e4e4e4
float right
margin-right 10px
padding 0 10px
border solid 1px #e4e4e4
border-radius 6px
line-height 20px
margin-top 4px
.visual-del-audio-time
float right
</style>
<template>
<div class="visual-dl-chart-page">
<ui-expand-panel
:info="total"
:title="title">
<ui-audio
class="visual-dl-chart-audio"
v-for="(tagInfo, index) in filteredPageList"
:key="index"
:tag-info="tagInfo"
:runs="config.runs"
:running="config.running"
/>
<v-pagination
class="visual-dl-sm-pagination"
v-if="total > pageSize"
v-model="currentPage"
:length="pageLength"
/>
</ui-expand-panel>
</div>
</template>
<script>
import ExpandPanel from '../../common/component/ExpandPanel';
import AudioPanel from './AudioPanel';
import {cloneDeep, flatten} from 'lodash';
export default {
props: {
config: {
type: Object,
required: true,
},
tagList: {
type: Array,
required: true,
},
title: {
type: String,
required: true,
},
},
components: {
'ui-audio': AudioPanel,
'ui-expand-panel': ExpandPanel,
},
computed: {
filteredRunsList() {
let tagList = this.tagList || [];
let runs = this.config.runs || [];
let list = cloneDeep(tagList);
return flatten(list.slice().map((item) => {
return item.tagList.filter((one) => runs.includes(one.run));
}));
},
filteredPageList() {
let list = this.filteredRunsList || [];
return list.slice((this.currentPage - 1) * this.pageSize, this.currentPage * this.pageSize);
},
total() {
let list = this.filteredRunsList || [];
return list.length;
},
pageLength() {
return Math.ceil(this.total / this.pageSize);
},
},
data() {
return {
// current page
currentPage: 1,
// item per page
pageSize: 8,
};
},
};
</script>
<style lang="stylus">
@import '~style/variables';
+prefix-classes('visual-dl-')
.chart-page
.audio-chart-box
overflow hidden
float left
.visual-dl-chart-audio
float left
.audio-chart-box:after
content ""
clear both
display block
.sm-pagination
height 50px
float left
width 100%
</style>
<template>
<div class="visual-dl-page-config-com">
<v-text-field
label="Group name RegExp"
hint="input a tag group name to search"
v-model="config.groupNameReg"
dark
/>
<v-btn
:color="config.running ? 'primary' : 'error'"
v-model="config.running"
v-if="!isDemo"
@click="toggleAllRuns"
class="visual-dl-page-run-toggle"
dark
block
>
{{ config.running ? 'Running' : 'Stopped' }}
</v-btn>
</div>
</template>
<script>
export default {
props: {
config: {
type: Object,
required: true,
},
},
data() {
return {
isDemo: process.env.NODE_ENV === 'demo',
};
},
methods: {
toggleAllRuns() {
this.config.running = !this.config.running;
},
},
};
</script>
<style lang="stylus">
+prefix-classes('visual-dl-page-')
.config-com
padding 20px
.run-toggle
margin-top 20px
.checkbox-group-label
display flex
margin-top 20px
margin-bottom 10px
</style>
<template>
<div>
<div class="visual-dl-app-menu">
<v-toolbar
color="primary"
dark>
<v-toolbar-title class="appbar-menu-title"/>
<v-toolbar-items>
<v-menu
open-on-hover
offset-y
:close-on-content-click="false">
<v-btn
slot="activator"
depressed
@mouseover="runsSelectorOpen = true"
@mouseout="runsSelectorOpen = false"
:ripple="false"
:color="runsSelectorOpen ? 'dark_primary' : 'primary'"
:class="runsSelectorOpen ? 'runs-selected-menu-open' : 'runs-selected-menu'"
> <span class="runs-selected-text">{{ $t("lang.runs") }}: {{ runs.length == 0 ? $t("lang.notRunsSelect") : runs.join(', ') }} </span>
<v-icon>arrow_drop_down</v-icon>
</v-btn>
<v-list dense>
<v-list-tile
v-for="(item, index) in availableRuns"
:key="index"
@mouseover="runsSelectorOpen = true"
@mouseout="runsSelectorOpen = false">
<v-list-tile-action>
<v-checkbox
:value="item"
:key="item"
:label="item"
v-model="runs" />
</v-list-tile-action>
</v-list-tile>
</v-list>
</v-menu>
<v-btn
v-for="item in items"
:key="item.name"
flat
dark
:class="selected.toLowerCase() === item.name.toLowerCase() ? 'menu-item-selected': 'menu-item'"
@click="handleItemClick(item)"
>{{ $t('lang.' + item.name) }}</v-btn>
</v-toolbar-items>
</v-toolbar>
</div>
</div>
</template>
<script>
import {getRuns} from '../../service';
export default {
props: {
initialRoute: {
type: String,
required: true,
},
},
name: 'AppMenu',
data() {
return {
runsSelectorOpen: false,
availableRuns: [],
runs: [],
selected: this.initialRoute,
items: [
{
url: '/metrics',
title: 'METRICS',
name: 'metrics',
},
{
url: '/samples',
title: 'SAMPLES',
name: 'samples',
},
{
url: '/graphs',
title: 'GRAPHS',
name: 'graphs',
},
{
url: '/HighDimensional',
title: 'HighDimensional',
name: 'HighDimensional',
},
],
};
},
created() {
this.runs = this.$route.query.runs; // maintain runs state after refresh
getRuns().then(({errno, data}) => {
this.availableRuns = data;
if (!this.runs) this.runs = data;
// use replace here instead of push so that user cannot go back to empty run state
this.$router.replace( {path: this.initialRoute, query: {runs: this.runs}});
});
},
watch: {
runs: function(val) {
if (this.runs) {
this.$router.push( {query: {runs: this.runs}});
}
},
'$route'(to, from) { // this will get called when back button is hit that changes path or query
this.runs = this.$route.query.runs;
this.selected = this.$route.name;
},
},
methods: {
handleItemClick: function(item) {
this.selected = item.name;
this.$router.push( {path: item.url, query: {runs: this.runs}});
},
},
};
</script>
<style lang="stylus">
@import '~style/variables';
.visual-dl-app-menu
.appbar-menu-title
flex none
margin-right 10px
background url('../../assets/ic_logo.svg') no-repeat
width 180px
height 24px
.menu-item
font-size 16px
background none
padding 0 10px
color #fff
opacity 0.6
display flex
flex-direction row
font-weight bold
.menu-item:hover
opacity 1
.menu-item-selected
@extends .visual-dl-app-menu .menu-item
opacity 1
.runs-selected-menu
font-size 16px
text-transform none
opacity 0.75
.runs-selected-menu-open
@extends .visual-dl-app-menu .runs-selected-menu
opacity 1
.runs-selected-text
text-align left
padding-right 6px
overflow hidden
text-overflow ellipsis
max-width 200px
.theme--light .input-group:not(.input-group--error) label
color #000
.input-group label
overflow visible
</style>
<template>
<div class="visual-dl-expand-panel">
<h3
class="visual-dl-expand-head"
@click="isShow = !isShow"
>
<span>{{ title }}</span>
<span class="visual-dl-expand-head-info">
<v-icon
class="visual-dl-expand-head-arrow"
size="20">{{ iconName }}</v-icon>
<span class="visual-dl-expand-head-num">({{ info }})</span>
</span>
</h3>
<div
v-if="isShow"
class="visual-dl-expand-panel-content"
>
<slot/>
</div>
</div>
</template>
<script>
export default {
props: {
title: {
type: String,
required: true,
},
info: {
type: Number,
required: true,
},
},
computed: {
iconName() {
return this.isShow ? 'expand_less' : 'expand_more';
},
},
data() {
return {
isShow: true,
};
},
};
</script>
<style lang="stylus">
.visual-dl-expand-panel
.visual-dl-expand-head
border solid 1px #ccc
line-height 50px
height 50px
padding 0 20px
margin-right 2%
cursor pointer
position relative
.visual-dl-expand-head-info
position absolute
left 90%
.visual-dl-expand-head-arrow
vertical-align middle
.visual-dl-expand-head-num
line-height 20px
font-size 12px
font-weight normal
.visual-dl-expand-panel-content:after
content: "";
clear: both;
display: block;
</style>
import NotificationItem from './NotificationItem';
let seed = 1;
// instances
const instances = [];
/**
* caculate top dist
*
* @param {number} topDist top dist
* @return {number} final top dist
*/
function calcTopDist(topDist = 16) {
for (let i = 0, len = instances.length; i < len; i++) {
topDist += (instances[i].vm.el.offsetHeight + 16);
}
return topDist;
}
/**
* Notification main func
*
* @param {Object} options options
* @return {NotificationItem} instance
*/
const notification = function(options = {}) {
options.top = calcTopDist(options.offset);
const {onClose, onClick} = options;
delete options.onClick;
delete options.onClose;
delete options.offset;
const instance = {
vm: new NotificationItem({
data: options,
}),
id: `notification_${seed++}`,
};
if (typeof onClick === 'function') {
instance.vm.on('itemClick', onClick);
}
instance.vm.on('close', () => {
notification.close(instance.id, onClose);
});
instance.vm.attach(document.body);
instances.push(instance);
return instance.vm;
};
/**
* close
*
* @param {string} id instance id
* @param {Function} onClose cusmtom func
*/
notification.close = function(id, onClose) {
let index;
let removedHeight;
let len = instances.length;
for (let i = 0; i < len; i++) {
if (id === instances[i].id) {
if (typeof onClose === 'function') {
onClose(instances[i]);
}
index = i;
removedHeight = instances[i].vm.el.offsetHeight;
// distroy instance
instances[i].vm.dispose();
instances[i] = null;
// reomve instance fron instances
instances.splice(i, 1);
break;
}
}
// change the left notification's height
if (len > 1) {
for (let i = index; i < len - 1; i++) {
instances[i].vm.el.style.top = `${parseInt(instances[i].vm.el.style.top, 10) - removedHeight - 16}px`;
}
}
};
// fout type func
['success', 'warning', 'info', 'error'].forEach((type) => {
notification[type] = (options) => {
if (typeof options === 'string') {
options = {
message: options,
};
}
options = options || {};
options.type = type;
return notification(options);
};
});
export default notification;
## Notification
### base usage
```san Notification
<template>
<div>
<s-button
variants="raised info"
on-click="handleClick01">
auto close
</s-button>
<s-button
variants="raised info"
on-click="handleClick02">
no auto close
</s-button>
</div>
</template>
<script>
import Notification from '../src/Notification';
import '../src/Notification/Notification.styl';
import Button from '../src/Button';
import '../src/Button/Button.styl';
export default {
components: {
'san-button': Button
},
// auto close
handleClick01() {
Notification({
message: 'welcome',
title: 'success'
})
},
// no auto close
handleClick02() {
Notification({
message: 'welcome',
title: 'success',
duration: 0
})
}
}
</script>
```
### with icon
```san Notification
<template>
<div>
<s-button
variants="raised info"
on-click="handleClick01">
success
</s-button>
<s-button
variants="raised info"
on-click="handleClick02">
warning
</s-button>
<s-button
variants="raised info"
on-click="handleClick03">
info
</s-button>
<s-button
variants="raised info"
on-click="handleClick04">
error
</s-button>
<s-button
variants="raised info"
on-click="handleClick05">
simplify
</s-button>
</div>
</template>
<script>
import Notification from '../src/Notification';
import '../src/Notification/Notification.styl';
import Button from '../src/Button';
import '../src/Button/Button.styl';
export default {
components: {
'san-button': Button
},
handleClick01() {
Notification({
message: 'welcome',
title: 'success',
type: 'success'
})
},
handleClick02() {
Notification({
message: 'warning',
title: 'warning',
type: 'warning'
})
},
handleClick03() {
Notification({
message: 'info',
title: 'info',
type: 'info'
})
},
handleClick04() {
Notification({
message: '不可以攻击己方水晶',
title: '错误',
type: 'error'
})
},
handleClick05() {
Notification.success('simplify')
}
}
</script>
```
### width offset
```san Notification
<template>
<div>
<s-button
variants="raised info"
on-click="handleClick01">
width offset
</s-button>
</div>
</template>
<script>
import Notification from '../src/Notification';
import '../src/Notification/Notification.styl';
import Button from '../src/Button';
import '../src/Button/Button.styl';
export default {
components: {
'san-button': Button
},
handleClick01() {
Notification({
message: 'offset 100px',
title: 'success',
offset:100
})
}
}
</script>
```
## API
### Props
| name | type | fefault | desc |
| --- | --- | --- | --- |
| title | String | | title |
| message | String | | content |
| customClass |String| | custom class |
| offset | Number | | offset to the top |
| onClick | Function | | on-click callback |
| onClose | Function | | on-close callback |
| duration | Number | 3000 | duration |
| type | String | | include success,error,warning,info, others not use |
.sm-notification
position: fixed
display: flex
z-index: 9999
right: 16px
top 16px
width: 330px
padding: 20px
box-sizing border-box
border-radius 2px
background-color #fff
box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04);
transition: all .4s;
overflow: hidden
&.state-hidden
transform translateX(346px)
&.state-open
transform translateX(0)
&-group
color: #000
&-type
margin auto 0
margin-right 20px
&.type-success
color: #13ce66
&.type-info
color: #50bfff
&.type-warning
color: #f7ba2a
&.type-error
color: #ff4949
&-title
color: #1f2d3d
font-size 16px
&-content
color: #8d9baf
padding: 5px 0
&-close
position: absolute
cursor: pointer
right 20px
top: 20px
&-btn
transition all .3s
color #bfcbd9
&:hover
color: #777F8C
import {Component} from 'san';
import Icon from 'san-mui/Icon';
const typeMap = {
success: 'check_circle',
info: 'info',
warning: 'error',
error: 'cancel'
};
export default class NotificationItem extends Component {
static template = `
<div
class="sm-notification {{customClass}} {{closed ? 'state-hidden' : 'state-open'}}"
style="top: {{top}}px"
on-mouseenter="clearTimer"
on-mouseleave="startTimer"
on-click="handleClick">
<san-icon
s-if="type"
class="sm-notification-type type-{{type}}"
size="50">{{iconType}}</san-icon>
<div class="sm-notification-group" >
<p class="sm-notification-title">{{title}}</p>
<div class="sm-notification-content">{{message}}</div>
<div on-click="close($event)" class="sm-notification-close">
<san-icon size="20" class="sm-notification-close-btn">close</san-icon>
</div>
</div>
</div>
`;
initData() {
return {
title: '',
message: '',
duration: 3000,
closed: true
};
}
static components = {
'san-icon': Icon
};
static computed = {
iconType() {
return typeMap[this.data.get('type')];
}
};
handleClick() {
this.fire('itemClick');
}
/**
* close
*
* @param {Object} e event Object
*/
close(e) {
if (e) {
e.stopPropagation();
}
this.data.set('closed', true);
this.el.addEventListener('transitionend', () => {
this.fire('close');
});
}
/**
* clear timer
*/
clearTimer() {
clearTimeout(this.timer);
}
/**
* start timet
*/
startTimer() {
const duration = this.data.get('duration');
if (duration > 0) {
this.timer = setTimeout(() => {
if (!this.closed) {
this.close();
}
}, duration);
}
}
attached() {
if (this.el.parentNode !== document.body) {
document.body.appendChild(this.el);
}
requestAnimationFrame(() => {
this.data.set('closed', false);
});
this.startTimer();
}
detached() {
this.clearTimer();
}
}
<template>
<v-card
hover
color="tag_background"
class="visual-dl-tags-tab">
<div
@click="$emit('click')">
<span :class="active ? 'visual-dl-tags-tab-text-active':'visual-dl-tags-tab-text-inactive' ">{{ title }} &nbsp; ({{ total }})</span>
</div>
</v-card>
</template>
<script>
export default {
props: {
title: {
type: String,
required: true,
},
total: {
type: Number,
required: true,
},
active: {
type: Boolean,
required: true,
},
},
};
</script>
<style lang="stylus">
.visual-dl-tags-search-input
outline none
font-size 12px
.visual-dl-tags-tab
border-radius 17px
line-height 34px
height 34px
padding 0 14px
margin-right 16px
cursor pointer
position relative
display inline-block
.visual-dl-tags-tab-text-active
font-size 12px
font-weight bold
.visual-dl-tags-tab-text-inactive
font-size 12px
font-weight normal
color #555555
</style>
html {
font-family: "RobotoDraft", "Roboto", sans-serif;
}
// initual style
body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, dl, dt, dd, ul, ol, li, pre, form, fieldset, legend, button, input, textarea, th, td { margin:0; padding:0; } body, button, input, select, textarea { font:12px/1.5tahoma, arial, \5b8b\4f53; } h1, h2, h3, h4, h5, h6{ font-size:100%; } address, cite, dfn, em, var { font-style:normal; } code, kbd, pre, samp { font-family:couriernew, courier, monospace; } small{ font-size:12px; } ul, ol { list-style:none; } a { text-decoration:none; } a:hover { text-decoration:underline; } sup { vertical-align:text-top; } sub{ vertical-align:text-bottom; } legend { color:#000; } fieldset, img { border:0; } button, input, select, textarea { font-size:100%; } table { border-collapse:collapse; border-spacing:0; }
@import './Notification/Notification.styl'
// modify some styles of san-mui
.sm-icon
width 20px
height 20px
overflow hidden
.sm-radio,
.sm-checkbox
margin-top 2px
margin-bottom 4px
margin-right 10px
float left
width 100%
.sm-radio-wrapper,
.sm-checkbox-wrapper
justify-content start
.sm-radio-label,
.sm-checkbox-label
font-size 12px
.sm-radio-icon
.sm-checkbox-icon
width 20px
height 20px
margin-right 10px
.sm-radio-ripple-wrapper
.sm-checkbox-ripple-wrapper
width 20px
height 20px
top 0px
left 0px
.sm-checkbox-svg-icon,
.sm-radio-svg-icon
width 20px
height 20px
.sm-checkbox-icon-uncheck
.sm-radio-icon-uncheck
color #58666e
.sm-radio-label,
.sm-checkbox-label
color #58666e
.sm-dropdown-menu
.sm-text-field
margin-bottom 0px
min-height 30px
border-bottom solid 1px #e4e4e4
.sm-text-field-content
padding 0
padding-left 4px
input
cursor pointer
.sm-dropdown-menu-icon
top 6px
right 0
bottom 0
.sm-icon
color #58666e
.sm-popover-content
.sm-menu-item
line-height 30px
font-size 14px
color #58666e
.sm-menu-item.state-selected
color #ff4081
.sm-text-field
width 100%
.sm-text-field-input
color #58666e
.sm-form-item
margin-top 10px
overflow hidden
.label
color rgba(0,0,0,0.54)
font-size 12px
line-height 20px
.group-box
overflow hidden
.collapse-transition
transition: 0.3s height ease-in-out, 0.3s padding-top ease-in-out, 0.3s padding-bottom ease-in-out;
.sm-pagination
margin 30px 0
font-size 12px
\ No newline at end of file
export default function autoAdjustHeight() {
// compute the container height
let containerHeight = window.innerHeight - 64;
let containerLeftEl = document.getElementsByClassName('visual-dl-page-left')[0];
let containerRightEl = document.getElementsByClassName('visual-dl-page-right')[0];
containerLeftEl.style.height = containerHeight + 'px';
containerRightEl.style.height = containerHeight + 'px';
window.addEventListener('resize', () => {
let containerHeight = window.innerHeight - 64;
containerLeftEl.style.height = containerHeight + 'px';
containerRightEl.style.height = containerHeight + 'px';
});
}
import XLSX from 'xlsx';
import FileSaver from 'file-saver';
const aoaToSheet = XLSX.utils.aoa_to_sheet;
const saveAs = FileSaver.saveAs;
function s2ab(s) {
if (typeof ArrayBuffer !== 'undefined') {
let buf = new ArrayBuffer(s.length);
let view = new Uint8Array(buf);
for (let i = 0; i !== s.length; ++i) {
view[i] = s.charCodeAt(i) & 0xFF;
}
return buf;
}
let buf = new Array(s.length);
for (let i = 0; i !== s.length; ++i) {
buf[i] = s.charCodeAt(i) & 0xFF;
}
return buf;
}
/**
* download Excel
*
* @desc transform data like [['A', 'B', 'C'], ['1', '2', '3'],[['1-1', '2-1', '3-1']]] to xlsx and download
* @param {Array} data the data for the xlsx
* @param {string} name filename
*/
export const generateXLSXandAutoDownload = function(data, name) {
let wopts = {
bookType: 'xlsx',
bookSST: false,
type: 'binary',
};
let ws = aoaToSheet(data);
let wb = {
SheetNames: ['Export'],
Sheets: {},
Props: {},
};
wb.Sheets.Export = ws;
let wbout = XLSX.write(wb, wopts);
saveAs(
new Blob(
[s2ab(wbout)],
{
type: 'application/octet-stream',
}
),
name + '.xlsx' || 'sheetjs.xlsx'
);
};
/**
* download json
*
* @desc download json
* @param {Array} data the data for the xlsx
* @param {string} name filename
*/
export const generateJsonAndDownload = function(data, name) {
saveAs(
new Blob(
[s2ab(JSON.stringify(data, null, ' '))],
{
type: 'application/octet-stream',
}
),
name + '.json' || 'json.json'
);
};
import axios from 'axios';
import qs from 'qs';
// import Notification from '../component/Notification';
// const STATUS = 'status';
// const STATUSINFO = 'msg';
const instance = axios.create({
baseURL: '/',
timeout: 30000,
});
// for better ux, don't send the error msg because there will be too many errors
const responseErrorStatus = (response) => {
const data = response.data;
// if (data[STATUS] !== 0) {
// Notification.error(data[STATUSINFO]);
// return Promise.reject(data);
// }
return data;
};
// for better ux, don't send the error msg because there will be too many errors
const responseNetError = (error) => {
// Notification.error('net error');
return Promise.reject(error);
};
// post form
const formInstance = axios.create({
baseURL: '/',
timeout: 3000,
transformRequest: [(data) => qs.stringify(data)],
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'application/json,application/vnd.ms-excel',
},
});
formInstance.interceptors.response.use(responseErrorStatus, responseNetError);
instance.interceptors.response.use(responseErrorStatus, responseNetError);
export const makeService = (url, opt = {method: 'get'}) => (params = {}) => {
if (opt.method === 'delete' || opt.method === 'get') {
params = {params};
}
return instance[opt.method](url, params);
};
export const makeFormService = (url, method = 'post') => (params = {}) => formInstance[method](url, params);
import quantile from './quantile';
export {
quantile,
};
export default function(x) {
return x === null ? NaN : +x;
}
import number from './number';
export default function(values, p, valueof) {
if (valueof == null) {
return valueof = number;
}
let n = values.length;
if (!(n)) {
return;
}
if ((p = +p) <= 0 || n < 2) {
return +valueof(values[0], 0, values);
}
if (p >= 1) {
return +valueof(values[n - 1], n - 1, values);
}
let i = (n - 1) * p;
let i0 = Math.floor(i);
let value0 = +valueof(values[i0], i0, values);
let value1 = +valueof(values[i0 + 1], i0 + 1, values);
return value0 + (value1 - value0) * (i - i0);
}
import {router} from 'san-router';
export function routeTo(url, params = {}) {
let paramsArr = Object.keys(params).map((key) => `${key}=${params[key]}`);
let urlParams = (url.indexOf('?') > -1 ? '&' : '?') + paramsArr.join('&');
router.locator.redirect(urlParams.length > 1 ? `${url}${urlParams}` : url);
}
<template>
<div class="visual-dl-page-container">
<div class="visual-dl-page-left">
<ui-chart
:do-download="doDownload"
:do-restore="doRestore"
:scale="config.scale"
@curNodeUpdated="curNode = $event"
@triggerDownload="doDownload = $event"
@triggerRestore="doRestore = $event"
/>
</div>
<div class="visual-dl-page-right">
<div class="visual-dl-page-config-container">
<ui-config
:cur-node="curNode"
:do-download="doDownload"
:config="config"
@triggerDownload="doDownload = $event"
@triggerRestore="doRestore = $event"
/>
</div>
</div>
</div>
</template>
<script>
import autoAdjustHeight from '../common/util/autoAdjustHeight';
import Config from './ui/Config';
import Chart from './ui/Chart';
export default {
components: {
'ui-config': Config,
'ui-chart': Chart,
},
name: 'Graph',
data() {
return {
doDownload: false,
doRestore: false,
curNode: {},
config: {
scale: 0.5,
},
};
},
mounted() {
autoAdjustHeight();
},
methods: {},
};
</script>
<style lang="stylus">
</style>
<template>
<div class="visual-dl-graph-charts">
<svg
:style="{ width: imageWidth + 'px', height: imageHeight + 'px' }"
class="visual-dl-page-left"
ref="graphSvg">
<g/>
</svg>
</div>
</template>
<script>
// service
import {getPluginGraphsGraph} from '../../service';
// Loading the JS lib file will bind saveSvgAsPng to window,
// which does an SVG -> PNG -> download process.
import './svgToPngDownloadHelper.js';
// for d3 drawing
import * as d3 from 'd3';
import has from 'lodash/has';
import isArrayLike from 'lodash/isArrayLike';
export default {
props: {
'doDownload': {
type: Boolean,
required: true,
},
'doRestore': {
type: Boolean,
required: true,
},
'scale': {
type: Number,
required: true,
},
},
computed: {},
data() {
return {
imageHeight: 0,
imageWidth: 0,
originImageWidth: 0,
originImageHeight: 0,
graphZoom: null,
svgSelection: null,
zoomScale: null,
graphConfig: {
drawInputNode: false,
drawOutputNode: false,
drawTempNode: false,
inputMap: {},
},
};
},
watch: {
doDownload: function(val) {
let chartScope = this;
if (this.doDownload) {
// in order to download the full graph image, we need to first restore it
// to its original size
this.restoreImage(true);
chartScope.$emit('triggerDownload', false);
}
},
doRestore: function(val) {
this.restoreImage(false);
},
scale: function(val) {
let k = this.zoomScale(val);
let svg = d3.select('svg');
svg.call(this.graphZoom.transform, d3.zoomIdentity.scale(k));
},
},
methods: {
// get the relate operator of a variable
getVarRelateDict(graphData) {
let dic = {};
for (let i = 0; i < graphData['node'].length; ++i) {
let curOperatorNode = graphData['node'][i];
let nodeKey = 'opNode_' + i;
// record all relate operator of a variable
if (has(curOperatorNode, 'output') && isArrayLike(curOperatorNode['output'])) {
for (let j = 0; j < curOperatorNode['output'].length; ++j) {
let outputData = curOperatorNode['output'][j];
if (!dic[outputData]) {
dic[outputData] = {'input': [], 'output': []};
}
let arr = dic[outputData]['input'];
arr[arr.length] = nodeKey;
}
}
if (has(curOperatorNode, 'input') && isArrayLike(curOperatorNode['input'])) {
for (let j = 0; j < curOperatorNode['input'].length; ++j) {
let inputData = curOperatorNode['input'][j];
if (!dic[inputData]) {
dic[inputData] = {'input': [], 'output': []};
}
let arr = dic[inputData]['output'];
arr[arr.length] = nodeKey;
}
}
}
return dic;
},
getInputNodeStyle() {
return 'opacity: 0.1; ' +
'stroke-width: 3px; ' +
'stroke: #333; ' +
'stroke-color: #41b3a3; ' +
'fill: #6c648b; ';
},
getOutputNodeStyle() {
return 'opacity: 0.1;' +
'stroke-width: 3px; ' +
'stroke-dasharray: 5, 5;' +
'stroke: #333;' +
'stroke-color: #41b3a3; ' +
'fill: #015249; ';
},
getTempNodeStyle() {
return getOutputNodeStyle();
},
getOpNodeStyle() {
return 'stroke-width: 3px; ' +
'opacity: 0.1; ' +
'rx: 10; ' +
'ry: 10; ' +
'stroke: #333; ' +
'stroke-color: #41b3a3; ' +
'fill: #008c99; ';
},
setGraphNode(graph, nodeKey, labelVal, shapeVal, className, styleVal) {
graph.setNode(
nodeKey,
{
label: labelVal,
shape: shapeVal,
class: className,
style: styleVal,
}
);
},
buildInputNodeLabel(inputNode) {
// TODO(daming-lu): need more complex compound node
let nodeLabel = 'id: ' + inputNode['name'] + '\n'
+ 'type: ' + inputNode['data_type'] + '\n'
+ 'dims: ' + inputNode['shape'].join(' x ');
return nodeLabel;
},
buildGraph(graph, graphData) {
// add operator node
for (let i = 0; i < graphData['node'].length; ++i) {
let curOperatorNode = graphData['node'][i];
let nodeKey = 'opNode_' + i;
// add operator node
let curOpLabel = curOperatorNode['opType'];
curOpLabel = curOpLabel + ' '.repeat(Math.floor(curOpLabel.length/5));
this.setGraphNode(graph, nodeKey, curOpLabel, 'rect', 'operator', this.getOpNodeStyle());
}
let dic = this.getVarRelateDict(graphData);
for (let obj in dic) {
if (!dic.hasOwnProperty(obj)) continue;
// add input node
if (dic[obj]['input'].length === 0 && this.graphConfig.drawInputNode === true) {
let temp = obj.indexOf('@');
let nodeKey = obj;
if (temp > 0) {
nodeKey = obj.substr(0, temp);
}
let index = this.graphConfig.inputMap[nodeKey];
let curInputNode = graphData['input'][index];
this.setGraphNode(graph, nodeKey,
this.buildInputNodeLabel(curInputNode), 'rect', 'input', this.getInputNodeStyle());
for (let output in dic[obj]['output']) {
if (!dic[obj]['output'].hasOwnProperty(output)) continue;
graph.setEdge(nodeKey, dic[obj]['output'][output]);
}
}
// add output node
if (dic[obj]['output'].length === 0 && this.graphConfig.drawOutputNode === true) {
let nodeKey = obj;
let outputPadding = ' '.repeat(Math.floor(nodeKey.length/2));
this.setGraphNode(graph, nodeKey, nodeKey + outputPadding, 'diamond', 'output', this.getOutputNodeStyle());
for (let input in dic[obj]['input']) {
if (!dic[obj]['input'].hasOwnProperty(input)) continue;
graph.setEdge(nodeKey, dic[obj]['input'][input]);
}
}
for (let input in dic[obj]['input']) {
if (!dic[obj]['input'].hasOwnProperty(input)) continue;
for (let output in dic[obj]['output']) {
if (!dic[obj]['output'].hasOwnProperty(output)) continue;
if (this.graphConfig.drawTempNode === true) {
let nodeKey = obj;
let outputPadding = ' '.repeat(Math.floor(nodeKey.length/2));
this.setGraphNode(graph,
nodeKey, nodeKey + outputPadding, 'diamond', 'output', this.getOutputNodeStyle());
graph.setEdge(dic[obj]['input'][input], nodeKey);
graph.setEdge(nodeKey, dic[obj]['output'][output]);
} else {
graph.setEdge(dic[obj]['input'][input], dic[obj]['output'][output]);
}
}
}
}
},
restoreImage(thenDownload) {
let chartScope = this;
let svg = d3.select('svg');
this.imageWidth = this.originImageWidth;
this.imageHeight = this.originImageHeight;
if (thenDownload) {
svg.transition()
.duration(750)
.call(this.graphZoom.transform, d3.zoomIdentity.translate(0, 0))
.on('end', function() {
let svg = chartScope.$refs.graphSvg;
saveSvgAsPng(svg, 'graph.png', {scale: 1.0});
});
} else {
svg.transition()
.duration(750)
.call(this.graphZoom.transform, d3.zoomIdentity.translate(0, 0));
}
this.$emit('triggerRestore', false);
},
},
created() {
// scale
let linearScale = d3.scaleLinear();
linearScale.domain([0.1, 1]);
linearScale.range([0.75, 1.25]);
this.zoomScale = linearScale;
},
mounted() {
// some model is too large to draw in dagred3, so don't draw input and output node in default
let chartScope = this;
getPluginGraphsGraph().then(({errno, data}) => {
if (has(data, 'data') === false) {
return;
}
let graphData = data.data;
if (has(graphData, 'node') === false) {
return;
}
// d3 svg drawing
let g = new dagreD3.graphlib.Graph()
.setGraph({})
.setDefaultEdgeLabel(function() {
return {};
});
// eslint-disable-next-line
let render = new dagreD3.render();
if (has(graphData, 'input') === true && this.graphConfig.drawInputNode === true) {
for (let i = 0; i < graphData['input'].length; ++i) {
let name = graphData['input'][i]['name'];
this.graphConfig.inputMap[name] = i;
}
}
this.buildGraph(g, graphData);
let svg = d3.select('svg')
.attr('font-family', 'sans-serif')
.attr('font-size', '28px');
render(d3.select('svg g'), g);
let graphSelection = d3.select('svg g');
let graphWidth = g.graph().width;
let graphHeight = g.graph().height;
svg.attr('viewBox', '0 0 ' + graphWidth + ' ' + graphHeight);
this.imageWidth = graphWidth * 1.1;
this.imageHeight = graphHeight;
this.originImageWidth = graphWidth * 1.1;
this.originImageHeight = graphHeight;
// zooming
let zooming = function(d) {
graphSelection.attr('transform', d3.event.transform);
let newViewBoxWidth = d3.event.transform.k * graphWidth;
let newViewBoxHeight = d3.event.transform.k * graphHeight;
chartScope.imageWidth = newViewBoxWidth;
chartScope.imageHeight = newViewBoxHeight;
};
let zoom = d3.zoom().on('zoom', zooming);
chartScope.graphZoom = zoom;
// TODO(daming-lu): enable zoom would have conflict with scale slider
// need to find a coordinated way to handle panning and zooming.
// svg.call(zoom);
svg.selectAll('.node').on('click', function(d, i) {
let curNode = g.node(d);
let nodeType = curNode.class;
let nodeInfo = null;
if (nodeType === 'operator') {
let opIndex = d.slice(7); // remove prefix "opNode_"
nodeInfo = graphData.node[opIndex];
} else if (nodeType === 'input') {
nodeInfo = graphData.input[this.graphConfig.inputMap[d]];
} else {
nodeInfo = 'output';
}
chartScope.$emit('curNodeUpdated',
{
'nodeType': nodeType,
'nodeInfo': nodeInfo,
});
});
});
},
};
</script>
<style lang="stylus">
.node
cursor: pointer
.edgePath path.path
stroke: #333
stroke-width: 1.5px
.visual-dl-graph-charts
width inherit
margin 0 auto
margin-bottom 20px
.visual-dl-chart-box
height 600px
.visual-dl-img-box
border solid 1px #e4e4e4
position relative
background #f0f0f0
overflow hidden
img
box-sizing border-box
margin 0 auto
display block
.small-img-box
width 30px
box-sizing border-box
position absolute
right 0
top 0
border-left solid 1px #e4e4e4
border-bottom solid 1px #e4e4e4
background #f0f0f0
z-index 1
.screen-handler
box-sizing border-box
position absolute
width 30px
height 20px
border solid 1px #666
top 0
left -1px
</style>
<template>
<div class="visual-dl-graph-config-com">
<div class="graph-config-upper">
<v-btn
class="visual-dl-graph-config-button"
color="primary"
@click="handleDownload"
dark>
<v-icon style="margin-right: 6px">file_download</v-icon>
{{ $t("lang.downloadImage") }}
</v-btn>
<v-btn
class="visual-dl-graph-config-button"
color="primary"
@click="resetImage"
dark>
<v-icon style="margin-right: 6px">restore</v-icon>
{{ $t("lang.restoreImage") }}
</v-btn>
<v-slider
:label="$t('lang.scale')"
max="1"
min="0.1"
step="0.1"
v-model="config.scale"
dark/>
</div>
<div class="node-info">
<h3>{{ $t("lang.nodeInfo") }}: </h3>
<div v-if="curNode.nodeType === 'input'">
<div>{{ $t("lang.nodeType") }}: {{ curNode.nodeType }}</div>
<div>{{ $t("lang.nodeName") }}: {{ curNode.nodeInfo.name }}</div>
<div>{{ $t("lang.dataShape") }}: {{ curNode.nodeInfo.shape }}</div>
<div>{{ $t("lang.dataType") }}: {{ curNode.nodeInfo.data_type }}</div>
</div>
<div v-else-if="curNode.nodeType === 'output'">
<div>{{ $t("lang.nodeType") }}: {{ curNode.nodeType }}</div>
</div>
<div v-else-if="curNode.nodeType === 'operator'">
<div>{{ $t("lang.nodeType") }}: {{ curNode.nodeType }}</div>
<div>{{ $t("lang.input") }}: {{ curNode.nodeInfo.input }}</div>
<div>{{ $t("lang.opType") }}: {{ curNode.nodeInfo.opType }}</div>
<div>{{ $t("lang.output") }}: {{ curNode.nodeInfo.output }}</div>
</div>
<div v-else/>
</div>
</div>
</template>
<script>
export default {
props: {
'doDownload': {
type: Boolean,
required: true,
},
'curNode': {
type: Object,
default: {},
},
'config': {
type: Object,
required: true,
},
}, methods: {
handleDownload() {
this.$emit('triggerDownload', true);
},
resetImage() {
this.$emit('triggerRestore', true);
},
},
};
</script>
<style lang="stylus">
@import '../../style/variables';
+prefix-classes('visual-dl-graph-')
.config-com
width 90%
margin 20px auto
color $-right-font-color
.config-button
width 200px
margin-top 20px
.visual-dl-graph-config-com
.sm-icon
width 36px
height 26px
.graph-config-upper
height 300px
.node-info
font-family 'Courier New', sans-serif
font-weight bold
</style>
export const dragMovelHandler = (event, callback) => {
let target = event.target;
// keep the dragged position in the data-x/data-y attributes
let x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx;
let y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
callback(target, x, y);
};
export const tansformElement = (target, x, y) => {
// translate the element
target.style.webkitTransform = target.style.transform
= 'translate(' + x + 'px, ' + y + 'px)';
// update the posiion attributes
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
};
export const relativeMove = ({triggerEl, x, y}, relativeEl) => {
let {offsetWidth: tWidth, offsetHeight: tHeight} = triggerEl;
let {offsetWidth: rWidth, offsetHeight: rHeight} = relativeEl;
let rX = (x / tWidth) * rWidth;
let rY = (y / tHeight) * rHeight;
tansformElement(relativeEl, -rX, -rY);
};
// URL for this library : https://github.com/exupero/saveSvgAsPng
// Blog about it: https://spin.atomicobject.com/2014/01/21/convert-svg-to-png/
(function() {
var out$ = window;
var doctype = '<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [<!ENTITY nbsp "&#160;">]>';
function isElement(obj) {
return obj instanceof HTMLElement || obj instanceof SVGElement;
}
function requireDomNode(el) {
if (!isElement(el)) {
throw new Error('an HTMLElement or SVGElement is required; got ' + el);
}
}
function isExternal(url) {
return url && url.lastIndexOf('http',0) == 0 && url.lastIndexOf(window.location.host) == -1;
}
function inlineImages(el, callback) {
requireDomNode(el);
var images = el.querySelectorAll('image'),
left = images.length,
checkDone = function() {
if (left === 0) {
callback();
}
};
checkDone();
for (var i = 0; i < images.length; i++) {
(function(image) {
var href = image.getAttributeNS("http://www.w3.org/1999/xlink", "href");
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var img = new Image();
img.crossOrigin="anonymous";
href = href || image.getAttribute('href');
if (isExternal(href)) {
href += (href.indexOf('?') === -1 ? '?' : '&') + 't=' + (new Date().valueOf());
}
if (href) {
img.src = href;
img.onload = function() {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
image.setAttributeNS("http://www.w3.org/1999/xlink", "href", canvas.toDataURL('image/png'));
left--;
checkDone();
}
img.onerror = function() {
console.log("Could not load "+href);
left--;
checkDone();
}
} else {
left--;
checkDone();
}
})(images[i]);
}
}
function styles(el, options, cssLoadedCallback) {
var selectorRemap = options.selectorRemap;
var modifyStyle = options.modifyStyle;
var modifyCss = options.modifyCss || function(selector, properties) {
var selector = selectorRemap ? selectorRemap(selector) : selector;
var cssText = modifyStyle ? modifyStyle(properties) : properties;
return selector + " { " + cssText + " }\n";
};
var css = "";
// Each font that has an external link is saved into queue, and processed asynchronously.
var fontsQueue = [];
var sheets = document.styleSheets;
for (var i = 0; i < sheets.length; i++) {
try {
var rules = sheets[i].cssRules;
} catch (e) {
console.warn("Stylesheet could not be loaded: "+sheets[i].href);
continue;
}
if (rules != null) {
for (var j = 0, match; j < rules.length; j++, match = null) {
var rule = rules[j];
if (typeof(rule.style) != "undefined") {
var selectorText;
try {
selectorText = rule.selectorText;
} catch(err) {
console.warn('The following CSS rule has an invalid selector: "' + rule + '"', err);
}
try {
if (selectorText) {
match = el.querySelector(selectorText) || (el.parentNode && el.parentNode.querySelector(selectorText));
}
} catch(err) {
console.warn('Invalid CSS selector "' + selectorText + '"', err);
}
if (match) {
css += modifyCss(rule.selectorText, rule.style.cssText);
} else if(rule.cssText.match(/^@font-face/)) {
// below we are trying to find matches to external link. E.g.
// @font-face {
// // ...
// src: local('Abel'), url(https://fonts.gstatic.com/s/abel/v6/UzN-iejR1VoXU2Oc-7LsbvesZW2xOQ-xsNqO47m55DA.woff2);
// }
//
// This regex will save extrnal link into first capture group
var fontUrlRegexp = /url\(["']?(.+?)["']?\)/;
// TODO: This needs to be changed to support multiple url declarations per font.
var fontUrlMatch = rule.cssText.match(fontUrlRegexp);
var externalFontUrl = (fontUrlMatch && fontUrlMatch[1]) || '';
var fontUrlIsDataURI = externalFontUrl.match(/^data:/);
if (fontUrlIsDataURI) {
// We should ignore data uri - they are already embedded
externalFontUrl = '';
}
if (externalFontUrl === 'about:blank') {
// no point trying to load this
externalFontUrl = '';
}
if (externalFontUrl) {
// okay, we are lucky. We can fetch this font later
//handle url if relative
if (externalFontUrl.startsWith('../')) {
externalFontUrl = sheets[i].href + '/../' + externalFontUrl
} else if (externalFontUrl.startsWith('./')) {
externalFontUrl = sheets[i].href + '/.' + externalFontUrl
}
fontsQueue.push({
text: rule.cssText,
// Pass url regex, so that once font is downladed, we can run `replace()` on it
fontUrlRegexp: fontUrlRegexp,
format: getFontMimeTypeFromUrl(externalFontUrl),
url: externalFontUrl
});
} else {
// otherwise, use previous logic
css += rule.cssText + '\n';
}
}
}
}
}
}
// Now all css is processed, it's time to handle scheduled fonts
processFontQueue(fontsQueue);
function getFontMimeTypeFromUrl(fontUrl) {
var supportedFormats = {
'woff2': 'font/woff2',
'woff': 'font/woff',
'otf': 'application/x-font-opentype',
'ttf': 'application/x-font-ttf',
'eot': 'application/vnd.ms-fontobject',
'sfnt': 'application/font-sfnt',
'svg': 'image/svg+xml'
};
var extensions = Object.keys(supportedFormats);
for (var i = 0; i < extensions.length; ++i) {
var extension = extensions[i];
// TODO: This is not bullet proof, it needs to handle edge cases...
if (fontUrl.indexOf('.' + extension) > 0) {
return supportedFormats[extension];
}
}
// If you see this error message, you probably need to update code above.
console.error('Unknown font format for ' + fontUrl+ '; Fonts may not be working correctly');
return 'application/octet-stream';
}
function processFontQueue(queue) {
if (queue.length > 0) {
// load fonts one by one until we have anything in the queue:
var font = queue.pop();
processNext(font);
} else {
// no more fonts to load.
cssLoadedCallback(css);
}
function processNext(font) {
// TODO: This could benefit from caching.
var oReq = new XMLHttpRequest();
oReq.addEventListener('load', fontLoaded);
oReq.addEventListener('error', transferFailed);
oReq.addEventListener('abort', transferFailed);
oReq.open('GET', font.url);
oReq.responseType = 'arraybuffer';
oReq.send();
function fontLoaded() {
// TODO: it may be also worth to wait until fonts are fully loaded before
// attempting to rasterize them. (e.g. use https://developer.mozilla.org/en-US/docs/Web/API/FontFaceSet )
var fontBits = oReq.response;
var fontInBase64 = arrayBufferToBase64(fontBits);
updateFontStyle(font, fontInBase64);
}
function transferFailed(e) {
console.warn('Failed to load font from: ' + font.url);
console.warn(e)
css += font.text + '\n';
processFontQueue(queue);
}
function updateFontStyle(font, fontInBase64) {
var dataUrl = 'url("data:' + font.format + ';base64,' + fontInBase64 + '")';
css += font.text.replace(font.fontUrlRegexp, dataUrl) + '\n';
// schedule next font download on next tick.
setTimeout(function() {
processFontQueue(queue)
}, 0);
}
}
}
function arrayBufferToBase64(buffer) {
var binary = '';
var bytes = new Uint8Array(buffer);
var len = bytes.byteLength;
for (var i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return window.btoa(binary);
}
}
function getDimension(el, clone, dim) {
var v = (el.viewBox && el.viewBox.baseVal && el.viewBox.baseVal[dim]) ||
(clone.getAttribute(dim) !== null && !clone.getAttribute(dim).match(/%$/) && parseInt(clone.getAttribute(dim))) ||
el.getBoundingClientRect()[dim] ||
parseInt(clone.style[dim]) ||
parseInt(window.getComputedStyle(el).getPropertyValue(dim));
return (typeof v === 'undefined' || v === null || isNaN(parseFloat(v))) ? 0 : v;
}
function reEncode(data) {
data = encodeURIComponent(data);
data = data.replace(/%([0-9A-F]{2})/g, function(match, p1) {
var c = String.fromCharCode('0x'+p1);
return c === '%' ? '%25' : c;
});
return decodeURIComponent(data);
}
out$.prepareSvg = function(el, options, cb) {
requireDomNode(el);
options = options || {};
options.scale = options.scale || 1;
options.responsive = options.responsive || false;
var xmlns = "http://www.w3.org/2000/xmlns/";
inlineImages(el, function() {
var outer = document.createElement("div");
var clone = el.cloneNode(true);
var width, height;
if(el.tagName == 'svg') {
width = options.width || getDimension(el, clone, 'width');
height = options.height || getDimension(el, clone, 'height');
} else if(el.getBBox) {
var box = el.getBBox();
width = box.x + box.width;
height = box.y + box.height;
clone.setAttribute('transform', clone.getAttribute('transform').replace(/translate\(.*?\)/, ''));
var svg = document.createElementNS('http://www.w3.org/2000/svg','svg')
svg.appendChild(clone)
clone = svg;
} else {
console.error('Attempted to render non-SVG element', el);
return;
}
clone.setAttribute("version", "1.1");
if (!clone.getAttribute('xmlns')) {
clone.setAttributeNS(xmlns, "xmlns", "http://www.w3.org/2000/svg");
}
if (!clone.getAttribute('xmlns:xlink')) {
clone.setAttributeNS(xmlns, "xmlns:xlink", "http://www.w3.org/1999/xlink");
}
if (options.responsive) {
clone.removeAttribute('width');
clone.removeAttribute('height');
clone.setAttribute('preserveAspectRatio', 'xMinYMin meet');
} else {
clone.setAttribute("width", width * options.scale);
clone.setAttribute("height", height * options.scale);
}
clone.setAttribute("viewBox", [
options.left || 0,
options.top || 0,
width,
height
].join(" "));
var fos = clone.querySelectorAll('foreignObject > *');
for (var i = 0; i < fos.length; i++) {
if (!fos[i].getAttribute('xmlns')) {
fos[i].setAttributeNS(xmlns, "xmlns", "http://www.w3.org/1999/xhtml");
}
}
outer.appendChild(clone);
// In case of custom fonts we need to fetch font first, and then inline
// its url into data-uri format (encode as base64). That's why style
// processing is done asynchonously. Once all inlining is finshed
// cssLoadedCallback() is called.
styles(el, options, cssLoadedCallback);
function cssLoadedCallback(css) {
// here all fonts are inlined, so that we can render them properly.
var s = document.createElement('style');
s.setAttribute('type', 'text/css');
s.innerHTML = "<![CDATA[\n" + css + "\n]]>";
var defs = document.createElement('defs');
defs.appendChild(s);
clone.insertBefore(defs, clone.firstChild);
if (cb) {
var outHtml = outer.innerHTML;
outHtml = outHtml.replace(/NS\d+:href/gi, 'xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href');
cb(outHtml, width, height);
}
}
});
}
out$.svgAsDataUri = function(el, options, cb) {
out$.prepareSvg(el, options, function(svg) {
var uri = 'data:image/svg+xml;base64,' + window.btoa(reEncode(doctype + svg));
if (cb) {
cb(uri);
}
});
}
out$.svgAsPngUri = function(el, options, cb) {
requireDomNode(el);
options = options || {};
options.encoderType = options.encoderType || 'image/png';
options.encoderOptions = options.encoderOptions || 0.8;
var convertToPng = function(src, w, h) {
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
canvas.width = w;
canvas.height = h;
var pixelRatio = window.devicePixelRatio || 1;
canvas.style.width = canvas.width+'px';
canvas.style.height = canvas.height+'px';
canvas.width *= pixelRatio;
canvas.height *= pixelRatio;
context.setTransform(pixelRatio,0,0,pixelRatio,0,0);
if(options.canvg) {
options.canvg(canvas, src);
} else {
context.drawImage(src, 0, 0);
}
if(options.backgroundColor){
context.globalCompositeOperation = 'destination-over';
context.fillStyle = options.backgroundColor;
context.fillRect(0, 0, canvas.width, canvas.height);
}
var png;
try {
png = canvas.toDataURL(options.encoderType, options.encoderOptions);
} catch (e) {
if ((typeof SecurityError !== 'undefined' && e instanceof SecurityError) || e.name == "SecurityError") {
console.error("Rendered SVG images cannot be downloaded in this browser.");
return;
} else {
throw e;
}
}
cb(png);
}
if(options.canvg) {
out$.prepareSvg(el, options, convertToPng);
} else {
out$.svgAsDataUri(el, options, function(uri) {
var image = new Image();
image.onload = function() {
convertToPng(image, image.width, image.height);
}
image.onerror = function() {
console.error(
'There was an error loading the data URI as an image on the following SVG\n',
window.atob(uri.slice(26)), '\n',
"Open the following link to see browser's diagnosis\n",
uri);
}
image.src = uri;
});
}
}
out$.download = function(name, uri) {
if (navigator.msSaveOrOpenBlob) {
navigator.msSaveOrOpenBlob(uriToBlob(uri), name);
} else {
var saveLink = document.createElement('a');
var downloadSupported = 'download' in saveLink;
if (downloadSupported) {
saveLink.download = name;
saveLink.style.display = 'none';
document.body.appendChild(saveLink);
try {
var blob = uriToBlob(uri);
var url = URL.createObjectURL(blob);
saveLink.href = url;
saveLink.onclick = function() {
requestAnimationFrame(function() {
URL.revokeObjectURL(url);
})
};
} catch (e) {
console.warn('This browser does not support object URLs. Falling back to string URL.');
saveLink.href = uri;
}
saveLink.click();
document.body.removeChild(saveLink);
}
else {
window.open(uri, '_temp', 'menubar=no,toolbar=no,status=no');
}
}
}
function uriToBlob(uri) {
var byteString = window.atob(uri.split(',')[1]);
var mimeString = uri.split(',')[0].split(':')[1].split(';')[0]
var buffer = new ArrayBuffer(byteString.length);
var intArray = new Uint8Array(buffer);
for (var i = 0; i < byteString.length; i++) {
intArray[i] = byteString.charCodeAt(i);
}
return new Blob([buffer], {type: mimeString});
}
out$.saveSvg = function(el, name, options) {
requireDomNode(el);
options = options || {};
out$.svgAsDataUri(el, options, function(uri) {
out$.download(name, uri);
});
}
out$.saveSvgAsPng = function(el, name, options) {
requireDomNode(el);
options = options || {};
out$.svgAsPngUri(el, options, function(uri) {
out$.download(name, uri);
});
}
// if define is defined create as an AMD module
if (typeof define !== 'undefined') {
define(function() {
return out$;
});
}
})();
<template>
<div class="visual-dl-page-container">
<div class="visual-dl-page-left">
<ui-chart
:config="config"
:display-word-label="config.displayWordLabel"
:search-text="config.searchText"
:dimension="config.dimension"
:embedding-data="embeddingData"
:show-loading="showLoading"
/>
</div>
<div class="visual-dl-page-right">
<div class="visual-dl-page-config-container">
<ui-config
:config="config"
/>
</div>
</div>
</div>
</template>
<script>
import {getHighDimensionalDatasets} from '../service';
import autoAdjustHeight from '../common/util/autoAdjustHeight';
import Config from './ui/Config';
import Chart from './ui/Chart';
// the time to refresh chart data
const intervalTime = 30;
export default {
components: {
'ui-config': Config,
'ui-chart': Chart,
},
name: 'HighDimensional',
props: {
runs: {
type: Array,
required: true,
},
},
data() {
return {
config: {
searchText: '',
displayWordLabel: true,
dimension: '2',
reduction: 'pca',
selectedRun: '',
running: true,
},
embeddingData: [],
showLoading: false,
isDemo: process.env.NODE_ENV === 'demo',
};
},
created() {
// Setting selectedRun should trigger fetchDatasets
if (this.runs.length > 0) {
this.config.selectedRun = this.runs[0];
}
if (this.config.running && !this.isDemo) {
this.startInterval();
}
},
beforeDestroy() {
this.stopInterval();
},
watch: {
'config.dimension': function(val) {
this.fetchDatasets();
},
'config.reduction': function(val) {
this.fetchDatasets();
},
'config.selectedRun': function(val) {
this.fetchDatasets();
},
'config.running': function(val) {
(val && !this.isDemo) ? this.startInterval() : this.stopInterval();
},
runs: function(val) {
if (this.runs.length > 0) {
this.config.selectedRun = this.runs[0];
}
}
},
mounted() {
autoAdjustHeight();
},
methods: {
stopInterval() {
clearInterval(this.getOringDataInterval);
},
// get origin data per {{intervalTime}} seconds
startInterval() {
this.getOringDataInterval = setInterval(() => {
this.fetchDatasets();
}, intervalTime * 1000);
},
fetchDatasets() {
this.showLoading = true;
// Fetch the data from the server. Passing dimension and reduction method
let params = {
dimension: this.config.dimension,
reduction: this.config.reduction,
run: this.config.selectedRun,
};
getHighDimensionalDatasets(params).then(({errno, data}) => {
this.showLoading = false;
let vectorData = data.embedding;
let labels = data.labels;
for ( let i = 0; i < vectorData.length; i ++) {
vectorData[i].push(labels[i]);
}
this.embeddingData = vectorData;
});
},
},
};
</script>
<style lang="stylus">
</style>
<template>
<v-card
hover
class="visual-dl-page-charts">
<div
ref="chartBox"
class="visual-dl-chart-box"
:style="computedStyle"/>
<div class="visual-dl-chart-actions">
<v-btn
color="toolbox_icon"
flat
icon
@click="isSelectZoomEnable = !isSelectZoomEnable"
class="chart-toolbox-icons">
<img
v-if="!isSelectZoomEnable"
src="../../assets/ic_zoom_select_off.svg">
<img
v-if="isSelectZoomEnable"
src="../../assets/ic_zoom_select_on.svg">
</v-btn>
<v-btn
color="toolbox_icon"
flat
icon
@click="restoreChart"
class="chart-toolbox-icons">
<img src="../../assets/ic_undo.svg">
</v-btn>
<v-btn
color="toolbox_icon"
flat
icon
@click="saveChartAsImage"
class="chart-toolbox-icons" >
<img src="../../assets/ic_download.svg">
</v-btn>
</div>
</v-card>
</template>
<script>
import echarts from 'echarts';
import 'echarts-gl';
export default {
props: {
embeddingData: {
type: Array,
required: true,
},
config: {
type: Object,
required: true,
},
displayWordLabel: {
type: Boolean,
required: true,
},
searchText: {
type: String,
required: true,
},
dimension: {
type: String,
required: true,
},
showLoading: {
type: Boolean,
required: true,
},
},
data() {
return {
width: 900,
height: 600,
regularLabelColor: '#008c99',
matchedLabelColor: '#c23531',
isSelectZoomEnable: true,
};
},
computed: {
computedStyle() {
return 'height:' + this.height + 'px;' +
'width:' + this.width + 'px;';
},
},
created() {},
mounted() {
this.createChart();
this.set2DChartOptions();
this.setDisplayWordLabel();
this.toggleSelectZoom(true);
},
watch: {
embeddingData: function(val) {
// Got new data, pass to the filter function to render the 'matched' set and 'not matched' set
this.filterSeriesDataAndSetOption(this.searchText);
},
displayWordLabel: function(val) {
this.setDisplayWordLabel();
},
dimension: function(val) {
this.myChart.clear();
if (val === '2') {
this.set2DChartOptions();
this.setDisplayWordLabel();
} else {
this.set3DChartOptions();
this.setDisplayWordLabel();
}
},
searchText: function(val) {
this.filterSeriesDataAndSetOption(val);
},
showLoading: function(val) {
if (val) {
this.myChart.showLoading();
} else {
this.myChart.hideLoading();
}
},
isSelectZoomEnable: function(val) {
this.toggleSelectZoom(val);
},
},
methods: {
createChart() {
// Initialize the eChartBox
let el = this.$refs.chartBox;
this.myChart = echarts.init(el);
},
set2DChartOptions() {
let option = {
animation: false,
xAxis: {},
yAxis: {},
toolbox: {
show: true,
showTitle: false,
itemSize: 0,
feature: {
dataZoom: {
},
restore: {},
saveAsImage: {},
},
},
series: [{
name: 'all',
symbolSize: 10,
data: [],
type: 'scatter',
color: this.regularLabelColor,
},
{
name: 'matched',
animation: false,
symbolSize: 10,
data: [],
itemStyle: {
normal: {
opacity: 1,
},
},
label: {
normal: {
show: true,
formatter: function(param) {
return param.data[param.data.length - 1];
},
position: 'top',
},
},
type: 'scatter',
},
],
};
this.myChart.setOption(option);
},
set3DChartOptions() {
let symbolSize = 8;
let option3d = {
animation: false,
grid3D: {},
xAxis3D: {
type: 'category',
},
yAxis3D: {},
xAxis3D: {},
zAxis3D: {},
dataset: {
source: this.embeddingData,
},
series: [
{
name: 'all',
type: 'scatter3D',
symbolSize: symbolSize,
data: [],
color: this.regularLabelColor,
},
{
name: 'matched',
animation: false,
symbolSize: symbolSize,
data: [],
label: {
normal: {
show: true,
formatter: function(param) {
return param.data[param.data.length - 1];
},
position: 'top',
textStyle: {
color: this.matchedLabelColor,
},
},
},
type: 'scatter3D',
},
],
};
this.myChart.setOption(option3d);
},
setDisplayWordLabel() {
this.myChart.setOption({
series: [{
// Grab the 'all' series data
name: 'all',
label: {
normal: {
show: this.displayWordLabel,
formatter: function(param) {
return param.data[param.data.length - 1];
},
position: 'top',
textStyle: {
color: this.regularLabelColor,
},
},
emphasis: {
show: true,
},
},
}],
});
},
filterSeriesDataAndSetOption(keyWord) {
// Filter the data that has the hasPrefix
let matchedWords = [];
let notMatchedWords = [];
if (keyWord != '') {
keyWord = keyWord.toLowerCase();
this.embeddingData.forEach( function(dataItem) {
let word = dataItem[dataItem.length - 1];
if (typeof word == 'string' && word.toLowerCase().startsWith(keyWord)) {
matchedWords.push(dataItem);
} else {
notMatchedWords.push(dataItem);
}
});
} else {
notMatchedWords = this.embeddingData;
}
// Update the matched series data
this.myChart.setOption({
series: [{
// Grab the 'matched' series data
name: 'matched',
data: matchedWords,
},
{
// Grab the 'all' series data
name: 'all',
data: notMatchedWords,
}],
});
},
toggleSelectZoom(enable) {
let instance = this;
setTimeout(function() {
instance.myChart.dispatchAction({
type: 'takeGlobalCursor',
key: 'dataZoomSelect',
dataZoomSelectActive: enable,
});
}, 0);
},
restoreChart() {
this.myChart.dispatchAction({
type: 'restore',
});
},
saveChartAsImage() {
let dataUrl = this.myChart.getDataURL({
pixelRatio: 1,
backgroundColor: '#fff',
});
let fileName = 'embedding';
let link = document.createElement('a');
link.download = fileName;
link.href = dataUrl;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
},
},
};
</script>
<style lang="stylus">
.visual-dl-page-charts
float left
padding 10px
position relative
.visual-dl-chart-actions
opacity 0
transition: opacity .3s ease-out;
position absolute
top 4px
right 10px
img
width 30px
height 30px
position absolute
top 0
bottom 0
margin auto
.chart-toolbox-icons
width 25px
height 25px
margin-left -4px
margin-right -4px
.visual-dl-page-charts:hover
.visual-dl-chart-actions
opacity 1
</style>
<template>
<div class="visual-dl-page-config-com">
<v-text-field
:label="$t('lang.search')"
:hint="$t('lang.searchByLabel')"
v-model="config.searchText"
dark
/>
<v-checkbox
class="visual-dl-page-config-checkbox"
:label="$t('lang.displayAllLabel')"
v-model="config.displayWordLabel"
dark/>
<v-radio-group
:label="$t('lang.dimension')"
v-model="config.dimension"
dark>
<v-radio
:label="$t('lang.2D')"
value="2"/>
<v-radio
:label="$t('lang.3D')"
value="3"/>
</v-radio-group>
<v-radio-group
:label="$t('lang.reductionMethod')"
v-model="config.reduction"
dark>
<v-radio
label="PCA"
value="pca"/>
<v-radio
label="T-SNE"
value="tsne"/>
</v-radio-group>
<v-btn
:color="config.running ? 'primary' : 'error'"
v-model="config.running"
v-if="!isDemo"
@click="toggleAllRuns"
class="visual-dl-page-run-toggle"
dark
block
>
{{ config.running ? $t('lang.startRunning') : $t('lang.stopRunning') }}
</v-btn>
</div>
</template>
<script>
export default {
props: {
config: {
type: Object,
required: true,
},
},
data() {
return {
isDemo: process.env.NODE_ENV === 'demo',
};
},
methods: {
toggleAllRuns() {
this.config.running = !this.config.running;
},
},
};
</script>
<style lang="stylus">
+prefix-classes('visual-dl-page-')
.config-com
padding 20px
.slider-block
display flex
align-items center
.smoothing-slider
display inline
.slider-span
width 40px
.run-toggle
margin-top 20px
.config-selector
margin-top 12px
margin-bottom 20px
.checkbox-group-label
display flex
margin-top 20px
margin-bottom 10px
</style>
<template>
<div class="visual-dl-page-container">
<div class="visual-dl-page-left">
<ui-chart-page
:config="config"
:tag-list="filteredTagsList"
:title="'Tags matching ' + config.groupNameReg"
/>
<ui-chart-page
v-for="item in groupedTags"
:key="item.group"
:config="config"
:tag-list="item.tags"
:title="item.group"
/>
</div>
<div class="visual-dl-page-right">
<div class="visual-dl-page-config-container">
<ui-config
:config="config"
/>
</div>
</div>
</div>
</template>
<script>
import {getPluginHistogramsTags} from '../service';
import Config from './ui/Config';
import ChartPage from './ui/ChartPage';
import {flatten, uniq} from 'lodash';
import autoAdjustHeight from '../common/util/autoAdjustHeight';
export default {
components: {
'ui-config': Config,
'ui-chart-page': ChartPage,
},
props: {
runs: {
type: Array,
required: true,
},
},
data() {
return {
tags: [],
config: {
groupNameReg: '.*',
horizontal: 'step',
chartType: 'offset',
runs: [],
running: true,
},
filteredTagsList: [],
};
},
computed: {
tagsList() {
let tags = this.tags;
let runs = Object.keys(tags);
let tagsArray = runs.map((run) => Object.keys(tags[run]));
let allUniqTags = uniq(flatten(tagsArray));
// get the data for every chart
return allUniqTags.map((tag) => {
let tagList = runs.map((run) => {
return {
run,
tag: tags[run][tag],
};
}).filter((item) => item.tag !== undefined);
return {
tagList,
tag,
group: tag.split('/')[0],
};
});
},
groupedTags() {
let tagsList = this.tagsList || [];
// put data in group
let groupData = {};
tagsList.forEach((item) => {
let group = item.group;
if (groupData[group] === undefined) {
groupData[group] = [];
groupData[group].push(item);
} else {
groupData[group].push(item);
}
});
// to array
let groups = Object.keys(groupData);
return groups.map((group) => {
return {
group,
tags: groupData[group],
};
});
},
},
created() {
getPluginHistogramsTags().then(({errno, data}) => {
this.tags = data;
// filter when inited
let groupNameReg = this.config.groupNameReg;
this.filterTagsList(groupNameReg);
});
this.config.runs = this.runs;
},
mounted() {
autoAdjustHeight();
},
watch: {
'config.groupNameReg': function(val) {
this.throttledFilterTagsList();
},
runs: function(val) {
this.config.runs = val;
}
},
methods: {
filterTagsList(groupNameReg) {
if (!groupNameReg) {
this.filteredTagsList = [];
return;
}
let tagsList = this.tagsList || [];
let regExp = new RegExp(groupNameReg);
let filtedTagsList = tagsList.filter((item) => regExp.test(item.tag));
this.filteredTagsList = filtedTagsList;
},
throttledFilterTagsList: _.debounce(
function() {
this.filterTagsList(this.config.groupNameReg);
}, 300
),
},
};
</script>
<style lang="stylus">
</style>
import {min, max, range} from 'lodash';
export function tansformBackendData(histogramData) {
let [time, step, items] = histogramData;
return {
time,
step,
min: min(items.map(([left, right, count]) => left)),
max: max(items.map(([left, right, count]) => right)),
items: items.map(([left, right, count]) => ({left, right, count})),
};
}
export function computeNewHistogram(histogram, min, max, binsNum = 30) {
if (max === min) {
// Create bins even if all the data has a single value.
max = min * 1.1 + 1;
min = min / 1.1 - 1;
}
let stepWidth = (max - min) / binsNum;
let itemIndex = 0;
return range(min, max, stepWidth).map((binLeft) => {
let binRight = binLeft + stepWidth;
let yValue = 0;
while (itemIndex < histogram.items.length) {
let itemRight = Math.min(max, histogram.items[itemIndex].right);
let itemLeft = Math.max(min, histogram.items[itemIndex].left);
let overlap = Math.min(itemRight, binRight) - Math.max(itemLeft, binLeft);
let count = (overlap / (itemRight - itemLeft)) * histogram.items[itemIndex].count;
yValue += overlap > 0 ? count : 0;
// If `itemRight` is bigger than `binRight`, then this bin is
// finished and there also has data for the next bin, so don't increment
// `itemIndex`.
if (itemRight > binRight) {
break;
}
itemIndex++;
}
return {x: binLeft, dx: stepWidth, y: yValue};
});
}
export function tansformToVisData(tempData, time, step) {
return tempData.map(function(dataItem) {
return [time, step, dataItem.x + dataItem.dx / 2, Math.floor(dataItem.y)];
});
}
export function originDataToChartData(originData) {
let tempData = originData.map(tansformBackendData);
let globalMin = min(tempData.map(({min}) => min));
let globalMax = max(tempData.map(({max}) => max));
let chartData = tempData.map(function(item) {
let histoBins = computeNewHistogram(item, globalMin, globalMax);
let {time, step} = item;
return {
time,
step,
items: tansformToVisData(histoBins, time, step),
};
});
return {
min: globalMin,
max: globalMax,
chartData,
};
}
<template>
<v-card
hover
class="visual-dl-page-charts">
<div
class="visual-dl-chart-box"
ref="visual_dl_chart_box"/>
<div class="visual-dl-chart-actions">
<v-btn
color="toolbox_icon"
flat
icon
@click="isExpand = !isExpand"
class="chart-toolbox-icons" >
<img
v-if="!isExpand"
src="../../assets/ic_fullscreen_off.svg">
<img
v-if="isExpand"
src="../../assets/ic_fullscreen_on.svg">
</v-btn>
</div>
</v-card>
</template>
<script>
// libs
import echarts from 'echarts';
import {originDataToChartData} from '../histogramHelper';
import {format, precisionRound} from 'd3-format';
// service
import {getPluginHistogramsHistograms} from '../../service';
let zrDrawElement = {};
zrDrawElement.hoverDots = [];
// the time to refresh chart data
const intervalTime = 15;
const p = Math.max(0, precisionRound(0.01, 1.01) - 1);
const yValueFormat = format('.' + p + 'e');
export default {
props: {
tagInfo: {
type: Object,
required: true,
},
runs: {
type: Array,
required: true,
},
running: {
type: Boolean,
required: true,
},
chartType: {
type: String,
required: true,
},
},
data() {
return {
originData: [],
isExpand: false,
isDemo: process.env.NODE_ENV === 'demo',
};
},
watch: {
originData: function(val) {
this.initChartOption();
},
chartType: function(val) {
this.initChartOption();
},
running: function(val) {
(val && !this.isDemo) ? this.startInterval() : this.stopInterval();
},
isExpand: function(val) {
this.expandArea(val);
},
},
mounted() {
let tagInfo = this.tagInfo;
this.initChart(tagInfo);
if (this.running && !this.isDemo) {
this.startInterval();
}
},
beforeDestroy() {
this.stopInterval();
},
methods: {
initChart(tagInfo) {
this.createChart();
this.getOriginChartData(tagInfo);
},
createChart() {
let el = this.$refs.visual_dl_chart_box;
this.myChart = echarts.init(el);
},
initChartOption() {
this.myChart.clear();
let zr = this.myChart.getZr();
let hoverDots = zrDrawElement.hoverDots;
if (hoverDots != null && hoverDots.length !== 0) {
hoverDots.forEach((dot) => zr.remove(dot));
}
let chartType = this.chartType;
let data = this.originData;
let visData = originDataToChartData(data);
let tagInfo = this.tagInfo;
let title = tagInfo.tag.displayName + '(' + tagInfo.run + ')';
this.setChartOptions(visData, title, chartType);
},
setChartOptions(visData, tag, chartType) {
let grid = {
left: 45,
top: 60,
right: 40,
bottom: 36,
};
let title = {
text: tag,
textStyle: {
fontSize: '12',
fontWeight: 'normal',
},
};
if (chartType === 'overlay') {
this.setOverlayChartOption(visData, title, grid);
} else if (chartType === 'offset') {
this.setOffsetChartOption(visData, title, grid);
}
},
setOverlayChartOption({chartData, min, max}, title, grid) {
let seriesOption = chartData.map(({time, step, items}) => ({
name: 'step' + step,
type: 'line',
showSymbol: false,
hoverAnimation: false,
z: 0,
data: items,
animationDuration: 100,
lineStyle: {
normal: {
width: 1,
color: '#008c99',
},
},
encode: {
x: [2],
y: [3],
},
})
);
let option = {
title: title,
axisPointer: {
link: {xAxisIndex: 'all'},
show: true,
snap: true,
triggerTooltip: true,
},
grid: grid,
xAxis: {
type: 'value',
},
yAxis: {
type: 'value',
axisLine: {
onZero: false,
},
axisLabel: {
formatter(value, index) {
return yValueFormat(value);
},
},
axisPointer: {
label: {
formatter({value}) {
return yValueFormat(value);
},
},
},
},
series: seriesOption,
};
let zr1 = this.myChart.getZr();
zr1.on('mousemove', function(e) {
zr1.remove(zrDrawElement.hoverLine);
zr1.remove(zrDrawElement.tooltip);
zr1.remove(zrDrawElement.tooltipX);
zr1.remove(zrDrawElement.tooltipY);
zrDrawElement.hoverDots.forEach((dot) => zr1.remove(dot));
zrDrawElement.hoverDots.length = 0;
});
this.myChart.setOption(option, {notMerge: true});
},
setOffsetChartOption({chartData, min, max}, title, grid) {
let rawData = [];
let minX = min;
let maxX = max;
let minZ = Infinity;
let maxZ = -Infinity;
let ecChart = this.myChart;
let maxStep = -Infinity;
let minStep = Infinity;
grid.top = 126;
grid.left = 16;
grid.right = 40;
chartData.forEach(function(dataItem) {
let lineData = [];
maxStep = Math.max(dataItem.step, maxStep);
minStep = Math.min(dataItem.step, minStep);
dataItem.items.forEach(([time, step, x, y]) => {
minZ = Math.min(minZ, y);
maxZ = Math.max(maxZ, y);
lineData.push(x, step, y);
});
rawData.push(lineData);
});
let option = {
textStyle: {
fontFamily: 'Merriweather Sans',
},
title,
color: ['#006069'],
visualMap: {
type: 'continuous',
show: false,
min: minStep,
max: maxStep,
dimension: 1,
inRange: {
colorLightness: [0.2, 0.4],
},
},
xAxis: {
min: minX,
max: maxX,
axisLine: {
onZero: false,
},
axisLabel: {
fontSize: '11',
formatter: function(value) {
return Math.round(value * 100) / 100;
},
},
splitLine: {
show: false,
},
},
yAxis: {
position: 'right',
axisLine: {
onZero: false,
},
inverse: true,
splitLine: {
show: false,
},
axisLabel: {
fontSize: '11',
},
},
grid,
series: [{
type: 'custom',
dimensions: ['x', 'y'],
renderItem: function(params, api) {
let points = makePolyPoints(
params.dataIndex,
api.value,
api.coord,
params.coordSys.y - 10
);
return {
type: 'polygon',
silent: true,
shape: {
points,
},
style: api.style({
stroke: '#bbb',
lineWidth: 1,
}),
};
},
data: rawData,
}],
};
function makePolyPoints(dataIndex, getValue, getCoord, yValueMapHeight) {
let points = [];
for (let i = 0; i < rawData[dataIndex].length;) {
let x = getValue(i++);
let y = getValue(i++);
let z = getValue(i++);
points.push(getPoint(x, y, z, getCoord, yValueMapHeight));
}
return points;
}
function getPoint(x, y, z, getCoord, yValueMapHeight) {
let pt = getCoord([x, y]);
// linear map in z axis
pt[1] -= (z - minZ) / (maxZ - minZ) * yValueMapHeight;
return pt;
}
let zr = ecChart.getZr();
function removeTooltip() {
if (zrDrawElement.hoverLine) {
zr.remove(zrDrawElement.hoverLine);
zr.remove(zrDrawElement.tooltip);
zrDrawElement.hoverDots.forEach((dot) => zr.remove(dot));
zrDrawElement.hoverDots.length = 0;
zr.remove(zrDrawElement.tooltipX);
zr.remove(zrDrawElement.tooltipY);
}
}
zr.on('mouseout', (e) => {
removeTooltip();
});
zr.on('mousemove', (e) => {
removeTooltip();
let nearestIndex = findNearestValue(e.offsetX, e.offsetY);
if (nearestIndex) {
let getCoord = function(pt) {
return ecChart.convertToPixel('grid', pt);
};
let gridRect = ecChart.getModel().getComponent('grid', 0).coordinateSystem.getRect();
let linePoints = makePolyPoints(
nearestIndex.itemIndex,
function(i) {
return rawData[nearestIndex.itemIndex][i];
},
getCoord,
gridRect.y - 10
);
zr.add(zrDrawElement.hoverLine = new echarts.graphic.Polyline({
silent: true,
shape: {
points: linePoints,
},
style: {
stroke: '#5c5c5c',
lineWidth: 2,
},
z: 999,
}));
let itemX;
rawData.forEach((dataItem) => {
let binIndex = nearestIndex.binIndex;
let x = dataItem[binIndex * 3];
let y = dataItem[binIndex * 3 + 1];
let z = dataItem[binIndex * 3 + 2];
let pt = getPoint(x, y, z, getCoord, gridRect.y - 10);
itemX = pt[0];
let dot = new echarts.graphic.Circle({
shape: {
cx: pt[0],
cy: pt[1],
r: 3,
},
style: {
fill: '#000',
stroke: '#ccc',
lineWidth: 1,
},
z: 1000,
});
zr.add(dot);
zrDrawElement.hoverDots.push(dot);
});
let hoveredItem = chartData[nearestIndex.itemIndex];
zrDrawElement.tooltip = new echarts.graphic.Text({
position: [e.offsetX + 30, e.offsetY - 50],
style: {
fontFamily: 'Merriweather Sans',
text: yValueFormat(hoveredItem.items[nearestIndex.binIndex][3]),
textFill: '#000',
fontSize: 14,
textBackgroundColor: '#eee',
textBorderColor: '#008c99',
textBorderWidth: 2,
textBorderRadius: 5,
textPadding: 10,
rich: {},
},
z: 2000,
});
zr.add(zrDrawElement.tooltip);
zrDrawElement.tooltipX = new echarts.graphic.Text({
position: [
itemX,
gridRect.y + gridRect.height,
],
style: {
fontFamily: 'Merriweather Sans',
text: Math.round(hoveredItem.items[nearestIndex.binIndex][2] * 1000) / 1000,
textFill: '#fff',
textAlign: 'center',
fontSize: 12,
textBackgroundColor: '#333',
textBorderWidth: 2,
textPadding: [5, 7],
rich: {},
},
z: 2000,
});
zr.add(zrDrawElement.tooltipX);
zrDrawElement.tooltipY = new echarts.graphic.Text({
position: [
gridRect.x + gridRect.width,
linePoints[linePoints.length - 1][1],
],
style: {
fontFamily: 'Merriweather Sans',
text: hoveredItem.step,
textFill: '#fff',
textVerticalAlign: 'middle',
fontSize: 12,
textBackgroundColor: '#333',
textBorderWidth: 2,
textPadding: [5, 7],
rich: {},
},
z: 2000,
});
zr.add(zrDrawElement.tooltipY);
}
});
function findNearestValue(px, py) {
let value = ecChart.convertFromPixel('grid', [px, py]);
let itemIndex;
let nearestY = Infinity;
let binIndex;
chartData.forEach((item, index) => {
let dist = Math.abs(value[1] - item.step);
if (dist < nearestY) {
nearestY = dist;
itemIndex = index;
}
});
if (itemIndex != null) {
let dataItem = chartData[itemIndex];
let nearestX = Infinity;
dataItem.items.forEach((item, index) => {
let dist = Math.abs(item[2] - value[0]);
if (dist < nearestX) {
nearestX = dist;
binIndex = index;
}
});
if (binIndex != null) {
return {
itemIndex: itemIndex,
binIndex: binIndex,
};
}
}
}
ecChart.setOption(option, {notMerge: true});
},
// get origin data per 60 seconds
startInterval() {
this.getOringDataInterval = setInterval(() => {
let tagInfo = this.tagInfo;
this.getOriginChartData(tagInfo);
}, intervalTime * 1000);
},
stopInterval() {
clearInterval(this.getOringDataInterval);
},
getOriginChartData(tagInfo) {
let run = tagInfo.run;
let tag = tagInfo.tag;
let params = {
run,
tag: tag.displayName,
};
getPluginHistogramsHistograms(params).then(({status, data}) => {
if (status === 0) {
this.originData = data;
}
});
},
expandArea(expand) {
let pageBoxWidth = document.getElementsByClassName('visual-dl-chart-page')[0].offsetWidth;
let width = pageBoxWidth * 0.96; // 4% margin
if (expand) {
let el = this.$refs.visual_dl_chart_box;
el.style.width = width + 'px';
el.style.height = '600px';
this.isExpand = true;
this.myChart.resize({
width: width,
height: 600,
});
} else {
let el = this.$refs.visual_dl_chart_box;
el.style.width = '400px';
el.style.height = '300px';
this.isExpand = false;
this.myChart.resize({
width: 400,
height: 300,
});
}
},
},
};
</script>
<style lang="stylus">
.visual-dl-page-charts
float left
margin 2% 2% 0 0
background #fff
padding 10px
position relative
.visual-dl-chart-box
width 400px
height 300px
.visual-dl-chart-actions
opacity 0
transition: opacity .3s ease-out;
position absolute
top 4px
right 10px
img
width 30px
height 30px
position absolute
top 0
bottom 0
margin auto
.chart-toolbox-icons
width 25px
height 25px
margin-left -4px
margin-right -4px
.visual-dl-page-charts:hover
.visual-dl-chart-actions
opacity 1
</style>
<template>
<!-- ClassName visual-dl-chart-page used in chart.san, change they all if you need!-->
<div class="visual-dl-chart-page">
<ui-expand-panel
:info="total"
:title="title">
<div class="visual-dl-chart-page-box">
<ui-chart
v-for="(tagInfo, index) in filteredPageList"
:key="index"
:tag-info="tagInfo"
:runs="config.runs"
:chart-type="config.chartType"
:running="config.running"
/>
</div>
<v-pagination
class="visual-dl-sm-pagination"
v-if="total > pageSize"
v-model="currentPage"
:length="pageLength"
/>
</ui-expand-panel>
</div>
</template>
<script>
import ExpandPanel from '../../common/component/ExpandPanel';
import Chart from './Chart';
import {cloneDeep, flatten} from 'lodash';
export default {
props: {
config: {
type: Object,
required: true,
},
tagList: {
type: Array,
required: true,
},
title: {
type: String,
required: true,
},
},
components: {
'ui-chart': Chart,
'ui-expand-panel': ExpandPanel,
},
computed: {
filteredRunsList() {
let tagList = this.tagList || [];
let runs = this.config.runs || [];
let list = cloneDeep(tagList);
return flatten(list.slice().map((item) => {
return item.tagList.filter((one) => runs.includes(one.run));
}));
},
filteredPageList() {
let list = this.filteredRunsList;
let currentPage = this.currentPage;
let pageSize = this.pageSize;
return list.slice((currentPage - 1) * pageSize, currentPage * pageSize);
},
total() {
let list = this.filteredRunsList || [];
return list.length;
},
pageLength() {
return Math.ceil(this.total / this.pageSize);
},
},
data() {
return {
// current page
currentPage: 1,
// item per page
pageSize: 4,
};
},
methods: {
handlePageChange({pageNum}) {
this.currentPage = pageNum;
},
},
};
</script>
<style lang="stylus">
@import '../../style/variables';
+prefix-classes('visual-dl-')
.chart-page
.chart-box
float left
.chart-page-box:after
content: "";
clear: both;
display: block;
padding-bottom: 2%
</style>
<template>
<div class="visual-dl-page-config-com">
<v-text-field
label="Group name RegExp"
hint="input a tag group name to search"
v-model="config.groupNameReg"
dark
/>
<v-radio-group
label="Histogram mode"
v-model="config.chartType"
dark>
<v-radio
v-for="mode in chartTypeItems"
:key="mode.name"
:label="mode.name"
:value="mode.value"/>
</v-radio-group>
<v-btn
class="visual-dl-page-run-toggle"
:color="config.running ? 'primary' : 'error'"
v-model="config.running"
v-if="!isDemo"
@click="toggleAllRuns"
dark
block
>
{{ config.running ? 'Running' : 'Stopped' }}
</v-btn>
</div>
</template>
<script>
export default {
props: {
config: {
type: Object,
required: true,
},
},
data() {
return {
chartTypeItems: [
{
name: 'Overlay',
value: 'overlay',
},
{
name: 'Offset',
value: 'offset',
},
],
isDemo: process.env.NODE_ENV === 'demo',
};
},
methods: {
toggleAllRuns() {
let running = this.config.running;
this.config.running = !running;
},
},
};
</script>
<style lang="stylus">
+prefix-classes('visual-dl-page-')
.config-com
padding 20px
.run-toggle
margin-top 20px
.checkbox-group-label
display flex
margin-top 20px
margin-bottom 10px
</style>
<template>
<div class="visual-dl-page-container">
<div class="visual-dl-page-left">
<ui-chart-page
:expand="true"
:config="filteredConfig"
:tag-list="filteredTagsList"
:title="'Tags matching ' + config.groupNameReg"
/>
<ui-chart-page
v-for="item in groupedTags"
:key="item.group"
:config="filteredConfig"
:tag-list="item.tags"
:title="item.group"
/>
</div>
<div class="visual-dl-page-right">
<div class="visual-dl-page-config-container">
<ui-config
:config="config"
/>
</div>
</div>
</div>
</template>
<script>
import {getPluginImagesTags} from '../service';
import {flatten, uniq} from 'lodash';
import autoAdjustHeight from '../common/util/autoAdjustHeight';
import Config from './ui/Config';
import ChartPage from './ui/ChartPage';
export default {
name: 'Images',
components: {
'ui-config': Config,
'ui-chart-page': ChartPage,
},
props: {
runs: {
type: Array,
required: true,
},
},
data() {
return {
tags: [],
config: {
groupNameReg: '.*',
isActualImageSize: false,
runs: [],
running: true,
},
filteredTagsList: [],
};
},
computed: {
tagsList() {
let tags = this.tags;
let runs = Object.keys(tags);
let tagsArray = runs.map((run) => Object.keys(tags[run]));
let allUniqTags = uniq(flatten(tagsArray));
// get the data for every chart
return allUniqTags.map((tag) => {
let tagList = runs.map((run) => {
return {
run,
tag: tags[run][tag],
};
}).filter((item) => item.tag !== undefined);
return {
tagList,
tag,
group: tag.split('/')[0],
};
});
},
groupedTags() {
let tagsList = this.tagsList || [];
// put data in group
let groupData = {};
tagsList.forEach((item) => {
let group = item.group;
if (groupData[group] === undefined) {
groupData[group] = [];
groupData[group].push(item);
} else {
groupData[group].push(item);
}
});
// to array
let groups = Object.keys(groupData);
return groups.map((group) => {
return {
group,
tags: groupData[group],
};
});
},
filteredConfig() {
let config = this.config || {};
let filteredConfig = {};
Object.keys(config).forEach((key) => {
let val = config[key];
filteredConfig[key] = val;
});
return filteredConfig;
},
},
created() {
getPluginImagesTags().then(({errno, data}) => {
this.tags = data;
// filter when inited
let groupNameReg = this.config.groupNameReg;
this.filterTagsList(groupNameReg);
});
this.config.runs = this.runs;
},
mounted() {
autoAdjustHeight();
},
watch: {
'config.groupNameReg': function(val) {
this.throttledFilterTagsList();
},
runs: function(val) {
this.config.runs = val;
}
},
methods: {
filterTagsList(groupNameReg) {
if (!groupNameReg) {
this.filteredTagsList = [];
return;
}
let tagsList = this.tagsList || [];
let regExp = new RegExp(groupNameReg);
this.filteredTagsList = tagsList.filter((item) => regExp.test(item.tag));
},
throttledFilterTagsList: _.debounce(
function() {
this.filterTagsList(this.config.groupNameReg);
}, 300
),
},
};
</script>
<style lang="stylus">
</style>
<template>
<div class="visual-dl-chart-page">
<ui-expand-panel
:info="total"
:title="title">
<ui-image
class="visual-dl-chart-image"
v-for="(tagInfo, index) in filteredPageList"
:key="index"
:tag-info="tagInfo"
:is-actual-image-size="config.isActualImageSize"
:runs="config.runs"
:running="config.running"
/>
<v-pagination
class="visual-dl-sm-pagination"
v-if="total > pageSize"
v-model="currentPage"
:length="pageLength"
/>
</ui-expand-panel>
</div>
</template>
<script>
import ExpandPanel from '../../common/component/ExpandPanel';
import Image from './Image';
import {cloneDeep, flatten} from 'lodash';
export default {
props: {
config: {
type: Object,
required: true,
},
tagList: {
type: Array,
required: true,
},
title: {
type: String,
required: true,
},
},
components: {
'ui-image': Image,
'ui-expand-panel': ExpandPanel,
},
computed: {
filteredRunsList() {
let tagList = this.tagList || [];
let runs = this.config.runs || [];
let list = cloneDeep(tagList);
return flatten(list.slice().map((item) => {
return item.tagList.filter((one) => runs.includes(one.run));
}));
},
filteredPageList() {
let list = this.filteredRunsList || [];
return list.slice((this.currentPage - 1) * this.pageSize, this.currentPage * this.pageSize);
},
total() {
let list = this.filteredRunsList || [];
return list.length;
},
pageLength() {
return Math.ceil(this.total / this.pageSize);
},
},
data() {
return {
// current page
currentPage: 1,
// item per page
pageSize: 8,
};
},
};
</script>
<style lang="stylus">
@import '~style/variables';
+prefix-classes('visual-dl-')
.chart-page
.image-chart-box
overflow hidden
float left
.visual-dl-chart-image
float left
.image-chart-box:after
content ""
clear both
display block
.sm-pagination
height 50px
float left
width 100%
</style>
<template>
<div class="visual-dl-page-config-com">
<v-text-field
label="Group name RegExp"
hint="input a tag group name to search"
v-model="config.groupNameReg"
dark
/>
<v-checkbox
label="Show actual image size"
v-model="config.isActualImageSize"
dark/>
<v-btn
:color="config.running ? 'primary' : 'error'"
v-model="config.running"
v-if="!isDemo"
@click="toggleAllRuns"
class="visual-dl-page-run-toggle"
dark
block
>
{{ config.running ? 'Running' : 'Stopped' }}
</v-btn>
</div>
</template>
<script>
export default {
props: {
config: {
type: Object,
required: true,
},
},
data() {
return {
isDemo: process.env.NODE_ENV === 'demo',
};
},
methods: {
toggleAllRuns() {
this.config.running = !this.config.running;
},
},
};
</script>
<style lang="stylus">
+prefix-classes('visual-dl-page-')
.config-com
padding 20px
.run-toggle
margin-top 20px
.checkbox-group-label
display flex
margin-top 20px
margin-bottom 10px
</style>
<template>
<v-card
hover
class="visual-dl-image">
<h3 class="visual-dl-image-title">{{ tagInfo.tag.displayName }}
<span class="visual-dl-image-run-icon">{{ tagInfo.run }}</span>
</h3>
<p>
<span>Step:</span>
<span>{{ imgData.step }}</span>
<span class="visual-del-image-time">{{ imgData.wallTime | formatTime }}</span>
</p>
<v-slider
:max="steps"
:min="slider.min"
:step="1"
v-model="currentIndex"
/>
<img
:width="imageWidth"
:height="imageHeight"
:src="imgData.imgSrc" >
</v-card>
</template>
<script>
import {getPluginImagesImages} from '../../service';
const defaultImgWidth = 400;
const defaultImgHeight = 300;
// the time to refresh chart data
const intervalTime = 30;
export default {
props: {
tagInfo: {
type: Object,
required: true,
},
runs: {
type: Array,
required: true,
},
running: {
type: Boolean,
required: true,
},
isActualImageSize: {
type: Boolean,
required: true,
},
},
computed: {
steps() {
let data = this.data || [];
return data.length - 1;
},
imageWidth() {
return this.isActualImageSize ? this.imgData.width : defaultImgWidth;
},
imageHeight() {
return this.isActualImageSize ? this.imgData.height : defaultImgHeight;
},
},
filters: {
formatTime: function(value) {
if (!value) {
return;
}
// The value was made in seconds, must convert it to milliseconds
let time = new Date(value * 1000);
let options = {
weekday: 'short', year: 'numeric', month: 'short',
day: 'numeric', hour: '2-digit', minute: '2-digit', second: '2-digit',
};
return time.toLocaleDateString('en-US', options);
},
},
data() {
return {
currentIndex: 0,
slider: {
value: '0',
label: '',
min: 0,
step: 1,
},
imgData: {},
data: [],
height: defaultImgHeight,
weight: defaultImgWidth,
isDemo: process.env.NODE_ENV === 'demo',
};
},
created() {
this.getOriginChartsData();
},
mounted() {
if (this.running && !this.isDemo) {
this.startInterval();
}
},
beforeDestroy() {
this.stopInterval();
},
watch: {
running: function(val) {
(val && !this.isDemo) ? this.startInterval() : this.stopInterval();
},
currentIndex: function(index) {
/* eslint-disable fecs-camelcase */
if (this.data && this.data[index]) {
let currentImgInfo = this.data ? this.data[index] : {};
let {height, width, query, step, wallTime} = currentImgInfo;
let url = '/data/plugin/images/individualImage?ts=' + wallTime;
let imgSrc = [url, query].join('&');
this.imgData = {
imgSrc,
height,
width,
step,
wallTime,
};
}
/* eslint-enable fecs-camelcase */
},
},
methods: {
stopInterval() {
clearInterval(this.getOringDataInterval);
},
// get origin data per {{intervalTime}} seconds
startInterval() {
this.getOringDataInterval = setInterval(() => {
this.getOriginChartsData();
}, intervalTime * 1000);
},
getOriginChartsData() {
// let {run, tag} = this.tagInfo;
let run = this.tagInfo.run;
let tag = this.tagInfo.tag;
let {displayName, samples} = tag;
let params = {
run,
tag: displayName,
samples,
};
getPluginImagesImages(params).then(({status, data}) => {
if (status === 0) {
this.data = data;
this.currentIndex = data.length - 1;
}
});
},
},
};
</script>
<style lang="stylus">
.visual-dl-image
font-size 12px
width 420px
float left
margin 20px 30px 10px 0
background #fff
padding 10px
.visual-dl-image-title
font-size 14px
line-height 30px
.visual-dl-image-run-icon
background #e4e4e4
float right
margin-right 10px
padding 0 10px
border solid 1px #e4e4e4
border-radius 6px
line-height 20px
margin-top 4px
.visual-del-image-time
float right
</style>
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue';
import VueI18n from 'vue-i18n';
import App from './App';
import Vuetify from 'vuetify';
import router from '@/router';
Vue.config.productionTip = false;
Vue.use(VueI18n);
const DEFAULT_LANG = 'zh';
const locales = {
zh: require('./assets/language/zh.json'),
en: require('./assets/language/en.json'),
};
const i18n = new VueI18n({
locale: DEFAULT_LANG,
messages: locales,
});
Vue.use(Vuetify, {
theme: {
primary: '#008c99',
accent: '#008c99',
toolbox_icon: '#999999',
dark_primary: '#00727c',
tag_background: '#f5f5f5',
},
});
/* eslint-disable no-new */
new Vue({
el: '#root',
router,
i18n: i18n,
components: {App},
template: '<App/>',
});
<template>
<div class="visual-dl-page-container">
<div class="visual-dl-page-left">
<div>
<v-card
hover
color="tag_background"
class="visual-dl-tags-tab">
<v-icon>search</v-icon>
<input
type="search"
v-model="config.groupNameReg"
autocomplete="false"
:placeholder="$t('lang.searchTagInReg')"
class="visual-dl-tags-search-input">
</v-card>
<ui-tags-tab
:total="tagsListCount(allTagsMatchingList)"
:title="config.groupNameReg.trim().length == 0 ? $t('lang.all') : config.groupNameReg"
:active="selectedGroup === '' "
@click="selectedGroup = '' "
/>
<ui-tags-tab
v-for="item in groupedTags"
:total="tagsListCount(item.tags)"
:title="item.group"
:key="item.group"
:active="item.group === selectedGroup"
@click="selectedGroup = item.group"
/>
</div>
<ui-chart-page
:config="config"
:tag-list="finalTagsList"
:total="tagsListCount(finalTagsList)"
/>
</div>
<div class="visual-dl-page-right">
<div class="visual-dl-page-config-container">
<ui-config
:config="config"
/>
</div>
</div>
</div>
</template>
<script>
import {getPluginScalarsTags, getPluginHistogramsTags} from '../service';
import {cloneDeep, flatten, uniq} from 'lodash';
import autoAdjustHeight from '../common/util/autoAdjustHeight';
import TagsTab from '../common/component/TagsTab';
import Config from './ui/Config';
import ChartPage from './ui/ChartPage';
export default {
components: {
'ui-config': Config,
'ui-chart-page': ChartPage,
'ui-tags-tab': TagsTab,
},
props: {
runs: {
type: Array,
required: true,
},
},
data() {
return {
tagInfo: {scalar: {}, histogram: {}},
config: {
groupNameReg: '',
// scalar 'enabled' will be false when no scalar logs available, 'display' is toggled by user in config
scalar: {enabled: false, display: false},
histogram: {enabled: false, display: false},
smoothing: 0.6,
horizontal: 'step',
sortingMethod: 'default',
outlier: false,
runs: [],
running: true,
chartType: 'offset',
},
filteredTagsList: {scalar: [], histogram: []},
selectedGroup: '',
};
},
computed: {
finalTagsList() {
if (this.selectedGroup === '') {
return this.allTagsMatchingList;
} else {
let list;
this.groupedTags.forEach((item) => {
if (item.group === this.selectedGroup) {
list = item.tags;
}
});
return list;
}
},
allTagsMatchingList() {
let list = cloneDeep(this.filteredTagsList);
list.scalar = this.filteredListByRunsForScalar(list.scalar);
list.histogram = this.filteredListByRunsForHistogram(list.histogram);
return list;
},
tagsList() {
let list = {};
Object.keys(this.tagInfo).forEach((type) => {
let tags = this.tagInfo[type];
let runs = Object.keys(tags);
let tagsArray = runs.map((run) => Object.keys(tags[run]));
let allUniqTags = uniq(flatten(tagsArray));
// get the data for every chart
let tagsForEachType = allUniqTags.map((tag) => {
let tagList = runs.map((run) => {
return {
run,
tag: tags[run][tag],
};
}).filter((item) => item.tag !== undefined);
return {
tagList,
tag,
group: tag.split('/')[0],
};
});
list[type] = tagsForEachType;
});
return list;
},
groupedTags() {
let tagsList = this.tagsList || [];
// put data in group
let groupData = {};
Object.keys(tagsList).forEach((type) => {
let tagsForEachType = tagsList[type];
tagsForEachType.forEach((item) => {
let group = item.group;
if (groupData[group] === undefined) {
groupData[group] = {};
}
if (groupData[group][type] === undefined) {
groupData[group][type] = [];
}
groupData[group][type].push(item);
});
});
// to array
let groups = Object.keys(groupData);
let groupList = groups.map((group) => {
groupData[group].scalar = this.filteredListByRunsForScalar(groupData[group].scalar);
groupData[group].histogram = this.filteredListByRunsForHistogram(groupData[group].histogram);
return {
group,
tags: groupData[group],
};
});
return groupList;
},
},
created() {
getPluginScalarsTags().then(({errno, data}) => {
if (!data) return;
this.tagInfo.scalar = data;
this.config.scalar.enabled = true;
this.config.scalar.display = true;
this.filterTagsList(this.config.groupNameReg);
});
getPluginHistogramsTags().then(({errno, data}) => {
if (!data) return;
this.tagInfo.histogram = data;
this.config.histogram.enabled = true;
this.config.histogram.display = true;
this.filterTagsList(this.config.groupNameReg);
});
this.config.runs = this.runs;
},
mounted() {
autoAdjustHeight();
},
watch: {
'config.groupNameReg': function(val) {
this.throttledFilterTagsList();
},
'runs': function(val) {
this.config.runs = val;
},
},
methods: {
filterTagsList(groupNameReg) {
if (!groupNameReg || groupNameReg.trim().length == 0) {
this.filteredTagsList = cloneDeep(this.tagsList);
return;
}
this.selectedGroup = '';
let tagsList = this.tagsList || {};
let regExp = new RegExp(groupNameReg);
Object.keys(tagsList).forEach((type) => {
let tagsForEachType = tagsList[type];
this.filteredTagsList[type] = tagsForEachType.filter((item) => regExp.test(item.tag));
});
},
throttledFilterTagsList: _.debounce(
function() {
this.filterTagsList(this.config.groupNameReg);
}, 300
),
filteredListByRunsForScalar(scalar) {
if (!this.config.scalar.display) return [];
let runs = this.config.runs || [];
let list = cloneDeep(scalar) || [];
list = list.map((item) => {
item.tagList = item.tagList.filter((one) => runs.includes(one.run));
return item;
});
return list.filter((item) => item.tagList.length > 0);
},
filteredListByRunsForHistogram(histogram) {
if (!this.config.histogram.display) return [];
let runs = this.config.runs || [];
let list = cloneDeep(histogram) || [];
return flatten(list.map((item) => {
return item.tagList.filter((one) => runs.includes(one.run));
}));
},
tagsListCount(tagsList) {
let count = 0;
if (tagsList.scalar !== undefined) count += tagsList.scalar.length;
if (tagsList.histogram !== undefined) count += tagsList.histogram.length;
return count;
},
},
};
</script>
<style lang="stylus">
</style>
import {min, max, range} from 'lodash';
export function tansformBackendData(histogramData) {
let [time, step, items] = histogramData;
return {
time,
step,
min: min(items.map(([left, right, count]) => left)),
max: max(items.map(([left, right, count]) => right)),
items: items.map(([left, right, count]) => ({left, right, count})),
};
}
export function computeNewHistogram(histogram, min, max, binsNum = 30) {
if (max === min) {
// Create bins even if all the data has a single value.
max = min * 1.1 + 1;
min = min / 1.1 - 1;
}
let stepWidth = (max - min) / binsNum;
let itemIndex = 0;
return range(min, max, stepWidth).map((binLeft) => {
let binRight = binLeft + stepWidth;
let yValue = 0;
while (itemIndex < histogram.items.length) {
let itemRight = Math.min(max, histogram.items[itemIndex].right);
let itemLeft = Math.max(min, histogram.items[itemIndex].left);
let overlap = Math.min(itemRight, binRight) - Math.max(itemLeft, binLeft);
let count = (overlap / (itemRight - itemLeft)) * histogram.items[itemIndex].count;
yValue += overlap > 0 ? count : 0;
// If `itemRight` is bigger than `binRight`, then this bin is
// finished and there also has data for the next bin, so don't increment
// `itemIndex`.
if (itemRight > binRight) {
break;
}
itemIndex++;
}
return {x: binLeft, dx: stepWidth, y: yValue};
});
}
export function tansformToVisData(tempData, time, step) {
return tempData.map(function(dataItem) {
return [time, step, dataItem.x + dataItem.dx / 2, Math.floor(dataItem.y)];
});
}
export function originDataToChartData(originData) {
let tempData = originData.map(tansformBackendData);
let globalMin = min(tempData.map(({min}) => min));
let globalMax = max(tempData.map(({max}) => max));
let chartData = tempData.map(function(item) {
let histoBins = computeNewHistogram(item, globalMin, globalMax);
let {time, step} = item;
return {
time,
step,
items: tansformToVisData(histoBins, time, step),
};
});
return {
min: globalMin,
max: globalMax,
chartData,
};
}
<template>
<div class="visual-dl-chart-page">
<div
ref="chartPageBox"
class="visual-dl-chart-page-box">
<ui-scalar-chart
v-for="(tagInfo, index) in filteredScalarTagList"
:tag-info="tagInfo"
:smoothing="config.smoothing"
:horizontal="config.horizontal"
:sorting-method="config.sortingMethod"
:outlier="config.outlier"
:runs="config.runs"
:running="config.running"
/>
<ui-histogram-chart
v-for="(tagInfo, index) in filteredHistogramTagList"
:tag-info="tagInfo"
:runs="config.runs"
:chart-type="config.chartType"
:running="config.running"
/>
</div>
<v-pagination
v-if="total > pageSize"
v-model="currentPage"
:length="pageLength"
/>
</div>
</template>
<script>
import ScalarChart from './ScalarChart';
import HistogramChart from './HistogramChart';
export default {
components: {
'ui-scalar-chart': ScalarChart,
'ui-histogram-chart': HistogramChart,
},
props: {
config: {
type: Object,
required: true,
},
tagList: {
type: Object,
required: true,
},
total: {
type: Number,
required: true,
},
},
data() {
return {
// current page
currentPage: 1,
// item per page
pageSize: 12,
};
},
computed: {
filteredScalarTagList() {
return this.tagList.scalar.slice((this.currentPage - 1) * this.pageSize, this.currentPage * this.pageSize);
},
filteredHistogramTagList() {
let offset = this.tagList.scalar.length;
let start = (this.currentPage - 1) * this.pageSize - offset;
if (start < 0) start = 0;
let end = this.currentPage * this.pageSize - offset;
if (end < 0) end = 0;
return this.tagList.histogram.slice(start, end);
},
pageLength() {
return Math.ceil(this.total / this.pageSize);
},
},
watch: {
'config.runs': function(val) {
this.currentPage = 1;
},
tagList: function(val) {
this.currentPage = 1;
},
},
};
</script>
<style lang="stylus">
@import '~style/variables';
+prefix-classes('visual-dl-')
.chart-page
.chart-page-box:after
content: "";
clear: both;
display: block;
padding-bottom: 2%
</style>
<template>
<div class="visual-dl-page-config-com">
<v-checkbox
class="visual-dl-page-config-checkbox"
:label="$t('lang.scalars')"
v-model="config.scalar.display"
:disabled="!config.scalar.enabled"
dark/>
<div class="visual-dl-page-component-block">
<div class="visual-dl-page-control-block">
<span :class="'visual-dl-page-control-span' + (config.scalar.display ? '' : ' visual-dl-page-disabled-text')">{{ $t("lang.smoothing") }}</span>
<v-slider
:max="0.99"
:min="0"
:step="0.01"
v-model="smoothingValue"
class="visual-dl-page-smoothing-slider"
dark
:disabled="!config.scalar.display"/>
<span :class="'visual-dl-page-slider-span' + (config.scalar.display ? '' : ' visual-dl-page-disabled-text')">{{ smoothingValue }}</span>
</div>
<div class="visual-dl-page-control-block">
<span :class="'visual-dl-page-control-span' + (config.scalar.display ? '' : ' visual-dl-page-disabled-text')">{{ $t("lang.xAxis") }}</span>
<v-select
:items="horizontalItems"
v-model="config.horizontal"
class="visual-dl-page-config-selector"
dark
dense
:disabled="!config.scalar.display"
/>
</div>
<div class="visual-dl-page-control-block">
<span :class="'visual-dl-page-control-span' + (config.scalar.display ? '' : ' visual-dl-page-disabled-text')">{{ $t("lang.toolTipSorting") }}</span>
<v-select
:items="sortingMethodItems"
v-model="config.sortingMethod"
class="visual-dl-page-config-selector"
dark
dense
:disabled="!config.scalar.display"
/>
</div>
<v-checkbox
class="visual-dl-page-outliers-checkbox"
:label="$t('lang.ignoreOutliers')"
v-model="config.outlier"
dark
:disabled="!config.scalar.display"/>
</div>
<v-checkbox
class="visual-dl-page-config-checkbox"
:label="$t('lang.histogram')"
v-model="config.histogram.display"
:disabled="!config.histogram.enabled"
dark/>
<div class="visual-dl-page-component-block">
<div class="visual-dl-page-control-block">
<span :class="'visual-dl-page-control-span' + (config.histogram.display ? '' : ' visual-dl-page-disabled-text')">{{ $t("lang.mode") }}</span>
<v-select
:items="chartTypeItems"
v-model="config.chartType"
class="visual-dl-page-config-selector"
dark
dense
:disabled="!config.histogram.display"
/>
</div>
</div>
<v-btn
:color="config.running ? 'primary' : 'error'"
v-model="config.running"
v-if="!isDemo"
@click="toggleAllRuns"
class="visual-dl-page-run-toggle"
dark
block
>
{{ config.running ? $t("lang.startRunning") : $t("lang.stopRunning") }}
</v-btn>
</div>
</template>
<script>
export default {
props: {
config: {
type: Object,
required: true,
},
},
data() {
return {
smoothingValue: this.config.smoothing,
isDemo: process.env.NODE_ENV === 'demo',
};
},
computed: {
sortingMethodItems() {
return [
{
text: this.$i18n.t('lang.default'),
value: 'default',
},
{
text: this.$i18n.t('lang.descending'),
value: 'descending',
},
{
text: this.$i18n.t('lang.ascending'),
value: 'ascending',
},
{
text: this.$i18n.t('lang.nearest'),
value: 'nearest',
},
];
},
chartTypeItems() {
return [
{
text: this.$i18n.t('lang.overlay'),
value: 'overlay',
},
{
text: this.$i18n.t('lang.offset'),
value: 'offset',
},
];
},
horizontalItems() {
return [
{
text: this.$i18n.t('lang.step'),
value: 'step',
},
{
text: this.$i18n.t('lang.relative'),
value: 'relative',
},
{
text: this.$i18n.t('lang.wall'),
value: 'wall',
},
];
},
},
watch: {
smoothingValue: _.debounce(
function() {
this.config.smoothing = this.smoothingValue;
}, 50
),
},
methods: {
toggleAllRuns() {
this.config.running = !this.config.running;
},
},
};
</script>
<style lang="stylus">
+prefix-classes('visual-dl-page-')
.config-com
padding 20px
.component-block
padding-left 33px
padding-bottom 20px
margin-top -10px
.control-block
height 36px
display flex
align-items center
.control-span
font-size 12px
width 110px
margin-top 8px
.disabled-text
opacity 0.5
.smoothing-slider
display inline
.slider-span
width 35px
font-size 13px
.run-toggle
margin-top 20px
.config-checkbox label
font-size 13px
font-weight bold
.outliers-checkbox
margin-top 10px
.outliers-checkbox label
font-size 12px
.input-group--select .input-group__selections__comma
font-size 12px
</style>
<template>
<v-card
hover
class="visual-dl-page-charts">
<div
class="visual-dl-chart-box"
ref="visual_dl_chart_box"/>
<div class="visual-dl-chart-actions">
<v-btn
color="toolbox_icon"
flat
icon
@click="isExpand = !isExpand"
class="chart-toolbox-icons" >
<img
v-if="!isExpand"
src="../../assets/ic_fullscreen_off.svg">
<img
v-if="isExpand"
src="../../assets/ic_fullscreen_on.svg">
</v-btn>
</div>
</v-card>
</template>
<script>
// libs
import echarts from 'echarts';
import {originDataToChartData} from '../histogramHelper';
import {format, precisionRound} from 'd3-format';
// service
import {getPluginHistogramsHistograms} from '../../service';
let zrDrawElement = {};
zrDrawElement.hoverDots = [];
// the time to refresh chart data
const intervalTime = 15;
const p = Math.max(0, precisionRound(0.01, 1.01) - 1);
const yValueFormat = format('.' + p + 'e');
export default {
props: {
tagInfo: {
type: Object,
required: true,
},
runs: {
type: Array,
required: true,
},
running: {
type: Boolean,
required: true,
},
chartType: {
type: String,
required: true,
},
},
data() {
return {
originData: [],
isExpand: false,
isDemo: process.env.NODE_ENV === 'demo',
};
},
watch: {
tagInfo: function(val) {
this.initChart(val);
this.stopInterval();
if (this.running && !this.isDemo) {
this.startInterval();
}
},
originData: function(val) {
this.initChartOption();
},
chartType: function(val) {
this.initChartOption();
},
running: function(val) {
(val && !this.isDemo) ? this.startInterval() : this.stopInterval();
},
isExpand: function(val) {
this.expandArea(val);
},
},
mounted() {
let tagInfo = this.tagInfo;
this.initChart(tagInfo);
if (this.running && !this.isDemo) {
this.startInterval();
}
},
beforeDestroy() {
this.stopInterval();
},
methods: {
initChart(tagInfo) {
this.createChart();
this.getOriginChartData(tagInfo);
},
createChart() {
let el = this.$refs.visual_dl_chart_box;
this.myChart = echarts.init(el);
},
initChartOption() {
this.myChart.clear();
let zr = this.myChart.getZr();
let hoverDots = zrDrawElement.hoverDots;
if (hoverDots != null && hoverDots.length !== 0) {
hoverDots.forEach((dot) => zr.remove(dot));
}
let chartType = this.chartType;
let data = this.originData;
let visData = originDataToChartData(data);
let tagInfo = this.tagInfo;
let title = tagInfo.tag.displayName + '(' + tagInfo.run + ')';
this.setChartOptions(visData, title, chartType);
},
setChartOptions(visData, tag, chartType) {
let grid = {
left: 45,
top: 60,
right: 40,
bottom: 36,
};
let title = {
text: tag,
textStyle: {
fontSize: '12',
fontWeight: 'normal',
},
};
if (chartType === 'overlay') {
this.setOverlayChartOption(visData, title, grid);
} else if (chartType === 'offset') {
this.setOffsetChartOption(visData, title, grid);
}
},
setOverlayChartOption({chartData, min, max}, title, grid) {
let seriesOption = chartData.map(({time, step, items}) => ({
name: 'step' + step,
type: 'line',
showSymbol: false,
hoverAnimation: false,
z: 0,
data: items,
animationDuration: 100,
lineStyle: {
normal: {
width: 1,
color: '#008c99',
},
},
encode: {
x: [2],
y: [3],
},
})
);
let option = {
title: title,
axisPointer: {
link: {xAxisIndex: 'all'},
show: true,
snap: true,
triggerTooltip: true,
},
grid: grid,
xAxis: {
type: 'value',
},
yAxis: {
type: 'value',
axisLine: {
onZero: false,
},
axisLabel: {
formatter(value, index) {
return yValueFormat(value);
},
},
axisPointer: {
label: {
formatter({value}) {
return yValueFormat(value);
},
},
},
},
series: seriesOption,
};
let zr1 = this.myChart.getZr();
zr1.on('mousemove', function(e) {
zr1.remove(zrDrawElement.hoverLine);
zr1.remove(zrDrawElement.tooltip);
zr1.remove(zrDrawElement.tooltipX);
zr1.remove(zrDrawElement.tooltipY);
zrDrawElement.hoverDots.forEach((dot) => zr1.remove(dot));
zrDrawElement.hoverDots.length = 0;
});
this.myChart.setOption(option, {notMerge: true});
},
setOffsetChartOption({chartData, min, max}, title, grid) {
let rawData = [];
let minX = min;
let maxX = max;
let minZ = Infinity;
let maxZ = -Infinity;
let ecChart = this.myChart;
let maxStep = -Infinity;
let minStep = Infinity;
grid.top = 126;
grid.left = 16;
grid.right = 40;
chartData.forEach(function(dataItem) {
let lineData = [];
maxStep = Math.max(dataItem.step, maxStep);
minStep = Math.min(dataItem.step, minStep);
dataItem.items.forEach(([time, step, x, y]) => {
minZ = Math.min(minZ, y);
maxZ = Math.max(maxZ, y);
lineData.push(x, step, y);
});
rawData.push(lineData);
});
let option = {
textStyle: {
fontFamily: 'Merriweather Sans',
},
title,
color: ['#006069'],
visualMap: {
type: 'continuous',
show: false,
min: minStep,
max: maxStep,
dimension: 1,
inRange: {
colorLightness: [0.2, 0.4],
},
},
xAxis: {
min: minX,
max: maxX,
axisLine: {
onZero: false,
},
axisLabel: {
fontSize: '11',
formatter: function(value) {
return Math.round(value * 100) / 100;
},
},
splitLine: {
show: false,
},
},
yAxis: {
position: 'right',
axisLine: {
onZero: false,
},
inverse: true,
splitLine: {
show: false,
},
axisLabel: {
fontSize: '11',
},
},
grid,
series: [{
type: 'custom',
dimensions: ['x', 'y'],
renderItem: function(params, api) {
let points = makePolyPoints(
params.dataIndex,
api.value,
api.coord,
params.coordSys.y - 10
);
return {
type: 'polygon',
silent: true,
shape: {
points,
},
style: api.style({
stroke: '#bbb',
lineWidth: 1,
}),
};
},
data: rawData,
}],
};
function makePolyPoints(dataIndex, getValue, getCoord, yValueMapHeight) {
let points = [];
for (let i = 0; i < rawData[dataIndex].length;) {
let x = getValue(i++);
let y = getValue(i++);
let z = getValue(i++);
points.push(getPoint(x, y, z, getCoord, yValueMapHeight));
}
return points;
}
function getPoint(x, y, z, getCoord, yValueMapHeight) {
let pt = getCoord([x, y]);
// linear map in z axis
pt[1] -= (z - minZ) / (maxZ - minZ) * yValueMapHeight;
return pt;
}
let zr = ecChart.getZr();
function removeTooltip() {
if (zrDrawElement.hoverLine) {
zr.remove(zrDrawElement.hoverLine);
zr.remove(zrDrawElement.tooltip);
zrDrawElement.hoverDots.forEach((dot) => zr.remove(dot));
zrDrawElement.hoverDots.length = 0;
zr.remove(zrDrawElement.tooltipX);
zr.remove(zrDrawElement.tooltipY);
}
}
zr.on('mouseout', (e) => {
removeTooltip();
});
zr.on('mousemove', (e) => {
removeTooltip();
let nearestIndex = findNearestValue(e.offsetX, e.offsetY);
if (nearestIndex) {
let getCoord = function(pt) {
return ecChart.convertToPixel('grid', pt);
};
let gridRect = ecChart.getModel().getComponent('grid', 0).coordinateSystem.getRect();
let linePoints = makePolyPoints(
nearestIndex.itemIndex,
function(i) {
return rawData[nearestIndex.itemIndex][i];
},
getCoord,
gridRect.y - 10
);
zr.add(zrDrawElement.hoverLine = new echarts.graphic.Polyline({
silent: true,
shape: {
points: linePoints,
},
style: {
stroke: '#5c5c5c',
lineWidth: 2,
},
z: 999,
}));
let itemX;
rawData.forEach((dataItem) => {
let binIndex = nearestIndex.binIndex;
let x = dataItem[binIndex * 3];
let y = dataItem[binIndex * 3 + 1];
let z = dataItem[binIndex * 3 + 2];
let pt = getPoint(x, y, z, getCoord, gridRect.y - 10);
itemX = pt[0];
let dot = new echarts.graphic.Circle({
shape: {
cx: pt[0],
cy: pt[1],
r: 3,
},
style: {
fill: '#000',
stroke: '#ccc',
lineWidth: 1,
},
z: 1000,
});
zr.add(dot);
zrDrawElement.hoverDots.push(dot);
});
let hoveredItem = chartData[nearestIndex.itemIndex];
zrDrawElement.tooltip = new echarts.graphic.Text({
position: [e.offsetX + 30, e.offsetY - 50],
style: {
fontFamily: 'Merriweather Sans',
text: yValueFormat(hoveredItem.items[nearestIndex.binIndex][3]),
textFill: '#000',
fontSize: 14,
textBackgroundColor: '#eee',
textBorderColor: '#008c99',
textBorderWidth: 2,
textBorderRadius: 5,
textPadding: 10,
rich: {},
},
z: 2000,
});
zr.add(zrDrawElement.tooltip);
zrDrawElement.tooltipX = new echarts.graphic.Text({
position: [
itemX,
gridRect.y + gridRect.height,
],
style: {
fontFamily: 'Merriweather Sans',
text: Math.round(hoveredItem.items[nearestIndex.binIndex][2] * 1000) / 1000,
textFill: '#fff',
textAlign: 'center',
fontSize: 12,
textBackgroundColor: '#333',
textBorderWidth: 2,
textPadding: [5, 7],
rich: {},
},
z: 2000,
});
zr.add(zrDrawElement.tooltipX);
zrDrawElement.tooltipY = new echarts.graphic.Text({
position: [
gridRect.x + gridRect.width,
linePoints[linePoints.length - 1][1],
],
style: {
fontFamily: 'Merriweather Sans',
text: hoveredItem.step,
textFill: '#fff',
textVerticalAlign: 'middle',
fontSize: 12,
textBackgroundColor: '#333',
textBorderWidth: 2,
textPadding: [5, 7],
rich: {},
},
z: 2000,
});
zr.add(zrDrawElement.tooltipY);
}
});
function findNearestValue(px, py) {
let value = ecChart.convertFromPixel('grid', [px, py]);
let itemIndex;
let nearestY = Infinity;
let binIndex;
chartData.forEach((item, index) => {
let dist = Math.abs(value[1] - item.step);
if (dist < nearestY) {
nearestY = dist;
itemIndex = index;
}
});
if (itemIndex != null) {
let dataItem = chartData[itemIndex];
let nearestX = Infinity;
dataItem.items.forEach((item, index) => {
let dist = Math.abs(item[2] - value[0]);
if (dist < nearestX) {
nearestX = dist;
binIndex = index;
}
});
if (binIndex != null) {
return {
itemIndex: itemIndex,
binIndex: binIndex,
};
}
}
}
ecChart.setOption(option, {notMerge: true});
},
// get origin data per 60 seconds
startInterval() {
this.getOringDataInterval = setInterval(() => {
let tagInfo = this.tagInfo;
this.getOriginChartData(tagInfo);
}, intervalTime * 1000);
},
stopInterval() {
clearInterval(this.getOringDataInterval);
},
getOriginChartData(tagInfo) {
let run = tagInfo.run;
let tag = tagInfo.tag;
let params = {
run,
tag: tag.displayName,
};
getPluginHistogramsHistograms(params).then(({status, data}) => {
if (status === 0) {
this.originData = data;
}
});
},
expandArea(expand) {
let pageBoxWidth = document.getElementsByClassName('visual-dl-chart-page')[0].offsetWidth;
let width = pageBoxWidth * 0.96; // 4% margin
if (expand) {
let el = this.$refs.visual_dl_chart_box;
el.style.width = width + 'px';
el.style.height = '600px';
this.isExpand = true;
this.myChart.resize({
width: width,
height: 600,
});
} else {
let el = this.$refs.visual_dl_chart_box;
el.style.width = '400px';
el.style.height = '300px';
this.isExpand = false;
this.myChart.resize({
width: 400,
height: 300,
});
}
},
},
};
</script>
<style lang="stylus">
.visual-dl-page-charts
float left
margin 2% 2% 0 0
background #fff
padding 10px
position relative
.visual-dl-chart-box
width 400px
height 300px
.visual-dl-chart-actions
opacity 0
transition: opacity .3s ease-out;
position absolute
top 4px
right 10px
img
width 30px
height 30px
position absolute
top 0
bottom 0
margin auto
.chart-toolbox-icons
width 25px
height 25px
margin-left -4px
margin-right -4px
.visual-dl-page-charts:hover
.visual-dl-chart-actions
opacity 1
</style>
<template>
<v-card
hover
class="visual-dl-page-charts">
<div
ref="chartBox"
class="visual-dl-chart-box"
:style="computedStyle"/>
<div class="visual-dl-chart-actions">
<v-btn
color="toolbox_icon"
flat
icon
@click="isSelectZoomEnable = !isSelectZoomEnable"
class="chart-toolbox-icons">
<img
v-if="!isSelectZoomEnable"
src="../../assets/ic_zoom_select_off.svg">
<img
v-if="isSelectZoomEnable"
src="../../assets/ic_zoom_select_on.svg">
</v-btn>
<v-btn
color="toolbox_icon"
flat
icon
@click="restoreChart"
class="chart-toolbox-icons">
<img src="../../assets/ic_undo.svg">
</v-btn>
<v-btn
color="toolbox_icon"
flat
icon
@click="isExpand = !isExpand"
class="chart-toolbox-icons" >
<img
v-if="!isExpand"
src="../../assets/ic_fullscreen_off.svg">
<img
v-if="isExpand"
src="../../assets/ic_fullscreen_on.svg">
</v-btn>
<v-btn
color="toolbox_icon"
flat
icon
@click="saveChartAsImage"
class="chart-toolbox-icons" >
<img src="../../assets/ic_download.svg">
</v-btn>
<v-menu v-if="tagInfo.tagList.length > 0">
<v-btn
color="toolbox_icon"
slot="activator"
flat
icon
class="chart-toolbox-icons">
<v-icon >more_vert</v-icon>
</v-btn>
<v-list dense>
<v-list-tile>
<v-list-tile-content>
<v-list-tile-title>{{ $t("lang.downloadDataInJson") }}</v-list-tile-title>
</v-list-tile-content>
<v-list-tile-action>
<v-icon>expand_more</v-icon>
</v-list-tile-action>
</v-list-tile>
<v-list-tile
v-for="subItem in tagInfo.tagList"
:key="subItem.run"
@click="handleDownLoad(subItem.run)">
<v-list-tile-content>
<v-list-tile-title>&nbsp;&nbsp;&nbsp;{{ subItem.run }}</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
</v-menu>
</div>
</v-card>
</template>
<script>
// libs
import echarts from 'echarts';
import axios from 'axios';
import {isFinite, flatten, maxBy, minBy, sortBy, max, min} from 'lodash';
import {generateJsonAndDownload} from '../../common/util/downLoadFile';
import {quantile} from '../../common/util/index';
import moment from 'moment';
// service
import {getPluginScalarsScalars} from '../../service';
const originLinesOpacity = 0.3;
const lineWidth = 1.5;
const minQuantile = 0.05;
const maxQuantile = 0.95;
// the time to refresh chart data
const intervalTime = 15;
export default {
props: {
tagInfo: {
type: Object,
required: true,
},
runs: {
type: Array,
required: true,
},
running: {
type: Boolean,
required: true,
},
smoothing: {
type: Number,
required: true,
},
horizontal: {
type: String,
required: true,
},
sortingMethod: {
type: String,
required: true,
},
outlier: {
type: Boolean,
required: true,
},
},
computed: {
computedStyle() {
return 'height:' + this.height + 'px;'
+ 'width:' + this.width + 'px;';
},
},
data() {
return {
isDemo: process.env.NODE_ENV === 'demo',
width: 400,
height: 300,
isExpand: false,
isSelectZoomEnable: true,
originData: [],
};
},
watch: {
originData: function(val) {
this.setChartData();
this.setChartsOutlier();
this.setChartHorizon();
},
smoothing: function(val) {
this.setChartData();
},
outlier: function(val) {
this.setChartsOutlier();
},
horizontal: function(val) {
this.setChartHorizon();
},
tagInfo: function(val) {
// Should Clean up the chart before each use.
this.myChart.clear();
this.setChartsOptions(val);
this.getOriginChartData(val);
},
isExpand: function(val) {
this.expandArea(val);
},
isSelectZoomEnable: function(val) {
this.toggleSelectZoom(val);
},
},
mounted() {
this.initChart(this.tagInfo);
this.toggleSelectZoom(true);
if (this.running && !this.isDemo) {
this.startInterval();
}
this.$watch('running', function(running) {
// if it is demo, do not trigger interval
running = running && !this.isDemo;
running ? this.startInterval() : this.stopInterval();
});
},
beforeDestroy() {
this.stopInterval();
},
methods: {
// Create a Scalar Chart, initialize it with default settings, then load datas
initChart(tagInfo) {
this.createChart();
this.setChartsOptions(tagInfo);
this.getOriginChartData(tagInfo);
},
createChart() {
let el = this.$refs.chartBox;
this.myChart = echarts.init(el);
},
setChartsOptions({tagList, tag}) {
// Create two lines, one line is original, the other line is for smoothing
let seriesOption = tagList.map((item) => [
{
name: item.run,
type: 'line',
showSymbol: false,
hoverAnimation: false,
z: 0,
data: [],
animationDuration: 100,
lineStyle: {
normal: {
opacity: originLinesOpacity,
width: lineWidth,
},
},
},
{
name: item.run,
type: 'line',
showSymbol: false,
hoverAnimation: false,
z: 1,
data: [],
animationDuration: 100,
lineStyle: {
normal: {
width: lineWidth,
},
},
},
]
);
seriesOption = flatten(seriesOption);
let legendOptions = tagList.map((item) => item.run);
let instance = this;
let option = {
textStyle: {
fontFamily: 'Merriweather Sans',
},
color: [
'#008c99',
'#c23531',
'#FF9900',
'#109618',
'#990099',
'#3B3EAC',
'#DD4477',
'#AAAA11',
'#5574A6',
'#8B0707',
],
title: {
text: tag,
textStyle: {
fontSize: 13,
fontWeight: 'normal',
},
},
tooltip: {
trigger: 'axis',
axisPointer: {
animation: true,
},
textStyle: {
fontSize: '13',
},
position: ['10%', '90%'],
formatter(params, ticket, callback) {
let data = instance.getFormatterPoints(params[0].data);
return instance.transformFormatterData(data);
},
},
toolbox: {
show: true,
showTitle: false,
itemSize: 0,
feature: {
dataZoom: {},
},
},
legend: {
data: legendOptions,
top: 39,
},
grid: {
left: 48,
top: 75,
right: 40,
bottom: 36,
},
xAxis: {
type: 'value',
name: this.horizontal,
axisLabel: {
fontSize: '11',
},
splitNumber: this.isExpand ? 10 : 5,
},
yAxis: {
type: 'value',
axisLabel: {
fontSize: '11',
formatter(value) {
return value.toString().slice(0, 5);
},
},
},
series: seriesOption,
};
this.myChart.setOption(option);
},
// Get origin data per 60 seconds
startInterval() {
this.getOriginDataInterval = setInterval(() => {
this.getOriginChartData(this.tagInfo);
}, intervalTime * 1000);
},
stopInterval() {
clearInterval(this.getOriginDataInterval);
},
getOriginChartData({tagList, tag}) {
let requestList = tagList.map((item) => {
let params = {
run: item.run,
tag: tag,
};
return getPluginScalarsScalars(params);
});
axios.all(requestList).then((resArray) => {
if (resArray.every((res) => res.status === 0)) {
this.originData = resArray.map((res) => res.data);
}
});
},
setChartData() {
let seriesData = this.originData.map((lineData) => {
if (lineData.length == 0) return [];
// add the smoothed data
this.transformDataset(lineData);
return [
{
data: lineData,
encode: {
// map 1 dimension to xAixs.
x: [1],
// map 2 dimension to yAixs.
y: [2],
},
},
{
data: lineData,
encode: {
// Map 1 dimension to xAixs.
x: [1],
// Map 3 dimension to yAixs,
// the third number is smoothed value.
y: [3],
},
},
];
});
this.myChart.setOption({
series: flatten(seriesData),
});
},
getChartOptions() {
return this.myChart.getOption() || {};
},
handleDownLoad(runItemForDownload) {
let options = this.getChartOptions();
let series = options.series || [];
let seriesItem = series.find((item) => item.name === runItemForDownload) || {};
let fileName = this.tagInfo.tag.replace(/\//g, '-');
generateJsonAndDownload(seriesItem.data, fileName);
},
transformDataset(seriesData) {
// smooth
this.transformData(seriesData, this.smoothing);
},
/**
* @desc 1、add smooth data depend on smoothingWeight. see https://en.wikipedia.org/wiki/Moving_average for detail
* 2、add relative data
* @param {Object} seriesData: echarts series Object
* @param {number} smoothingWeight smooth weight, between 0 ~ 1
*/
transformData(seriesData, smoothingWeight) {
let data = seriesData;
let last = data.length > 0 ? 0 : NaN;
let numAccum = 0;
let startValue;
data.forEach((d, i) => {
let nextVal = d[2];
// second to millisecond.
let millisecond = Math.floor(d[0] * 1000);
if (i === 0) {
startValue = millisecond;
}
// Relative time, millisecond to hours.
d[4] = Math.floor(millisecond - startValue) / (60 * 60 * 1000);
if (!isFinite(nextVal)) {
d[3] = nextVal;
} else {
last = last * smoothingWeight + (1 - smoothingWeight) * nextVal;
numAccum++;
let debiasWeight = 1;
if (smoothingWeight !== 1.0) {
debiasWeight = 1.0 - Math.pow(smoothingWeight, numAccum);
}
d[3] = last / debiasWeight;
}
});
},
// Chart outlier options methods and functions ---- start.
// Compute Y domain from originData.
setChartsOutlier() {
let domainRangeArray = this.originData.map((seriesData) => this.computeDataRange(seriesData, this.outlier));
// Compare, get the best Y domain.
let flattenNumbers = flatten(domainRangeArray);
let finalMax = max(flattenNumbers);
let finalMin = min(flattenNumbers);
// Add padding.
let PaddedYDomain = this.paddedYDomain(finalMin, finalMax);
this.setChartOutlierOptions(PaddedYDomain);
// Store Y domain, if originData is not change, Y domain keep same.
},
// Compute max and min from array, if outlier is true, return quantile range.
computeDataRange(arr, isQuantile) {
// Get data range.
if (arr.length == 0) return [];
let max;
let min;
if (!isQuantile) {
// Get the orgin data range.
max = maxBy(arr, (item) => item[2])[2];
min = minBy(arr, (item) => item[2])[2];
} else {
// Get the quantile range.
let sorted = sortBy(arr, [(item) => item[2]]);
min = quantile(sorted, minQuantile, (item) => item[2]);
max = quantile(arr, maxQuantile, (item) => item[2]);
}
return [min, max];
},
paddedYDomain(min, max) {
return {
max: max > 0 ? max * 1.1 : max * 0.9,
min: min > 0 ? min * 0.9 : min * 1.1,
};
},
setChartOutlierOptions({min, max}) {
this.myChart.setOption({
yAxis: {
min,
max,
},
});
},
// Chart horizontal options methods and functions ---- start.
setChartHorizon() {
let seriesOption = this.myChart.getOption().series;
let encodeSeries = (val) => {
return {
encode: {
x: [val],
},
};
};
let stepSeries = seriesOption.map((item) => encodeSeries(1));
let relativeSeries = seriesOption.map((item) => encodeSeries(4));
let wallSeries = seriesOption.map((item) => encodeSeries(0));
let horizontalToxAxisOptions = {
step: {
xAxis: {
type: 'value',
name: this.$t('lang.step'),
axisLabel: {
fontSize: '11',
},
splitNumber: this.isExpand ? 10 : 5,
},
series: stepSeries,
},
relative: {
xAxis: {
type: 'value',
name: this.$t('lang.relative'),
axisLabel: {
fontSize: '11',
},
splitNumber: this.isExpand ? 10 : 5,
},
series: relativeSeries,
},
wall: {
xAxis: {
type: 'time',
name: this.$t('lang.wall'),
axisLabel: {
fontSize: '11',
formatter: function(value, index) {
// The value is in seconds, need to convert to milliseconds
let date = new Date(value * 1000);
return date.toLocaleTimeString();
},
},
},
series: wallSeries,
},
};
this.myChart.setOption(horizontalToxAxisOptions[this.horizontal]);
},
expandArea(expand) {
let pageBoxWidth = document.getElementsByClassName('visual-dl-chart-page-box')[0].offsetWidth;
let width = pageBoxWidth * 0.96; // 4% margin
if (expand) {
let el = this.$refs.chartBox;
el.style.width = width + 'px';
el.style.height = '600px';
this.myChart.resize({
width: width,
height: 600,
});
} else {
let el = this.$refs.chartBox;
el.style.width = '400px';
el.style.height = '300px';
this.myChart.resize({
width: 400,
height: 300,
});
}
this.myChart.setOption({
xAxis: {
splitNumber: this.isExpand ? 10 : 5,
},
});
},
toggleSelectZoom(enable) {
let instance = this;
setTimeout(function() {
instance.myChart.dispatchAction({
type: 'takeGlobalCursor',
key: 'dataZoomSelect',
dataZoomSelectActive: enable,
});
}, 0);
},
restoreChart() {
this.myChart.dispatchAction({
type: 'restore',
});
},
saveChartAsImage() {
let dataUrl = this.myChart.getDataURL({
pixelRatio: 1,
backgroundColor: '#fff',
});
let fileName = this.tagInfo.tag.replace(/\//g, '-');
let link = document.createElement('a');
link.download = fileName;
link.href = dataUrl;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
},
getFormatterPoints(data) {
let originData = this.originData;
let tagList = this.tagInfo.tagList;
let sortingMethod = this.sortingMethod;
// Can't know exactly the tigger runs.
// If the step is same, regard the point as the trigger point.
let [, step, triggerValue] = data;
let points = originData.map((series, index) => {
let nearestItem;
if (step === 0) {
nearestItem = series[0];
} else {
for (let i = 0; i < series.length; i++) {
let item = series[i];
if (item[1] === step) {
nearestItem = item;
break;
}
if (item[1] > step) {
let index = i - 1;
nearestItem = series[index >= 0 ? index : 0];
break;
}
if (!nearestItem) {
nearestItem = series[series.length - 1];
}
}
}
return {
run: tagList[index].run,
item: nearestItem,
};
});
if (sortingMethod === 'default' || !sortingMethod) {
return points;
}
let sortedPoints;
switch (sortingMethod) {
case 'descending':
sortedPoints = sortBy(points, (one) => one.item[3]);
sortedPoints.reverse();
break;
case 'ascending':
sortedPoints = sortBy(points, (one) => one.item[3]);
break;
case 'nearest':
// Compare other ponts width the trigger point, caculate the nearest sort.
sortedPoints = sortBy(points, (one) => one.item[3] - triggerValue);
break;
default:
sortedPoints = points;
}
return sortedPoints;
},
transformFormatterData(data) {
let indexPropMap = {
Time: 0,
Step: 1,
Value: 2,
Smoothed: 3,
Relative: 4,
};
let widthPropMap = {
Run: 60,
Time: 120,
Step: 40,
Value: 50,
Smoothed: 60,
Relative: 60,
};
let transformedData = data.map((item) => {
let data = item.item;
return {
Run: item.run,
// Keep six number for easy-read.
Smoothed: data[indexPropMap.Smoothed].toString().slice(0, 6),
Value: data[indexPropMap.Value].toString().slice(0, 6),
Step: data[indexPropMap.Step],
Time: moment(Math.floor(data[indexPropMap.Time] * 1000), 'x').format('YYYY-MM-DD HH:mm:ss'),
// Relative display value should take easy-read into consideration.
// Better to tranform data to 'day:hour', 'hour:minutes', 'minute: seconds' and second only.
Relative: Math.floor(data[indexPropMap.Relative] * 60 * 60) + 's',
};
});
let headerHtml = '<tr style="font-size:14px;">';
headerHtml += Object.keys(transformedData[0]).map((key) => {
return '<td style="padding: 0 4px; font-family: \'Merriweather Sans\'; font-weight: bold; width:' +
widthPropMap[key] + 'px;">' + key + '</td>';
}).join('');
headerHtml += '</tr>';
let content = transformedData.map((item) => {
let str = '<tr style="font-size:12px;">';
str += Object.keys(item).map((val) => {
return '<td style="padding: 0 4px; overflow: hidden;">' + item[val] + '</td>';
}).join('');
str += '</tr>';
return str;
}).join('');
return '<table style="text-align: left;table-layout: fixed;width: 500px;"><thead>' + headerHtml + '</thead>'
+ '<tbody>' + content + '</tbody><table>';
},
},
};
</script>
<style lang="stylus">
.visual-dl-page-charts
float left
margin 2% 2% 0 0
padding 10px
position relative
.visual-dl-chart-actions
opacity 0
transition: opacity .3s ease-out;
position absolute
top 4px
right 10px
img
width 30px
height 30px
position absolute
top 0
bottom 0
margin auto
.chart-toolbox-icons
width 25px
height 25px
margin-left -4px
margin-right -4px
.visual-dl-page-charts:hover
.visual-dl-chart-actions
opacity 1
</style>
import Vue from 'vue';
import Router from 'vue-router';
import Metrics from '@/metrics/Metrics';
import Samples from '@/samples/Samples';
import Graph from '@/graph/Graph';
import HighDimensional from '@/high-dimensional/HighDimensional';
Vue.use(Router);
export default new Router({
routes: [
{
path: '/metrics',
name: 'Metrics',
component: Metrics,
props: (route) => ({
runs: route.query.runs
})
},
{
path: '/samples',
name: 'Samples',
component: Samples,
props: (route) => ({
runs: route.query.runs
})
},
{
path: '/graphs',
name: 'Graph',
component: Graph,
},
{
path: '/HighDimensional',
name: 'HighDimensional',
component: HighDimensional,
props: (route) => ({
runs: route.query.runs
})
},
],
});
<template>
<div class="visual-dl-page-container">
<div class="visual-dl-page-left">
<div>
<v-card
hover
color="tag_background"
class="visual-dl-tags-tab">
<v-icon>search</v-icon>
<input
type="search"
v-model="config.groupNameReg"
autocomplete="false"
:placeholder="$t('lang.searchTagInReg')"
class="visual-dl-tags-search-input">
</v-card>
<ui-tags-tab
:total="tagsListCount(allTagsMatchingList)"
:title="config.groupNameReg.trim().length == 0 ? $t('lang.all') : config.groupNameReg"
:active="selectedGroup === '' "
@click="selectedGroup = '' "
/>
<ui-tags-tab
v-for="item in groupedTags"
:total="tagsListCount(item.tags)"
:title="item.group"
:key="item.group"
:active="item.group === selectedGroup"
@click="selectedGroup = item.group"
/>
</div>
<ui-sample-page
:config="config"
:tag-list="finalTagsList"
:total="tagsListCount(finalTagsList)"
/>
</div>
<div class="visual-dl-page-right">
<div class="visual-dl-page-config-container">
<ui-config
:config="config"
/>
</div>
</div>
</div>
</template>
<script>
import {getPluginImagesTags, getPluginAudioTags, getPluginTextsTags} from '../service';
import {cloneDeep, flatten, uniq} from 'lodash';
import autoAdjustHeight from '../common/util/autoAdjustHeight';
import TagsTab from '../common/component/TagsTab';
import Config from './ui/Config';
import SamplePage from './ui/SamplePage';
export default {
name: 'Samples',
components: {
'ui-config': Config,
'ui-sample-page': SamplePage,
'ui-tags-tab': TagsTab,
},
props: {
runs: {
type: Array,
required: true,
},
},
data() {
return {
tagInfo: {image: {}, audio: {}, text: {}},
config: {
groupNameReg: '',
image: {enabled: false, display: false},
audio: {enabled: false, display: false},
text: {enabled: false, display: false},
isActualImageSize: false,
runs: [],
running: true,
},
filteredTagsList: {image: {}, audio: {}, text: {}},
selectedGroup: '',
};
},
computed: {
finalTagsList() {
if (this.selectedGroup === '') {
return this.allTagsMatchingList;
} else {
let list;
this.groupedTags.forEach((item) => {
if (item.group === this.selectedGroup) {
list = item.tags;
}
});
return list;
}
},
allTagsMatchingList() {
let list = cloneDeep(this.filteredTagsList);
this.filteredListByRuns(list);
return list;
},
tagsList() {
let list = {};
Object.keys(this.tagInfo).forEach((type) => {
let tags = this.tagInfo[type];
let runs = Object.keys(tags);
let tagsArray = runs.map((run) => Object.keys(tags[run]));
let allUniqTags = uniq(flatten(tagsArray));
// get the data for every chart
let tagsForEachType = allUniqTags.map((tag) => {
let tagList = runs.map((run) => {
return {
run,
tag: tags[run][tag],
};
}).filter((item) => item.tag !== undefined);
return {
tagList,
tag,
group: tag.split('/')[0],
};
});
list[type] = tagsForEachType;
});
return list;
},
groupedTags() {
let tagsList = this.tagsList || [];
// put data in group
let groupData = {};
Object.keys(tagsList).forEach((type) => {
let tagsForEachType = tagsList[type];
tagsForEachType.forEach((item) => {
let group = item.group;
if (groupData[group] === undefined) {
groupData[group] = {};
}
if (groupData[group][type] === undefined) {
groupData[group][type] = [];
}
groupData[group][type].push(item);
});
});
// to array
let groups = Object.keys(groupData);
let groupList = groups.map((group) => {
this.filteredListByRuns(groupData[group]);
return {
group,
tags: groupData[group],
};
});
return groupList;
},
},
created() {
getPluginImagesTags().then(({errno, data}) => {
if (!data) return;
this.tagInfo.image = data;
this.config.image.enabled = true;
this.config.image.display = true;
this.filterTagsList(this.config.groupNameReg);
});
getPluginAudioTags().then(({errno, data}) => {
if (!data) return;
this.tagInfo.audio = data;
this.config.audio.enabled = true;
this.config.audio.display = true;
this.filterTagsList(this.config.groupNameReg);
});
getPluginTextsTags().then(({errno, data}) => {
if (!data) return;
this.tagInfo.text = data;
this.config.text.enabled = true;
this.config.text.display = true;
this.filterTagsList(this.config.groupNameReg);
});
this.config.runs = this.runs;
},
mounted() {
autoAdjustHeight();
},
watch: {
'config.groupNameReg': function(val) {
this.throttledFilterTagsList();
},
'runs': function(val) {
this.config.runs = val;
},
},
methods: {
filterTagsList(groupNameReg) {
if (!groupNameReg || groupNameReg.trim().length == 0) {
this.filteredTagsList = cloneDeep(this.tagsList);
return;
}
this.selectedGroup = '';
let tagsList = this.tagsList || [];
let regExp = new RegExp(groupNameReg);
Object.keys(tagsList).forEach((type) => {
let tagsForEachType = tagsList[type];
this.filteredTagsList[type] = tagsForEachType.filter((item) => regExp.test(item.tag));
});
},
throttledFilterTagsList: _.debounce(
function() {
this.filterTagsList(this.config.groupNameReg);
}, 300
),
filteredListByRuns(list) {
list.image = !this.config.image.display ? [] : this.filteredTypeByRuns(list.image);
list.audio = !this.config.audio.display ? [] : this.filteredTypeByRuns(list.audio);
list.text = !this.config.text.display ? [] : this.filteredTypeByRuns(list.text);
},
filteredTypeByRuns(tagList) {
let runs = this.config.runs || [];
let list = cloneDeep(tagList) || [];
return flatten(list.map((item) => {
return item.tagList.filter((one) => runs.includes(one.run));
}));
},
tagsListCount(tagsList) {
let count = 0;
if (tagsList.image !== undefined) count += tagsList.image.length;
if (tagsList.audio !== undefined) count += tagsList.audio.length;
if (tagsList.text !== undefined) count += tagsList.text.length;
return count;
},
},
};
</script>
<style lang="stylus">
</style>
<template>
<v-card
hover
class="visual-dl-audio">
<h3 class="visual-dl-audio-title">{{ tagInfo.tag.displayName }}
<span class="visual-dl-audio-run-icon">{{ tagInfo.run }}</span>
</h3>
<p>
<span>{{ $t('lang.step') }}:</span>
<span>{{ audioData.step }}</span>
<span class="visual-del-audio-time">{{ audioData.wallTime | formatTime(this.$i18n.locale) }}</span>
</p>
<v-slider
:max="steps"
:min="slider.min"
:step="1"
v-model="currentIndex"
/>
<audio
controls
:src="audioData.audioSrc">
Your browser does not support the audio element.
</audio>
</v-card>
</template>
<script>
import {getPluginAudioAudio} from '../../service';
// the time to refresh chart data
const intervalTime = 30;
export default {
props: {
tagInfo: {
type: Object,
required: true,
},
runs: {
type: Array,
required: true,
},
running: {
type: Boolean,
required: true,
},
},
computed: {
steps() {
let data = this.data || [];
return data.length - 1;
},
},
filters: {
formatTime: function(value, language) {
if (!value) {
return;
}
// The value was made in seconds, must convert it to milliseconds
let time = new Date(value * 1000);
let options = {
weekday: 'short', year: 'numeric', month: 'short',
day: 'numeric', hour: '2-digit', minute: '2-digit', second: '2-digit',
};
let enc = language === 'zh' ? 'zh-CN' : 'en-US';
return time.toLocaleDateString(enc, options);
},
},
data() {
return {
currentIndex: 0,
slider: {
value: '0',
label: '',
min: 0,
step: 1,
},
audioData: {},
data: [],
isDemo: process.env.NODE_ENV === 'demo',
};
},
created() {
this.getOriginAudioData();
},
mounted() {
if (this.running && !this.isDemo) {
this.startInterval();
}
},
beforeDestroy() {
this.stopInterval();
},
watch: {
running: function(val) {
(val && !this.isDemo) ? this.startInterval() : this.stopInterval();
},
currentIndex: function(index) {
if (this.data && this.data[index]) {
let currentAudioInfo = this.data ? this.data[index] : {};
let {query, step, wallTime} = currentAudioInfo;
let url = '/data/plugin/audio/individualAudio?ts=' + wallTime;
let audioSrc = [url, query].join('&');
this.audioData = {
audioSrc,
step,
wallTime,
};
}
},
tagInfo: function(val) {
this.currentIndex = 0;
this.getOriginAudioData();
},
},
methods: {
stopInterval() {
clearInterval(this.getOringDataInterval);
},
// get origin data per {{intervalTime}} seconds
startInterval() {
this.getOringDataInterval = setInterval(() => {
this.getOriginAudioData();
}, intervalTime * 1000);
},
getOriginAudioData() {
// let {run, tag} = this.tagInfo;
let run = this.tagInfo.run;
let tag = this.tagInfo.tag;
let {displayName, samples} = tag;
let params = {
run,
tag: displayName,
samples,
};
getPluginAudioAudio(params).then(({status, data}) => {
if (status === 0) {
this.data = data;
this.currentIndex = data.length - 1;
}
});
},
},
};
</script>
<style lang="stylus">
.visual-dl-audio
font-size 12px
width 420px
float left
margin 20px 30px 10px 0
background #fff
padding 10px
.visual-dl-audio-title
font-size 14px
line-height 30px
.visual-dl-audio-run-icon
background #e4e4e4
float right
margin-right 10px
padding 0 10px
border solid 1px #e4e4e4
border-radius 6px
line-height 20px
margin-top 4px
.visual-del-audio-time
float right
</style>
<template>
<div class="visual-dl-page-config-com">
<v-checkbox
class="visual-dl-page-config-checkbox"
:label="$t('lang.image')"
v-model="config.image.display"
:disabled="!config.image.enabled"
dark/>
<div class="visual-dl-page-component-block">
<v-checkbox
class="visual-dl-page-subconfig-checkbox"
:label="$t('lang.showActualImageSize')"
v-model="config.isActualImageSize"
dark
:disabled="!config.image.display"/>
</div>
<v-checkbox
class="visual-dl-page-config-checkbox"
:label="$t('lang.audio')"
v-model="config.audio.display"
:disabled="!config.audio.enabled"
dark/>
<v-checkbox
class="visual-dl-page-config-checkbox"
:label="$t('lang.text')"
v-model="config.text.display"
:disabled="!config.text.enabled"
dark/>
<v-btn
:color="config.running ? 'primary' : 'error'"
v-model="config.running"
v-if="!isDemo"
@click="toggleAllRuns"
class="visual-dl-page-run-toggle"
dark
block
>
{{ config.running ? $t('lang.startRunning') : $t('lang.stopRunning') }}
</v-btn>
</div>
</template>
<script>
export default {
props: {
config: {
type: Object,
required: true,
},
},
data() {
return {
isDemo: process.env.NODE_ENV === 'demo',
};
},
methods: {
toggleAllRuns() {
this.config.running = !this.config.running;
},
},
};
</script>
<style lang="stylus">
+prefix-classes('visual-dl-page-')
.config-com
padding 20px
.component-block
padding-left 33px
padding-bottom 20px
margin-top -10px
.disabled-text
opacity 0.5
.run-toggle
margin-top 20px
.config-checkbox label
font-size 13px
font-weight bold
.subconfig-checkbox
margin-top 10px
.subconfig-checkbox label
font-size 12px
.input-group--select .input-group__selections__comma
font-size 12px
</style>
<template>
<v-card
hover
class="visual-dl-image">
<h3 class="visual-dl-image-title">{{ tagInfo.tag.displayName }}
<span class="visual-dl-image-run-icon">{{ tagInfo.run }}</span>
</h3>
<p>
<span>{{ $t('lang.step') }}:</span>
<span>{{ imgData.step }}</span>
<span class="visual-del-image-time">{{ imgData.wallTime | formatTime }}</span>
</p>
<v-slider
:max="steps"
:min="slider.min"
:step="1"
v-model="currentIndex"
/>
<img
:width="imageWidth"
:height="imageHeight"
:src="imgData.imgSrc" >
</v-card>
</template>
<script>
import {getPluginImagesImages} from '../../service';
const defaultImgWidth = 400;
const defaultImgHeight = 300;
// the time to refresh chart data
const intervalTime = 30;
export default {
props: {
tagInfo: {
type: Object,
required: true,
},
runs: {
type: Array,
required: true,
},
running: {
type: Boolean,
required: true,
},
isActualImageSize: {
type: Boolean,
required: true,
},
},
computed: {
steps() {
let data = this.data || [];
return data.length - 1;
},
imageWidth() {
return this.isActualImageSize ? this.imgData.width : defaultImgWidth;
},
imageHeight() {
return this.isActualImageSize ? this.imgData.height : defaultImgHeight;
},
},
filters: {
formatTime: function(value) {
if (!value) {
return;
}
// The value was made in seconds, must convert it to milliseconds
let time = new Date(value * 1000);
let options = {
weekday: 'short', year: 'numeric', month: 'short',
day: 'numeric', hour: '2-digit', minute: '2-digit', second: '2-digit',
};
return time.toLocaleDateString('en-US', options);
},
},
data() {
return {
currentIndex: 0,
slider: {
value: '0',
label: '',
min: 0,
step: 1,
},
imgData: {},
data: [],
height: defaultImgHeight,
weight: defaultImgWidth,
isDemo: process.env.NODE_ENV === 'demo',
};
},
created() {
this.getOriginChartsData();
},
mounted() {
if (this.running && !this.isDemo) {
this.startInterval();
}
},
beforeDestroy() {
this.stopInterval();
},
watch: {
running: function(val) {
(val && !this.isDemo) ? this.startInterval() : this.stopInterval();
},
currentIndex: function(index) {
/* eslint-disable fecs-camelcase */
if (this.data && this.data[index]) {
let currentImgInfo = this.data ? this.data[index] : {};
let {height, width, query, step, wallTime} = currentImgInfo;
let url = '/data/plugin/images/individualImage?ts=' + wallTime;
let imgSrc = [url, query].join('&');
this.imgData = {
imgSrc,
height,
width,
step,
wallTime,
};
}
/* eslint-enable fecs-camelcase */
},
tagInfo: function(val) {
this.currentIndex = 0;
this.getOriginChartsData();
},
},
methods: {
stopInterval() {
clearInterval(this.getOringDataInterval);
},
// get origin data per {{intervalTime}} seconds
startInterval() {
this.getOringDataInterval = setInterval(() => {
this.getOriginChartsData();
}, intervalTime * 1000);
},
getOriginChartsData() {
// let {run, tag} = this.tagInfo;
let run = this.tagInfo.run;
let tag = this.tagInfo.tag;
let {displayName, samples} = tag;
let params = {
run,
tag: displayName,
samples,
};
getPluginImagesImages(params).then(({status, data}) => {
if (status === 0) {
this.data = data;
this.currentIndex = data.length - 1;
}
});
},
},
};
</script>
<style lang="stylus">
.visual-dl-image
font-size 12px
width 420px
float left
margin 20px 30px 10px 0
background #fff
padding 10px
.visual-dl-image-title
font-size 14px
line-height 30px
.visual-dl-image-run-icon
background #e4e4e4
float right
margin-right 10px
padding 0 10px
border solid 1px #e4e4e4
border-radius 6px
line-height 20px
margin-top 4px
.visual-del-image-time
float right
</style>
<template>
<div class="visual-dl-chart-page">
<div class="visual-dl-sample-chart-box">
<ui-image
v-for="(tagInfo, index) in filteredImageTagList"
:key="index"
:tag-info="tagInfo"
:is-actual-image-size="config.isActualImageSize"
:runs="config.runs"
:running="config.running"
/>
</div>
<div class="visual-dl-sample-chart-box">
<ui-audio
v-for="(tagInfo, index) in filteredAudioTagList"
:key="index"
:tag-info="tagInfo"
:runs="config.runs"
:running="config.running"
/>
</div>
<div class="visual-dl-sample-chart-box">
<ui-text
v-for="(tagInfo, index) in filteredTextTagList"
:key="index"
:tag-info="tagInfo"
:runs="config.runs"
:running="config.running"
/>
</div>
<v-pagination
class="visual-dl-sm-pagination"
v-if="total > pageSize"
v-model="currentPage"
:length="pageLength"
/>
</div>
</template>
<script>
import Image from './Image';
import Audio from './Audio';
import Text from './Text';
export default {
components: {
'ui-image': Image,
'ui-audio': Audio,
'ui-text': Text,
},
props: {
config: {
type: Object,
required: true,
},
tagList: {
type: Object,
required: true,
},
total: {
type: Number,
required: true,
},
},
data() {
return {
// current page
currentPage: 1,
// item per page
pageSize: 12,
};
},
computed: {
filteredImageTagList() {
return this.tagList.image.slice((this.currentPage - 1) * this.pageSize, this.currentPage * this.pageSize);
},
filteredAudioTagList() {
let offset = this.tagList.image.length;
let start = (this.currentPage - 1) * this.pageSize - offset;
if (start < 0) start = 0;
let end = this.currentPage * this.pageSize - offset;
if (end < 0) end = 0;
return this.tagList.audio.slice(start, end);
},
filteredTextTagList() {
let offset = this.tagList.image.length + this.tagList.audio.length;
let start = (this.currentPage - 1) * this.pageSize - offset;
if (start < 0) start = 0;
let end = this.currentPage * this.pageSize - offset;
if (end < 0) end = 0;
return this.tagList.text.slice(start, end);
},
pageLength() {
return Math.ceil(this.total / this.pageSize);
},
},
watch: {
'config.runs': function(val) {
this.currentPage = 1;
},
tagList: function(val) {
this.currentPage = 1;
},
},
};
</script>
<style lang="stylus">
@import '~style/variables';
+prefix-classes('visual-dl-')
.chart-page
.sample-chart-box
overflow hidden
float left
.visual-dl-chart-image
float left
.sample-chart-box:after
content ""
clear both
display block
.sm-pagination
height 50px
float left
width 100%
</style>
<template>
<v-card
hover
class="visual-dl-text">
<h3 class="visual-dl-text-title">{{ tagInfo.tag.displayName }}
<span class="visual-dl-text-run-icon">{{ tagInfo.run }}</span>
</h3>
<p>
<span>{{ $t('lang.step') }}:</span>
<span>{{ textData.step }}</span>
<span class="visual-del-text-time">{{ textData.wallTime | formatTime(this.$i18n.locale) }}</span>
</p>
<v-slider
:max="steps"
:min="slider.min"
:step="1"
v-model="currentIndex"
/>
<p> {{ textData.message }} </p>
</v-card>
</template>
<script>
import {getPluginTextsTexts} from '../../service';
// the time to refresh chart data
const intervalTime = 30;
export default {
props: {
tagInfo: {
type: Object,
required: true,
},
runs: {
type: Array,
required: true,
},
running: {
type: Boolean,
required: true,
},
},
computed: {
steps() {
let data = this.data || [];
return data.length - 1;
},
},
filters: {
formatTime: function(value, language) {
if (!value) {
return;
}
// The value was made in seconds, must convert it to milliseconds
let time = new Date(value * 1000);
let options = {
weekday: 'short', year: 'numeric', month: 'short',
day: 'numeric', hour: '2-digit', minute: '2-digit', second: '2-digit',
};
let enc = language === 'zh' ? 'zh-CN' : 'en-US';
return time.toLocaleDateString(enc, options);
},
},
data() {
return {
currentIndex: 0,
slider: {
value: '0',
label: '',
min: 0,
step: 1,
},
textData: {},
data: [],
};
},
created() {
this.getOriginChartsData();
},
mounted() {
if (this.running) {
this.startInterval();
}
},
beforeDestroy() {
this.stopInterval();
},
watch: {
running: function(val) {
val ? this.startInterval() : this.stopInterval();
},
currentIndex: function(index) {
if (this.data && this.data[index]) {
let currentTextInfo = this.data ? this.data[index] : {};
let wallTime = currentTextInfo[0];
let step = currentTextInfo[1];
let message = currentTextInfo[2];
this.textData = {
step,
wallTime,
message,
};
}
},
tagInfo: function(val) {
this.currentIndex = 0;
this.getOriginChartsData();
},
},
methods: {
stopInterval() {
clearInterval(this.getOringDataInterval);
},
// get origin data per {{intervalTime}} seconds
startInterval() {
this.getOringDataInterval = setInterval(() => {
this.getOriginChartsData();
}, intervalTime * 1000);
},
getOriginChartsData() {
// let {run, tag} = this.tagInfo;
let run = this.tagInfo.run;
let tag = this.tagInfo.tag;
let {displayName, samples} = tag;
let params = {
run,
tag: displayName,
samples,
};
getPluginTextsTexts(params).then(({status, data}) => {
if (status === 0) {
this.data = data;
this.currentIndex = data.length - 1;
}
});
},
},
};
</script>
<style lang="stylus">
.visual-dl-text
font-size 12px
width 420px
float left
margin 20px 30px 10px 0
background #fff
padding 10px
.visual-dl-text-title
font-size 14px
line-height 30px
.visual-dl-text-run-icon
background #e4e4e4
float right
margin-right 10px
padding 0 10px
border solid 1px #e4e4e4
border-radius 6px
line-height 20px
margin-top 4px
.visual-dl-chart-actions
.sm-form-item
width 300px
display inline-block
.visual-del-text-time
float right
</style>
<template>
<div class="visual-dl-page-container">
<div class="visual-dl-page-left">
<ui-chart-page
:config="config"
:tag-list="filteredTagsList"
:title="'Tags matching' + config.groupNameReg"
/>
<ui-chart-page
v-for="item in groupedTags"
:key="item.group"
:config="config"
:tag-list="item.tags"
:title="item.group"
/>
</div>
<div class="visual-dl-page-right">
<div class="visual-dl-page-config-container">
<ui-config
:config="config"
/>
</div>
</div>
</div>
</template>
<script>
import {getPluginScalarsTags} from '../service';
import {flatten, uniq} from 'lodash';
import autoAdjustHeight from '../common/util/autoAdjustHeight';
import Config from './ui/Config';
import ChartPage from './ui/ChartPage';
export default {
components: {
'ui-config': Config,
'ui-chart-page': ChartPage,
},
props: {
runs: {
type: Array,
required: true,
},
},
data() {
return {
tags: [],
config: {
groupNameReg: '.*',
smoothing: 0.6,
horizontal: 'step',
sortingMethod: 'default',
outlier: false,
runs: [],
running: true,
},
filteredTagsList: [],
};
},
computed: {
tagsList() {
let tags = this.tags;
let runs = Object.keys(tags);
let tagsArray = runs.map((run) => Object.keys(tags[run]));
let allUniqTags = uniq(flatten(tagsArray));
// get the data for every chart
return allUniqTags.map((tag) => {
let tagList = runs.map((run) => {
return {
run,
tag: tags[run][tag],
};
}).filter((item) => item.tag !== undefined);
return {
tagList,
tag,
group: tag.split('/')[0],
};
});
},
groupedTags() {
let tagsList = this.tagsList || [];
// put data in group
let groupData = {};
tagsList.forEach((item) => {
let group = item.group;
if (groupData[group] === undefined) {
groupData[group] = [];
groupData[group].push(item);
} else {
groupData[group].push(item);
}
});
// to array
let groups = Object.keys(groupData);
return groups.map((group) => {
return {
group,
tags: groupData[group],
};
});
},
},
created() {
getPluginScalarsTags().then(({errno, data}) => {
this.tags = data;
// filter when inited
let groupNameReg = this.config.groupNameReg;
this.filterTagsList(groupNameReg);
});
this.config.runs = this.runs;
},
mounted() {
autoAdjustHeight();
},
watch: {
'config.groupNameReg': function(val) {
this.throttledFilterTagsList();
},
runs: function(val) {
this.config.runs = val;
}
},
methods: {
filterTagsList(groupNameReg) {
if (!groupNameReg) {
this.filteredTagsList = [];
return;
}
let tagsList = this.tagsList || [];
let regExp = new RegExp(groupNameReg);
this.filteredTagsList = tagsList.filter((item) => regExp.test(item.tag));
},
throttledFilterTagsList: _.debounce(
function() {
this.filterTagsList(this.config.groupNameReg);
}, 300
),
},
};
</script>
<style lang="stylus">
</style>
<template>
<v-card
hover
class="visual-dl-page-charts">
<div
ref="chartBox"
class="visual-dl-chart-box"
:style="computedStyle"/>
<div class="visual-dl-chart-actions">
<v-btn
color="toolbox_icon"
flat
icon
@click="isSelectZoomEnable = !isSelectZoomEnable"
class="chart-toolbox-icons">
<img
v-if="!isSelectZoomEnable"
src="../../assets/ic_zoom_select_off.svg">
<img
v-if="isSelectZoomEnable"
src="../../assets/ic_zoom_select_on.svg">
</v-btn>
<v-btn
color="toolbox_icon"
flat
icon
@click="restoreChart"
class="chart-toolbox-icons">
<img src="../../assets/ic_undo.svg">
</v-btn>
<v-btn
color="toolbox_icon"
flat
icon
@click="isExpand = !isExpand"
class="chart-toolbox-icons" >
<img
v-if="!isExpand"
src="../../assets/ic_fullscreen_off.svg">
<img
v-if="isExpand"
src="../../assets/ic_fullscreen_on.svg">
</v-btn>
<v-btn
color="toolbox_icon"
flat
icon
@click="saveChartAsImage"
class="chart-toolbox-icons" >
<img src="../../assets/ic_download.svg">
</v-btn>
<v-menu v-if="tagInfo.tagList.length > 0">
<v-btn
color="toolbox_icon"
slot="activator"
flat
icon
class="chart-toolbox-icons">
<v-icon >more_vert</v-icon>
</v-btn>
<v-list dense>
<v-list-tile>
<v-list-tile-content>
<v-list-tile-title>Download data in JSON</v-list-tile-title>
</v-list-tile-content>
<v-list-tile-action>
<v-icon>expand_more</v-icon>
</v-list-tile-action>
</v-list-tile>
<v-list-tile
v-for="subItem in tagInfo.tagList"
:key="subItem.run"
@click="handleDownLoad(subItem.run)">
<v-list-tile-content>
<v-list-tile-title>&nbsp;&nbsp;&nbsp;{{ subItem.run }}</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
</v-menu>
</div>
</v-card>
</template>
<script>
// libs
import echarts from 'echarts';
import axios from 'axios';
import {isFinite, flatten, maxBy, minBy, sortBy, max, min} from 'lodash';
import {generateJsonAndDownload} from '../../common/util/downLoadFile';
import {quantile} from '../../common/util/index';
import moment from 'moment';
// service
import {getPluginScalarsScalars} from '../../service';
const originLinesOpacity = 0.3;
const lineWidth = 1.5;
const minQuantile = 0.05;
const maxQuantile = 0.95;
// the time to refresh chart data
const intervalTime = 15;
export default {
props: {
tagInfo: {
type: Object,
required: true,
},
runs: {
type: Array,
required: true,
},
running: {
type: Boolean,
required: true,
},
smoothing: {
type: Number,
required: true,
},
horizontal: {
type: String,
required: true,
},
sortingMethod: {
type: String,
required: true,
},
outlier: {
type: Boolean,
required: true,
},
},
computed: {
computedStyle() {
return 'height:' + this.height + 'px;'
+ 'width:' + this.width + 'px;';
},
},
data() {
return {
isDemo: process.env.NODE_ENV === 'demo',
width: 400,
height: 300,
isExpand: false,
isSelectZoomEnable: true,
originData: [],
};
},
watch: {
originData: function(val) {
this.setChartData();
this.setChartsOutlier();
this.setChartHorizon();
},
smoothing: function(val) {
this.setChartData();
},
outlier: function(val) {
this.setChartsOutlier();
},
horizontal: function(val) {
this.setChartHorizon();
},
tagInfo: function(val) {
// Should Clean up the chart before each use.
this.myChart.clear();
this.setChartsOptions(val);
this.getOriginChartData(val);
},
isExpand: function(val) {
this.expandArea(val);
},
isSelectZoomEnable: function(val) {
this.toggleSelectZoom(val);
},
},
mounted() {
this.initChart(this.tagInfo);
this.toggleSelectZoom(true);
if (this.running && !this.isDemo) {
this.startInterval();
}
this.$watch('running', function(running) {
// if it is demo, do not trigger interval
running = running && !this.isDemo;
running ? this.startInterval() : this.stopInterval();
});
},
beforeDestroy() {
this.stopInterval();
},
methods: {
// Create a Scalar Chart, initialize it with default settings, then load datas
initChart(tagInfo) {
this.createChart();
this.setChartsOptions(tagInfo);
this.getOriginChartData(tagInfo);
},
createChart() {
let el = this.$refs.chartBox;
this.myChart = echarts.init(el);
},
setChartsOptions({tagList, tag}) {
// Create two lines, one line is original, the other line is for smoothing
let seriesOption = tagList.map((item) => [
{
name: item.run,
type: 'line',
showSymbol: false,
hoverAnimation: false,
z: 0,
data: [],
animationDuration: 100,
lineStyle: {
normal: {
opacity: originLinesOpacity,
width: lineWidth,
},
},
},
{
name: item.run,
type: 'line',
showSymbol: false,
hoverAnimation: false,
z: 1,
data: [],
animationDuration: 100,
lineStyle: {
normal: {
width: lineWidth,
},
},
},
]
);
seriesOption = flatten(seriesOption);
let legendOptions = tagList.map((item) => item.run);
let instance = this;
let option = {
textStyle: {
fontFamily: 'Merriweather Sans',
},
color: [
'#008c99',
'#c23531',
'#FF9900',
'#109618',
'#990099',
'#3B3EAC',
'#DD4477',
'#AAAA11',
'#5574A6',
'#8B0707',
],
title: {
text: tag,
textStyle: {
fontSize: 13,
fontWeight: 'normal',
},
},
tooltip: {
trigger: 'axis',
axisPointer: {
animation: true,
},
textStyle: {
fontSize: '13',
},
position: ['10%', '90%'],
formatter(params, ticket, callback) {
let data = instance.getFormatterPoints(params[0].data);
return instance.transformFormatterData(data);
},
},
toolbox: {
show: true,
showTitle: false,
itemSize: 0,
feature: {
dataZoom: {},
},
},
legend: {
data: legendOptions,
top: 39,
},
grid: {
left: 48,
top: 75,
right: 40,
bottom: 36,
},
xAxis: {
type: 'value',
name: this.horizontal,
axisLabel: {
fontSize: '11',
},
splitNumber: this.isExpand ? 10 : 5,
},
yAxis: {
type: 'value',
axisLabel: {
fontSize: '11',
formatter(value) {
return value.toString().slice(0, 5);
},
},
},
series: seriesOption,
};
this.myChart.setOption(option);
},
// Get origin data per 60 seconds
startInterval() {
this.getOriginDataInterval = setInterval(() => {
this.getOriginChartData(this.tagInfo);
}, intervalTime * 1000);
},
stopInterval() {
clearInterval(this.getOriginDataInterval);
},
getOriginChartData({tagList, tag}) {
let requestList = tagList.map((item) => {
let params = {
run: item.run,
tag: tag,
};
return getPluginScalarsScalars(params);
});
axios.all(requestList).then((resArray) => {
if (resArray.every((res) => res.status === 0)) {
this.originData = resArray.map((res) => res.data);
}
});
},
setChartData() {
let seriesData = this.originData.map((lineData) => {
if (lineData.length == 0) return [];
// add the smoothed data
this.transformDataset(lineData);
return [
{
data: lineData,
encode: {
// map 1 dimension to xAixs.
x: [1],
// map 2 dimension to yAixs.
y: [2],
},
},
{
data: lineData,
encode: {
// Map 1 dimension to xAixs.
x: [1],
// Map 3 dimension to yAixs,
// the third number is smoothed value.
y: [3],
},
},
];
});
this.myChart.setOption({
series: flatten(seriesData),
});
},
getChartOptions() {
return this.myChart.getOption() || {};
},
handleDownLoad(runItemForDownload) {
let options = this.getChartOptions();
let series = options.series || [];
let seriesItem = series.find((item) => item.name === runItemForDownload) || {};
let fileName = this.tagInfo.tag.replace(/\//g, '-');
generateJsonAndDownload(seriesItem.data, fileName);
},
transformDataset(seriesData) {
// smooth
this.transformData(seriesData, this.smoothing);
},
/**
* @desc 1、add smooth data depend on smoothingWeight. see https://en.wikipedia.org/wiki/Moving_average for detail
* 2、add relative data
* @param {Object} seriesData: echarts series Object
* @param {number} smoothingWeight smooth weight, between 0 ~ 1
*/
transformData(seriesData, smoothingWeight) {
let data = seriesData;
let last = data.length > 0 ? 0 : NaN;
let numAccum = 0;
let startValue;
data.forEach((d, i) => {
let nextVal = d[2];
// second to millisecond.
let millisecond = Math.floor(d[0] * 1000);
if (i === 0) {
startValue = millisecond;
}
// Relative time, millisecond to hours.
d[4] = Math.floor(millisecond - startValue) / (60 * 60 * 1000);
if (!isFinite(nextVal)) {
d[3] = nextVal;
} else {
last = last * smoothingWeight + (1 - smoothingWeight) * nextVal;
numAccum++;
let debiasWeight = 1;
if (smoothingWeight !== 1.0) {
debiasWeight = 1.0 - Math.pow(smoothingWeight, numAccum);
}
d[3] = last / debiasWeight;
}
});
},
// Chart outlier options methods and functions ---- start.
// Compute Y domain from originData.
setChartsOutlier() {
let domainRangeArray = this.originData.map((seriesData) => this.computeDataRange(seriesData, this.outlier));
// Compare, get the best Y domain.
let flattenNumbers = flatten(domainRangeArray);
let finalMax = max(flattenNumbers);
let finalMin = min(flattenNumbers);
// Add padding.
let PaddedYDomain = this.paddedYDomain(finalMin, finalMax);
this.setChartOutlierOptions(PaddedYDomain);
// Store Y domain, if originData is not change, Y domain keep same.
},
// Compute max and min from array, if outlier is true, return quantile range.
computeDataRange(arr, isQuantile) {
// Get data range.
if (arr.length == 0) return [];
let max;
let min;
if (!isQuantile) {
// Get the orgin data range.
max = maxBy(arr, (item) => item[2])[2];
min = minBy(arr, (item) => item[2])[2];
} else {
// Get the quantile range.
let sorted = sortBy(arr, [(item) => item[2]]);
min = quantile(sorted, minQuantile, (item) => item[2]);
max = quantile(arr, maxQuantile, (item) => item[2]);
}
return [min, max];
},
paddedYDomain(min, max) {
return {
max: max > 0 ? max * 1.1 : max * 0.9,
min: min > 0 ? min * 0.9 : min * 1.1,
};
},
setChartOutlierOptions({min, max}) {
this.myChart.setOption({
yAxis: {
min,
max,
},
});
},
// Chart horizontal options methods and functions ---- start.
setChartHorizon() {
let seriesOption = this.myChart.getOption().series;
let encodeSeries = (val) => {
return {
encode: {
x: [val],
},
};
};
let stepSeries = seriesOption.map((item) => encodeSeries(1));
let relativeSeries = seriesOption.map((item) => encodeSeries(4));
let wallSeries = seriesOption.map((item) => encodeSeries(0));
let horizontalToxAxisOptions = {
step: {
xAxis: {
type: 'value',
name: this.horizontal,
axisLabel: {
fontSize: '11',
},
splitNumber: this.isExpand ? 10 : 5,
},
series: stepSeries,
},
relative: {
xAxis: {
type: 'value',
name: this.horizontal,
axisLabel: {
fontSize: '11',
},
splitNumber: this.isExpand ? 10 : 5,
},
series: relativeSeries,
},
wall: {
xAxis: {
type: 'time',
name: this.horizontal,
axisLabel: {
fontSize: '11',
formatter: function(value, index) {
// The value is in seconds, need to convert to milliseconds
let date = new Date(value * 1000);
return date.toLocaleTimeString();
},
},
},
series: wallSeries,
},
};
this.myChart.setOption(horizontalToxAxisOptions[this.horizontal]);
},
expandArea(expand) {
let pageBoxWidth = document.getElementsByClassName('visual-dl-chart-page-box')[0].offsetWidth;
let width = pageBoxWidth * 0.96; // 4% margin
if (expand) {
let el = this.$refs.chartBox;
el.style.width = width + 'px';
el.style.height = '600px';
this.myChart.resize({
width: width,
height: 600,
});
} else {
let el = this.$refs.chartBox;
el.style.width = '400px';
el.style.height = '300px';
this.myChart.resize({
width: 400,
height: 300,
});
}
this.myChart.setOption({
xAxis: {
splitNumber: this.isExpand ? 10 : 5,
},
});
},
toggleSelectZoom(enable) {
let instance = this;
setTimeout(function() {
instance.myChart.dispatchAction({
type: 'takeGlobalCursor',
key: 'dataZoomSelect',
dataZoomSelectActive: enable,
});
}, 0);
},
restoreChart() {
this.myChart.dispatchAction({
type: 'restore',
});
},
saveChartAsImage() {
let dataUrl = this.myChart.getDataURL({
pixelRatio: 1,
backgroundColor: '#fff',
});
let fileName = this.tagInfo.tag.replace(/\//g, '-');
let link = document.createElement('a');
link.download = fileName;
link.href = dataUrl;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
},
getFormatterPoints(data) {
let originData = this.originData;
let tagList = this.tagInfo.tagList;
let sortingMethod = this.sortingMethod;
// Can't know exactly the tigger runs.
// If the step is same, regard the point as the trigger point.
let [, step, triggerValue] = data;
let points = originData.map((series, index) => {
let nearestItem;
if (step === 0) {
nearestItem = series[0];
} else {
for (let i = 0; i < series.length; i++) {
let item = series[i];
if (item[1] === step) {
nearestItem = item;
break;
}
if (item[1] > step) {
let index = i - 1;
nearestItem = series[index >= 0 ? index : 0];
break;
}
if (!nearestItem) {
nearestItem = series[series.length - 1];
}
}
}
return {
run: tagList[index].run,
item: nearestItem,
};
});
if (sortingMethod === 'default' || !sortingMethod) {
return points;
}
let sortedPoints;
switch (sortingMethod) {
case 'descending':
sortedPoints = sortBy(points, (one) => one.item[3]);
sortedPoints.reverse();
break;
case 'ascending':
sortedPoints = sortBy(points, (one) => one.item[3]);
break;
case 'nearest':
// Compare other ponts width the trigger point, caculate the nearest sort.
sortedPoints = sortBy(points, (one) => one.item[3] - triggerValue);
break;
default:
sortedPoints = points;
}
return sortedPoints;
},
transformFormatterData(data) {
let indexPropMap = {
Time: 0,
Step: 1,
Value: 2,
Smoothed: 3,
Relative: 4,
};
let widthPropMap = {
Run: 60,
Time: 120,
Step: 40,
Value: 50,
Smoothed: 60,
Relative: 60,
};
let transformedData = data.map((item) => {
let data = item.item;
return {
Run: item.run,
// Keep six number for easy-read.
Smoothed: data[indexPropMap.Smoothed].toString().slice(0, 6),
Value: data[indexPropMap.Value].toString().slice(0, 6),
Step: data[indexPropMap.Step],
Time: moment(Math.floor(data[indexPropMap.Time] * 1000), 'x').format('YYYY-MM-DD HH:mm:ss'),
// Relative display value should take easy-read into consideration.
// Better to tranform data to 'day:hour', 'hour:minutes', 'minute: seconds' and second only.
Relative: Math.floor(data[indexPropMap.Relative] * 60 * 60) + 's',
};
});
let headerHtml = '<tr style="font-size:14px;">';
headerHtml += Object.keys(transformedData[0]).map((key) => {
return '<td style="padding: 0 4px; font-family: \'Merriweather Sans\'; font-weight: bold; width:' +
widthPropMap[key] + 'px;">' + key + '</td>';
}).join('');
headerHtml += '</tr>';
let content = transformedData.map((item) => {
let str = '<tr style="font-size:12px;">';
str += Object.keys(item).map((val) => {
return '<td style="padding: 0 4px; overflow: hidden;">' + item[val] + '</td>';
}).join('');
str += '</tr>';
return str;
}).join('');
return '<table style="text-align: left;table-layout: fixed;width: 500px;"><thead>' + headerHtml + '</thead>'
+ '<tbody>' + content + '</tbody><table>';
},
},
};
</script>
<style lang="stylus">
.visual-dl-page-charts
float left
margin 2% 2% 0 0
padding 10px
position relative
.visual-dl-chart-actions
opacity 0
transition: opacity .3s ease-out;
position absolute
top 4px
right 10px
img
width 30px
height 30px
position absolute
top 0
bottom 0
margin auto
.chart-toolbox-icons
width 25px
height 25px
margin-left -4px
margin-right -4px
.visual-dl-page-charts:hover
.visual-dl-chart-actions
opacity 1
</style>
<template>
<div class="visual-dl-chart-page">
<ui-expand-panel
:info="tagList.length"
:title="title">
<div
ref="chartPageBox"
class="visual-dl-chart-page-box">
<ui-chart
v-for="(tagInfo, index) in filteredTagList"
:key="index"
:tag-info="tagInfo"
:smoothing="config.smoothing"
:horizontal="config.horizontal"
:sorting-method="config.sortingMethod"
:outlier="config.outlier"
:runs="config.runs"
:running="config.running"
/>
</div>
<v-pagination
v-if="total > pageSize"
v-model="currentPage"
:length="pageLength"
/>
</ui-expand-panel>
</div>
</template>
<script>
import ExpandPanel from '../../common/component/ExpandPanel';
import Chart from './Chart';
import {cloneDeep} from 'lodash';
export default {
components: {
'ui-chart': Chart,
'ui-expand-panel': ExpandPanel,
},
props: {
config: {
type: Object,
required: true,
},
tagList: {
type: Array,
required: true,
},
title: {
type: String,
required: true,
},
},
computed: {
filteredRunsList() {
let tagList = this.tagList || [];
let runs = this.config.runs || [];
let list = cloneDeep(tagList);
return list.slice().map((item) => {
item.tagList = item.tagList.filter((one) => runs.includes(one.run));
return item;
});
},
filteredTagList() {
let tagList = this.filteredRunsList || [];
return tagList.slice((this.currentPage - 1) * this.pageSize, this.currentPage * this.pageSize);
},
total() {
let tagList = this.tagList || [];
return tagList.length;
},
pageLength() {
return Math.ceil(this.total / this.pageSize);
},
},
data() {
return {
// current page
currentPage: 1,
// item per page
pageSize: 8,
};
},
};
</script>
<style lang="stylus">
@import '~style/variables';
+prefix-classes('visual-dl-')
.chart-page
.chart-page-box:after
content: "";
clear: both;
display: block;
padding-bottom: 2%
</style>
<template>
<div class="visual-dl-page-config-com">
<v-text-field
label="Group name RegExp"
hint="input a tag group name"
v-model="config.groupNameReg"
dark
/>
<div class="visual-dl-page-slider-block">
<v-slider
label="Smoothing"
:max="0.99"
:min="0"
:step="0.01"
v-model="smoothingValue"
class="visual-dl-page-smoothing-slider"
dark/>
<span class="visual-dl-page-slider-span">{{ smoothingValue }}</span>
</div>
<v-radio-group
label="X-Axis"
v-model="config.horizontal"
dark>
<v-radio
label="Step"
value="step"/>
<v-radio
label="Relative"
value="relative"/>
<v-radio
label="Wall Time"
value="wall"/>
</v-radio-group>
<v-select
:items="sortingMethodItems"
v-model="config.sortingMethod"
label="Tooltip sorting method"
class="visual-dl-page-config-selector"
dark
dense
/>
<v-checkbox
class="visual-dl-page-config-checkbox"
label="Ignore outliers in chart scaling"
v-model="config.outlier"
dark/>
<v-btn
:color="config.running ? 'primary' : 'error'"
v-model="config.running"
v-if="!isDemo"
@click="toggleAllRuns"
class="visual-dl-page-run-toggle"
dark
block
>
{{ config.running ? 'Running' : 'Stopped' }}
</v-btn>
</div>
</template>
<script>
export default {
props: {
config: {
type: Object,
required: true,
},
},
data() {
return {
horizontalItems: [
{
name: 'Step',
value: 'step',
},
{
name: 'Relative',
value: 'relative',
},
{
name: 'Wall',
value: 'wall',
},
],
sortingMethodItems: [
'default', 'descending', 'ascending', 'nearest',
],
smoothingValue: this.config.smoothing,
isDemo: process.env.NODE_ENV === 'demo',
};
},
watch: {
smoothingValue: _.debounce(
function() {
this.config.smoothing = this.smoothingValue;
}, 500
),
},
methods: {
toggleAllRuns() {
this.config.running = !this.config.running;
},
},
};
</script>
<style lang="stylus">
+prefix-classes('visual-dl-page-')
.config-com
padding 20px
.slider-block
display flex
align-items center
.smoothing-slider
display inline
.slider-span
width 40px
.run-toggle
margin-top 20px
.config-checkbox label
font-size 13px
.config-selector
margin-top 12px
margin-bottom 20px
.checkbox-group-label
display flex
margin-top 20px
margin-bottom 10px
</style>
import {makeService} from './common/util/http';
export const getPluginScalarsTags = makeService('/data/plugin/scalars/tags');
export const getRuns = makeService('/data/runs');
export const getLanguage = makeService('/data/language');
export const getPluginScalarsScalars = makeService('/data/plugin/scalars/scalars');
export const getPluginImagesTags = makeService('/data/plugin/images/tags');
export const getPluginImagesImages = makeService('/data/plugin/images/images');
export const getPluginHistogramsTags = makeService('/data/plugin/histograms/tags');
export const getPluginHistogramsHistograms = makeService('/data/plugin/histograms/histograms');
export const getPluginGraphsGraph = makeService('/data/plugin/graphs/graph');
export const getPluginTextsTags = makeService('/data/plugin/texts/tags');
export const getPluginTextsTexts = makeService('/data/plugin/texts/texts');
export const getPluginAudioTags = makeService('/data/plugin/audio/tags');
export const getPluginAudioAudio = makeService('/data/plugin/audio/audio');
export const getHighDimensionalDatasets = makeService('/data/plugin/embeddings/embeddings');
//stylus variables define before import statement
$input-font-size = 14px
@import '../../node_modules/vuetify/src/stylus/main'
//css define after import statement
.input-group.input-group--slider label
font-size $input-font-size
.input-group__details
min-height 14px
\ No newline at end of file
prefix = 'visual-dl-'
$-theme-color = #008c99
$-top-menu-font-color = #fff
$-left-background-color = #303a3a
$-content-text-color = #303a3a
$-left-border-color = #e9e9e9
$-right-font-color = rgba(#fff, 0.7)
<template>
<div class="visual-dl-page-container">
<div class="visual-dl-page-left">
<ui-chart-page
:expand="true"
:config="filteredConfig"
:tag-list="filteredTagsList"
:title="'Tags matching ' + config.groupNameReg"
/>
<ui-chart-page
v-for="item in groupedTags"
:key="item.group"
:config="filteredConfig"
:tag-list="item.tags"
:title="item.group"
/>
</div>
<div class="visual-dl-page-right">
<div class="visual-dl-page-config-container">
<ui-config
:config="config"
/>
</div>
</div>
</div>
</template>
<script>
import {getPluginTextsTags} from '../service';
import {flatten, uniq} from 'lodash';
import autoAdjustHeight from '../common/util/autoAdjustHeight';
import Config from './ui/Config';
import ChartPage from './ui/ChartPage';
export default {
name: 'Texts',
components: {
'ui-config': Config,
'ui-chart-page': ChartPage,
},
props: {
runs: {
type: Array,
required: true,
},
},
data() {
return {
tags: [],
config: {
groupNameReg: '.*',
runs: [],
running: true,
},
filteredTagsList: [],
};
},
computed: {
tagsList() {
let tags = this.tags;
let runs = Object.keys(tags);
let tagsArray = runs.map((run) => Object.keys(tags[run]));
let allUniqTags = uniq(flatten(tagsArray));
// get the data for every chart
return allUniqTags.map((tag) => {
let tagList = runs.map((run) => {
return {
run,
tag: tags[run][tag],
};
}).filter((item) => item.tag !== undefined);
return {
tagList,
tag,
group: tag.split('/')[0],
};
});
},
groupedTags() {
let tagsList = this.tagsList || [];
// put data in group
let groupData = {};
tagsList.forEach((item) => {
let group = item.group;
if (groupData[group] === undefined) {
groupData[group] = [];
groupData[group].push(item);
} else {
groupData[group].push(item);
}
});
// to array
let groups = Object.keys(groupData);
return groups.map((group) => {
return {
group,
tags: groupData[group],
};
});
},
filteredConfig() {
let config = this.config || {};
let filteredConfig = {};
Object.keys(config).forEach((key) => {
let val = config[key];
filteredConfig[key] = val;
});
return filteredConfig;
},
},
created() {
getPluginTextsTags().then(({errno, data}) => {
this.tags = data;
// filter when inited
let groupNameReg = this.config.groupNameReg;
this.filterTagsList(groupNameReg);
});
this.config.runs = this.runs;
},
mounted() {
autoAdjustHeight();
},
watch: {
'config.groupNameReg': function(val) {
this.throttledFilterTagsList();
},
runs: function(val) {
this.config.runs = val;
}
},
methods: {
filterTagsList(groupNameReg) {
if (!groupNameReg) {
this.filteredTagsList = [];
return;
}
let tagsList = this.tagsList || [];
let regExp = new RegExp(groupNameReg);
this.filteredTagsList = tagsList.filter((item) => regExp.test(item.tag));
},
throttledFilterTagsList: _.debounce(
function() {
this.filterTagsList(this.config.groupNameReg);
}, 300
),
},
};
</script>
<style lang="stylus">
</style>
<template>
<v-card
hover
class="visual-dl-text">
<h3 class="visual-dl-text-title">{{ tagInfo.tag.displayName }}
<span class="visual-dl-text-run-icon">{{ tagInfo.run }}</span>
</h3>
<p>
<span>Step:</span>
<span>{{ textData.step }}</span>
<span class="visual-del-text-time">{{ textData.wallTime | formatTime }}</span>
</p>
<v-slider
:max="steps"
:min="slider.min"
:step="1"
v-model="currentIndex"
/>
<p> {{ textData.message }} </p>
</v-card>
</template>
<script>
import {getPluginTextsTexts} from '../../service';
// the time to refresh chart data
const intervalTime = 30;
export default {
props: {
tagInfo: {
type: Object,
required: true,
},
runs: {
type: Array,
required: true,
},
running: {
type: Boolean,
required: true,
},
},
computed: {
steps() {
let data = this.data || [];
return data.length - 1;
},
},
filters: {
formatTime: function(value) {
if (!value) {
return;
}
// The value was made in seconds, must convert it to milliseconds
let time = new Date(value * 1000);
let options = {
weekday: 'short', year: 'numeric', month: 'short',
day: 'numeric', hour: '2-digit', minute: '2-digit', second: '2-digit',
};
return time.toLocaleDateString('en-US', options);
},
},
data() {
return {
currentIndex: 0,
slider: {
value: '0',
label: '',
min: 0,
step: 1,
},
textData: {},
data: [],
};
},
created() {
this.getOriginChartsData();
},
mounted() {
if (this.running) {
this.startInterval();
}
},
beforeDestroy() {
this.stopInterval();
},
watch: {
running: function(val) {
val ? this.startInterval() : this.stopInterval();
},
currentIndex: function(index) {
if (this.data && this.data[index]) {
let currentTextInfo = this.data ? this.data[index] : {};
let wallTime = currentTextInfo[0];
let step = currentTextInfo[1];
let message = currentTextInfo[2];
this.textData = {
step,
wallTime,
message,
};
}
},
},
methods: {
stopInterval() {
clearInterval(this.getOringDataInterval);
},
// get origin data per {{intervalTime}} seconds
startInterval() {
this.getOringDataInterval = setInterval(() => {
this.getOriginChartsData();
}, intervalTime * 1000);
},
getOriginChartsData() {
// let {run, tag} = this.tagInfo;
let run = this.tagInfo.run;
let tag = this.tagInfo.tag;
let {displayName, samples} = tag;
let params = {
run,
tag: displayName,
samples,
};
getPluginTextsTexts(params).then(({status, data}) => {
if (status === 0) {
this.data = data;
this.currentIndex = data.length - 1;
}
});
},
},
};
</script>
<style lang="stylus">
.visual-dl-text
font-size 12px
width 420px
float left
margin 20px 30px 10px 0
background #fff
padding 10px
.visual-dl-text-title
font-size 14px
line-height 30px
.visual-dl-text-run-icon
background #e4e4e4
float right
margin-right 10px
padding 0 10px
border solid 1px #e4e4e4
border-radius 6px
line-height 20px
margin-top 4px
.visual-dl-chart-actions
.sm-form-item
width 300px
display inline-block
.visual-del-text-time
float right
</style>
<template>
<div class="visual-dl-chart-page">
<ui-expand-panel
:info="tagList.length"
:title="title">
<div
ref="chartPageBox"
class="visual-dl-chart-page-box">
<ui-chart
v-for="(tagInfo, index) in filteredPageList"
:key="index"
:tag-info="tagInfo"
:group-name-reg="config.groupNameReg"
:outlier="config.outlier"
:runs="config.runs"
:running="config.running"
/>
</div>
<v-pagination
v-if="total > pageSize"
v-model="currentPage"
:length="pageLength"
/>
</ui-expand-panel>
</div>
</template>
<script>
import ExpandPanel from '../../common/component/ExpandPanel';
import Chart from './Chart';
import {cloneDeep, flatten} from 'lodash';
export default {
components: {
'ui-chart': Chart,
'ui-expand-panel': ExpandPanel,
},
props: {
config: {
type: Object,
required: true,
},
tagList: {
type: Array,
required: true,
},
title: {
type: String,
required: true,
},
},
computed: {
filteredRunsList() {
let tagList = this.tagList || [];
let runs = this.config.runs || [];
let list = cloneDeep(tagList);
return flatten(list.slice().map((item) => {
return item.tagList.filter((one) => runs.includes(one.run));
}));
},
filteredPageList() {
let list = this.filteredRunsList || [];
return list.slice((this.currentPage - 1) * this.pageSize, this.currentPage * this.pageSize);
},
total() {
let tagList = this.tagList || [];
return tagList.length;
},
pageLength() {
return Math.ceil(this.total / this.pageSize);
},
},
data() {
return {
// current page
currentPage: 1,
// item per page
pageSize: 8,
};
},
};
</script>
<style lang="stylus">
@import '~style/variables';
+prefix-classes('visual-dl-')
.chart-page
.chart-page-box:after
content: "";
clear: both;
display: block;
padding-bottom: 2%
</style>
<template>
<div class="visual-dl-page-config-com">
<v-text-field
label="Group name RegExp"
hint="input a tag group name"
v-model="config.groupNameReg"
dark
/>
<v-btn
:color="config.running ? 'primary' : 'error'"
v-model="config.running"
v-if="!isDemo"
@click="toggleAllRuns"
class="visual-dl-page-run-toggle"
dark
block
>
{{ config.running ? 'Running' : 'Stopped' }}
</v-btn>
</div>
</template>
<script>
export default {
props: {
config: {
type: Object,
required: true,
},
},
data() {
return {
isDemo: process.env.NODE_ENV === 'demo',
};
},
methods: {
toggleAllRuns() {
this.config.running = !this.config.running;
},
},
};
</script>
<style lang="stylus">
+prefix-classes('visual-dl-page-')
.config-com
padding 20px
.slider-block
display flex
align-items center
.smoothing-slider
display inline
.slider-span
width 40px
.run-toggle
margin-top 20px
.config-selector
margin-top 12px
margin-bottom 20px
.checkbox-group-label
display flex
margin-top 20px
margin-bottom 10px
</style>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Visual DL</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<link rel="shortcut icon" type="image/png" href="favicon.png" />
<link href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons' rel="stylesheet">
<script type="text/javascript" src="https://dagrejs.github.io/project/dagre-d3/latest/dagre-d3.min.js"></script>
</head>
<body>
<div id="root"></div>
</body>
</html>
'use strict';
function noopReplace (val) { return val; }
function HtmlReplacePlugin(options) {
this.replacer = options.replacer || noopReplace;
}
HtmlReplacePlugin.prototype.apply = function(compiler) {
var replacer = this.replacer;
compiler.plugin('compilation', function(compilation) {
compilation.plugin('html-webpack-plugin-after-html-processing', function(htmlPluginData, callback) {
htmlPluginData.html = replacer(htmlPluginData.html, htmlPluginData);
callback(null, htmlPluginData);
});
});
};
module.exports = HtmlReplacePlugin;
'use strict';
const webpack = require('webpack');
const rm = require('rimraf');
const ora = require('ora');
const chalk = require('chalk');
const HtmlReplacePlugin = require('./HtmlReplacePlugin');
// env 'production'
process.env.WEBPACK_ENV = 'production';
let webpackConfig = require('./webpack.prod.config');
let spinner = ora('building for production...');
spinner.start();
let feRoots = {
'index': './'
};
webpackConfig.plugins = webpackConfig.plugins.concat([
new HtmlReplacePlugin({
replacer: function(html, opt) {
var name = opt.outputName.replace(/\.html$/, '');
/*
We do not need the following hack, which was added here:
https://github.com/PaddlePaddle/VisualDL/commit/75f5c3b55fb411e0329b98d66253e60137f88bd5#diff-b6dc766994d45268924eff9a07f0765bR31
What it does is simply add './' in front of 'src' and 'href' to make sure it is loading local files.
But it should be able to load both local JS files and CDN files via 'https://...'
*/
// var feRoot = feRoots[name];
// if (feRoot) {
// html = html
// .replace(/href="/g, 'href="' + feRoot);
// .replace(/src="/g, 'src="' + feRoot);
// }
return html;
}
})
]);
rm(webpackConfig.output.path, err => {
if (err) throw err;
webpack(webpackConfig, function(err, stats) {
spinner.stop()
if (err) throw err
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false,
chunks: false,
chunkModules: false
}) + '\n\n');
console.log(chalk.cyan(' Build complete.\n'));
console.log(chalk.yellow(
' Tip: built files are meant to be served over an HTTP server.\n' +
' Opening index.html over file:// won\'t work.\n'
));
})
});
'use strict';
process.env.NODE_ENV = 'demo'; // this is the only diff from dev server
let devPort = 8999;
let opn = require('opn');
let express = require('express');
let webpack = require('webpack');
let proxyMiddleware = require('http-proxy-middleware');
let webpackConfig = require('./webpack.demo.config');
let autoresponse = require('autoresponse');
let path = require('path');
let port = devPort;
let autoOpenBrowser = false;
let app = express();
let compiler = webpack(webpackConfig);
let devMiddleware = require('webpack-dev-middleware')(compiler, {
publicPath: webpackConfig.output.publicPath,
disableHostCheck: true,
quiet: false,
noInfo: false,
stats: {
colors: true
},
headers: {'Access-Control-Allow-Origin': '*'}
});
let hotMiddleware = require('webpack-hot-middleware')(compiler, {
heartbeat: 2000
});
// force page reload when html-webpack-plugin template changes
compiler.plugin('compilation', function (compilation) {
compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
hotMiddleware.publish({
action: 'reload'
});
cb();
});
});
// autoresponse
let AutoresponseMatchs = ['data'];
let matchsReg = new RegExp(AutoresponseMatchs.join('\|'));
let excludeReg = /\.(html|js|map)$/;
let isAutoresponseRequest = (path) => {
return !excludeReg.test(path) && matchsReg.test(path);
}
app.use(autoresponse({
logLevel: 'debug',
root: path.dirname(__dirname),
rules: [
{
match: isAutoresponseRequest,
method: ['get', 'post', , 'delete']
}
]
}));
// serve webpack bundle output
app.use(devMiddleware);
// enable hot-reload and state-preserving
// compilation error display
app.use(hotMiddleware);
let uri = 'http://localhost:' + port;
let _resolve;
let readyPromise = new Promise(resolve => {
_resolve = resolve;
});
console.log('> Starting demo server...');
devMiddleware.waitUntilValid(() => {
console.log('> Listening at ' + uri + '\n');
// when env is testing, don't need open it
if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {
opn(uri);
}
_resolve();
});
let server = app.listen(port);
module.exports = {
ready: readyPromise,
close() {
server.close();
}
};
'use strict';
var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')
hotClient.subscribe(function (event) {
if (event.action === 'reload') {
window.location.reload()
}
})
'use strict';
process.env.NODE_ENV = 'dev';
let devPort = 8999;
let opn = require('opn');
let express = require('express');
let webpack = require('webpack');
let proxyMiddleware = require('http-proxy-middleware');
let webpackConfig = require('./webpack.dev.config');
let autoresponse = require('autoresponse');
let path = require('path');
let port = devPort;
let autoOpenBrowser = false;
let app = express();
let compiler = webpack(webpackConfig);
let devMiddleware = require('webpack-dev-middleware')(compiler, {
publicPath: webpackConfig.output.publicPath,
disableHostCheck: true,
quiet: false,
noInfo: false,
stats: {
colors: true
},
headers: {'Access-Control-Allow-Origin': '*'}
});
let hotMiddleware = require('webpack-hot-middleware')(compiler, {
heartbeat: 2000
});
// force page reload when html-webpack-plugin template changes
compiler.plugin('compilation', function (compilation) {
compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
hotMiddleware.publish({
action: 'reload'
});
cb();
});
});
// autoresponse
let AutoresponseMatchs = ['data'];
let matchsReg = new RegExp(AutoresponseMatchs.join('\|'));
let excludeReg = /\.(html|js|map)$/;
let isAutoresponseRequest = (path) => {
return !excludeReg.test(path) && matchsReg.test(path);
}
app.use(autoresponse({
logLevel: 'debug',
root: path.dirname(__dirname),
rules: [
{
match: isAutoresponseRequest,
method: ['get', 'post', , 'delete']
}
]
}));
// serve webpack bundle output
app.use(devMiddleware);
// enable hot-reload and state-preserving
// compilation error display
app.use(hotMiddleware);
let uri = 'http://localhost:' + port;
let _resolve;
let readyPromise = new Promise(resolve => {
_resolve = resolve;
});
console.log('> Starting dev server...');
devMiddleware.waitUntilValid(() => {
console.log('> Listening at ' + uri + '\n');
// when env is testing, don't need open it
if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {
opn(uri);
}
_resolve();
});
let server = app.listen(port);
module.exports = {
ready: readyPromise,
close() {
server.close();
}
};
'use strict';
const path = require('path');
const projectPath = path.resolve(__dirname, '..');
const HtmlWebpackPlugin = require('html-webpack-plugin');
/**
* default apps
*
* @type {Array}
*/
let defaultApps = [
{
name: 'index',
feRoot: '/dist'
}
];
/**
* get entry js file
*
* @param {Array} apps appname
* @return {string} file path
*/
function getModules(apps) {
let modules = {};
apps.forEach(function (item) {
let app = item.name;
modules[app] = path.join(projectPath, 'src/' + app + '.js');
});
return modules;
}
/**
* get HtmlWebpackPlugin
*
* @param {string} app appname
* @param {boolan} template use template
* @return {HtmlWebpackPlugin} HtmlWebpackPlugin
*/
function getTemplate(app, template) {
let templateUrl = 'template/index.html';
if (template) {
templateUrl = `ejs-render-loader!template/${template}.ejs`;
}
return new HtmlWebpackPlugin({
filename: app + '.html',
template: templateUrl
});
}
/**
* get entry config
*
* @param {string} app appname
* @param {boolan} template use template
* @return {Object} config
*/
function getEntry(app, template) {
let buildApps = defaultApps.filter(function (item) {
let name = item.name;
return name === app;
});
buildApps = buildApps.length > 0 ? buildApps : defaultApps;
return {
module: getModules(buildApps),
template: buildApps.map(item => getTemplate(item.name, template))
};
}
module.exports.get = getEntry;
module.exports.entry = defaultApps;
'use strict';
const webpack = require('webpack');
const path = require('path');
const projectPath = path.resolve(__dirname, '..');
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
const argv = require('yargs').argv;
const isDev = process.env.NODE_ENV === 'dev';
const entry = require('./entry');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
function getLoaders(isDev, ext) {
let arr = ['css-loader'];
if (ext) {
arr.push(ext + '-loader');
}
if (isDev) {
arr.unshift('style-loader');
return arr;
}
return ExtractTextPlugin.extract({
use: arr,
fallback: 'style-loader'
});
}
/**
* entry config
*
* @type {Object}
*/
const ENTR_CONFIG = entry.get(argv.app, argv.template);
/**
* webpack config
*
* @type {Object}
*/
const config = {
entry: ENTR_CONFIG.module,
output: {
path: path.resolve(projectPath, 'dist'),
filename: '[name].[hash].js'
},
resolve: {
alias: {
axios: 'axios/dist/axios.min.js',
'vue$': 'vue/dist/vue.esm.js',
'@': path.resolve(projectPath, 'src'),
style: path.resolve(__dirname, '../src/style')
},
extensions: ['.js', '.json', '.styl', '.css', '.html', '.vue']
},
module: {
noParse: [
/node_modules\/(axios)\//
],
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
},
{
test: /\.js$/,
exclude: /node_modules/,
include: [
path.resolve(projectPath, 'src')
],
loader: 'babel-loader'
},
{
test: /\.json$/,
loader: 'json-loader'
},
{
test: /\.html/,
loader: 'html-loader',
options: {
minimize: false
}
},
{
test: /\.css$/,
use: getLoaders(isDev)
},
{
test: /\.styl$/,
use: getLoaders(isDev, 'stylus')
},
{
test: /\.(gif|png|jpe?g|svg|wav)$/i,
loader: 'file-loader',
options: {
name: 'assets/[name].[hash].[ext]'
}
},
{
test: /\.woff2?$/,
loader: 'url-loader',
options: {
name: 'fonts/[name].[hash].[ext]',
limit: '10000',
mimetype: 'application/font-woff'
}
},
{
test: /\.(ttf|eot)$/,
loader: 'file-loader',
options: {
name: 'fonts/[name].[hash].[ext]'
}
}
]
},
plugins: [
new CaseSensitivePathsPlugin(),
new webpack.LoaderOptionsPlugin({
test: /\.(styl)$/
}),
new ExtractTextPlugin({filename: '[name].css'}),
new HtmlWebpackPlugin({favicon: 'src/assets/favicon.png'})
],
externals: {
dagreD3: 'dagre-d3',
}
};
// template config
config.plugins = config.plugins.concat(ENTR_CONFIG.template);
module.exports = config;
'use strict';
const webpack = require('webpack');
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin');
let merge = require('webpack-merge');
let baseWebpackConfig = require('./webpack.config');
// add hot-reload related code to entry chunks
Object.keys(baseWebpackConfig.entry).forEach(function (name) {
baseWebpackConfig.entry[name] = ['./tool/dev-client'].concat(baseWebpackConfig.entry[name]);
});
/**
* demo config
*
* @type {Object}
*/
module.exports = merge(baseWebpackConfig, {
// cheap-module-eval-source-map is faster for development
devtool: '#cheap-module-eval-source-map',
plugins: [
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': '"demo"' // only diff from webpack.dev.config.js
}
}),
// https://github.com/glenjamin/webpack-hot-middleware#installation--usage
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
// https://github.com/ampedandwired/html-webpack-plugin
new FriendlyErrorsPlugin()
]
});
'use strict';
const webpack = require('webpack');
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin');
let merge = require('webpack-merge');
let baseWebpackConfig = require('./webpack.config');
// add hot-reload related code to entry chunks
Object.keys(baseWebpackConfig.entry).forEach(function (name) {
baseWebpackConfig.entry[name] = ['./tool/dev-client'].concat(baseWebpackConfig.entry[name]);
});
/**
* dev config
*
* @type {Object}
*/
module.exports = merge(baseWebpackConfig, {
// cheap-module-eval-source-map is faster for development
devtool: '#cheap-module-eval-source-map',
plugins: [
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': '"dev"'
}
}),
// https://github.com/glenjamin/webpack-hot-middleware#installation--usage
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
// https://github.com/ampedandwired/html-webpack-plugin
new FriendlyErrorsPlugin()
]
});
'use strict';
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const path = require('path');
const autoprefixer = require('autoprefixer');
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin');
const bizCss = new ExtractTextPlugin('biz.[chunkhash].css');
let merge = require('webpack-merge');
let baseWebpackConfig = require('./webpack.config');
const autoPrefixOptions = {
browsers: [
'iOS >= 7',
'Android >= 4.0',
'ExplorerMobile >= 10',
'ie >= 9'
]
};
/**
* pro config
*
* @type {Object}
*/
module.exports = merge(baseWebpackConfig, {
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.LoaderOptionsPlugin({
test: /\.(styl)$/,
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
filename: 'vendor.[chunkhash].js',
minChunks: function (module, count) {
const resPath = module.resource;
return resPath && /\.js$/.test(resPath)
&& resPath.indexOf(
path.join(__dirname, '../node_modules')
) === 0;
}
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
'screw_ie8': true, // no ie6/7/8
'warnings': false
},
comments: false,
sourceMap: false
}),
bizCss,
new OptimizeCSSPlugin({
cssProcessorOptions: {
safe: true
}
})
]
});
{
"compilerOptions": {
"jsx": "preserve",
"target": "es2018",
"module": "esnext",
"moduleResolution": "node",
"lib": [
"esnext",
"esnext.asynciterable",
"dom"
],
"esModuleInterop": true,
"allowJs": true,
"resolveJsonModule": true,
"sourceMap": true,
"strict": true,
"noEmit": true,
"baseUrl": ".",
"paths": {
"~/*": [
"./*"
]
},
"types": [
"@types/node"
],
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"isolatedModules": true
},
"exclude": [
"node_modules"
],
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx"
]
}
{
"extend": "./tsconfig.json",
"compilerOptions": {
"module": "commonjs",
"esModuleInterop": true,
"typeRoots": ["types"],
"outDir": "dist"
},
"include": [
"server/**/*"
]
}
declare module '*.bmp' {
const src: string;
export default src;
}
declare module '*.gif' {
const src: string;
export default src;
}
declare module '*.jpg' {
const src: string;
export default src;
}
declare module '*.jpeg' {
const src: string;
export default src;
}
declare module '*.png' {
const src: string;
export default src;
}
declare module '*.webp' {
const src: string;
export default src;
}
declare module '*.svg' {
const src: string;
export default src;
}
declare module '*.module.css' {
const classes: {readonly [key: string]: string};
export default classes;
}
declare module '*.module.scss' {
const classes: {readonly [key: string]: string};
export default classes;
}
declare module '*.module.sass' {
const classes: {readonly [key: string]: string};
export default classes;
}
// dagre-d.ts
// Copied from existing type definition @types/dagre-d3, with some modification
declare module 'dagre-d3' {
import {Selection, BaseType} from 'd3';
import * as dagre from 'dagre';
export const graphlib = dagre.graphlib;
export const render: {new (): Render};
export const intersect: {
[shapeName: string]: (node: dagre.Node, points: Array<{}>, point: any) => void;
};
export interface Render {
arrows(): {
[arrowStyleName: string]: (
parent: Selection<BaseType, any, BaseType, any>,
id: string,
edge: dagre.Edge,
type: string
) => void;
};
(selection: Selection<BaseType, any, BaseType, any>, g: dagre.graphlib.Graph): void;
shapes(): {
[shapeStyleName: string]: (
parent: Selection<BaseType, any, BaseType, any>,
bbox: any,
node: dagre.Node
) => void;
};
}
}
declare module 'echarts-gl';
export interface Tag {
runs: string[];
label: string;
}
export type Dimension = '2d' | '3d';
import next, {NextPageContext} from 'next';
import i18NextExpressMiddleware from 'i18next-express-middleware';
declare module 'next' {
// FIXME: ~/node_modules/i18next-express-middleware/index.d.ts
interface NextI18NextPageContext extends NextPageContext {
req?: Express.Request;
res?: Express.Response;
}
}
declare module 'save-svg-as-png' {
export function saveSvgAsPng(node: Node, filename: string): Promise<void>;
}
export const color = ['#2932E1', '#25C9FF', '#981EFF', '#D8DAF6', '#E9F9FF', '#F3E8FF'];
export const title = {
textStyle: {
fontSize: 16,
fontWeight: 'bold'
},
top: 10,
left: 15
};
export const tooltip = {
trigger: 'axis',
position: ['10%', '95%'],
axisPointer: {
type: 'cross',
label: {
show: true
},
lineStyle: {
color: '#2932E1',
type: 'dashed'
},
crossStyle: {
color: '#2932E1',
type: 'dashed'
}
}
};
export const toolbox = {
show: true,
orient: 'vertical',
showTitle: false,
top: 50,
right: 8,
feature: {
saveAsImage: {
show: true
},
dataZoom: {
show: true
},
restore: {
show: true
}
},
tooltip: {
show: true
}
};
export const legend = {
top: 12,
right: 15,
itemWidth: 17,
itemHeight: 5,
textStyle: {
fontSize: 14
},
icon: 'roundRect'
};
export const grid = {
left: 50,
top: 60,
right: 50,
bottom: 50
};
export const xAxis = {
type: 'value',
name: '',
nameTextStyle: {
fontSize: 12,
color: '#666'
},
axisLine: {
lineStyle: {
color: '#CCC'
}
},
axisTick: {
show: false
},
axisLabel: {
fontSize: 12,
color: '#666'
},
splitLine: {
show: false
},
splitNumber: 5
};
export const yAxis = {
type: 'value',
splitNumber: 4,
axisLine: {
lineStyle: {
color: '#CCC'
}
},
axisTick: {
show: false
},
axisLabel: {
fontSize: 12,
color: '#666',
formatter: (v: number) => v.toString().slice(0, 5)
},
splitLine: {
lineStyle: {
color: '#EEE'
}
}
};
export const series = {
type: 'line',
showSymbol: false,
hoverAnimation: false,
animationDuration: 100,
lineStyle: {
width: 1.5
}
};
// TODO: use this instead
// https://github.com/zeit/swr/blob/master/examples/axios-typescript/libs/useRequest.ts
import fetch from 'isomorphic-unfetch';
import {NextPageContext} from 'next';
import {Request} from 'express';
/* eslint-disable @typescript-eslint/no-explicit-any */
export const fetcher = async (url: string, options?: any, baseUrl = ''): Promise<any> => {
const res = await fetch(baseUrl + process.env.API_URL + url, options);
const response = await res.json();
return response && 'data' in response ? response.data : response;
};
export const cycleFetcher = async (urls: string[], options?: any, baseUrl = ''): Promise<any> => {
return await Promise.all(urls.map(url => fetcher(url, options, baseUrl)));
};
type GetInitialProps<T = any> = (context: NextPageContext, f: typeof fetcher) => T | Promise<T>;
export const withFetcher = (getInitialProps: GetInitialProps) => (context: NextPageContext) => {
const {req} = context;
// FIXME
const baseUrl = req ? `${((req as unknown) as Request).protocol}://${req.headers.host}` : '';
return getInitialProps(context, (url: string, options: unknown) => fetcher(url, options, baseUrl));
};
import {NextComponentType, NextPageContext} from 'next';
import NextI18Next from 'next-i18next';
const isProduction = process.env.NODE_ENV === 'production';
const nextI18Next = new NextI18Next({
browserLanguageDetection: isProduction,
serverLanguageDetection: isProduction,
defaultNS: 'common',
defaultLanguage: 'en',
otherLanguages: ['zh'],
localeSubpaths: {
zh: 'zh'
}
});
// from ~/node_modules/next/types/index.d.ts
// https://gitlab.com/kachkaev/website-frontend/-/blob/master/src/i18n.ts#L64-68
export type NextI18NextPage<P = {}, IP = P> = NextComponentType<
NextPageContext,
IP & {namespacesRequired: string[]},
P & {namespacesRequired: string[]}
>;
export default nextI18Next;
export const {i18n, appWithTranslation, withTranslation, useTranslation, Router, Link, Trans} = nextI18Next;
import path from 'path';
import faker from 'faker';
import {Request, Response} from 'express';
const sleep = (time: number) => {
return new Promise(resolve => setTimeout(resolve, time));
};
export type Options = {
path: string;
delay?: number | ((method: string) => number);
};
export default (options: Options) => {
return async (req: Request, res: Response) => {
const method = req.path.replace(/^\//, '');
if (!method) {
res.status(404).send({});
return;
}
try {
let {default: mock} = await import(path.resolve(options.path, method));
if ('function' === typeof mock) {
mock = await mock(req, res);
}
// sleep
let delay = 0;
if ('function' === typeof options.delay) {
delay = options.delay(method);
} else if (options.delay) {
delay = options.delay;
}
await sleep(delay);
if (mock instanceof ArrayBuffer) {
res.send(Buffer.from(mock));
} else {
res.json(JSON.parse(faker.fake(JSON.stringify(mock, null, 4))));
}
} catch (e) {
res.status(500).send(e.message);
}
};
};
import cloneDeep from 'lodash/cloneDeep';
import minBy from 'lodash/minBy';
import maxBy from 'lodash/maxBy';
import sortBy from 'lodash/sortBy';
import moment from 'moment';
// https://en.wikipedia.org/wiki/Moving_average
export const transform = (seriesData: number[][], smoothingWeight: number) => {
const data: number[][] = cloneDeep(seriesData);
let last = data.length > 0 ? 0 : Number.NaN;
let numAccum = 0;
let startValue = 0;
data.forEach((d, i) => {
const nextVal = d[2];
// second to millisecond.
const millisecond = (d[0] = Math.floor(d[0] * 1000));
if (i === 0) {
startValue = millisecond;
}
// Relative time, millisecond to hours.
d[4] = Math.floor(millisecond - startValue) / (60 * 60 * 1000);
if (!isFinite(nextVal)) {
d[3] = nextVal;
} else {
last = last * smoothingWeight + (1 - smoothingWeight) * nextVal;
numAccum++;
let debiasWeight = 1;
if (smoothingWeight !== 1.0) {
debiasWeight = 1.0 - Math.pow(smoothingWeight, numAccum);
}
d[3] = last / debiasWeight;
}
});
return data;
};
export const quantile = (
values: number[][],
p: number,
valueOf: (value: number[], index: number, values: number[][]) => number
) => {
const n = values.length;
if (!n) {
return NaN;
}
if ((p = +p) <= 0 || n < 2) {
return valueOf(values[0], 0, values);
}
if (p >= 1) {
return valueOf(values[n - 1], n - 1, values);
}
const i = (n - 1) * p;
const i0 = Math.floor(i);
const value0 = valueOf(values[i0], i0, values);
const value1 = valueOf(values[i0 + 1], i0 + 1, values);
return value0 + (value1 - value0) * (i - i0);
};
export const range = (seriesData: number[][], outlier = false) => {
if (seriesData.length == 0) return;
if (!outlier) {
// Get the orgin data range.
return {
min: minBy(seriesData, items => items[2])?.[2] ?? 0,
max: maxBy(seriesData, items => items[2])?.[2] ?? 0
};
} else {
// Get the quantile range.
const sorted = sortBy(seriesData, [item => item[2]]);
return {
min: quantile(sorted, 0.05, item => item[2]),
max: quantile(seriesData, 0.95, item => item[2])
};
}
};
export type TooltipData = {
run: string;
item: number[];
};
// TODO: make it better, don't concat html
export const tooltip = (data: TooltipData[]) => {
const indexPropMap = {
Time: 0,
Step: 1,
Value: 2,
Smoothed: 3,
Relative: 4
};
const widthPropMap = {
Run: 60,
Time: 120,
Step: 40,
Value: 50,
Smoothed: 60,
Relative: 60
};
const transformedData = data.map(item => {
const data = item.item;
return {
Run: item.run,
// Keep six number for easy-read.
Smoothed: data[indexPropMap.Smoothed].toString().slice(0, 6),
Value: data[indexPropMap.Value].toString().slice(0, 6),
Step: data[indexPropMap.Step],
Time: moment(Math.floor(data[indexPropMap.Time]), 'x').format('YYYY-MM-DD HH:mm:ss'),
// Relative display value should take easy-read into consideration.
// Better to tranform data to 'day:hour', 'hour:minutes', 'minute: seconds' and second only.
Relative: Math.floor(data[indexPropMap.Relative] * 60 * 60) + 's'
};
});
let headerHtml = '<tr style="font-size:14px;">';
headerHtml += Object.keys(transformedData[0])
.map(key => {
return `<td style="padding: 0 4px; font-weight: bold; width: ${
widthPropMap[key as keyof typeof transformedData[0]]
}px;">${key}</td>`;
})
.join('');
headerHtml += '</tr>';
const content = transformedData
.map(item => {
let str = '<tr style="font-size:12px;">';
str += Object.keys(item)
.map(val => {
return `<td style="padding: 0 4px; overflow: hidden;">${item[val as keyof typeof item]}</td>`;
})
.join('');
str += '</tr>';
return str;
})
.join('');
// eslint-disable-next-line
return `<table style="text-align: left;table-layout: fixed;width: 500px;"><thead>${headerHtml}</thead><tbody>${content}</tbody><table>`;
};
import {createGlobalStyle, keyframes} from 'styled-components';
import {rem as rem16, em as em16, math, normalize, darken, lighten, size} from 'polished';
export {default as styled} from 'styled-components';
export * from 'styled-components';
export * from 'polished';
const fontSize = '14px';
export const rem = (pxval: string | number): string => rem16(pxval, fontSize);
export const em = (pxval: string | number, base?: string | number): string => em16(pxval, base || fontSize);
export const half = (value: string | number): string => math(`${value} / 2`);
// sizes
export const headerHeight = rem(60);
export const asideWidth = rem(260);
export const borderRadius = '4px';
export const progressSpinnerSize = '20px';
// colors
export const headerColor = '#1527C2';
export const primaryColor = '#2932E1';
export const primaryFocusedColor = lighten(0.08, primaryColor);
export const primaryActiveColor = lighten(0.12, primaryColor);
export const selectedColor = '#1A73E8';
export const lightColor = '#F4F5FC';
export const lightFocusedColor = darken(0.03, lightColor);
export const lightActiveColor = darken(0.06, lightColor);
export const textColor = '#333';
export const textLightColor = '#666';
export const textLighterColor = '#999';
export const textInvertColor = '#FFF';
export const bodyBackgroundColor = '#F4F4F4';
export const backgroundColor = '#FFF';
export const backgroundFocusedColor = '#F6F6F6';
export const borderColor = '#DDD';
export const borderFocusedColor = darken(0.15, borderColor);
export const progressBarColor = '#FFF';
// transitions
export const duration = '75ms';
export const easing = 'ease-in';
const spinner = keyframes`
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
`;
export type WithStyled = {
className?: string;
};
export const GlobalStyle = createGlobalStyle`
${normalize}
html {
font-size: ${fontSize};
font-family: 'Merriweather Sans', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
html,
body {
height: 100%;
background-color: ${bodyBackgroundColor};
color: ${textColor};
}
a {
text-decoration: none;
color: inherit;
&:visited {
color: currentColor;
}
}
* {
box-sizing: border-box;
}
#nprogress {
pointer-events: none;
}
#nprogress .bar {
background: ${progressBarColor};
position: fixed;
z-index: 99999;
top: 0;
left: 0;
width: 100%;
height: 2px;
}
#nprogress .peg {
display: block;
position: absolute;
right: 0;
width: ${rem(100)};
height: 100%;
box-shadow: 0 0 rem(10) ${progressBarColor}, 0 0 ${rem(5)} ${progressBarColor};
opacity: 1;
transform: rotate(3deg) translate(0px, -${rem(4)});
}
#nprogress .spinner {
display: block;
position: fixed;
z-index: 99999;
top: ${progressSpinnerSize};
right: ${progressSpinnerSize};
}
#nprogress .spinner-icon {
${size(`calc(${half(headerHeight)} - ${half(progressSpinnerSize)})`)}
box-sizing: border-box;
border: solid 2px transparent;
border-top-color: ${progressBarColor};
border-left-color: ${progressBarColor};
border-radius: 50%;
animation: ${spinner} 400ms linear infinite;
}
.nprogress-custom-parent {
overflow: hidden;
position: relative;
}
.nprogress-custom-parent #nprogress .spinner,
.nprogress-custom-parent #nprogress .bar {
position: absolute;
}
`;
因为 它太大了无法显示 source diff 。你可以改为 查看blob
...@@ -8,4 +8,4 @@ Pillow==5.0.0 ...@@ -8,4 +8,4 @@ Pillow==5.0.0
pre-commit==1.5.1 pre-commit==1.5.1
flask==0.12.2 flask==0.12.2
six==1.11.0 six==1.11.0
protobuf>=3.1.0 protobuf==3.6.1
...@@ -11,30 +11,9 @@ BUILD_DIR=$TOP_DIR/build ...@@ -11,30 +11,9 @@ BUILD_DIR=$TOP_DIR/build
mkdir -p $BUILD_DIR mkdir -p $BUILD_DIR
check_duplicated() {
filename_format=$1
file_num=`ls dist/${filename_format} | wc -l | awk '{$1=$1;print}'`
if [ "$file_num" != "1" ]; then
echo "dist have duplicate file for $file_num, please clean and rerun"
exit 1
fi
}
build_frontend() { build_frontend() {
cd $FRONTEND_DIR cd $FRONTEND_DIR
if [ ! -d "dist" ]; then ./scripts/build.sh
npm install
npm run build
fi
for file_name in "manifest.*.js" "index.*.js" "vendor.*.js"; do
echo $file_name
check_duplicated $file_name
done
}
build_frontend_fake() {
cd $FRONTEND_DIR
mkdir -p dist
} }
build_backend() { build_backend() {
...@@ -62,20 +41,15 @@ clean_env() { ...@@ -62,20 +41,15 @@ clean_env() {
} }
package() { package() {
cp -rf $FRONTEND_DIR/dist $TOP_DIR/visualdl/server/ # deprecated, will use nodejs in docker instead
# cp -rf $FRONTEND_DIR/dist $TOP_DIR/visualdl/server/
} }
ARG=$1 ARG=$1
echo "ARG: " $ARG echo "ARG: " $ARG
if [ "$ARG" = "travis-CI" ]; then
build_frontend_fake
else
build_frontend
fi
clean_env clean_env
build_frontend
build_backend build_backend
build_onnx_graph build_onnx_graph
package package
...@@ -8,17 +8,15 @@ SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" ...@@ -8,17 +8,15 @@ SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd $SCRIPT_DIR/../frontend cd $SCRIPT_DIR/../frontend
export PYTHONPATH=$PYTHONPATH:"$SCRIPT_DIR/.." export PYTHONPATH=$PYTHONPATH:"$SCRIPT_DIR/.."
rm -rf ./dist ./scripts/build.sh
mkdir dist
npm run build
# the config is the only diff from dev_server (webpack.demo.config.js) # TODO: use docker to start frontend enviroment
./node_modules/.bin/webpack --watch --config tool/webpack.demo.config.js --output-path=../visualdl/server/dist & yarn start
# Track webpack pid # Track pid
WEBPACKPID=$! FRONTEND_PID=$!
function finish { function finish {
kill -9 $WEBPACKPID kill -9 $FRONTEND_PID
} }
trap finish EXIT HUP INT QUIT PIPE TERM trap finish EXIT HUP INT QUIT PIPE TERM
......
...@@ -8,16 +8,15 @@ SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" ...@@ -8,16 +8,15 @@ SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd $SCRIPT_DIR/../frontend cd $SCRIPT_DIR/../frontend
export PYTHONPATH=$PYTHONPATH:"$SCRIPT_DIR/.." export PYTHONPATH=$PYTHONPATH:"$SCRIPT_DIR/.."
rm -rf ./dist ./scripts/build.sh
mkdir dist
npm run build
./node_modules/.bin/webpack --watch --config tool/webpack.dev.config.js --output-path=../visualdl/server/dist & # TODO: use docker to start frontend enviroment
# Track webpack pid yarn start
WEBPACKPID=$! # Track pid
FRONTEND_PID=$!
function finish { function finish {
kill -9 $WEBPACKPID kill -9 $FRONTEND_PID
} }
trap finish EXIT HUP INT QUIT PIPE TERM trap finish EXIT HUP INT QUIT PIPE TERM
......
...@@ -42,10 +42,6 @@ export PYTHONPATH="${core_path}:${python_path}" ...@@ -42,10 +42,6 @@ export PYTHONPATH="${core_path}:${python_path}"
# install the visualdl wheel first # install the visualdl wheel first
package() { package() {
# some bug with frontend build
# a environment variable to skip frontend build
export VS_BUILD_MODE="travis-CI"
cd $TOP_DIR/visualdl/server cd $TOP_DIR/visualdl/server
# manully install protobuf3 # manully install protobuf3
curl -OL https://github.com/google/protobuf/releases/download/v3.5.0/protoc-3.5.0-linux-x86_64.zip curl -OL https://github.com/google/protobuf/releases/download/v3.5.0/protoc-3.5.0-linux-x86_64.zip
...@@ -53,7 +49,6 @@ package() { ...@@ -53,7 +49,6 @@ package() {
export PATH="$PATH:$(pwd)/protoc3/bin" export PATH="$PATH:$(pwd)/protoc3/bin"
chmod +x protoc3/bin/* chmod +x protoc3/bin/*
cd $TOP_DIR cd $TOP_DIR
$python setup.py bdist_wheel $python setup.py bdist_wheel
$sudo $pip install dist/visualdl-${version_number}*.whl $sudo $pip install dist/visualdl-${version_number}*.whl
...@@ -72,13 +67,6 @@ backend_test() { ...@@ -72,13 +67,6 @@ backend_test() {
make test make test
} }
frontend_test() {
cd $TOP_DIR
cd frontend
npm install
npm run build
}
server_test() { server_test() {
$sudo $pip install google $sudo $pip install google
$sudo $pip install protobuf==3.5.1 $sudo $pip install protobuf==3.5.1
...@@ -109,8 +97,6 @@ bigfile_reject() { ...@@ -109,8 +97,6 @@ bigfile_reject() {
clean_env() { clean_env() {
rm -rf $TOP_DIR/build rm -rf $TOP_DIR/build
rm -rf $TOP_DIR/dist rm -rf $TOP_DIR/dist
rm -rf $TOP_DIR/frontend/node_modules
rm -rf $TOP_DIR/frontend/dist
rm -rf $TOP_DIR/visualdl/core.so rm -rf $TOP_DIR/visualdl/core.so
rm -rf $TOP_DIR/visualdl/python/core.so rm -rf $TOP_DIR/visualdl/python/core.so
rm -rf $TOP_DIR/visualdl/server/protoc3 rm -rf $TOP_DIR/visualdl/server/protoc3
...@@ -127,13 +113,9 @@ elif [ $mode = "all" ]; then ...@@ -127,13 +113,9 @@ elif [ $mode = "all" ]; then
# bigfile_reject should be tested first, or some files downloaded may fail this test. # bigfile_reject should be tested first, or some files downloaded may fail this test.
bigfile_reject bigfile_reject
package package
frontend_test
backend_test backend_test
server_test server_test
elif [ $mode = "local" ]; then elif [ $mode = "local" ]; then
#frontend_test
backend_test backend_test
server_test server_test
else
frontend_test
fi fi
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册