未验证 提交 e84e5be2 编写于 作者: D daminglu 提交者: GitHub

Polish graph (#395)

上级 274f4554
...@@ -52,7 +52,7 @@ before_install: ...@@ -52,7 +52,7 @@ before_install:
script: script:
- if [[ "$JOB" == "check_style" ]]; then ./scripts/check_style.sh; fi - if [[ "$JOB" == "check_style" ]]; then ./scripts/check_style.sh; fi
- if [[ "$JOB" == "test" ]]; then ./scripts/tests.sh all; WITH_PYTHON3=ON ./scripts/tests.sh all; fi - if [[ "$JOB" == "test" ]]; then ./scripts/tests.sh all; fi
- if [[ "$JOB" == "build_doc" ]]; then ./scripts/deploy_docs_on_travis.sh; fi; - if [[ "$JOB" == "build_doc" ]]; then ./scripts/deploy_docs_on_travis.sh; fi;
notifications: notifications:
......
...@@ -3,8 +3,11 @@ ...@@ -3,8 +3,11 @@
<div class="visual-dl-page-left"> <div class="visual-dl-page-left">
<ui-chart <ui-chart
:do-download="doDownload" :do-download="doDownload"
:do-restore="doRestore"
:scale="config.scale"
@curNodeUpdated="curNode = $event" @curNodeUpdated="curNode = $event"
@triggerDownload="doDownload = $event" @triggerDownload="doDownload = $event"
@triggerRestore="doRestore = $event"
/> />
</div> </div>
<div class="visual-dl-page-right"> <div class="visual-dl-page-right">
...@@ -12,7 +15,9 @@ ...@@ -12,7 +15,9 @@
<ui-config <ui-config
:cur-node="curNode" :cur-node="curNode"
:do-download="doDownload" :do-download="doDownload"
:config="config"
@triggerDownload="doDownload = $event" @triggerDownload="doDownload = $event"
@triggerRestore="doRestore = $event"
/> />
</div> </div>
</div> </div>
...@@ -34,7 +39,11 @@ export default { ...@@ -34,7 +39,11 @@ export default {
data() { data() {
return { return {
doDownload: false, doDownload: false,
doRestore: false,
curNode: {}, curNode: {},
config: {
scale: 0.5,
},
}; };
}, },
mounted() { mounted() {
......
<template> <template>
<div class="visual-dl-graph-charts"> <div class="visual-dl-graph-charts">
<svg <svg
:style="{ width: imageWidth + 'px', height: imageHeight + 'px' }"
class="visual-dl-page-left" class="visual-dl-page-left"
ref="graphSvg"> ref="graphSvg">
<g/> <g/>
...@@ -11,9 +12,9 @@ ...@@ -11,9 +12,9 @@
// service // service
import {getPluginGraphsGraph} from '../../service'; import {getPluginGraphsGraph} from '../../service';
// The name 'svgToPngDownloadHelper' is just a placeholder. // Loading the JS lib file will bind saveSvgAsPng to window,
// Loading the JS lib file will bind saveSvgAsPng to window. // which does an SVG -> PNG -> download process.
import * as svgToPngDownloadHelper from './svgToPngDownloadHelper.js'; import './svgToPngDownloadHelper.js';
// for d3 drawing // for d3 drawing
import * as d3 from 'd3'; import * as d3 from 'd3';
...@@ -27,22 +28,76 @@ export default { ...@@ -27,22 +28,76 @@ export default {
type: Boolean, type: Boolean,
required: true, required: true,
}, },
'doRestore': {
type: Boolean,
required: true,
},
'scale': {
type: Number,
required: true,
},
}, },
computed: {}, computed: {},
data() { data() {
return { return {
imageHeight: 0,
imageWidth: 0,
originImageWidth: 0,
originImageHeight: 0,
graphZoom: null,
svgSelection: null,
zoomScale: null,
}; };
}, },
watch: { watch: {
doDownload: function(val) { doDownload: function(val) {
let chartScope = this;
if (this.doDownload) { if (this.doDownload) {
let svg = this.$refs.graphSvg; // in order to download the full graph image, we need to first restore it
saveSvgAsPng(svg, "graph.png", {scale: 1.0}); // to its original size
this.$emit('triggerDownload', false); 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: {
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() { mounted() {
let chartScope = this; let chartScope = this;
getPluginGraphsGraph().then(({errno, data}) => { getPluginGraphsGraph().then(({errno, data}) => {
...@@ -148,26 +203,49 @@ export default { ...@@ -148,26 +203,49 @@ export default {
// add edges from inputs to node and from node to output // add edges from inputs to node and from node to output
if (has(curOperatorNode, 'input') && isArrayLike(curOperatorNode['input'])) { if (has(curOperatorNode, 'input') && isArrayLike(curOperatorNode['input'])) {
for (let e = 0; e < curOperatorNode['input'].length; ++e) { for (let e = 0; e < curOperatorNode['input'].length; ++e) {
g.setEdge(curOperatorNode['input'][e], nodeKey); g.setEdge(curOperatorNode['input'][e], nodeKey);
} }
} }
if (has(curOperatorNode, 'output') && isArrayLike(curOperatorNode['output'])) { if (has(curOperatorNode, 'output') && isArrayLike(curOperatorNode['output'])) {
g.setEdge(nodeKey, curOperatorNode['output'][0], { g.setEdge(nodeKey, curOperatorNode['output'][0], {
style: 'stroke: #333;stroke-width: 1.5px', style: 'stroke: #333;stroke-width: 1.5px',
}); });
} }
} }
// TODO(daming-lu): add prettier styles to diff nodes
let svg = d3.select('svg') let svg = d3.select('svg')
.attr('font-family', 'sans-serif') .attr('font-family', 'sans-serif')
.attr('font-size', '28px'); .attr('font-size', '28px');
render(d3.select('svg g'), g); render(d3.select('svg g'), g);
// adjust viewBox so that the whole graph can be shown, with scroll bar let graphSelection = d3.select('svg g');
svg.attr('viewBox', '0 0 ' + g.graph().width + ' ' + g.graph().height); let graphWidth = g.graph().width;
let graphHeight = g.graph().height;
svg.attr('viewBox', '0 0 ' + graphWidth + ' ' + graphHeight);
this.imageWidth = graphWidth;
this.imageHeight = graphHeight;
this.originImageWidth = graphWidth;
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) { svg.selectAll('.node').on('click', function(d, i) {
let curNode = g.node(d); let curNode = g.node(d);
...@@ -190,8 +268,6 @@ export default { ...@@ -190,8 +268,6 @@ export default {
}); });
}); });
}, },
methods: {},
}; };
</script> </script>
<style lang="stylus"> <style lang="stylus">
......
...@@ -9,7 +9,26 @@ ...@@ -9,7 +9,26 @@
<v-icon style="margin-right: 6px">file_download</v-icon> <v-icon style="margin-right: 6px">file_download</v-icon>
Download image Download image
</v-btn> </v-btn>
<v-btn
class="visual-dl-graph-config-button"
color="primary"
@click="resetImage"
dark>
<v-icon style="margin-right: 6px">restore</v-icon>
Restore image
</v-btn>
<v-slider
label="Scale"
max="1"
min="0.1"
step="0.1"
v-model="config.scale"
dark/>
</div> </div>
<div class="node-info"> <div class="node-info">
<h3>Node Info: </h3> <h3>Node Info: </h3>
...@@ -43,10 +62,18 @@ export default { ...@@ -43,10 +62,18 @@ export default {
'curNode': { 'curNode': {
type: Object, type: Object,
default: {}, default: {},
}}, methods: { },
'config': {
type: Object,
required: true,
},
}, methods: {
handleDownload() { handleDownload() {
this.$emit('triggerDownload', true); this.$emit('triggerDownload', true);
}, },
resetImage() {
this.$emit('triggerRestore', true);
},
}, },
}; };
</script> </script>
...@@ -66,7 +93,7 @@ export default { ...@@ -66,7 +93,7 @@ export default {
height 26px height 26px
.graph-config-upper .graph-config-upper
height 150px height 300px
.node-info .node-info
font-family 'Courier New', sans-serif font-family 'Courier New', sans-serif
......
...@@ -7,5 +7,5 @@ flake8==3.5.0 ...@@ -7,5 +7,5 @@ flake8==3.5.0
Pillow==5.0.0 Pillow==5.0.0
pre-commit==1.5.1 pre-commit==1.5.1
flask==0.12.2 flask==0.12.2
protobuf==3.5.1
six==1.11.0 six==1.11.0
protobuf==3.5.1
...@@ -35,6 +35,7 @@ fi ...@@ -35,6 +35,7 @@ fi
$sudo $pip install numpy $sudo $pip install numpy
$sudo $pip install Flask $sudo $pip install Flask
$sudo $pip install Pillow $sudo $pip install Pillow
$sudo $pip install six
$sudo $pip install protobuf $sudo $pip install protobuf
export PYTHONPATH="${core_path}:${python_path}" export PYTHONPATH="${core_path}:${python_path}"
......
# Download squeezenet model # Download squeezenet model
curl -LOk http://visualdl.bj.bcebos.com/squeezenet.tar.gz #curl -LOk http://visualdl.bj.bcebos.com/squeezenet.tar.gz
#curl -LOk https://www.dropbox.com/s/fip3jzxsjf2g6zc/squeezenet.tar.gz?dl=0 curl -LOk https://www.dropbox.com/s/fip3jzxsjf2g6zc/squeezenet.tar.gz
tar -xvzf squeezenet.tar.gz tar -xvzf squeezenet.tar.gz
cp squeezenet/model.pb squeezenet_model.pb cp squeezenet/model.pb squeezenet_model.pb
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册