提交 aa62fad6 authored 作者: Christof Angermueller's avatar Christof Angermueller

Add node profiling colors

上级 726cce89
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
<script type='text/javascript' src="http://cpettitt.github.io/project/dagre-d3/v0.1.5/dagre-d3.min.js"></script>
<script type='text/javascript' src="http://cpettitt.github.io/project/graphlib-dot/v0.4.10/graphlib-dot.min.js"></script>
</head>
<body>
<style>
svg {
margin-left:auto;
margin-right:auto;
display:block;
position: fixed;
border: 0px solid black;
top:5%; left:0%; right:0% bottom=10%
}
.nodeRect {
stroke: black;
border: 3px solid black;
}
.nodeEllipse {
stroke: black;
border: 3px solid black;
}
.nodeText {
color: black;
}
.edge {
stroke-width: 3px;
cursor: pointer;
opacity: 0.4;
}
.edgeLabelRect {
stroke: black;
border: 1px solid black;
fill: skyblue;
opacity: 0.9;
}
.edgeLabelText {
fill: black;
text-anchor: start;
}
.arrowHead {
stroke: green;
stroke-width: 1px;
}
.arrowHead_n {
stroke: green;
}
.arrowHead_r {
stroke-width: 3px;
fill: red;
stroke: red;
}
.arrowHead_b {
stroke: dodgerblue;
}
.edgeTooltip {
position: absolute;
text-align: center;
vertical-align: middle;
min-width: 10px;
min-height: 10px;
padding: 5px;
background: lightsteelblue;
border: 1px solid black;
border-radius: 8px;
pointer-events: none;
}
.nodeTooltip {
position: absolute;
text-align: left;
vertical-align: middle;
min-width: 10px;
min-height: 10px;
padding: 5px;
background: lightsteelblue;
border: 1px solid black;
border-radius: 8px;
pointer-events: none;
}
</style>
<div id='menu'>
<input name="resetNodes"
type="button"
value="Reset nodes"
onclick="resetNodes()"/>
<input name="releaseNodes"
type="button"
value="Release nodes"
onclick="releaseNodes()"/>
</div>
<script type="text/javascript">
var path='predict_profiled.dot';
var isProfiled = false;
var colorProfile = false;
// Global attributes
var pad = 10;
d3.select('body').select('svg').remove();
var svg = d3.select('body').append('svg')
.attr('width', '100%')
.attr('height', '95%');
var pane = svg.append('g');
var edgeDiv = d3.select('body').append('div')
.attr('class', 'edgeTooltip')
.style('opacity', 0.0);
var nodeDiv = d3.select('body').append('div')
.attr('class', 'nodeTooltip')
.style('opacity', 0.0);
// Definition head of edges
var markerData = [
{'id': 'n', 'color': 'black'},
{'id': 'r', 'color': 'red'},
{'id': 'b', 'color': 'dodgerblue'}];
svg.append("defs").selectAll('marker').data(markerData).enter().append("marker")
.attr("id", function(d) { return 'edgeArrow_' + d.id;})
.attr("markerWidth", 4)
.attr("markerHeight", 4)
.attr("refX", 2)
.attr("refY", 2)
.attr("orient", "auto")
.append("path")
.attr("d", "M0,0 L4,2 L0,4 Z")
.attr('fill', function(d) { return d.color;});
function toggleColors() {
colorProfile = !colorProfile;
updateNodes();
updateGraph();
}
function textSize(text, attr) {
var t = svg.append('text').text(text);
if (typeof(attr) != 'undefined') {
for (a in attr) {
t.attr(a, attr[a]);
}
}
var bbox = t.node().getBBox();
t.remove();
return bbox;
}
function exists(x) {
return typeof(x) != 'undefined';
}
function replaceAll(str, find, replace) {
return str.replace(new RegExp(find, 'g'), replace);
}
function parseProfile(profile) {
if (typeof(profile) == 'undefined') {
return;
}
profile = profile.replace('[', '');
profile = profile.replace(']', '');
profile = replaceAll(profile, ' ', '');
profile = profile.split(',');
if (profile.length < 2) {
return [];
}
profile = profile.map(function(x) { return parseFloat(x); });
return profile;
}
function profileColor(per) {
var colors = ["#fff5f0","#fee0d2","#fcbba1","#fc9272","#fb6a4a","#ef3b2c","#cb181d","#a50f15","#67000d"];
var s = d3.scale.linear()
.domain([0, 100])
.range([0, colors.length - 1]);
return colors[Math.round(s(per))];
}
function fillColor(d) {
if (colorProfile && typeof(d.value.profile) != 'undefined') {
return profileColor(d.value.profile[2]);
} else {
return typeof(d.value.fillcolor) == 'undefined' ? 'white' : d.value.fillcolor;
}
}
function formatTime(sec) {
var s;
if (sec < 0.1) {
s = (sec * 1000).toFixed(1) + 'ms';
} else {
s = sec.toFixed(1) + 's';
}
return s;
}
function nodeDetails(node) {
var s = '<b>' + node.value.label + '</b>';
var p = node.value.profile;
if (!isNaN(p[0])) {
s += '<br>Total time: ' + formatTime(p[0]);
}
if (!isNaN(p[1])) {
s += '<br>Total time: ' + p[1].toFixed(1) + '%';
}
if (!isNaN(p[2])) {
s += '<br>Profile time: ' + p[2].toFixed(1) + '%';
}
return s;
}
function updateNode(d, node) {
var shape;
if (d.value.shape == 'ellipse') {
node.selectAll('ellipse').remove();
shape = node.append('ellipse')
.attr('class', 'nodeEllipse')
.attr('cx', d.value.cx)
.attr('cy', d.value.cy)
.attr('rx', d.value.width * 0.6)
.attr('ry', d.value.height * 0.6);
} else {
node.selectAll('rect').remove();
shape = node.append('rect')
.attr('class', 'nodeRect')
.attr('width', d.value.width)
.attr('height', d.value.height);
}
shape.attr('fill', fillColor(d));
node.selectAll('text').remove();
var text = node.append('text')
.attr('class', 'nodeText')
.attr('x', pad)
.attr('dy', function(d) {return d.value.height - pad - 5;})
.text(function(d) {return d.value.label;});
}
function updateNodes() {
nodes.each(function(d) {var node = d3.select(this); updateNode(d, node);});
}
var dotGraph;
var graph = {};
var nodes = [];
var edges = [];
var layout;
var scaleDotX;
var scaleDotY;
d3.text(path, function(data) {
dotGraph = graphlibDot.parse(data);
// Calculate width and height
var posMax = [0, 0];
for (var nodeId in dotGraph._nodes) {
var node = dotGraph._nodes[nodeId];
node.value.label = node.id;
node.value.pos = node.value.pos.split(',').map(function(d) {return parseInt(d);});
node.value.width = parseInt(node.value.width);
node.value.height = parseInt(node.value.height);
posMax[0] = Math.max(posMax[0], node.value.pos[0] + node.value.width);
posMax[1] = Math.max(posMax[1], node.value.pos[1] + node.value.height);
}
dotWidth = posMax[0];
dotHeight = posMax[1];
//svg.attr('viewBox', '0,0,' + dotWidth + ',' + dotHeight);
scaleDotX = d3.scale.linear().domain([0, dotWidth]).range([20, dotWidth * 1.2]);
scaleDotY = d3.scale.linear().domain([0, dotHeight]).range([20, dotHeight * 1.2]);
// Parse nodes
var i = 0;
for (nodeId in dotGraph._nodes) {
var node = dotGraph._nodes[nodeId];
node.index = i++;
// x, y is center of node (not corner)
node.x = scaleDotX(node.value.pos[0]);
node.y = scaleDotY(dotHeight - (node.value.pos[1] + node.value.height));
var size = textSize(node.value.label, {'class': 'nodeText'});
node.value.width = size.width + 2 * pad;
node.value.height = size.height + 2 * pad;
node.value.cx = node.value.width / 2;
node.value.cy = node.value.height / 2;
node.value.profile = parseProfile(node.value.profile);
if (typeof(node.value.profile) != 'undefined') {
isProfiled = true;
}
node.fixed = true;
nodes.push(node);
dotGraph._nodes[nodeId] = node;
}
if (isProfiled) {
d3.select('body').select('#menu').append('input')
.attr('name', 'tColors')
.attr('type', 'button')
.attr('value', 'Toggle profile colors')
.attr('onclick', "toggleColors()");
}
// Parse edges
for (edgeId in dotGraph._edges) {
var edge = dotGraph._edges[edgeId];
edge.source = dotGraph._nodes[edge.u].index;
edge.target = dotGraph._nodes[edge.v].index;
var size = textSize(edge.value.label, {'class': 'edgeLabelText'});
edge.value.width = size.width + 2 * pad;
edge.value.height = size.height + 2 * pad;
if (!exists(edge.value.color)) {
edge.value.color = 'black';
}
switch (edge.value.color) {
case 'dodgerblue':
edge.value.type = 'b';
break;
case 'red':
edge.value.type = 'r';
break;
default:
edge.value.type = 'n';
}
edges.push(edge);
dotGraph._edges[edgeId] = edge;
}
// Setup graph
graph['nodes'] = nodes;
graph['edges'] = edges;
var isEdgeOver = false;
var isEdgeLabelOver = false;
// Add edges
edges = pane.append('g').attr('id', 'edges').selectAll('path').data(graph['edges']).enter().append('path')
.attr('class', 'edge')
.attr('stroke', function(d) {return d.value.color;})
.attr('marker-mid', function(d) { return 'url(#edgeArrow_' + d.value.type + ')';})
.on('mouseover', function(d) {
var edge = d3.select(this);
edge.transition()
.duration(200)
.style('opacity', 1.0);
edgeDiv.transition()
.duration(200)
.style('opacity', .9);
edgeDiv
.html(d.value.label)
.style('left', (d3.event.pageX) + 'px')
.style('top', (d3.event.pageY - 28) + 'px');
})
.on('mouseout', function(d) {
var edge = d3.select(this);
edge.transition()
.duration(200)
.style('opacity', 0.4);
edgeDiv.transition()
.duration(200)
.style('opacity', 0);
});
// Add nodes
nodes = pane.append('g').attr('id', 'nodes').selectAll('g').data(graph['nodes']).enter().append('g');
function setNodeSize(node) {
var size = textSize(node.value.label, {'class': 'nodeText'});
node.value.width = size.width + 2 * pad;
node.value.height = size.height + 2 * pad;
node.value.cx = node.value.width / 2;
node.value.cy = node.value.height / 2;
}
updateNodes();
function hideNodeDiv() {
nodeDiv.transition()
.duration(200)
.style('opacity', 0);
}
var editNode = false;
nodes.on('dblclick', function(d) {
var pos = this.getBBox();
var node = d3.select(this);
if (d3.event.defaultPrevented) return;
editNode = true;
hideNodeDiv();
var form = node.append('foreignObject')
.attr('x', pos.x)
.attr('y', pos.y)
.attr('width', d.value.width)
.attr('height', 25);
var input = form.append('xhtml:form').append('input')
.attr('style', 'width: ' + d.value.width + 'px')
.attr('value', function() {
this.focus();
return d.value.label;
})
.on('blur', function() {
d.value.label = input.node().value;
setNodeSize(d);
updateNode(d, node);
form.remove(); // TODO: check this
editNode = false;
})
.on('keypress', function() {
if (!d3.event) {
d3.event = window.event;
}
var event = d3.event;
if (event.keyCode == 13) {
if (typeof(event.cancelBubble)) {
event.cancelBubble = true;
}
if (event.stopPropagation) {
event.stopPropagation();
}
event.preventDefault();
d.value.label = input.node().value;
setNodeSize(d);
updateNode(d, node);
form.remove(); // TODO: check this
editNode = false;
}
});
});
nodes.on('mouseover', function(node) {
if (editNode || typeof(node.value.profile) == 'undefined') {
return;
}
edges.each(function (d, i) {
var edge = d3.select(this);
if (d.source == node || d.target == node) {
edge.transition()
.duration(200)
.style('opacity', 1.0);
}
});
nodeDiv.transition()
.duration(200)
.style('opacity', .9);
nodeDiv
.html(nodeDetails(node))
.style('left', (d3.event.pageX) + 30 + 'px')
.style('top', (d3.event.pageY - 28) + 'px');
});
nodes.on('mouseout', function(node) {
edges.each(function (d, i) {
var edge = d3.select(this);
if (d.source.index == node.index || d.target.index == node.index) {
edge.transition()
.duration(200)
.style('opacity', 0.4);
}
});
hideNodeDiv();
});
nodes.on('contextmenu', function(d) {
releaseNode(d);
});
// Zoom and translate event handler
function zoom(d) {
pane.attr('transform', 'translate(' + d3.event.translate + ') scale(' + d3.event.scale + ')');
}
// Force layout
layout = d3.layout.force()
.nodes(graph['nodes'])
.links(graph['edges'])
.size([dotWidth, dotHeight])
.charge(-3000)
.linkDistance(50)
.linkStrength(0.1)
.on('tick', updateGraph);
// Drag behavour
var drag = layout.drag()
.on('dragstart', function(d) {
d3.event.sourceEvent.stopPropagation();
d3.event.sourceEvent.preventDefault();
d.fixed = true;
});
nodes.call(drag);
// Zoom behaviour
var bZoom = d3.behavior.zoom()
.scaleExtent([0.2, 8])
//.on("dblclick.zoom", null)
.on('zoom', zoom);
svg.call(bZoom);
svg.on("dblclick.zoom", null);
// Start force layout
layout.start();
});
function length(x1, y1, x2, y2) {
return Math.sqrt(Math.pow(x1-x2, 2) + Math.pow(y1-y2, 2));
}
function pathPos(x1, y1, x2, y2, c) {
x = (1 - c) * x1 + c * x2;
y = (1 - c) * y1 + c * y2;
p = x + ',' + y;
return p;
}
// Update graph
function updateGraph() {
// Update nodes
nodes.attr('transform', function(d) { return 'translate(' + (d.x - d.value.cx) + ' ' + (d.y - d.value.cy) + ')'; });
// Update edges
edges.attr('d', function(d) {
var dist = 100;
var l = length(d.source.x, d.source.y, d.target.x, d.target.y);
var n = Math.max(2, Math.floor(l / dist));
var marker = [];
for (var i = 1; i < n; ++i) {
marker.push(i / n);
}
var markerPos = marker.map(function(c) {return pathPos(d.source.x, d.source.y, d.target.x, d.target.y, c);});
var markerPos = ' L' + markerPos.join(' L');
return 'M' + d.source.x + ',' + d.source.y + markerPos + ' L' + d.target.x + ',' + d.target.y;
});
}
function releaseNode(d) {
d.fixed = false;
layout.start();
}
function releaseNodes() {
graph['nodes'].forEach (function (d) {
d.fixed = false;
});
layout.start();
}
function resetNodes() {
layout.stop();
var nodes = graph['nodes'];
nodes.forEach(function (node, i){
nodes[i].x = scaleDotX(node.value.pos[0]);
nodes[i].y = scaleDotY(dotHeight - (node.value.pos[1] + node.value.height));
nodes[i].px = nodes[i].x;
nodes[i].py = nodes[i].y;
nodes[i].fixed = true;
});
updateGraph();
layout.start();
}
</script>
</body>
</html>
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Couldn't import dot_parser, loading of dot files will not be possible.\n"
]
}
],
"source": [
"import numpy\n",
"import numpy.random as rng\n",
"import theano\n",
"import theano.tensor as T\n",
"import theano.printing as pr\n",
"import theano.d3printing as d3p\n",
"from theano.d3printing.formatting import GraphFormatter\n",
"from theano import ProfileMode\n",
"import pydot as pd\n",
"\n",
"from IPython.display import SVG"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"%load_ext autoreload\n",
"%autoreload 2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Model "
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"n = 100\n",
"m = 50\n",
"h = 10\n",
"\n",
"W = theano.shared(np.random.normal(0, 1, (m, h)).astype(theano.config.floatX), borrow=True)\n",
"X = T.dmatrix('X')\n",
"Z = T.nnet.sigmoid(T.dot(X, W))\n",
"zm = T.mean(Z)\n",
"\n",
"predict_profiled = theano.function([X], [Z, zm], profile=True)\n",
"data = rng.rand(n, m)\n",
"dZ, dzm = predict_profiled(data)\n",
"\n",
"predict_unprofiled = theano.function([X], [Z, zm], profile=False)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"gf = GraphFormatter()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Profiled graphed "
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The output file is available at predict_profiled.html\n"
]
}
],
"source": [
"g = gf.to_pydot(predict_profiled)\n",
"d3p.d3print(predict_profiled, 'predict_profiled.html')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[open](./predict_profiled.html) "
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/svg+xml": [
"<svg height=\"592pt\" viewBox=\"0.00 0.00 931.00 592.00\" width=\"931pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
"<g class=\"graph\" id=\"graph0\" transform=\"scale(1 1) rotate(0) translate(4 588)\">\n",
"<title>G</title>\n",
"<polygon fill=\"white\" points=\"-4,4 -4,-588 927,-588 927,4 -4,4\" stroke=\"none\"/>\n",
"<!-- Shape_i{1} -->\n",
"<g class=\"node\" id=\"node1\"><title>Shape_i{1}</title>\n",
"<ellipse cx=\"763\" cy=\"-478\" fill=\"cyan\" rx=\"52.9443\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"763\" y=\"-474.3\">Shape_i{1}</text>\n",
"</g>\n",
"<!-- MakeVector -->\n",
"<g class=\"node\" id=\"node6\"><title>MakeVector</title>\n",
"<ellipse cx=\"602\" cy=\"-390\" fill=\"none\" rx=\"55.3436\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"602\" y=\"-386.3\">MakeVector</text>\n",
"</g>\n",
"<!-- Shape_i{1}&#45;&gt;MakeVector -->\n",
"<g class=\"edge\" id=\"edge6\"><title>Shape_i{1}-&gt;MakeVector</title>\n",
"<path d=\"M735.689,-462.411C708.974,-448.141 668.114,-426.315 638.598,-410.549\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"639.915,-407.285 629.445,-405.66 636.617,-413.459 639.915,-407.285\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"775\" y=\"-430.3\">1 TensorType(int64, scalar)</text>\n",
"</g>\n",
"<!-- TensorType(float64, matrix) -->\n",
"<g class=\"node\" id=\"node2\"><title>TensorType(float64, matrix)</title>\n",
"<polygon fill=\"limegreen\" points=\"728,-584 552,-584 552,-548 728,-548 728,-584\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"640\" y=\"-562.3\">TensorType(float64, matrix)</text>\n",
"</g>\n",
"<!-- TensorType(float64, matrix)&#45;&gt;Shape_i{1} -->\n",
"<g class=\"edge\" id=\"edge1\"><title>TensorType(float64, matrix)-&gt;Shape_i{1}</title>\n",
"<path d=\"M728.218,-549.113C737.934,-544.301 746.871,-538.067 754,-530 759.757,-523.486 762.449,-514.618 763.57,-506.103\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"767.066,-506.289 764.259,-496.073 760.082,-505.81 767.066,-506.289\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"843\" y=\"-518.3\">TensorType(float64, matrix)</text>\n",
"</g>\n",
"<!-- Dot22 -->\n",
"<g class=\"node\" id=\"node5\"><title>Dot22</title>\n",
"<ellipse cx=\"242\" cy=\"-478\" fill=\"none\" rx=\"33.1991\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"242\" y=\"-474.3\">Dot22</text>\n",
"</g>\n",
"<!-- TensorType(float64, matrix)&#45;&gt;Dot22 -->\n",
"<g class=\"edge\" id=\"edge4\"><title>TensorType(float64, matrix)-&gt;Dot22</title>\n",
"<path d=\"M610.316,-547.87C600.623,-542.227 589.827,-535.889 580,-530 568.361,-523.026 566.88,-518.266 554,-514 467.597,-485.383 440.342,-507.083 350,-496 328.021,-493.304 303.645,-489.534 283.621,-486.23\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"284.023,-482.749 273.583,-484.552 282.869,-489.653 284.023,-482.749\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"665\" y=\"-518.3\">1 TensorType(float64, matrix)</text>\n",
"</g>\n",
"<!-- Shape_i{0} -->\n",
"<g class=\"node\" id=\"node3\"><title>Shape_i{0}</title>\n",
"<ellipse cx=\"412\" cy=\"-478\" fill=\"cyan\" rx=\"52.9443\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"412\" y=\"-474.3\">Shape_i{0}</text>\n",
"</g>\n",
"<!-- Shape_i{0}&#45;&gt;MakeVector -->\n",
"<g class=\"edge\" id=\"edge5\"><title>Shape_i{0}-&gt;MakeVector</title>\n",
"<path d=\"M437.912,-462.25C457.204,-451.547 484.353,-437.066 509,-426 523.976,-419.276 540.668,-412.715 555.731,-407.125\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"557.173,-410.324 565.36,-403.6 554.766,-403.751 557.173,-410.324\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"587\" y=\"-430.3\">0 TensorType(int64, scalar)</text>\n",
"</g>\n",
"<!-- name=X TensorType(float64, matrix) -->\n",
"<g class=\"node\" id=\"node4\"><title>name=X TensorType(float64, matrix)</title>\n",
"<polygon fill=\"limegreen\" points=\"456,-584 228,-584 228,-548 456,-548 456,-584\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"342\" y=\"-562.3\">name=X TensorType(float64, matrix)</text>\n",
"</g>\n",
"<!-- name=X TensorType(float64, matrix)&#45;&gt;Shape_i{0} -->\n",
"<g class=\"edge\" id=\"edge2\"><title>name=X TensorType(float64, matrix)-&gt;Shape_i{0}</title>\n",
"<path d=\"M361.08,-547.903C366.78,-542.42 372.872,-536.166 378,-530 384.666,-521.984 391.209,-512.635 396.748,-504.146\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"399.704,-506.02 402.118,-495.704 393.798,-502.262 399.704,-506.02\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"470\" y=\"-518.3\">TensorType(float64, matrix)</text>\n",
"</g>\n",
"<!-- name=X TensorType(float64, matrix)&#45;&gt;Dot22 -->\n",
"<g class=\"edge\" id=\"edge3\"><title>name=X TensorType(float64, matrix)-&gt;Dot22</title>\n",
"<path d=\"M240.099,-547.929C223.328,-543.107 209.578,-537.169 204,-530 196.089,-519.832 203.283,-508.338 213.457,-498.839\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"215.81,-501.433 221.218,-492.323 211.309,-496.073 215.81,-501.433\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"289\" y=\"-518.3\">0 TensorType(float64, matrix)</text>\n",
"</g>\n",
"<!-- Elemwise{ScalarSigmoid}[(0, 0)] -->\n",
"<g class=\"node\" id=\"node7\"><title>Elemwise{ScalarSigmoid}[(0, 0)]</title>\n",
"<ellipse cx=\"242\" cy=\"-390\" fill=\"#ffaabb\" rx=\"134.307\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"242\" y=\"-386.3\">Elemwise{ScalarSigmoid}[(0, 0)]</text>\n",
"</g>\n",
"<!-- Dot22&#45;&gt;Elemwise{ScalarSigmoid}[(0, 0)] -->\n",
"<g class=\"edge\" id=\"edge7\"><title>Dot22-&gt;Elemwise{ScalarSigmoid}[(0, 0)]</title>\n",
"<path d=\"M242,-459.597C242,-447.746 242,-431.817 242,-418.292\" fill=\"none\" stroke=\"red\"/>\n",
"<polygon fill=\"red\" points=\"245.5,-418.084 242,-408.084 238.5,-418.084 245.5,-418.084\" stroke=\"red\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"322\" y=\"-430.3\">TensorType(float64, matrix)</text>\n",
"</g>\n",
"<!-- Elemwise{Cast{float64}} -->\n",
"<g class=\"node\" id=\"node9\"><title>Elemwise{Cast{float64}}</title>\n",
"<ellipse cx=\"602\" cy=\"-302\" fill=\"#ffaabb\" rx=\"104.937\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"602\" y=\"-298.3\">Elemwise{Cast{float64}}</text>\n",
"</g>\n",
"<!-- MakeVector&#45;&gt;Elemwise{Cast{float64}} -->\n",
"<g class=\"edge\" id=\"edge9\"><title>MakeVector-&gt;Elemwise{Cast{float64}}</title>\n",
"<path d=\"M602,-371.597C602,-359.746 602,-343.817 602,-330.292\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"605.5,-330.084 602,-320.084 598.5,-330.084 605.5,-330.084\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"676\" y=\"-342.3\">TensorType(int64, vector)</text>\n",
"</g>\n",
"<!-- TensorType(float64, matrix) id=6 -->\n",
"<g class=\"node\" id=\"node8\"><title>TensorType(float64, matrix) id=6</title>\n",
"<polygon fill=\"dodgerblue\" points=\"356.25,-320 151.75,-320 151.75,-284 356.25,-284 356.25,-320\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"254\" y=\"-298.3\">TensorType(float64, matrix) id=6</text>\n",
"</g>\n",
"<!-- Elemwise{ScalarSigmoid}[(0, 0)]&#45;&gt;TensorType(float64, matrix) id=6 -->\n",
"<g class=\"edge\" id=\"edge8\"><title>Elemwise{ScalarSigmoid}[(0, 0)]-&gt;TensorType(float64, matrix) id=6</title>\n",
"<path d=\"M244.428,-371.597C246.082,-359.746 248.305,-343.817 250.192,-330.292\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"253.701,-330.472 251.616,-320.084 246.768,-329.504 253.701,-330.472\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"330\" y=\"-342.3\">TensorType(float64, matrix)</text>\n",
"</g>\n",
"<!-- Sum{acc_dtype=float64} -->\n",
"<g class=\"node\" id=\"node10\"><title>Sum{acc_dtype=float64}</title>\n",
"<ellipse cx=\"103\" cy=\"-248\" fill=\"none\" rx=\"103.012\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"103\" y=\"-244.3\">Sum{acc_dtype=float64}</text>\n",
"</g>\n",
"<!-- Elemwise{ScalarSigmoid}[(0, 0)]&#45;&gt;Sum{acc_dtype=float64} -->\n",
"<g class=\"edge\" id=\"edge10\"><title>Elemwise{ScalarSigmoid}[(0, 0)]-&gt;Sum{acc_dtype=float64}</title>\n",
"<path d=\"M144.123,-377.632C116.496,-372.297 91.5885,-364.685 83,-354 65.1182,-331.754 75.9432,-298.337 87.4351,-275.202\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"90.5714,-276.758 92.1497,-266.282 84.3826,-273.487 90.5714,-276.758\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"163\" y=\"-342.3\">TensorType(float64, matrix)</text>\n",
"</g>\n",
"<!-- Subtensor{int64} -->\n",
"<g class=\"node\" id=\"node11\"><title>Subtensor{int64}</title>\n",
"<ellipse cx=\"670\" cy=\"-194\" fill=\"#ffaaff\" rx=\"74.6146\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"670\" y=\"-190.3\">Subtensor{int64}</text>\n",
"</g>\n",
"<!-- Elemwise{Cast{float64}}&#45;&gt;Subtensor{int64} -->\n",
"<g class=\"edge\" id=\"edge11\"><title>Elemwise{Cast{float64}}-&gt;Subtensor{int64}</title>\n",
"<path d=\"M629.37,-284.551C636.239,-279.342 643.053,-273.072 648,-266 657.078,-253.024 662.508,-236.173 665.701,-222.144\" fill=\"none\" stroke=\"dodgerblue\"/>\n",
"<polygon fill=\"dodgerblue\" points=\"669.185,-222.571 667.731,-212.077 662.323,-221.188 669.185,-222.571\" stroke=\"dodgerblue\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"748.5\" y=\"-244.3\">0 TensorType(float64, vector)</text>\n",
"</g>\n",
"<!-- Subtensor{int64} id=8 -->\n",
"<g class=\"node\" id=\"node13\"><title>Subtensor{int64} id=8</title>\n",
"<ellipse cx=\"462\" cy=\"-194\" fill=\"#ffaaff\" rx=\"93.3873\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"462\" y=\"-190.3\">Subtensor{int64} id=8</text>\n",
"</g>\n",
"<!-- Elemwise{Cast{float64}}&#45;&gt;Subtensor{int64} id=8 -->\n",
"<g class=\"edge\" id=\"edge13\"><title>Elemwise{Cast{float64}}-&gt;Subtensor{int64} id=8</title>\n",
"<path d=\"M516.396,-291.457C500.826,-286.113 486.044,-278.059 475,-266 464.308,-254.325 461.003,-236.882 460.398,-222.207\" fill=\"none\" stroke=\"dodgerblue\"/>\n",
"<polygon fill=\"dodgerblue\" points=\"463.897,-222.122 460.367,-212.132 456.897,-222.143 463.897,-222.122\" stroke=\"dodgerblue\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"559.5\" y=\"-244.3\">0 TensorType(float64, vector)</text>\n",
"</g>\n",
"<!-- Elemwise{Composite{((i0 / i1) / i2)}}[(0, 0)] -->\n",
"<g class=\"node\" id=\"node15\"><title>Elemwise{Composite{((i0 / i1) / i2)}}[(0, 0)]</title>\n",
"<ellipse cx=\"462\" cy=\"-106\" fill=\"#ffaabb\" rx=\"176.177\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"462\" y=\"-102.3\">Elemwise{Composite{((i0 / i1) / i2)}}[(0, 0)]</text>\n",
"</g>\n",
"<!-- Sum{acc_dtype=float64}&#45;&gt;Elemwise{Composite{((i0 / i1) / i2)}}[(0, 0)] -->\n",
"<g class=\"edge\" id=\"edge15\"><title>Sum{acc_dtype=float64}-&gt;Elemwise{Composite{((i0 / i1) / i2)}}[(0, 0)]</title>\n",
"<path d=\"M119.532,-230.175C136.346,-214 163.864,-190.002 192,-176 243.475,-150.382 305.343,-133.68 356.863,-123.136\" fill=\"none\" stroke=\"red\"/>\n",
"<polygon fill=\"red\" points=\"357.569,-126.564 366.69,-121.173 356.198,-119.699 357.569,-126.564\" stroke=\"red\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"275.5\" y=\"-190.3\">0 TensorType(float64, scalar)</text>\n",
"</g>\n",
"<!-- Subtensor{int64}&#45;&gt;Elemwise{Composite{((i0 / i1) / i2)}}[(0, 0)] -->\n",
"<g class=\"edge\" id=\"edge17\"><title>Subtensor{int64}-&gt;Elemwise{Composite{((i0 / i1) / i2)}}[(0, 0)]</title>\n",
"<path d=\"M661.082,-175.699C654.339,-164.365 644.024,-150.185 631,-142 617.889,-133.761 603.185,-127.421 588.064,-122.551\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"588.664,-119.077 578.08,-119.557 586.654,-125.782 588.664,-119.077\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"731.5\" y=\"-146.3\">2 TensorType(float64, scalar)</text>\n",
"</g>\n",
"<!-- val=1 int64 -->\n",
"<g class=\"node\" id=\"node12\"><title>val=1 int64</title>\n",
"<polygon fill=\"limegreen\" points=\"902.25,-320 821.75,-320 821.75,-284 902.25,-284 902.25,-320\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"862\" y=\"-298.3\">val=1 int64</text>\n",
"</g>\n",
"<!-- val=1 int64&#45;&gt;Subtensor{int64} -->\n",
"<g class=\"edge\" id=\"edge12\"><title>val=1 int64-&gt;Subtensor{int64}</title>\n",
"<path d=\"M860.642,-283.734C858.414,-267.462 852.531,-243.606 837,-230 823.252,-217.956 783.956,-209.391 746.935,-203.749\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"746.978,-200.219 736.577,-202.235 745.965,-207.145 746.978,-200.219\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"877\" y=\"-244.3\">1 int64</text>\n",
"</g>\n",
"<!-- Subtensor{int64} id=8&#45;&gt;Elemwise{Composite{((i0 / i1) / i2)}}[(0, 0)] -->\n",
"<g class=\"edge\" id=\"edge16\"><title>Subtensor{int64} id=8-&gt;Elemwise{Composite{((i0 / i1) / i2)}}[(0, 0)]</title>\n",
"<path d=\"M462,-175.597C462,-163.746 462,-147.817 462,-134.292\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"465.5,-134.084 462,-124.084 458.5,-134.084 465.5,-134.084\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"545.5\" y=\"-146.3\">1 TensorType(float64, scalar)</text>\n",
"</g>\n",
"<!-- val=0 int64 -->\n",
"<g class=\"node\" id=\"node14\"><title>val=0 int64</title>\n",
"<polygon fill=\"limegreen\" points=\"455.25,-320 374.75,-320 374.75,-284 455.25,-284 455.25,-320\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"415\" y=\"-298.3\">val=0 int64</text>\n",
"</g>\n",
"<!-- val=0 int64&#45;&gt;Subtensor{int64} id=8 -->\n",
"<g class=\"edge\" id=\"edge14\"><title>val=0 int64-&gt;Subtensor{int64} id=8</title>\n",
"<path d=\"M411.23,-283.946C408.807,-268.911 407.505,-246.84 416,-230 418.201,-225.638 421.228,-221.669 424.688,-218.102\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"427.133,-220.611 432.272,-211.345 422.477,-215.384 427.133,-220.611\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"436\" y=\"-244.3\">1 int64</text>\n",
"</g>\n",
"<!-- TensorType(float64, scalar) id=13 -->\n",
"<g class=\"node\" id=\"node16\"><title>TensorType(float64, scalar) id=13</title>\n",
"<polygon fill=\"dodgerblue\" points=\"566,-36 358,-36 358,-0 566,-0 566,-36\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"462\" y=\"-14.3\">TensorType(float64, scalar) id=13</text>\n",
"</g>\n",
"<!-- Elemwise{Composite{((i0 / i1) / i2)}}[(0, 0)]&#45;&gt;TensorType(float64, scalar) id=13 -->\n",
"<g class=\"edge\" id=\"edge18\"><title>Elemwise{Composite{((i0 / i1) / i2)}}[(0, 0)]-&gt;TensorType(float64, scalar) id=13</title>\n",
"<path d=\"M462,-87.5966C462,-75.7459 462,-59.8169 462,-46.2917\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"465.5,-46.084 462,-36.084 458.5,-46.084 465.5,-46.084\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"540\" y=\"-58.3\">TensorType(float64, scalar)</text>\n",
"</g>\n",
"</g>\n",
"</svg>"
],
"text/plain": [
"<IPython.core.display.SVG object>"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"SVG(g.create_svg())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Unprofiled graph"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The output file is available at predict_unprofiled.html\n"
]
}
],
"source": [
"g = gf.to_pydot(predict_unprofiled)\n",
"d3p.d3print(predict_unprofiled, 'predict_unprofiled.html')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[open](./predict_unprofiled.html) "
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/svg+xml": [
"<svg height=\"592pt\" viewBox=\"0.00 0.00 931.00 592.00\" width=\"931pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
"<g class=\"graph\" id=\"graph0\" transform=\"scale(1 1) rotate(0) translate(4 588)\">\n",
"<title>G</title>\n",
"<polygon fill=\"white\" points=\"-4,4 -4,-588 927,-588 927,4 -4,4\" stroke=\"none\"/>\n",
"<!-- Shape_i{1} -->\n",
"<g class=\"node\" id=\"node1\"><title>Shape_i{1}</title>\n",
"<ellipse cx=\"763\" cy=\"-478\" fill=\"cyan\" rx=\"52.9443\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"763\" y=\"-474.3\">Shape_i{1}</text>\n",
"</g>\n",
"<!-- MakeVector -->\n",
"<g class=\"node\" id=\"node6\"><title>MakeVector</title>\n",
"<ellipse cx=\"602\" cy=\"-390\" fill=\"none\" rx=\"55.3436\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"602\" y=\"-386.3\">MakeVector</text>\n",
"</g>\n",
"<!-- Shape_i{1}&#45;&gt;MakeVector -->\n",
"<g class=\"edge\" id=\"edge6\"><title>Shape_i{1}-&gt;MakeVector</title>\n",
"<path d=\"M735.689,-462.411C708.974,-448.141 668.114,-426.315 638.598,-410.549\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"639.915,-407.285 629.445,-405.66 636.617,-413.459 639.915,-407.285\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"775\" y=\"-430.3\">1 TensorType(int64, scalar)</text>\n",
"</g>\n",
"<!-- TensorType(float64, matrix) -->\n",
"<g class=\"node\" id=\"node2\"><title>TensorType(float64, matrix)</title>\n",
"<polygon fill=\"limegreen\" points=\"728,-584 552,-584 552,-548 728,-548 728,-584\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"640\" y=\"-562.3\">TensorType(float64, matrix)</text>\n",
"</g>\n",
"<!-- TensorType(float64, matrix)&#45;&gt;Shape_i{1} -->\n",
"<g class=\"edge\" id=\"edge1\"><title>TensorType(float64, matrix)-&gt;Shape_i{1}</title>\n",
"<path d=\"M728.218,-549.113C737.934,-544.301 746.871,-538.067 754,-530 759.757,-523.486 762.449,-514.618 763.57,-506.103\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"767.066,-506.289 764.259,-496.073 760.082,-505.81 767.066,-506.289\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"843\" y=\"-518.3\">TensorType(float64, matrix)</text>\n",
"</g>\n",
"<!-- Dot22 -->\n",
"<g class=\"node\" id=\"node5\"><title>Dot22</title>\n",
"<ellipse cx=\"242\" cy=\"-478\" fill=\"none\" rx=\"33.1991\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"242\" y=\"-474.3\">Dot22</text>\n",
"</g>\n",
"<!-- TensorType(float64, matrix)&#45;&gt;Dot22 -->\n",
"<g class=\"edge\" id=\"edge4\"><title>TensorType(float64, matrix)-&gt;Dot22</title>\n",
"<path d=\"M610.316,-547.87C600.623,-542.227 589.827,-535.889 580,-530 568.361,-523.026 566.88,-518.266 554,-514 467.597,-485.383 440.342,-507.083 350,-496 328.021,-493.304 303.645,-489.534 283.621,-486.23\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"284.023,-482.749 273.583,-484.552 282.869,-489.653 284.023,-482.749\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"665\" y=\"-518.3\">1 TensorType(float64, matrix)</text>\n",
"</g>\n",
"<!-- Shape_i{0} -->\n",
"<g class=\"node\" id=\"node3\"><title>Shape_i{0}</title>\n",
"<ellipse cx=\"412\" cy=\"-478\" fill=\"cyan\" rx=\"52.9443\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"412\" y=\"-474.3\">Shape_i{0}</text>\n",
"</g>\n",
"<!-- Shape_i{0}&#45;&gt;MakeVector -->\n",
"<g class=\"edge\" id=\"edge5\"><title>Shape_i{0}-&gt;MakeVector</title>\n",
"<path d=\"M437.912,-462.25C457.204,-451.547 484.353,-437.066 509,-426 523.976,-419.276 540.668,-412.715 555.731,-407.125\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"557.173,-410.324 565.36,-403.6 554.766,-403.751 557.173,-410.324\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"587\" y=\"-430.3\">0 TensorType(int64, scalar)</text>\n",
"</g>\n",
"<!-- name=X TensorType(float64, matrix) -->\n",
"<g class=\"node\" id=\"node4\"><title>name=X TensorType(float64, matrix)</title>\n",
"<polygon fill=\"limegreen\" points=\"456,-584 228,-584 228,-548 456,-548 456,-584\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"342\" y=\"-562.3\">name=X TensorType(float64, matrix)</text>\n",
"</g>\n",
"<!-- name=X TensorType(float64, matrix)&#45;&gt;Shape_i{0} -->\n",
"<g class=\"edge\" id=\"edge2\"><title>name=X TensorType(float64, matrix)-&gt;Shape_i{0}</title>\n",
"<path d=\"M361.08,-547.903C366.78,-542.42 372.872,-536.166 378,-530 384.666,-521.984 391.209,-512.635 396.748,-504.146\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"399.704,-506.02 402.118,-495.704 393.798,-502.262 399.704,-506.02\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"470\" y=\"-518.3\">TensorType(float64, matrix)</text>\n",
"</g>\n",
"<!-- name=X TensorType(float64, matrix)&#45;&gt;Dot22 -->\n",
"<g class=\"edge\" id=\"edge3\"><title>name=X TensorType(float64, matrix)-&gt;Dot22</title>\n",
"<path d=\"M240.099,-547.929C223.328,-543.107 209.578,-537.169 204,-530 196.089,-519.832 203.283,-508.338 213.457,-498.839\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"215.81,-501.433 221.218,-492.323 211.309,-496.073 215.81,-501.433\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"289\" y=\"-518.3\">0 TensorType(float64, matrix)</text>\n",
"</g>\n",
"<!-- Elemwise{ScalarSigmoid}[(0, 0)] -->\n",
"<g class=\"node\" id=\"node7\"><title>Elemwise{ScalarSigmoid}[(0, 0)]</title>\n",
"<ellipse cx=\"242\" cy=\"-390\" fill=\"#ffaabb\" rx=\"134.307\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"242\" y=\"-386.3\">Elemwise{ScalarSigmoid}[(0, 0)]</text>\n",
"</g>\n",
"<!-- Dot22&#45;&gt;Elemwise{ScalarSigmoid}[(0, 0)] -->\n",
"<g class=\"edge\" id=\"edge7\"><title>Dot22-&gt;Elemwise{ScalarSigmoid}[(0, 0)]</title>\n",
"<path d=\"M242,-459.597C242,-447.746 242,-431.817 242,-418.292\" fill=\"none\" stroke=\"red\"/>\n",
"<polygon fill=\"red\" points=\"245.5,-418.084 242,-408.084 238.5,-418.084 245.5,-418.084\" stroke=\"red\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"322\" y=\"-430.3\">TensorType(float64, matrix)</text>\n",
"</g>\n",
"<!-- Elemwise{Cast{float64}} -->\n",
"<g class=\"node\" id=\"node9\"><title>Elemwise{Cast{float64}}</title>\n",
"<ellipse cx=\"602\" cy=\"-302\" fill=\"#ffaabb\" rx=\"104.937\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"602\" y=\"-298.3\">Elemwise{Cast{float64}}</text>\n",
"</g>\n",
"<!-- MakeVector&#45;&gt;Elemwise{Cast{float64}} -->\n",
"<g class=\"edge\" id=\"edge9\"><title>MakeVector-&gt;Elemwise{Cast{float64}}</title>\n",
"<path d=\"M602,-371.597C602,-359.746 602,-343.817 602,-330.292\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"605.5,-330.084 602,-320.084 598.5,-330.084 605.5,-330.084\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"676\" y=\"-342.3\">TensorType(int64, vector)</text>\n",
"</g>\n",
"<!-- TensorType(float64, matrix) id=6 -->\n",
"<g class=\"node\" id=\"node8\"><title>TensorType(float64, matrix) id=6</title>\n",
"<polygon fill=\"dodgerblue\" points=\"356.25,-320 151.75,-320 151.75,-284 356.25,-284 356.25,-320\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"254\" y=\"-298.3\">TensorType(float64, matrix) id=6</text>\n",
"</g>\n",
"<!-- Elemwise{ScalarSigmoid}[(0, 0)]&#45;&gt;TensorType(float64, matrix) id=6 -->\n",
"<g class=\"edge\" id=\"edge8\"><title>Elemwise{ScalarSigmoid}[(0, 0)]-&gt;TensorType(float64, matrix) id=6</title>\n",
"<path d=\"M244.428,-371.597C246.082,-359.746 248.305,-343.817 250.192,-330.292\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"253.701,-330.472 251.616,-320.084 246.768,-329.504 253.701,-330.472\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"330\" y=\"-342.3\">TensorType(float64, matrix)</text>\n",
"</g>\n",
"<!-- Sum{acc_dtype=float64} -->\n",
"<g class=\"node\" id=\"node10\"><title>Sum{acc_dtype=float64}</title>\n",
"<ellipse cx=\"103\" cy=\"-248\" fill=\"none\" rx=\"103.012\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"103\" y=\"-244.3\">Sum{acc_dtype=float64}</text>\n",
"</g>\n",
"<!-- Elemwise{ScalarSigmoid}[(0, 0)]&#45;&gt;Sum{acc_dtype=float64} -->\n",
"<g class=\"edge\" id=\"edge10\"><title>Elemwise{ScalarSigmoid}[(0, 0)]-&gt;Sum{acc_dtype=float64}</title>\n",
"<path d=\"M144.123,-377.632C116.496,-372.297 91.5885,-364.685 83,-354 65.1182,-331.754 75.9432,-298.337 87.4351,-275.202\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"90.5714,-276.758 92.1497,-266.282 84.3826,-273.487 90.5714,-276.758\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"163\" y=\"-342.3\">TensorType(float64, matrix)</text>\n",
"</g>\n",
"<!-- Subtensor{int64} -->\n",
"<g class=\"node\" id=\"node11\"><title>Subtensor{int64}</title>\n",
"<ellipse cx=\"670\" cy=\"-194\" fill=\"#ffaaff\" rx=\"74.6146\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"670\" y=\"-190.3\">Subtensor{int64}</text>\n",
"</g>\n",
"<!-- Elemwise{Cast{float64}}&#45;&gt;Subtensor{int64} -->\n",
"<g class=\"edge\" id=\"edge11\"><title>Elemwise{Cast{float64}}-&gt;Subtensor{int64}</title>\n",
"<path d=\"M629.37,-284.551C636.239,-279.342 643.053,-273.072 648,-266 657.078,-253.024 662.508,-236.173 665.701,-222.144\" fill=\"none\" stroke=\"dodgerblue\"/>\n",
"<polygon fill=\"dodgerblue\" points=\"669.185,-222.571 667.731,-212.077 662.323,-221.188 669.185,-222.571\" stroke=\"dodgerblue\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"748.5\" y=\"-244.3\">0 TensorType(float64, vector)</text>\n",
"</g>\n",
"<!-- Subtensor{int64} id=8 -->\n",
"<g class=\"node\" id=\"node13\"><title>Subtensor{int64} id=8</title>\n",
"<ellipse cx=\"462\" cy=\"-194\" fill=\"#ffaaff\" rx=\"93.3873\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"462\" y=\"-190.3\">Subtensor{int64} id=8</text>\n",
"</g>\n",
"<!-- Elemwise{Cast{float64}}&#45;&gt;Subtensor{int64} id=8 -->\n",
"<g class=\"edge\" id=\"edge13\"><title>Elemwise{Cast{float64}}-&gt;Subtensor{int64} id=8</title>\n",
"<path d=\"M516.396,-291.457C500.826,-286.113 486.044,-278.059 475,-266 464.308,-254.325 461.003,-236.882 460.398,-222.207\" fill=\"none\" stroke=\"dodgerblue\"/>\n",
"<polygon fill=\"dodgerblue\" points=\"463.897,-222.122 460.367,-212.132 456.897,-222.143 463.897,-222.122\" stroke=\"dodgerblue\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"559.5\" y=\"-244.3\">0 TensorType(float64, vector)</text>\n",
"</g>\n",
"<!-- Elemwise{Composite{((i0 / i1) / i2)}}[(0, 0)] -->\n",
"<g class=\"node\" id=\"node15\"><title>Elemwise{Composite{((i0 / i1) / i2)}}[(0, 0)]</title>\n",
"<ellipse cx=\"462\" cy=\"-106\" fill=\"#ffaabb\" rx=\"176.177\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"462\" y=\"-102.3\">Elemwise{Composite{((i0 / i1) / i2)}}[(0, 0)]</text>\n",
"</g>\n",
"<!-- Sum{acc_dtype=float64}&#45;&gt;Elemwise{Composite{((i0 / i1) / i2)}}[(0, 0)] -->\n",
"<g class=\"edge\" id=\"edge15\"><title>Sum{acc_dtype=float64}-&gt;Elemwise{Composite{((i0 / i1) / i2)}}[(0, 0)]</title>\n",
"<path d=\"M119.532,-230.175C136.346,-214 163.864,-190.002 192,-176 243.475,-150.382 305.343,-133.68 356.863,-123.136\" fill=\"none\" stroke=\"red\"/>\n",
"<polygon fill=\"red\" points=\"357.569,-126.564 366.69,-121.173 356.198,-119.699 357.569,-126.564\" stroke=\"red\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"275.5\" y=\"-190.3\">0 TensorType(float64, scalar)</text>\n",
"</g>\n",
"<!-- Subtensor{int64}&#45;&gt;Elemwise{Composite{((i0 / i1) / i2)}}[(0, 0)] -->\n",
"<g class=\"edge\" id=\"edge17\"><title>Subtensor{int64}-&gt;Elemwise{Composite{((i0 / i1) / i2)}}[(0, 0)]</title>\n",
"<path d=\"M661.082,-175.699C654.339,-164.365 644.024,-150.185 631,-142 617.889,-133.761 603.185,-127.421 588.064,-122.551\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"588.664,-119.077 578.08,-119.557 586.654,-125.782 588.664,-119.077\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"731.5\" y=\"-146.3\">2 TensorType(float64, scalar)</text>\n",
"</g>\n",
"<!-- val=1 int64 -->\n",
"<g class=\"node\" id=\"node12\"><title>val=1 int64</title>\n",
"<polygon fill=\"limegreen\" points=\"902.25,-320 821.75,-320 821.75,-284 902.25,-284 902.25,-320\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"862\" y=\"-298.3\">val=1 int64</text>\n",
"</g>\n",
"<!-- val=1 int64&#45;&gt;Subtensor{int64} -->\n",
"<g class=\"edge\" id=\"edge12\"><title>val=1 int64-&gt;Subtensor{int64}</title>\n",
"<path d=\"M860.642,-283.734C858.414,-267.462 852.531,-243.606 837,-230 823.252,-217.956 783.956,-209.391 746.935,-203.749\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"746.978,-200.219 736.577,-202.235 745.965,-207.145 746.978,-200.219\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"877\" y=\"-244.3\">1 int64</text>\n",
"</g>\n",
"<!-- Subtensor{int64} id=8&#45;&gt;Elemwise{Composite{((i0 / i1) / i2)}}[(0, 0)] -->\n",
"<g class=\"edge\" id=\"edge16\"><title>Subtensor{int64} id=8-&gt;Elemwise{Composite{((i0 / i1) / i2)}}[(0, 0)]</title>\n",
"<path d=\"M462,-175.597C462,-163.746 462,-147.817 462,-134.292\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"465.5,-134.084 462,-124.084 458.5,-134.084 465.5,-134.084\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"545.5\" y=\"-146.3\">1 TensorType(float64, scalar)</text>\n",
"</g>\n",
"<!-- val=0 int64 -->\n",
"<g class=\"node\" id=\"node14\"><title>val=0 int64</title>\n",
"<polygon fill=\"limegreen\" points=\"455.25,-320 374.75,-320 374.75,-284 455.25,-284 455.25,-320\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"415\" y=\"-298.3\">val=0 int64</text>\n",
"</g>\n",
"<!-- val=0 int64&#45;&gt;Subtensor{int64} id=8 -->\n",
"<g class=\"edge\" id=\"edge14\"><title>val=0 int64-&gt;Subtensor{int64} id=8</title>\n",
"<path d=\"M411.23,-283.946C408.807,-268.911 407.505,-246.84 416,-230 418.201,-225.638 421.228,-221.669 424.688,-218.102\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"427.133,-220.611 432.272,-211.345 422.477,-215.384 427.133,-220.611\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"436\" y=\"-244.3\">1 int64</text>\n",
"</g>\n",
"<!-- TensorType(float64, scalar) id=13 -->\n",
"<g class=\"node\" id=\"node16\"><title>TensorType(float64, scalar) id=13</title>\n",
"<polygon fill=\"dodgerblue\" points=\"566,-36 358,-36 358,-0 566,-0 566,-36\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"462\" y=\"-14.3\">TensorType(float64, scalar) id=13</text>\n",
"</g>\n",
"<!-- Elemwise{Composite{((i0 / i1) / i2)}}[(0, 0)]&#45;&gt;TensorType(float64, scalar) id=13 -->\n",
"<g class=\"edge\" id=\"edge18\"><title>Elemwise{Composite{((i0 / i1) / i2)}}[(0, 0)]-&gt;TensorType(float64, scalar) id=13</title>\n",
"<path d=\"M462,-87.5966C462,-75.7459 462,-59.8169 462,-46.2917\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"465.5,-46.084 462,-36.084 458.5,-46.084 465.5,-46.084\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"540\" y=\"-58.3\">TensorType(float64, scalar)</text>\n",
"</g>\n",
"</g>\n",
"</svg>"
],
"text/plain": [
"<IPython.core.display.SVG object>"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"SVG(g.create_svg())"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.10"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
digraph G {
graph [bb="0,0,923,584"];
node [label="\N"];
"Shape_i{1}" [fillcolor=cyan,
height=0.5,
pos="763,478",
profile="[9.5367431640625e-07, None, 0.5673758865248227]",
shape=ellipse,
style=filled,
type=colored,
width=1.4763];
MakeVector [height=0.5,
pos="602,390",
profile="[1.9073486328125e-06, None, 1.1347517730496455]",
shape=ellipse,
width=1.5402];
"Shape_i{1}" -> MakeVector [label="1 TensorType(int64, scalar)",
lp="775,434",
pos="e,629.45,405.66 735.69,462.41 708.97,448.14 668.11,426.32 638.6,410.55"];
"TensorType(float64, matrix)" [fillcolor=limegreen,
height=0.5,
pos="640,566",
profile="[9.989738464355469e-05, None, 59.43262411347518]",
shape=box,
style=filled,
width=2.4444];
"TensorType(float64, matrix)" -> "Shape_i{1}" [label="TensorType(float64, matrix)",
lp="843,522",
pos="e,764.26,496.07 728.22,549.11 737.93,544.3 746.87,538.07 754,530 759.76,523.49 762.45,514.62 763.57,506.1"];
Dot22 [height=0.5,
pos="242,478",
profile="[9.989738464355469e-05, None, 59.43262411347518]",
shape=ellipse,
width=0.92774];
"TensorType(float64, matrix)" -> Dot22 [label="1 TensorType(float64, matrix)",
lp="665,522",
pos="e,273.58,484.55 610.32,547.87 600.62,542.23 589.83,535.89 580,530 568.36,523.03 566.88,518.27 554,514 467.6,485.38 440.34,507.08 \
350,496 328.02,493.3 303.64,489.53 283.62,486.23"];
"Shape_i{0}" [fillcolor=cyan,
height=0.5,
pos="412,478",
profile="[0.0, None, 0.0]",
shape=ellipse,
style=filled,
type=colored,
width=1.4763];
"Shape_i{0}" -> MakeVector [label="0 TensorType(int64, scalar)",
lp="587,434",
pos="e,565.36,403.6 437.91,462.25 457.2,451.55 484.35,437.07 509,426 523.98,419.28 540.67,412.72 555.73,407.13"];
"name=X TensorType(float64, matrix)" [fillcolor=limegreen,
height=0.5,
pos="342,566",
profile="[9.989738464355469e-05, None, 59.43262411347518]",
shape=box,
style=filled,
width=3.1667];
"name=X TensorType(float64, matrix)" -> "Shape_i{0}" [label="TensorType(float64, matrix)",
lp="470,522",
pos="e,402.12,495.7 361.08,547.9 366.78,542.42 372.87,536.17 378,530 384.67,521.98 391.21,512.63 396.75,504.15"];
"name=X TensorType(float64, matrix)" -> Dot22 [label="0 TensorType(float64, matrix)",
lp="289,522",
pos="e,221.22,492.32 240.1,547.93 223.33,543.11 209.58,537.17 204,530 196.09,519.83 203.28,508.34 213.46,498.84"];
"Elemwise{ScalarSigmoid}[(0, 0)]" [fillcolor="#FFAABB",
height=0.5,
pos="242,390",
profile="[1.0967254638671875e-05, None, 6.524822695035461]",
shape=ellipse,
style=filled,
type=colored,
width=3.7297];
Dot22 -> "Elemwise{ScalarSigmoid}[(0, 0)]" [color=red,
label="TensorType(float64, matrix)",
lp="322,434",
pos="e,242,408.08 242,459.6 242,447.75 242,431.82 242,418.29"];
"Elemwise{Cast{float64}}" [fillcolor="#FFAABB",
height=0.5,
pos="602,302",
profile="[2.86102294921875e-06, None, 1.702127659574468]",
shape=ellipse,
style=filled,
type=colored,
width=2.9207];
MakeVector -> "Elemwise{Cast{float64}}" [label="TensorType(int64, vector)",
lp="676,346",
pos="e,602,320.08 602,371.6 602,359.75 602,343.82 602,330.29"];
"TensorType(float64, matrix) id=6" [fillcolor=dodgerblue,
height=0.5,
pos="254,302",
profile="[1.0967254638671875e-05, None, 6.524822695035461]",
shape=box,
style=filled,
width=2.8403];
"Elemwise{ScalarSigmoid}[(0, 0)]" -> "TensorType(float64, matrix) id=6" [label="TensorType(float64, matrix)",
lp="330,346",
pos="e,251.62,320.08 244.43,371.6 246.08,359.75 248.3,343.82 250.19,330.29"];
"Sum{acc_dtype=float64}" [height=0.5,
pos="103,248",
profile="[1.9073486328125e-06, None, 1.1347517730496455]",
shape=ellipse,
width=2.8658];
"Elemwise{ScalarSigmoid}[(0, 0)]" -> "Sum{acc_dtype=float64}" [label="TensorType(float64, matrix)",
lp="163,346",
pos="e,92.15,266.28 144.12,377.63 116.5,372.3 91.588,364.68 83,354 65.118,331.75 75.943,298.34 87.435,275.2"];
"Subtensor{int64}" [fillcolor="#FFAAFF",
height=0.5,
pos="670,194",
profile="[0.0, None, 0.0]",
shape=ellipse,
style=filled,
type=colored,
width=2.0659];
"Elemwise{Cast{float64}}" -> "Subtensor{int64}" [color=dodgerblue,
label="0 TensorType(float64, vector)",
lp="748.5,248",
pos="e,667.73,212.08 629.37,284.55 636.24,279.34 643.05,273.07 648,266 657.08,253.02 662.51,236.17 665.7,222.14"];
"Subtensor{int64} id=8" [fillcolor="#FFAAFF",
height=0.5,
pos="462,194",
profile="[2.1457672119140625e-06, None, 1.2765957446808511]",
shape=ellipse,
style=filled,
type=colored,
width=2.5916];
"Elemwise{Cast{float64}}" -> "Subtensor{int64} id=8" [color=dodgerblue,
label="0 TensorType(float64, vector)",
lp="559.5,248",
pos="e,460.37,212.13 516.4,291.46 500.83,286.11 486.04,278.06 475,266 464.31,254.32 461,236.88 460.4,222.21"];
"Elemwise{Composite{((i0 / i1) / i2)}}[(0, 0)]" [fillcolor="#FFAABB",
height=0.5,
pos="462,106",
profile="[0.0, None, 0.0]",
shape=ellipse,
style=filled,
type=colored,
width=4.8998];
"Sum{acc_dtype=float64}" -> "Elemwise{Composite{((i0 / i1) / i2)}}[(0, 0)]" [color=red,
label="0 TensorType(float64, scalar)",
lp="275.5,194",
pos="e,366.69,121.17 119.53,230.18 136.35,214 163.86,190 192,176 243.47,150.38 305.34,133.68 356.86,123.14"];
"Subtensor{int64}" -> "Elemwise{Composite{((i0 / i1) / i2)}}[(0, 0)]" [label="2 TensorType(float64, scalar)",
lp="731.5,150",
pos="e,578.08,119.56 661.08,175.7 654.34,164.37 644.02,150.18 631,142 617.89,133.76 603.18,127.42 588.06,122.55"];
"val=1 int64" [fillcolor=limegreen,
height=0.5,
pos="862,302",
profile="[0.0, None, 0.0]",
shape=box,
style=filled,
width=1.1181];
"val=1 int64" -> "Subtensor{int64}" [label="1 int64",
lp="877,248",
pos="e,736.58,202.24 860.64,283.73 858.41,267.46 852.53,243.61 837,230 823.25,217.96 783.96,209.39 746.94,203.75"];
"Subtensor{int64} id=8" -> "Elemwise{Composite{((i0 / i1) / i2)}}[(0, 0)]" [label="1 TensorType(float64, scalar)",
lp="545.5,150",
pos="e,462,124.08 462,175.6 462,163.75 462,147.82 462,134.29"];
"val=0 int64" [fillcolor=limegreen,
height=0.5,
pos="415,302",
profile="[2.1457672119140625e-06, None, 1.2765957446808511]",
shape=box,
style=filled,
width=1.1181];
"val=0 int64" -> "Subtensor{int64} id=8" [label="1 int64",
lp="436,248",
pos="e,432.27,211.35 411.23,283.95 408.81,268.91 407.5,246.84 416,230 418.2,225.64 421.23,221.67 424.69,218.1"];
"TensorType(float64, scalar) id=13" [fillcolor=dodgerblue,
height=0.5,
pos="462,18",
profile="[0.0, None, 0.0]",
shape=box,
style=filled,
width=2.8889];
"Elemwise{Composite{((i0 / i1) / i2)}}[(0, 0)]" -> "TensorType(float64, scalar) id=13" [label="TensorType(float64, scalar)",
lp="540,62",
pos="e,462,36.084 462,87.597 462,75.746 462,59.817 462,46.292"];
}
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
<script type='text/javascript' src="http://cpettitt.github.io/project/dagre-d3/v0.1.5/dagre-d3.min.js"></script>
<script type='text/javascript' src="http://cpettitt.github.io/project/graphlib-dot/v0.4.10/graphlib-dot.min.js"></script>
</head>
<body>
<style>
svg {
margin-left:auto;
margin-right:auto;
display:block;
position: fixed;
border: 0px solid black;
top:5%; left:0%; right:0% bottom=10%
}
.nodeRect {
stroke: black;
border: 3px solid black;
}
.nodeEllipse {
stroke: black;
border: 3px solid black;
}
.nodeText {
color: black;
}
.edge {
stroke-width: 3px;
cursor: pointer;
opacity: 0.4;
}
.edgeLabelRect {
stroke: black;
border: 1px solid black;
fill: skyblue;
opacity: 0.9;
}
.edgeLabelText {
fill: black;
text-anchor: start;
}
.arrowHead {
stroke: green;
stroke-width: 1px;
}
.arrowHead_n {
stroke: green;
}
.arrowHead_r {
stroke-width: 3px;
fill: red;
stroke: red;
}
.arrowHead_b {
stroke: dodgerblue;
}
.edgeTooltip {
position: absolute;
text-align: center;
vertical-align: middle;
min-width: 10px;
min-height: 10px;
padding: 5px;
background: lightsteelblue;
border: 1px solid black;
border-radius: 8px;
pointer-events: none;
}
.nodeTooltip {
position: absolute;
text-align: left;
vertical-align: middle;
min-width: 10px;
min-height: 10px;
padding: 5px;
background: lightsteelblue;
border: 1px solid black;
border-radius: 8px;
pointer-events: none;
}
</style>
<div id='menu'>
<input name="resetNodes"
type="button"
value="Reset nodes"
onclick="resetNodes()"/>
<input name="releaseNodes"
type="button"
value="Release nodes"
onclick="releaseNodes()"/>
</div>
<script type="text/javascript">
var path='predict_profiled.dot';
var isProfiled = false;
var colorProfile = false;
// Global attributes
var pad = 10;
d3.select('body').select('svg').remove();
var svg = d3.select('body').append('svg')
.attr('width', '100%')
.attr('height', '95%');
var pane = svg.append('g');
var edgeDiv = d3.select('body').append('div')
.attr('class', 'edgeTooltip')
.style('opacity', 0.0);
var nodeDiv = d3.select('body').append('div')
.attr('class', 'nodeTooltip')
.style('opacity', 0.0);
// Definition head of edges
var markerData = [
{'id': 'n', 'color': 'black'},
{'id': 'r', 'color': 'red'},
{'id': 'b', 'color': 'dodgerblue'}];
svg.append("defs").selectAll('marker').data(markerData).enter().append("marker")
.attr("id", function(d) { return 'edgeArrow_' + d.id;})
.attr("markerWidth", 4)
.attr("markerHeight", 4)
.attr("refX", 2)
.attr("refY", 2)
.attr("orient", "auto")
.append("path")
.attr("d", "M0,0 L4,2 L0,4 Z")
.attr('fill', function(d) { return d.color;});
function toggleColors() {
colorProfile = !colorProfile;
updateNodes();
updateGraph();
}
function textSize(text, attr) {
var t = svg.append('text').text(text);
if (typeof(attr) != 'undefined') {
for (a in attr) {
t.attr(a, attr[a]);
}
}
var bbox = t.node().getBBox();
t.remove();
return bbox;
}
function exists(x) {
return typeof(x) != 'undefined';
}
function replaceAll(str, find, replace) {
return str.replace(new RegExp(find, 'g'), replace);
}
function parseProfile(profile) {
if (typeof(profile) == 'undefined') {
return;
}
profile = profile.replace('[', '');
profile = profile.replace(']', '');
profile = replaceAll(profile, ' ', '');
profile = profile.split(',');
if (profile.length < 2) {
return [];
}
profile = profile.map(function(x) { return parseFloat(x); });
return profile;
}
function profileColor(per) {
var colors = ["#fff5f0","#fee0d2","#fcbba1","#fc9272","#fb6a4a","#ef3b2c","#cb181d","#a50f15","#67000d"];
var s = d3.scale.linear()
.domain([0, 100])
.range([0, colors.length - 1]);
return colors[Math.round(s(per))];
}
function fillColor(d) {
if (colorProfile && typeof(d.value.profile) != 'undefined') {
return profileColor(d.value.profile[2]);
} else {
return typeof(d.value.fillcolor) == 'undefined' ? 'white' : d.value.fillcolor;
}
}
function formatTime(sec) {
var s;
if (sec < 0.1) {
s = (sec * 1000).toFixed(1) + 'ms';
} else {
s = sec.toFixed(1) + 's';
}
return s;
}
function nodeDetails(node) {
var s = '<b>' + node.value.label + '</b>';
var p = node.value.profile;
if (!isNaN(p[0])) {
s += '<br>Total time: ' + formatTime(p[0]);
}
if (!isNaN(p[1])) {
s += '<br>Total time: ' + p[1].toFixed(1) + '%';
}
if (!isNaN(p[2])) {
s += '<br>Profile time: ' + p[2].toFixed(1) + '%';
}
return s;
}
function updateNode(d, node) {
var shape;
if (d.value.shape == 'ellipse') {
node.selectAll('ellipse').remove();
shape = node.append('ellipse')
.attr('class', 'nodeEllipse')
.attr('cx', d.value.cx)
.attr('cy', d.value.cy)
.attr('rx', d.value.width * 0.6)
.attr('ry', d.value.height * 0.6);
} else {
node.selectAll('rect').remove();
shape = node.append('rect')
.attr('class', 'nodeRect')
.attr('width', d.value.width)
.attr('height', d.value.height);
}
shape.attr('fill', fillColor(d));
node.selectAll('text').remove();
var text = node.append('text')
.attr('class', 'nodeText')
.attr('x', pad)
.attr('dy', function(d) {return d.value.height - pad - 5;})
.text(function(d) {return d.value.label;});
}
function updateNodes() {
nodes.each(function(d) {var node = d3.select(this); updateNode(d, node);});
}
var dotGraph;
var graph = {};
var nodes = [];
var edges = [];
var layout;
var scaleDotX;
var scaleDotY;
d3.text(path, function(data) {
dotGraph = graphlibDot.parse(data);
// Calculate width and height
var posMax = [0, 0];
for (var nodeId in dotGraph._nodes) {
var node = dotGraph._nodes[nodeId];
node.value.label = node.id;
node.value.pos = node.value.pos.split(',').map(function(d) {return parseInt(d);});
node.value.width = parseInt(node.value.width);
node.value.height = parseInt(node.value.height);
posMax[0] = Math.max(posMax[0], node.value.pos[0] + node.value.width);
posMax[1] = Math.max(posMax[1], node.value.pos[1] + node.value.height);
}
dotWidth = posMax[0];
dotHeight = posMax[1];
//svg.attr('viewBox', '0,0,' + dotWidth + ',' + dotHeight);
scaleDotX = d3.scale.linear().domain([0, dotWidth]).range([20, dotWidth * 1.2]);
scaleDotY = d3.scale.linear().domain([0, dotHeight]).range([20, dotHeight * 1.2]);
// Parse nodes
var i = 0;
for (nodeId in dotGraph._nodes) {
var node = dotGraph._nodes[nodeId];
node.index = i++;
// x, y is center of node (not corner)
node.x = scaleDotX(node.value.pos[0]);
node.y = scaleDotY(dotHeight - (node.value.pos[1] + node.value.height));
var size = textSize(node.value.label, {'class': 'nodeText'});
node.value.width = size.width + 2 * pad;
node.value.height = size.height + 2 * pad;
node.value.cx = node.value.width / 2;
node.value.cy = node.value.height / 2;
node.value.profile = parseProfile(node.value.profile);
if (typeof(node.value.profile) != 'undefined') {
isProfiled = true;
}
node.fixed = true;
nodes.push(node);
dotGraph._nodes[nodeId] = node;
}
if (isProfiled) {
d3.select('body').select('#menu').append('input')
.attr('name', 'tColors')
.attr('type', 'button')
.attr('value', 'Toggle profile colors')
.attr('onclick', "toggleColors()");
}
// Parse edges
for (edgeId in dotGraph._edges) {
var edge = dotGraph._edges[edgeId];
edge.source = dotGraph._nodes[edge.u].index;
edge.target = dotGraph._nodes[edge.v].index;
var size = textSize(edge.value.label, {'class': 'edgeLabelText'});
edge.value.width = size.width + 2 * pad;
edge.value.height = size.height + 2 * pad;
if (!exists(edge.value.color)) {
edge.value.color = 'black';
}
switch (edge.value.color) {
case 'dodgerblue':
edge.value.type = 'b';
break;
case 'red':
edge.value.type = 'r';
break;
default:
edge.value.type = 'n';
}
edges.push(edge);
dotGraph._edges[edgeId] = edge;
}
// Setup graph
graph['nodes'] = nodes;
graph['edges'] = edges;
var isEdgeOver = false;
var isEdgeLabelOver = false;
// Add edges
edges = pane.append('g').attr('id', 'edges').selectAll('path').data(graph['edges']).enter().append('path')
.attr('class', 'edge')
.attr('stroke', function(d) {return d.value.color;})
.attr('marker-mid', function(d) { return 'url(#edgeArrow_' + d.value.type + ')';})
.on('mouseover', function(d) {
var edge = d3.select(this);
edge.transition()
.duration(200)
.style('opacity', 1.0);
edgeDiv.transition()
.duration(200)
.style('opacity', .9);
edgeDiv
.html(d.value.label)
.style('left', (d3.event.pageX) + 'px')
.style('top', (d3.event.pageY - 28) + 'px');
})
.on('mouseout', function(d) {
var edge = d3.select(this);
edge.transition()
.duration(200)
.style('opacity', 0.4);
edgeDiv.transition()
.duration(200)
.style('opacity', 0);
});
// Add nodes
nodes = pane.append('g').attr('id', 'nodes').selectAll('g').data(graph['nodes']).enter().append('g');
function setNodeSize(node) {
var size = textSize(node.value.label, {'class': 'nodeText'});
node.value.width = size.width + 2 * pad;
node.value.height = size.height + 2 * pad;
node.value.cx = node.value.width / 2;
node.value.cy = node.value.height / 2;
}
updateNodes();
function hideNodeDiv() {
nodeDiv.transition()
.duration(200)
.style('opacity', 0);
}
var editNode = false;
nodes.on('dblclick', function(d) {
var pos = this.getBBox();
var node = d3.select(this);
if (d3.event.defaultPrevented) return;
editNode = true;
hideNodeDiv();
var form = node.append('foreignObject')
.attr('x', pos.x)
.attr('y', pos.y)
.attr('width', d.value.width)
.attr('height', 25);
var input = form.append('xhtml:form').append('input')
.attr('style', 'width: ' + d.value.width + 'px')
.attr('value', function() {
this.focus();
return d.value.label;
})
.on('blur', function() {
d.value.label = input.node().value;
setNodeSize(d);
updateNode(d, node);
form.remove(); // TODO: check this
editNode = false;
})
.on('keypress', function() {
if (!d3.event) {
d3.event = window.event;
}
var event = d3.event;
if (event.keyCode == 13) {
if (typeof(event.cancelBubble)) {
event.cancelBubble = true;
}
if (event.stopPropagation) {
event.stopPropagation();
}
event.preventDefault();
d.value.label = input.node().value;
setNodeSize(d);
updateNode(d, node);
form.remove(); // TODO: check this
editNode = false;
}
});
});
nodes.on('mouseover', function(node) {
if (editNode || typeof(node.value.profile) == 'undefined') {
return;
}
edges.each(function (d, i) {
var edge = d3.select(this);
if (d.source == node || d.target == node) {
edge.transition()
.duration(200)
.style('opacity', 1.0);
}
});
nodeDiv.transition()
.duration(200)
.style('opacity', .9);
nodeDiv
.html(nodeDetails(node))
.style('left', (d3.event.pageX) + 30 + 'px')
.style('top', (d3.event.pageY - 28) + 'px');
});
nodes.on('mouseout', function(node) {
edges.each(function (d, i) {
var edge = d3.select(this);
if (d.source.index == node.index || d.target.index == node.index) {
edge.transition()
.duration(200)
.style('opacity', 0.4);
}
});
hideNodeDiv();
});
nodes.on('contextmenu', function(d) {
releaseNode(d);
});
// Zoom and translate event handler
function zoom(d) {
pane.attr('transform', 'translate(' + d3.event.translate + ') scale(' + d3.event.scale + ')');
}
// Force layout
layout = d3.layout.force()
.nodes(graph['nodes'])
.links(graph['edges'])
.size([dotWidth, dotHeight])
.charge(-3000)
.linkDistance(50)
.linkStrength(0.1)
.on('tick', updateGraph);
// Drag behavour
var drag = layout.drag()
.on('dragstart', function(d) {
d3.event.sourceEvent.stopPropagation();
d3.event.sourceEvent.preventDefault();
d.fixed = true;
});
nodes.call(drag);
// Zoom behaviour
var bZoom = d3.behavior.zoom()
.scaleExtent([0.2, 8])
//.on("dblclick.zoom", null)
.on('zoom', zoom);
svg.call(bZoom);
svg.on("dblclick.zoom", null);
// Start force layout
layout.start();
});
function length(x1, y1, x2, y2) {
return Math.sqrt(Math.pow(x1-x2, 2) + Math.pow(y1-y2, 2));
}
function pathPos(x1, y1, x2, y2, c) {
x = (1 - c) * x1 + c * x2;
y = (1 - c) * y1 + c * y2;
p = x + ',' + y;
return p;
}
// Update graph
function updateGraph() {
// Update nodes
nodes.attr('transform', function(d) { return 'translate(' + (d.x - d.value.cx) + ' ' + (d.y - d.value.cy) + ')'; });
// Update edges
edges.attr('d', function(d) {
var dist = 100;
var l = length(d.source.x, d.source.y, d.target.x, d.target.y);
var n = Math.max(2, Math.floor(l / dist));
var marker = [];
for (var i = 1; i < n; ++i) {
marker.push(i / n);
}
var markerPos = marker.map(function(c) {return pathPos(d.source.x, d.source.y, d.target.x, d.target.y, c);});
var markerPos = ' L' + markerPos.join(' L');
return 'M' + d.source.x + ',' + d.source.y + markerPos + ' L' + d.target.x + ',' + d.target.y;
});
}
function releaseNode(d) {
d.fixed = false;
layout.start();
}
function releaseNodes() {
graph['nodes'].forEach (function (d) {
d.fixed = false;
});
layout.start();
}
function resetNodes() {
layout.stop();
var nodes = graph['nodes'];
nodes.forEach(function (node, i){
nodes[i].x = scaleDotX(node.value.pos[0]);
nodes[i].y = scaleDotY(dotHeight - (node.value.pos[1] + node.value.height));
nodes[i].px = nodes[i].x;
nodes[i].py = nodes[i].y;
nodes[i].fixed = true;
});
updateGraph();
layout.start();
}
</script>
</body>
</html>
digraph G {
graph [bb="0,0,923,584"];
node [label="\N"];
"Shape_i{1}" [fillcolor=cyan,
height=0.5,
pos="763,478",
shape=ellipse,
style=filled,
type=colored,
width=1.4763];
MakeVector [height=0.5,
pos="602,390",
shape=ellipse,
width=1.5402];
"Shape_i{1}" -> MakeVector [label="1 TensorType(int64, scalar)",
lp="775,434",
pos="e,629.45,405.66 735.69,462.41 708.97,448.14 668.11,426.32 638.6,410.55"];
"TensorType(float64, matrix)" [fillcolor=limegreen,
height=0.5,
pos="640,566",
shape=box,
style=filled,
width=2.4444];
"TensorType(float64, matrix)" -> "Shape_i{1}" [label="TensorType(float64, matrix)",
lp="843,522",
pos="e,764.26,496.07 728.22,549.11 737.93,544.3 746.87,538.07 754,530 759.76,523.49 762.45,514.62 763.57,506.1"];
Dot22 [height=0.5,
pos="242,478",
shape=ellipse,
width=0.92774];
"TensorType(float64, matrix)" -> Dot22 [label="1 TensorType(float64, matrix)",
lp="665,522",
pos="e,273.58,484.55 610.32,547.87 600.62,542.23 589.83,535.89 580,530 568.36,523.03 566.88,518.27 554,514 467.6,485.38 440.34,507.08 \
350,496 328.02,493.3 303.64,489.53 283.62,486.23"];
"Shape_i{0}" [fillcolor=cyan,
height=0.5,
pos="412,478",
shape=ellipse,
style=filled,
type=colored,
width=1.4763];
"Shape_i{0}" -> MakeVector [label="0 TensorType(int64, scalar)",
lp="587,434",
pos="e,565.36,403.6 437.91,462.25 457.2,451.55 484.35,437.07 509,426 523.98,419.28 540.67,412.72 555.73,407.13"];
"name=X TensorType(float64, matrix)" [fillcolor=limegreen,
height=0.5,
pos="342,566",
shape=box,
style=filled,
width=3.1667];
"name=X TensorType(float64, matrix)" -> "Shape_i{0}" [label="TensorType(float64, matrix)",
lp="470,522",
pos="e,402.12,495.7 361.08,547.9 366.78,542.42 372.87,536.17 378,530 384.67,521.98 391.21,512.63 396.75,504.15"];
"name=X TensorType(float64, matrix)" -> Dot22 [label="0 TensorType(float64, matrix)",
lp="289,522",
pos="e,221.22,492.32 240.1,547.93 223.33,543.11 209.58,537.17 204,530 196.09,519.83 203.28,508.34 213.46,498.84"];
"Elemwise{ScalarSigmoid}[(0, 0)]" [fillcolor="#FFAABB",
height=0.5,
pos="242,390",
shape=ellipse,
style=filled,
type=colored,
width=3.7297];
Dot22 -> "Elemwise{ScalarSigmoid}[(0, 0)]" [color=red,
label="TensorType(float64, matrix)",
lp="322,434",
pos="e,242,408.08 242,459.6 242,447.75 242,431.82 242,418.29"];
"Elemwise{Cast{float64}}" [fillcolor="#FFAABB",
height=0.5,
pos="602,302",
shape=ellipse,
style=filled,
type=colored,
width=2.9207];
MakeVector -> "Elemwise{Cast{float64}}" [label="TensorType(int64, vector)",
lp="676,346",
pos="e,602,320.08 602,371.6 602,359.75 602,343.82 602,330.29"];
"TensorType(float64, matrix) id=6" [fillcolor=dodgerblue,
height=0.5,
pos="254,302",
shape=box,
style=filled,
width=2.8403];
"Elemwise{ScalarSigmoid}[(0, 0)]" -> "TensorType(float64, matrix) id=6" [label="TensorType(float64, matrix)",
lp="330,346",
pos="e,251.62,320.08 244.43,371.6 246.08,359.75 248.3,343.82 250.19,330.29"];
"Sum{acc_dtype=float64}" [height=0.5,
pos="103,248",
shape=ellipse,
width=2.8658];
"Elemwise{ScalarSigmoid}[(0, 0)]" -> "Sum{acc_dtype=float64}" [label="TensorType(float64, matrix)",
lp="163,346",
pos="e,92.15,266.28 144.12,377.63 116.5,372.3 91.588,364.68 83,354 65.118,331.75 75.943,298.34 87.435,275.2"];
"Subtensor{int64}" [fillcolor="#FFAAFF",
height=0.5,
pos="670,194",
shape=ellipse,
style=filled,
type=colored,
width=2.0659];
"Elemwise{Cast{float64}}" -> "Subtensor{int64}" [color=dodgerblue,
label="0 TensorType(float64, vector)",
lp="748.5,248",
pos="e,667.73,212.08 629.37,284.55 636.24,279.34 643.05,273.07 648,266 657.08,253.02 662.51,236.17 665.7,222.14"];
"Subtensor{int64} id=8" [fillcolor="#FFAAFF",
height=0.5,
pos="462,194",
shape=ellipse,
style=filled,
type=colored,
width=2.5916];
"Elemwise{Cast{float64}}" -> "Subtensor{int64} id=8" [color=dodgerblue,
label="0 TensorType(float64, vector)",
lp="559.5,248",
pos="e,460.37,212.13 516.4,291.46 500.83,286.11 486.04,278.06 475,266 464.31,254.32 461,236.88 460.4,222.21"];
"Elemwise{Composite{((i0 / i1) / i2)}}[(0, 0)]" [fillcolor="#FFAABB",
height=0.5,
pos="462,106",
shape=ellipse,
style=filled,
type=colored,
width=4.8998];
"Sum{acc_dtype=float64}" -> "Elemwise{Composite{((i0 / i1) / i2)}}[(0, 0)]" [color=red,
label="0 TensorType(float64, scalar)",
lp="275.5,194",
pos="e,366.69,121.17 119.53,230.18 136.35,214 163.86,190 192,176 243.47,150.38 305.34,133.68 356.86,123.14"];
"Subtensor{int64}" -> "Elemwise{Composite{((i0 / i1) / i2)}}[(0, 0)]" [label="2 TensorType(float64, scalar)",
lp="731.5,150",
pos="e,578.08,119.56 661.08,175.7 654.34,164.37 644.02,150.18 631,142 617.89,133.76 603.18,127.42 588.06,122.55"];
"val=1 int64" [fillcolor=limegreen,
height=0.5,
pos="862,302",
shape=box,
style=filled,
width=1.1181];
"val=1 int64" -> "Subtensor{int64}" [label="1 int64",
lp="877,248",
pos="e,736.58,202.24 860.64,283.73 858.41,267.46 852.53,243.61 837,230 823.25,217.96 783.96,209.39 746.94,203.75"];
"Subtensor{int64} id=8" -> "Elemwise{Composite{((i0 / i1) / i2)}}[(0, 0)]" [label="1 TensorType(float64, scalar)",
lp="545.5,150",
pos="e,462,124.08 462,175.6 462,163.75 462,147.82 462,134.29"];
"val=0 int64" [fillcolor=limegreen,
height=0.5,
pos="415,302",
shape=box,
style=filled,
width=1.1181];
"val=0 int64" -> "Subtensor{int64} id=8" [label="1 int64",
lp="436,248",
pos="e,432.27,211.35 411.23,283.95 408.81,268.91 407.5,246.84 416,230 418.2,225.64 421.23,221.67 424.69,218.1"];
"TensorType(float64, scalar) id=13" [fillcolor=dodgerblue,
height=0.5,
pos="462,18",
shape=box,
style=filled,
width=2.8889];
"Elemwise{Composite{((i0 / i1) / i2)}}[(0, 0)]" -> "TensorType(float64, scalar) id=13" [label="TensorType(float64, scalar)",
lp="540,62",
pos="e,462,36.084 462,87.597 462,75.746 462,59.817 462,46.292"];
}
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
<script type='text/javascript' src="http://cpettitt.github.io/project/dagre-d3/v0.1.5/dagre-d3.min.js"></script>
<script type='text/javascript' src="http://cpettitt.github.io/project/graphlib-dot/v0.4.10/graphlib-dot.min.js"></script>
</head>
<body>
<style>
svg {
margin-left:auto;
margin-right:auto;
display:block;
position: fixed;
border: 0px solid black;
top:5%; left:0%; right:0% bottom=10%
}
.nodeRect {
stroke: black;
border: 3px solid black;
}
.nodeEllipse {
stroke: black;
border: 3px solid black;
}
.nodeText {
color: black;
}
.edge {
stroke-width: 3px;
cursor: pointer;
opacity: 0.4;
}
.edgeLabelRect {
stroke: black;
border: 1px solid black;
fill: skyblue;
opacity: 0.9;
}
.edgeLabelText {
fill: black;
text-anchor: start;
}
.arrowHead {
stroke: green;
stroke-width: 1px;
}
.arrowHead_n {
stroke: green;
}
.arrowHead_r {
stroke-width: 3px;
fill: red;
stroke: red;
}
.arrowHead_b {
stroke: dodgerblue;
}
.edgeTooltip {
position: absolute;
text-align: center;
vertical-align: middle;
min-width: 10px;
min-height: 10px;
padding: 5px;
background: lightsteelblue;
border: 1px solid black;
border-radius: 8px;
pointer-events: none;
}
.nodeTooltip {
position: absolute;
text-align: left;
vertical-align: middle;
min-width: 10px;
min-height: 10px;
padding: 5px;
background: lightsteelblue;
border: 1px solid black;
border-radius: 8px;
pointer-events: none;
}
</style>
<div id='menu'>
<input name="resetNodes"
type="button"
value="Reset nodes"
onclick="resetNodes()"/>
<input name="releaseNodes"
type="button"
value="Release nodes"
onclick="releaseNodes()"/>
</div>
<script type="text/javascript">
var path='predict_unprofiled.dot';
var isProfiled = false;
var colorProfile = false;
// Global attributes
var pad = 10;
d3.select('body').select('svg').remove();
var svg = d3.select('body').append('svg')
.attr('width', '100%')
.attr('height', '95%');
var pane = svg.append('g');
var edgeDiv = d3.select('body').append('div')
.attr('class', 'edgeTooltip')
.style('opacity', 0.0);
var nodeDiv = d3.select('body').append('div')
.attr('class', 'nodeTooltip')
.style('opacity', 0.0);
// Definition head of edges
var markerData = [
{'id': 'n', 'color': 'black'},
{'id': 'r', 'color': 'red'},
{'id': 'b', 'color': 'dodgerblue'}];
svg.append("defs").selectAll('marker').data(markerData).enter().append("marker")
.attr("id", function(d) { return 'edgeArrow_' + d.id;})
.attr("markerWidth", 4)
.attr("markerHeight", 4)
.attr("refX", 2)
.attr("refY", 2)
.attr("orient", "auto")
.append("path")
.attr("d", "M0,0 L4,2 L0,4 Z")
.attr('fill', function(d) { return d.color;});
function toggleColors() {
colorProfile = !colorProfile;
updateNodes();
updateGraph();
}
function textSize(text, attr) {
var t = svg.append('text').text(text);
if (typeof(attr) != 'undefined') {
for (a in attr) {
t.attr(a, attr[a]);
}
}
var bbox = t.node().getBBox();
t.remove();
return bbox;
}
function exists(x) {
return typeof(x) != 'undefined';
}
function replaceAll(str, find, replace) {
return str.replace(new RegExp(find, 'g'), replace);
}
function parseProfile(profile) {
if (typeof(profile) == 'undefined') {
return;
}
profile = profile.replace('[', '');
profile = profile.replace(']', '');
profile = replaceAll(profile, ' ', '');
profile = profile.split(',');
if (profile.length < 2) {
return [];
}
profile = profile.map(function(x) { return parseFloat(x); });
return profile;
}
function profileColor(per) {
var colors = ["#fff5f0","#fee0d2","#fcbba1","#fc9272","#fb6a4a","#ef3b2c","#cb181d","#a50f15","#67000d"];
var s = d3.scale.linear()
.domain([0, 100])
.range([0, colors.length - 1]);
return colors[Math.round(s(per))];
}
function fillColor(d) {
if (colorProfile && typeof(d.value.profile) != 'undefined') {
return profileColor(d.value.profile[2]);
} else {
return typeof(d.value.fillcolor) == 'undefined' ? 'white' : d.value.fillcolor;
}
}
function formatTime(sec) {
var s;
if (sec < 0.1) {
s = (sec * 1000).toFixed(1) + 'ms';
} else {
s = sec.toFixed(1) + 's';
}
return s;
}
function nodeDetails(node) {
var s = '<b>' + node.value.label + '</b>';
var p = node.value.profile;
if (!isNaN(p[0])) {
s += '<br>Total time: ' + formatTime(p[0]);
}
if (!isNaN(p[1])) {
s += '<br>Total time: ' + p[1].toFixed(1) + '%';
}
if (!isNaN(p[2])) {
s += '<br>Profile time: ' + p[2].toFixed(1) + '%';
}
return s;
}
function updateNode(d, node) {
var shape;
if (d.value.shape == 'ellipse') {
node.selectAll('ellipse').remove();
shape = node.append('ellipse')
.attr('class', 'nodeEllipse')
.attr('cx', d.value.cx)
.attr('cy', d.value.cy)
.attr('rx', d.value.width * 0.6)
.attr('ry', d.value.height * 0.6);
} else {
node.selectAll('rect').remove();
shape = node.append('rect')
.attr('class', 'nodeRect')
.attr('width', d.value.width)
.attr('height', d.value.height);
}
shape.attr('fill', fillColor(d));
node.selectAll('text').remove();
var text = node.append('text')
.attr('class', 'nodeText')
.attr('x', pad)
.attr('dy', function(d) {return d.value.height - pad - 5;})
.text(function(d) {return d.value.label;});
}
function updateNodes() {
nodes.each(function(d) {var node = d3.select(this); updateNode(d, node);});
}
var dotGraph;
var graph = {};
var nodes = [];
var edges = [];
var layout;
var scaleDotX;
var scaleDotY;
d3.text(path, function(data) {
dotGraph = graphlibDot.parse(data);
// Calculate width and height
var posMax = [0, 0];
for (var nodeId in dotGraph._nodes) {
var node = dotGraph._nodes[nodeId];
node.value.label = node.id;
node.value.pos = node.value.pos.split(',').map(function(d) {return parseInt(d);});
node.value.width = parseInt(node.value.width);
node.value.height = parseInt(node.value.height);
posMax[0] = Math.max(posMax[0], node.value.pos[0] + node.value.width);
posMax[1] = Math.max(posMax[1], node.value.pos[1] + node.value.height);
}
dotWidth = posMax[0];
dotHeight = posMax[1];
//svg.attr('viewBox', '0,0,' + dotWidth + ',' + dotHeight);
scaleDotX = d3.scale.linear().domain([0, dotWidth]).range([20, dotWidth * 1.2]);
scaleDotY = d3.scale.linear().domain([0, dotHeight]).range([20, dotHeight * 1.2]);
// Parse nodes
var i = 0;
for (nodeId in dotGraph._nodes) {
var node = dotGraph._nodes[nodeId];
node.index = i++;
// x, y is center of node (not corner)
node.x = scaleDotX(node.value.pos[0]);
node.y = scaleDotY(dotHeight - (node.value.pos[1] + node.value.height));
var size = textSize(node.value.label, {'class': 'nodeText'});
node.value.width = size.width + 2 * pad;
node.value.height = size.height + 2 * pad;
node.value.cx = node.value.width / 2;
node.value.cy = node.value.height / 2;
node.value.profile = parseProfile(node.value.profile);
if (typeof(node.value.profile) != 'undefined') {
isProfiled = true;
}
node.fixed = true;
nodes.push(node);
dotGraph._nodes[nodeId] = node;
}
if (isProfiled) {
d3.select('body').select('#menu').append('input')
.attr('name', 'tColors')
.attr('type', 'button')
.attr('value', 'Toggle profile colors')
.attr('onclick', "toggleColors()");
}
// Parse edges
for (edgeId in dotGraph._edges) {
var edge = dotGraph._edges[edgeId];
edge.source = dotGraph._nodes[edge.u].index;
edge.target = dotGraph._nodes[edge.v].index;
var size = textSize(edge.value.label, {'class': 'edgeLabelText'});
edge.value.width = size.width + 2 * pad;
edge.value.height = size.height + 2 * pad;
if (!exists(edge.value.color)) {
edge.value.color = 'black';
}
switch (edge.value.color) {
case 'dodgerblue':
edge.value.type = 'b';
break;
case 'red':
edge.value.type = 'r';
break;
default:
edge.value.type = 'n';
}
edges.push(edge);
dotGraph._edges[edgeId] = edge;
}
// Setup graph
graph['nodes'] = nodes;
graph['edges'] = edges;
var isEdgeOver = false;
var isEdgeLabelOver = false;
// Add edges
edges = pane.append('g').attr('id', 'edges').selectAll('path').data(graph['edges']).enter().append('path')
.attr('class', 'edge')
.attr('stroke', function(d) {return d.value.color;})
.attr('marker-mid', function(d) { return 'url(#edgeArrow_' + d.value.type + ')';})
.on('mouseover', function(d) {
var edge = d3.select(this);
edge.transition()
.duration(200)
.style('opacity', 1.0);
edgeDiv.transition()
.duration(200)
.style('opacity', .9);
edgeDiv
.html(d.value.label)
.style('left', (d3.event.pageX) + 'px')
.style('top', (d3.event.pageY - 28) + 'px');
})
.on('mouseout', function(d) {
var edge = d3.select(this);
edge.transition()
.duration(200)
.style('opacity', 0.4);
edgeDiv.transition()
.duration(200)
.style('opacity', 0);
});
// Add nodes
nodes = pane.append('g').attr('id', 'nodes').selectAll('g').data(graph['nodes']).enter().append('g');
function setNodeSize(node) {
var size = textSize(node.value.label, {'class': 'nodeText'});
node.value.width = size.width + 2 * pad;
node.value.height = size.height + 2 * pad;
node.value.cx = node.value.width / 2;
node.value.cy = node.value.height / 2;
}
updateNodes();
function hideNodeDiv() {
nodeDiv.transition()
.duration(200)
.style('opacity', 0);
}
var editNode = false;
nodes.on('dblclick', function(d) {
var pos = this.getBBox();
var node = d3.select(this);
if (d3.event.defaultPrevented) return;
editNode = true;
hideNodeDiv();
var form = node.append('foreignObject')
.attr('x', pos.x)
.attr('y', pos.y)
.attr('width', d.value.width)
.attr('height', 25);
var input = form.append('xhtml:form').append('input')
.attr('style', 'width: ' + d.value.width + 'px')
.attr('value', function() {
this.focus();
return d.value.label;
})
.on('blur', function() {
d.value.label = input.node().value;
setNodeSize(d);
updateNode(d, node);
form.remove(); // TODO: check this
editNode = false;
})
.on('keypress', function() {
if (!d3.event) {
d3.event = window.event;
}
var event = d3.event;
if (event.keyCode == 13) {
if (typeof(event.cancelBubble)) {
event.cancelBubble = true;
}
if (event.stopPropagation) {
event.stopPropagation();
}
event.preventDefault();
d.value.label = input.node().value;
setNodeSize(d);
updateNode(d, node);
form.remove(); // TODO: check this
editNode = false;
}
});
});
nodes.on('mouseover', function(node) {
if (editNode || typeof(node.value.profile) == 'undefined') {
return;
}
edges.each(function (d, i) {
var edge = d3.select(this);
if (d.source == node || d.target == node) {
edge.transition()
.duration(200)
.style('opacity', 1.0);
}
});
nodeDiv.transition()
.duration(200)
.style('opacity', .9);
nodeDiv
.html(nodeDetails(node))
.style('left', (d3.event.pageX) + 30 + 'px')
.style('top', (d3.event.pageY - 28) + 'px');
});
nodes.on('mouseout', function(node) {
edges.each(function (d, i) {
var edge = d3.select(this);
if (d.source.index == node.index || d.target.index == node.index) {
edge.transition()
.duration(200)
.style('opacity', 0.4);
}
});
hideNodeDiv();
});
nodes.on('contextmenu', function(d) {
releaseNode(d);
});
// Zoom and translate event handler
function zoom(d) {
pane.attr('transform', 'translate(' + d3.event.translate + ') scale(' + d3.event.scale + ')');
}
// Force layout
layout = d3.layout.force()
.nodes(graph['nodes'])
.links(graph['edges'])
.size([dotWidth, dotHeight])
.charge(-3000)
.linkDistance(50)
.linkStrength(0.1)
.on('tick', updateGraph);
// Drag behavour
var drag = layout.drag()
.on('dragstart', function(d) {
d3.event.sourceEvent.stopPropagation();
d3.event.sourceEvent.preventDefault();
d.fixed = true;
});
nodes.call(drag);
// Zoom behaviour
var bZoom = d3.behavior.zoom()
.scaleExtent([0.2, 8])
//.on("dblclick.zoom", null)
.on('zoom', zoom);
svg.call(bZoom);
svg.on("dblclick.zoom", null);
// Start force layout
layout.start();
});
function length(x1, y1, x2, y2) {
return Math.sqrt(Math.pow(x1-x2, 2) + Math.pow(y1-y2, 2));
}
function pathPos(x1, y1, x2, y2, c) {
x = (1 - c) * x1 + c * x2;
y = (1 - c) * y1 + c * y2;
p = x + ',' + y;
return p;
}
// Update graph
function updateGraph() {
// Update nodes
nodes.attr('transform', function(d) { return 'translate(' + (d.x - d.value.cx) + ' ' + (d.y - d.value.cy) + ')'; });
// Update edges
edges.attr('d', function(d) {
var dist = 100;
var l = length(d.source.x, d.source.y, d.target.x, d.target.y);
var n = Math.max(2, Math.floor(l / dist));
var marker = [];
for (var i = 1; i < n; ++i) {
marker.push(i / n);
}
var markerPos = marker.map(function(c) {return pathPos(d.source.x, d.source.y, d.target.x, d.target.y, c);});
var markerPos = ' L' + markerPos.join(' L');
return 'M' + d.source.x + ',' + d.source.y + markerPos + ' L' + d.target.x + ',' + d.target.y;
});
}
function releaseNode(d) {
d.fixed = false;
layout.start();
}
function releaseNodes() {
graph['nodes'].forEach (function (d) {
d.fixed = false;
});
layout.start();
}
function resetNodes() {
layout.stop();
var nodes = graph['nodes'];
nodes.forEach(function (node, i){
nodes[i].x = scaleDotX(node.value.pos[0]);
nodes[i].y = scaleDotY(dotHeight - (node.value.pos[1] + node.value.height));
nodes[i].px = nodes[i].x;
nodes[i].py = nodes[i].y;
nodes[i].fixed = true;
});
updateGraph();
layout.start();
}
</script>
</body>
</html>
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Couldn't import dot_parser, loading of dot files will not be possible.\n"
]
}
],
"source": [
"import pydot as pd\n",
"from IPython.display import SVG"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"g = pd.Dot(graph_type='digraph')\n",
"g.add_node(pd.Node('A', fillcolor='blue', style='filled', shape='box', label='A Label', time=''))\n",
"g.add_node(pd.Node('B', fillcolor='green', shape='ellipse'))\n",
"g.add_edge(pd.Edge('A', 'B', labels='A -> B'))"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"digraph G {\n",
"\tgraph [bb=\"0,0,62,108\"];\n",
"\tnode [label=\"\\N\"];\n",
"\tA\t [fillcolor=blue,\n",
"\t\theight=0.5,\n",
"\t\tlabel=\"A Label\",\n",
"\t\tpos=\"31,90\",\n",
"\t\tshape=box,\n",
"\t\tstyle=filled,\n",
"\t\twidth=0.86111];\n",
"\tB\t [fillcolor=green,\n",
"\t\theight=0.5,\n",
"\t\tpos=\"31,18\",\n",
"\t\tshape=ellipse,\n",
"\t\twidth=0.75];\n",
"\tA -> B\t [labels=\"A -> B\",\n",
"\t\tpos=\"e,31,36.104 31,71.697 31,63.983 31,54.712 31,46.112\"];\n",
"}\n",
"\n"
]
}
],
"source": [
"print(g.create_dot())"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"a = []"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"'[]'"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"str(a)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/svg+xml": [
"<svg height=\"116pt\" viewBox=\"0.00 0.00 70.00 116.00\" width=\"70pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
"<g class=\"graph\" id=\"graph0\" transform=\"scale(1 1) rotate(0) translate(4 112)\">\n",
"<title>G</title>\n",
"<polygon fill=\"white\" points=\"-4,4 -4,-112 66,-112 66,4 -4,4\" stroke=\"none\"/>\n",
"<!-- A -->\n",
"<g class=\"node\" id=\"node1\"><title>A</title>\n",
"<polygon fill=\"blue\" points=\"62,-108 0,-108 0,-72 62,-72 62,-108\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"31\" y=\"-86.3\">A Label</text>\n",
"</g>\n",
"<!-- B -->\n",
"<g class=\"node\" id=\"node2\"><title>B</title>\n",
"<ellipse cx=\"31\" cy=\"-18\" fill=\"none\" rx=\"27\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"31\" y=\"-14.3\">B</text>\n",
"</g>\n",
"<!-- A&#45;&gt;B -->\n",
"<g class=\"edge\" id=\"edge1\"><title>A-&gt;B</title>\n",
"<path d=\"M31,-71.6966C31,-63.9827 31,-54.7125 31,-46.1124\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"34.5001,-46.1043 31,-36.1043 27.5001,-46.1044 34.5001,-46.1043\" stroke=\"black\"/>\n",
"</g>\n",
"</g>\n",
"</svg>"
],
"text/plain": [
"<IPython.core.display.SVG object>"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"SVG(g.create_svg())"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"g = pd.Dot(graph_type='digraph')\n",
"\n",
"c1 = pd.Cluster('c1')\n",
"c1.add_node(pd.Node('A'))\n",
"c1.add_node(pd.Node('B'))\n",
"c1.add_edge(pd.Edge('A', 'B'))\n",
"g.add_subgraph(c1)\n",
"\n",
"c2 = pd.Cluster('c2')\n",
"c2.add_node(pd.Node('C'))\n",
"c2.add_node(pd.Node('D'))\n",
"c2.add_edge(pd.Edge('C', 'D'))\n",
"g.add_subgraph(c2)\n",
"\n",
"g.add_edge(pd.Edge('A', 'C'))"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"digraph G {\n",
"\tgraph [bb=\"0,0,164,212\"];\n",
"\tnode [label=\"\\N\"];\n",
"\tsubgraph cluster_c1 {\n",
"\t\tgraph [bb=\"8,80,78,204\"];\n",
"\t\tA\t\t [height=0.5,\n",
"\t\t\tpos=\"43,178\",\n",
"\t\t\twidth=0.75];\n",
"\t\tB\t\t [height=0.5,\n",
"\t\t\tpos=\"43,106\",\n",
"\t\t\twidth=0.75];\n",
"\t\tA -> B\t\t [pos=\"e,43,124.1 43,159.7 43,151.98 43,142.71 43,134.11\"];\n",
"\t}\n",
"\tsubgraph cluster_c2 {\n",
"\t\tgraph [bb=\"86,8,156,132\"];\n",
"\t\tC\t\t [height=0.5,\n",
"\t\t\tpos=\"121,106\",\n",
"\t\t\twidth=0.75];\n",
"\t\tD\t\t [height=0.5,\n",
"\t\t\tpos=\"121,34\",\n",
"\t\t\twidth=0.75];\n",
"\t\tC -> D\t\t [pos=\"e,121,52.104 121,87.697 121,79.983 121,70.712 121,62.112\"];\n",
"\t}\n",
"\tA -> C\t [pos=\"e,105.62,120.8 58.41,163.17 69.734,153.01 85.309,139.03 98.089,127.56\"];\n",
"}\n",
"\n"
]
}
],
"source": [
"print(g.create_dot())"
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 43,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"g.write_dot('nested.dot')"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/svg+xml": [
"<svg height=\"220pt\" viewBox=\"0.00 0.00 172.00 220.00\" width=\"172pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
"<g class=\"graph\" id=\"graph0\" transform=\"scale(1 1) rotate(0) translate(4 216)\">\n",
"<title>G</title>\n",
"<polygon fill=\"white\" points=\"-4,4 -4,-216 168,-216 168,4 -4,4\" stroke=\"none\"/>\n",
"<g class=\"cluster\" id=\"clust1\"><title>cluster_c1</title>\n",
"<polygon fill=\"none\" points=\"8,-80 8,-204 78,-204 78,-80 8,-80\" stroke=\"black\"/>\n",
"</g>\n",
"<g class=\"cluster\" id=\"clust2\"><title>cluster_c2</title>\n",
"<polygon fill=\"none\" points=\"86,-8 86,-132 156,-132 156,-8 86,-8\" stroke=\"black\"/>\n",
"</g>\n",
"<!-- A -->\n",
"<g class=\"node\" id=\"node1\"><title>A</title>\n",
"<ellipse cx=\"43\" cy=\"-178\" fill=\"none\" rx=\"27\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"43\" y=\"-174.3\">A</text>\n",
"</g>\n",
"<!-- B -->\n",
"<g class=\"node\" id=\"node2\"><title>B</title>\n",
"<ellipse cx=\"43\" cy=\"-106\" fill=\"none\" rx=\"27\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"43\" y=\"-102.3\">B</text>\n",
"</g>\n",
"<!-- A&#45;&gt;B -->\n",
"<g class=\"edge\" id=\"edge1\"><title>A-&gt;B</title>\n",
"<path d=\"M43,-159.697C43,-151.983 43,-142.712 43,-134.112\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"46.5001,-134.104 43,-124.104 39.5001,-134.104 46.5001,-134.104\" stroke=\"black\"/>\n",
"</g>\n",
"<!-- C -->\n",
"<g class=\"node\" id=\"node3\"><title>C</title>\n",
"<ellipse cx=\"121\" cy=\"-106\" fill=\"none\" rx=\"27\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"121\" y=\"-102.3\">C</text>\n",
"</g>\n",
"<!-- A&#45;&gt;C -->\n",
"<g class=\"edge\" id=\"edge3\"><title>A-&gt;C</title>\n",
"<path d=\"M58.4103,-163.17C69.7345,-153.008 85.309,-139.03 98.0887,-127.561\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"100.517,-130.085 105.622,-120.801 95.8416,-124.875 100.517,-130.085\" stroke=\"black\"/>\n",
"</g>\n",
"<!-- D -->\n",
"<g class=\"node\" id=\"node4\"><title>D</title>\n",
"<ellipse cx=\"121\" cy=\"-34\" fill=\"none\" rx=\"27\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"121\" y=\"-30.3\">D</text>\n",
"</g>\n",
"<!-- C&#45;&gt;D -->\n",
"<g class=\"edge\" id=\"edge2\"><title>C-&gt;D</title>\n",
"<path d=\"M121,-87.6966C121,-79.9827 121,-70.7125 121,-62.1124\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"124.5,-62.1043 121,-52.1043 117.5,-62.1044 124.5,-62.1043\" stroke=\"black\"/>\n",
"</g>\n",
"</g>\n",
"</svg>"
],
"text/plain": [
"<IPython.core.display.SVG object>"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"SVG(g.create_svg())"
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"g = pd.Dot(graph_type='digraph')\n",
"g.add_node(pd.Node('A', fillcolor='lightblue', style='filled', shape='box', label='A Label', foo='1'))\n",
"g.add_node(pd.Node('B', fillcolor='green', shape='ellipse'))\n",
"g.add_edge(pd.Edge('A', 'B', labels='A -> B'))"
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/svg+xml": [
"<svg height=\"116pt\" viewBox=\"0.00 0.00 70.00 116.00\" width=\"70pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
"<g class=\"graph\" id=\"graph0\" transform=\"scale(1 1) rotate(0) translate(4 112)\">\n",
"<title>G</title>\n",
"<polygon fill=\"white\" points=\"-4,4 -4,-112 66,-112 66,4 -4,4\" stroke=\"none\"/>\n",
"<!-- A -->\n",
"<g class=\"node\" id=\"node1\"><title>A</title>\n",
"<polygon fill=\"lightblue\" points=\"62,-108 0,-108 0,-72 62,-72 62,-108\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"31\" y=\"-86.3\">A Label</text>\n",
"</g>\n",
"<!-- B -->\n",
"<g class=\"node\" id=\"node2\"><title>B</title>\n",
"<ellipse cx=\"31\" cy=\"-18\" fill=\"none\" rx=\"27\" ry=\"18\" stroke=\"black\"/>\n",
"<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"31\" y=\"-14.3\">B</text>\n",
"</g>\n",
"<!-- A&#45;&gt;B -->\n",
"<g class=\"edge\" id=\"edge1\"><title>A-&gt;B</title>\n",
"<path d=\"M31,-71.6966C31,-63.9827 31,-54.7125 31,-46.1124\" fill=\"none\" stroke=\"black\"/>\n",
"<polygon fill=\"black\" points=\"34.5001,-46.1043 31,-36.1043 27.5001,-46.1044 34.5001,-46.1043\" stroke=\"black\"/>\n",
"</g>\n",
"</g>\n",
"</svg>"
],
"text/plain": [
"<IPython.core.display.SVG object>"
]
},
"execution_count": 41,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"SVG(g.create_svg())"
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"digraph G {\n",
"\tgraph [bb=\"0,0,62,108\"];\n",
"\tnode [label=\"\\N\"];\n",
"\tA\t [fillcolor=lightblue,\n",
"\t\tfoo=1,\n",
"\t\theight=0.5,\n",
"\t\tlabel=\"A Label\",\n",
"\t\tpos=\"31,90\",\n",
"\t\tshape=box,\n",
"\t\tstyle=filled,\n",
"\t\twidth=0.86111];\n",
"\tB\t [fillcolor=green,\n",
"\t\theight=0.5,\n",
"\t\tpos=\"31,18\",\n",
"\t\tshape=ellipse,\n",
"\t\twidth=0.75];\n",
"\tA -> B\t [labels=\"A -> B\",\n",
"\t\tpos=\"e,31,36.104 31,71.697 31,63.983 31,54.712 31,46.112\"];\n",
"}\n",
"\n"
]
}
],
"source": [
"print(g.create_dot())"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.10"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
...@@ -157,7 +157,7 @@ class GraphFormatter(object): ...@@ -157,7 +157,7 @@ class GraphFormatter(object):
apply_shape = 'ellipse' apply_shape = 'ellipse'
var_shape = 'box' var_shape = 'box'
for node_idx, node in enumerate(topo): for node_idx, node in enumerate(topo):
astr = self.apply_name(node, fct, topo, mode, profile) astr, aprof = self.apply_name(node, fct, topo, mode, profile)
use_color = None use_color = None
for opName, color in self.colorCodes.items(): for opName, color in self.colorCodes.items():
...@@ -165,12 +165,12 @@ class GraphFormatter(object): ...@@ -165,12 +165,12 @@ class GraphFormatter(object):
use_color = color use_color = color
if use_color is None: if use_color is None:
nw_node = pd.Node(astr, shape=apply_shape) nw_node = pd.Node(astr, shape=apply_shape, profile=aprof)
elif self.high_contrast: elif self.high_contrast:
nw_node = pd.Node(astr, style='filled', fillcolor=use_color, nw_node = pd.Node(astr, style='filled', fillcolor=use_color,
shape=apply_shape, type='colored') shape=apply_shape, type='colored', profile=aprof)
else: else:
nw_node = pd.Node(astr, color=use_color, shape=apply_shape) nw_node = pd.Node(astr, color=use_color, shape=apply_shape, profile=aprof)
g.add_node(nw_node) g.add_node(nw_node)
if self.cond_highlight: if self.cond_highlight:
if node in middle: if node in middle:
...@@ -180,6 +180,10 @@ class GraphFormatter(object): ...@@ -180,6 +180,10 @@ class GraphFormatter(object):
elif node in right: elif node in right:
c2.add_node(nw_node) c2.add_node(nw_node)
def make_node(*args, **kwargs):
t = {k:v for k,v in kwargs.items() if v is not None}
return pd.Node(*args, **t)
for id, var in enumerate(node.inputs): for id, var in enumerate(node.inputs):
varstr = self.var_name(var) varstr = self.var_name(var)
label = str(var.type) label = str(var.type)
...@@ -196,19 +200,19 @@ class GraphFormatter(object): ...@@ -196,19 +200,19 @@ class GraphFormatter(object):
param['color'] = 'red' param['color'] = 'red'
if var.owner is None: if var.owner is None:
if self.high_contrast: if self.high_contrast:
g.add_node(pd.Node(varstr, g.add_node(make_node(varstr,
style='filled', style='filled',
fillcolor=self.node_colors['input'], fillcolor=self.node_colors['input'],
shape=var_shape)) shape=var_shape, profile=aprof))
else: else:
g.add_node(pd.Node(varstr, color=self.node_colors['input'], g.add_node(make_node(varstr, color=self.node_colors['input'],
shape=var_shape)) shape=var_shape, profile=aprof))
g.add_edge(pd.Edge(varstr, astr, label=label, **param)) g.add_edge(pd.Edge(varstr, astr, label=label, **param))
elif var.name or not self.compact: elif var.name or not self.compact:
g.add_edge(pd.Edge(varstr, astr, label=label, **param)) g.add_edge(pd.Edge(varstr, astr, label=label, **param))
else: else:
# no name, so we don't make a var ellipse # no name, so we don't make a var ellipse
name = self.apply_name(var.owner, fct, topo, mode, profile) name, prof = self.apply_name(var.owner, fct, topo, mode, profile)
g.add_edge(pd.Edge(name, astr, g.add_edge(pd.Edge(name, astr,
label=label, **param)) label=label, **param))
...@@ -223,21 +227,21 @@ class GraphFormatter(object): ...@@ -223,21 +227,21 @@ class GraphFormatter(object):
if out: if out:
g.add_edge(pd.Edge(astr, varstr, label=label)) g.add_edge(pd.Edge(astr, varstr, label=label))
if self.high_contrast: if self.high_contrast:
g.add_node(pd.Node(varstr, style='filled', g.add_node(make_node(varstr, style='filled',
fillcolor=self.node_colors['output'], fillcolor=self.node_colors['output'],
shape=var_shape)) shape=var_shape, profile=aprof))
else: else:
g.add_node(pd.Node(varstr, color=self.node_colors['output'], g.add_node(make_node(varstr, color=self.node_colors['output'],
shape=var_shape)) shape=var_shape, profile=aprof))
elif len(var.clients) == 0: elif len(var.clients) == 0:
g.add_edge(pd.Edge(astr, varstr, label=label)) g.add_edge(pd.Edge(astr, varstr, label=label))
if self.high_contrast: if self.high_contrast:
g.add_node(pd.Node(varstr, style='filled', g.add_node(make_node(varstr, style='filled',
fillcolor=self.node_colors['unused'], fillcolor=self.node_colors['unused'],
shape=var_shape)) shape=var_shape, profile=aprof))
else: else:
g.add_node(pd.Node(varstr, color=self.node_colors['unused'], g.add_node(make_node(varstr, color=self.node_colors['unused'],
shape=var_shape)) shape=var_shape, profile=aprof))
elif var.name or not self.compact: elif var.name or not self.compact:
g.add_edge(pd.Edge(astr, varstr, label=label)) g.add_edge(pd.Edge(astr, varstr, label=label))
...@@ -296,12 +300,11 @@ class GraphFormatter(object): ...@@ -296,12 +300,11 @@ class GraphFormatter(object):
return varstr return varstr
def apply_name(self, node, fct, topo, mode=None, profile=None): def apply_name(self, node, fct, topo, mode=None, profile=None):
if node in self.apply_name_cache: if node in self.apply_name_cache:
return self.apply_name_cache[node] return self.apply_name_cache[node]
prof_str = '' prof = None
if mode: if mode:
time = mode.profile_stats[fct].apply_time.get(node, 0) time = mode.profile_stats[fct].apply_time.get(node, 0)
# second, % total time in profiler, %fct time in profiler # second, % total time in profiler, %fct time in profiler
...@@ -313,7 +316,7 @@ class GraphFormatter(object): ...@@ -313,7 +316,7 @@ class GraphFormatter(object):
pf = 0 pf = 0
else: else:
pf = time * 100 / mode.profile_stats[fct].fct_call_time pf = time * 100 / mode.profile_stats[fct].fct_call_time
prof_str = ' (%.3fs,%.3f%%,%.3f%%)' % (time, pt, pf) prof = [time, pt, pf]
elif profile: elif profile:
time = profile.apply_time.get(node, 0) time = profile.apply_time.get(node, 0)
# second, %fct time in profiler # second, %fct time in profiler
...@@ -321,9 +324,9 @@ class GraphFormatter(object): ...@@ -321,9 +324,9 @@ class GraphFormatter(object):
pf = 0 pf = 0
else: else:
pf = time * 100 / profile.fct_call_time pf = time * 100 / profile.fct_call_time
prof_str = ' (%.3fs,%.3f%%)' % (time, pf) prof = [time, None, pf]
applystr = str(node.op).replace(':', '_') applystr = str(node.op).replace(':', '_')
applystr += prof_str
if (applystr in self.all_strings) or self.with_ids: if (applystr in self.all_strings) or self.with_ids:
idx = ' id=' + str(topo.index(node)) idx = ' id=' + str(topo.index(node))
if len(applystr) + len(idx) > self.max_label_size: if len(applystr) + len(idx) > self.max_label_size:
...@@ -340,7 +343,11 @@ class GraphFormatter(object): ...@@ -340,7 +343,11 @@ class GraphFormatter(object):
applystr = (applystr[:self.max_label_size - 3 - len(suffix)] + applystr = (applystr[:self.max_label_size - 3 - len(suffix)] +
'...' + '...' +
suffix) suffix)
if prof is not None:
prof = str(prof)
else:
prof = ''
self.all_strings.add(applystr) self.all_strings.add(applystr)
self.apply_name_cache[node] = applystr self.apply_name_cache[node] = (applystr, prof)
return applystr return (applystr, prof)
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
...@@ -58,7 +59,7 @@ ...@@ -58,7 +59,7 @@
stroke: dodgerblue; stroke: dodgerblue;
} }
.tooltip { .edgeTooltip {
position: absolute; position: absolute;
text-align: center; text-align: center;
vertical-align: middle; vertical-align: middle;
...@@ -70,9 +71,22 @@ ...@@ -70,9 +71,22 @@
border-radius: 8px; border-radius: 8px;
pointer-events: none; pointer-events: none;
} }
.nodeTooltip {
position: absolute;
text-align: left;
vertical-align: middle;
min-width: 10px;
min-height: 10px;
padding: 5px;
background: lightsteelblue;
border: 1px solid black;
border-radius: 8px;
pointer-events: none;
}
</style> </style>
<div> <div id='menu'>
<input name="resetNodes" <input name="resetNodes"
type="button" type="button"
value="Reset nodes" value="Reset nodes"
...@@ -85,6 +99,8 @@ ...@@ -85,6 +99,8 @@
<script type="text/javascript"> <script type="text/javascript">
var path='%% DOT_FILE %%'; var path='%% DOT_FILE %%';
var isProfiled = false;
var colorProfile = false;
// Global attributes // Global attributes
var pad = 10; var pad = 10;
...@@ -95,7 +111,11 @@ ...@@ -95,7 +111,11 @@
var pane = svg.append('g'); var pane = svg.append('g');
var edgeDiv = d3.select('body').append('div') var edgeDiv = d3.select('body').append('div')
.attr('class', 'tooltip') .attr('class', 'edgeTooltip')
.style('opacity', 0.0);
var nodeDiv = d3.select('body').append('div')
.attr('class', 'nodeTooltip')
.style('opacity', 0.0); .style('opacity', 0.0);
// Definition head of edges // Definition head of edges
...@@ -114,6 +134,12 @@ ...@@ -114,6 +134,12 @@
.attr("d", "M0,0 L4,2 L0,4 Z") .attr("d", "M0,0 L4,2 L0,4 Z")
.attr('fill', function(d) { return d.color;}); .attr('fill', function(d) { return d.color;});
function toggleColors() {
colorProfile = !colorProfile;
updateNodes();
updateGraph();
}
function textSize(text, attr) { function textSize(text, attr) {
var t = svg.append('text').text(text); var t = svg.append('text').text(text);
if (typeof(attr) != 'undefined') { if (typeof(attr) != 'undefined') {
...@@ -130,6 +156,97 @@ ...@@ -130,6 +156,97 @@
return typeof(x) != 'undefined'; return typeof(x) != 'undefined';
} }
function replaceAll(str, find, replace) {
return str.replace(new RegExp(find, 'g'), replace);
}
function parseProfile(profile) {
if (typeof(profile) == 'undefined') {
return;
}
profile = profile.replace('[', '');
profile = profile.replace(']', '');
profile = replaceAll(profile, ' ', '');
profile = profile.split(',');
if (profile.length < 2) {
return [];
}
profile = profile.map(function(x) { return parseFloat(x); });
return profile;
}
function profileColor(per) {
var colors = ["#fff5f0","#fee0d2","#fcbba1","#fc9272","#fb6a4a","#ef3b2c","#cb181d","#a50f15","#67000d"];
var s = d3.scale.linear()
.domain([0, 100])
.range([0, colors.length - 1]);
return colors[Math.round(s(per))];
}
function fillColor(d) {
if (colorProfile && typeof(d.value.profile) != 'undefined') {
return profileColor(d.value.profile[2]);
} else {
return typeof(d.value.fillcolor) == 'undefined' ? 'white' : d.value.fillcolor;
}
}
function formatTime(sec) {
var s;
if (sec < 0.1) {
s = (sec * 1000).toFixed(1) + 'ms';
} else {
s = sec.toFixed(1) + 's';
}
return s;
}
function nodeDetails(node) {
var s = '<b>' + node.value.label + '</b>';
var p = node.value.profile;
if (!isNaN(p[0])) {
s += '<br>Total time: ' + formatTime(p[0]);
}
if (!isNaN(p[1])) {
s += '<br>Total time: ' + p[1].toFixed(1) + '%';
}
if (!isNaN(p[2])) {
s += '<br>Profile time: ' + p[2].toFixed(1) + '%';
}
return s;
}
function updateNode(d, node) {
var shape;
if (d.value.shape == 'ellipse') {
node.selectAll('ellipse').remove();
shape = node.append('ellipse')
.attr('class', 'nodeEllipse')
.attr('cx', d.value.cx)
.attr('cy', d.value.cy)
.attr('rx', d.value.width * 0.6)
.attr('ry', d.value.height * 0.6);
} else {
node.selectAll('rect').remove();
shape = node.append('rect')
.attr('class', 'nodeRect')
.attr('width', d.value.width)
.attr('height', d.value.height);
}
shape.attr('fill', fillColor(d));
node.selectAll('text').remove();
var text = node.append('text')
.attr('class', 'nodeText')
.attr('x', pad)
.attr('dy', function(d) {return d.value.height - pad - 5;})
.text(function(d) {return d.value.label;});
}
function updateNodes() {
nodes.each(function(d) {var node = d3.select(this); updateNode(d, node);});
}
var dotGraph; var dotGraph;
var graph = {}; var graph = {};
...@@ -173,12 +290,24 @@ ...@@ -173,12 +290,24 @@
node.value.height = size.height + 2 * pad; node.value.height = size.height + 2 * pad;
node.value.cx = node.value.width / 2; node.value.cx = node.value.width / 2;
node.value.cy = node.value.height / 2; node.value.cy = node.value.height / 2;
node.value.profile = parseProfile(node.value.profile);
if (typeof(node.value.profile) != 'undefined') {
isProfiled = true;
}
node.fixed = true; node.fixed = true;
nodes.push(node); nodes.push(node);
dotGraph._nodes[nodeId] = node; dotGraph._nodes[nodeId] = node;
} }
if (isProfiled) {
d3.select('body').select('#menu').append('input')
.attr('name', 'tColors')
.attr('type', 'button')
.attr('value', 'Toggle profile colors')
.attr('onclick', "toggleColors()");
}
// Parse edges // Parse edges
for (edgeId in dotGraph._edges) { for (edgeId in dotGraph._edges) {
var edge = dotGraph._edges[edgeId]; var edge = dotGraph._edges[edgeId];
...@@ -241,10 +370,8 @@ ...@@ -241,10 +370,8 @@
}); });
// Add nodes // Add nodes
nodes = pane.append('g').attr('id', 'nodes').selectAll('g').data(graph['nodes']).enter().append('g'); nodes = pane.append('g').attr('id', 'nodes').selectAll('g').data(graph['nodes']).enter().append('g');
function fillColor(f) {
return typeof(f) == 'undefined' ? 'white' : f;
}
function setNodeSize(node) { function setNodeSize(node) {
var size = textSize(node.value.label, {'class': 'nodeText'}); var size = textSize(node.value.label, {'class': 'nodeText'});
...@@ -254,44 +381,25 @@ ...@@ -254,44 +381,25 @@
node.value.cy = node.value.height / 2; node.value.cy = node.value.height / 2;
} }
function updateNode(d, node) { updateNodes();
var shape;
if (d.value.shape == 'ellipse') {
node.selectAll('ellipse').remove();
shape = node.append('ellipse')
.attr('class', 'nodeEllipse')
.attr('cx', d.value.cx)
.attr('cy', d.value.cy)
.attr('rx', d.value.width * 0.6)
.attr('ry', d.value.height * 0.6);
} else {
node.selectAll('rect').remove();
shape = node.append('rect')
.attr('class', 'nodeRect')
.attr('width', d.value.width)
.attr('height', d.value.height);
}
shape.attr('fill', fillColor(d.value.fillcolor));
node.selectAll('text').remove(); function hideNodeDiv() {
var text = node.append('text') nodeDiv.transition()
.attr('class', 'nodeText') .duration(200)
.attr('x', pad) .style('opacity', 0);
.attr('dy', function(d) {return d.value.height - pad - 5;})
.text(function(d) {return d.value.label;})
.on('dblclick', releaseNode);
} }
nodes.each(function(d) {var node = d3.select(this); updateNode(d, node);});
// TODO: activate again without interfering with click event var editNode = false;
//nodes.on('dblclick', releaseNode);
nodes.on('click', function(d) { nodes.on('dblclick', function(d) {
var pos = this.getBBox(); var pos = this.getBBox();
var node = d3.select(this); var node = d3.select(this);
if (d3.event.defaultPrevented) return; if (d3.event.defaultPrevented) return;
editNode = true;
hideNodeDiv();
var form = node.append('foreignObject') var form = node.append('foreignObject')
.attr('x', pos.x) .attr('x', pos.x)
.attr('y', pos.y) .attr('y', pos.y)
...@@ -308,6 +416,7 @@ ...@@ -308,6 +416,7 @@
setNodeSize(d); setNodeSize(d);
updateNode(d, node); updateNode(d, node);
form.remove(); // TODO: check this form.remove(); // TODO: check this
editNode = false;
}) })
.on('keypress', function() { .on('keypress', function() {
if (!d3.event) { if (!d3.event) {
...@@ -325,12 +434,17 @@ ...@@ -325,12 +434,17 @@
d.value.label = input.node().value; d.value.label = input.node().value;
setNodeSize(d); setNodeSize(d);
updateNode(d, node); updateNode(d, node);
form.remove(); // TODO: check thi form.remove(); // TODO: check this
editNode = false;
} }
}); });
}); });
nodes.on('mouseover', function(node) { nodes.on('mouseover', function(node) {
if (editNode || typeof(node.value.profile) == 'undefined') {
return;
}
edges.each(function (d, i) { edges.each(function (d, i) {
var edge = d3.select(this); var edge = d3.select(this);
if (d.source == node || d.target == node) { if (d.source == node || d.target == node) {
...@@ -339,8 +453,16 @@ ...@@ -339,8 +453,16 @@
.style('opacity', 1.0); .style('opacity', 1.0);
} }
}); });
nodeDiv.transition()
.duration(200)
.style('opacity', .9);
nodeDiv
.html(nodeDetails(node))
.style('left', (d3.event.pageX) + 30 + 'px')
.style('top', (d3.event.pageY - 28) + 'px');
}); });
nodes.on('mouseout', function(node) { nodes.on('mouseout', function(node) {
edges.each(function (d, i) { edges.each(function (d, i) {
var edge = d3.select(this); var edge = d3.select(this);
...@@ -350,6 +472,11 @@ ...@@ -350,6 +472,11 @@
.style('opacity', 0.4); .style('opacity', 0.4);
} }
}); });
hideNodeDiv();
});
nodes.on('contextmenu', function(d) {
releaseNode(d);
}); });
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论