提交 1f1f8eda authored 作者: Christof Angermueller's avatar Christof Angermueller

Add 150620_layout

上级 80e6144f
<!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;
}
.tooltip {
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;
}
</style>
<div>
<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='train.dot';
// 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', 'tooltip')
.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 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';
}
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.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.fixed = true;
nodes.push(node);
dotGraph._nodes[nodeId] = node;
}
// 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 fillColor(f) {
return typeof(f) == 'undefined' ? 'white' : f;
}
nodes.each(function(d) {
sel = d3.select(this);
var shape;
if (d.value.shape == 'ellipse') {
shape = sel.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 {
shape = sel.append('rect')
.attr('class', 'nodeRect')
.attr('width', d.value.width)
.attr('height', d.value.height);
}
shape.attr('fill', fillColor(d.value.fillcolor));
});
nodes.on('dblclick', releaseNode);
// Add nodes text
var nodesText = nodes.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;})
.attr('contenteditable', "true")
.on('dblclick', releaseNode);
// Drag-start event handler
function dragStart(d) {
d3.event.sourceEvent.stopPropagation();
d.fixed = true;
}
// 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', dragStart);
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": "markdown",
"metadata": {},
"source": [
"#Table of Contents\n",
"* [Model](#Model)\n",
"* [Example 1](#Example-1)\n",
"* [Example 2](#Example-2)\n",
"* [Example 3](#Example-3)\n"
]
},
{
"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 theano\n",
"import theano.tensor as T\n",
"import theano.printing as pr\n",
"import theano.d3printing as d3p\n",
"rng = numpy.random"
]
},
{
"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": true
},
"outputs": [],
"source": [
"# Training data\n",
"N = 400\n",
"feats = 784\n",
"D = (rng.randn(N, feats).astype(theano.config.floatX), rng.randint(size=N,low=0, high=2).astype(theano.config.floatX))\n",
"training_steps = 10000\n",
"\n",
"# Declare Theano symbolic variables\n",
"x = T.matrix(\"x\")\n",
"y = T.vector(\"y\")\n",
"w = theano.shared(rng.randn(feats).astype(theano.config.floatX), name=\"w\")\n",
"b = theano.shared(numpy.asarray(0., dtype=theano.config.floatX), name=\"b\")\n",
"x.tag.test_value = D[0]\n",
"y.tag.test_value = D[1]\n",
"\n",
"# Construct Theano expression graph\n",
"p_1 = 1 / (1 + T.exp(-T.dot(x, w)-b)) # Probability of having a one\n",
"prediction = p_1 > 0.5 # The prediction that is done: 0 or 1\n",
"\n",
"# Compute gradients\n",
"xent = -y*T.log(p_1) - (1-y)*T.log(1-p_1) # Cross-entropy\n",
"cost = xent.mean() + 0.01*(w**2).sum() # The cost to optimize\n",
"gw,gb = T.grad(cost, [w,b])\n",
"\n",
"# Training and prediction function\n",
"train = theano.function(inputs=[x,y], outputs=[prediction, xent], updates=[[w, w-0.01*gw], [b, b-0.01*gb]], name = \"train\")\n",
"predict = theano.function(inputs=[x], outputs=prediction, name = \"predict\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Example 1 "
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The output file is available at p1.png\n"
]
}
],
"source": [
"pr.pydotprint(p_1, outfile='p1.png', var_with_name_simple=True)\n",
"d3p.d3write(p_1, 'p1.dot')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<a href='p1.html'><img src='p1.png'/></a>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[open](./p1.html)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Example 2"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The output file is available at predict.png\n"
]
}
],
"source": [
"pr.pydotprint(predict, outfile='predict.png', var_with_name_simple=True)\n",
"d3p.d3write(predict, 'predict.dot')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<a href='predict.html'><img src='predict.png'/></a>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[open](./predict.html)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Example 3"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The output file is available at train.png\n"
]
}
],
"source": [
"pr.pydotprint(train, outfile='train.png', var_with_name_simple=True)\n",
"d3p.d3write(train, 'train.dot')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<a href='train.html'><img src='train.png'/></a>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[open](./train.html)"
]
}
],
"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,719,672"]; "DimShuffle{x}" [height=0.5, pos="558,478", shape=ellipse, width=1.8374]; "Elemwise{sub,no_inplace}" [fillcolor="#FFAABB", height=0.5, pos="461,390", shape=ellipse, style=filled, width=3.0624]; "DimShuffle{x}" -> "Elemwise{sub,no_inplace}" [label="1 TensorType(float64, (True,))", lp="632.5,434", pos="e,506.93,406.57 553.52,459.62 549.99,448.82 544.12,435.29 535,426 529.47,420.37 522.85,415.53 515.89,411.41"]; "name=b TensorType(float64, scalar)" [fillcolor=limegreen, height=0.5, pos="558,566", shape=box, style=filled, width=3.0625]; "name=b TensorType(float64, scalar)" -> "DimShuffle{x}" [label="TensorType(float64, scalar)", lp="636,522", pos="e,558,496.08 558,547.6 558,535.75 558,519.82 558,506.29"]; dot [height=0.5, pos="363,566", shape=ellipse, width=0.75]; "Elemwise{neg,no_inplace}" [fillcolor="#FFAABB", height=0.5, pos="363,478", shape=ellipse, style=filled, width=3.0624]; dot -> "Elemwise{neg,no_inplace}" [label="TensorType(float64, vector)", lp="442,522", pos="e,363,496.08 363,547.6 363,535.75 363,519.82 363,506.29"]; "name=x TensorType(float64, matrix)" [fillcolor=limegreen, height=0.5, pos="241,654", shape=box, style=filled, width=3.1181]; "name=x TensorType(float64, matrix)" -> dot [label="0 TensorType(float64, matrix)", lp="378,610", pos="e,340.56,576.07 255.77,636 265.61,625.35 279.21,611.84 293,602 304.81,593.57 318.95,586.09 331.42,580.22"]; "name=w TensorType(float64, vector)" [fillcolor=limegreen, height=0.5, pos="485,654", shape=box, style=filled, width=3.1389]; "name=w TensorType(float64, vector)" -> dot [label="1 TensorType(float64, vector)", lp="559.5,610", pos="e,389.41,570.28 481.35,635.78 478.2,624.78 472.59,610.94 463,602 445.54,585.73 420.08,576.96 399.23,572.27"]; "DimShuffle{x} id=2" [height=0.5, pos="247,302", shape=ellipse, width=2.3721]; "Elemwise{add,no_inplace}" [fillcolor="#FFAABB", height=0.5, pos="369,194", shape=ellipse, style=filled, width=3.0624]; "DimShuffle{x} id=2" -> "Elemwise{add,no_inplace}" [label="0 TensorType(int8, (True,))", lp="334,248", pos="e,290.21,206.6 244.34,283.76 242.92,267.96 243.54,244.85 256,230 262.8,221.89 271.45,215.63 280.91,210.8"]; "val=1 TensorType(int8, scalar)" [fillcolor=limegreen, height=0.5, pos="161,390", shape=box, style=filled, width=2.6389]; "val=1 TensorType(int8, scalar)" -> "DimShuffle{x} id=2" [label="TensorType(int8, scalar)", lp="305.5,346", pos="e,242.7,320.2 201.81,371.98 210.24,367.09 218.52,361.12 225,354 231.25,347.13 235.92,338.22 239.3,329.76"]; "DimShuffle{x} id=3" [height=0.5, pos="85,248", shape=ellipse, width=2.3721]; "val=1 TensorType(int8, scalar)" -> "DimShuffle{x} id=3" [label="TensorType(int8, scalar)", lp="151.5,346", pos="e,78.947,266.23 101.23,371.9 93.625,367.28 86.827,361.42 82,354 66.992,330.94 70.718,298.58 76.308,275.9"]; "Elemwise{true_div,no_inplace}" [fillcolor="#FFAABB", height=0.5, pos="164,106", shape=ellipse, style=filled, width=3.5561]; "DimShuffle{x} id=3" -> "Elemwise{true_div,no_inplace}" [label="0 TensorType(int8, (True,))", lp="172,194", pos="e,140.09,123.74 84.103,229.75 84.024,214.78 85.627,192.93 94,176 102.79,158.23 118.02,142.37 132.04,130.36"]; "Elemwise{neg,no_inplace}" -> "Elemwise{sub,no_inplace}" [label="0 TensorType(float64, vector)", lp="446.5,434", pos="e,389.83,403.99 357.87,459.89 355.74,449.21 355.15,435.69 362,426 366.99,418.94 373.53,413.29 380.88,408.78"]; "Elemwise{exp,no_inplace}" [fillcolor="#FFAABB", height=0.5, pos="461,302", shape=ellipse, style=filled, width=3.0624]; "Elemwise{sub,no_inplace}" -> "Elemwise{exp,no_inplace}" [label="TensorType(float64, vector)", lp="540,346", pos="e,461,320.08 461,371.6 461,359.75 461,343.82 461,330.29"]; "Elemwise{exp,no_inplace}" -> "Elemwise{add,no_inplace}" [label="1 TensorType(float64, vector)", lp="526.5,248", pos="e,394.8,211.6 452.54,284.02 444.46,268.82 431.28,246.48 416,230 412.01,225.7 407.43,221.56 402.74,217.73"]; "Elemwise{add,no_inplace}" -> "Elemwise{true_div,no_inplace}" [label="1 TensorType(float64, vector)", lp="369.5,150", pos="e,202.57,123.18 330.92,177.03 297.33,162.93 248.22,142.33 211.96,127.12"]; "TensorType(float64, vector) id=12" [fillcolor=dodgerblue, height=0.5, pos="164,18", shape=box, style=filled, width=2.9236]; "Elemwise{true_div,no_inplace}" -> "TensorType(float64, vector) id=12" [label="TensorType(float64, vector)", lp="243,62", pos="e,164,36.084 164,87.597 164,75.746 164,59.817 164,46.292"]; }
\ No newline at end of file
<!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;
}
.tooltip {
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;
}
</style>
<div>
<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='p1.dot';
// 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', 'tooltip')
.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 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';
}
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.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.fixed = true;
nodes.push(node);
dotGraph._nodes[nodeId] = node;
}
// 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 fillColor(f) {
return typeof(f) == 'undefined' ? 'white' : f;
}
nodes.each(function(d) {
sel = d3.select(this);
var shape;
if (d.value.shape == 'ellipse') {
shape = sel.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 {
shape = sel.append('rect')
.attr('class', 'nodeRect')
.attr('width', d.value.width)
.attr('height', d.value.height);
}
shape.attr('fill', fillColor(d.value.fillcolor));
});
nodes.on('dblclick', releaseNode);
// Add nodes text
var nodesText = nodes.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;})
.attr('contenteditable', "true")
.on('dblclick', releaseNode);
// Drag-start event handler
function dragStart(d) {
d3.event.sourceEvent.stopPropagation();
d.fixed = true;
}
// 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', dragStart);
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,1297,476"]; "InplaceDimShuffle{x}" [height=0.5, pos="1120,194", shape=ellipse, width=2.5686]; "Elemwise{Composite{GT(scalar_sigmoid((-((-i0) - i1))), i2)}}" [fillcolor="#FFAABB", height=0.5, pos="822,106", shape=ellipse, style=filled, width=6.6733]; "InplaceDimShuffle{x}" -> "Elemwise{Composite{GT(scalar_sigmoid((-((-i0) - i1))), i2)}}" [label="1 TensorType(float64, (True,))", lp="1130.5,150", pos="e,919.34,122.55 1087.3,177.07 1063.3,165.92 1029.7,151.41 999,142 976.72,135.18 952.45,129.37 929.22,124.56"]; "name=b TensorType(float64, scalar)" [fillcolor=limegreen, height=0.5, pos="1155,282", shape=box, style=filled, width=3.0625]; "name=b TensorType(float64, scalar)" -> "InplaceDimShuffle{x}" [color=dodgerblue, label="TensorType(float64, scalar)", lp="1219,238", pos="e,1127,212.08 1147.9,263.6 1143,251.51 1136.4,235.18 1130.8,221.49"]; "Shape_i{0}" [fillcolor=cyan, height=0.5, pos="123,370", shape=ellipse, style=filled, width=1.4763]; "AllocEmpty{dtype='float64'}" [fillcolor="#FFAA22", height=0.5, pos="117,282", shape=ellipse, style=filled, width=3.2589]; "Shape_i{0}" -> "AllocEmpty{dtype='float64'}" [label="TensorType(int64, scalar)", lp="194,326", pos="e,118.19,300.08 121.79,351.6 120.96,339.75 119.85,323.82 118.9,310.29"]; "name=x TensorType(float64, matrix)" [fillcolor=limegreen, height=0.5, pos="212,458", shape=box, style=filled, width=3.1181]; "name=x TensorType(float64, matrix)" -> "Shape_i{0}" [label="TensorType(float64, matrix)", lp="206,414", pos="e,119.68,388.12 146.59,439.97 138.58,435.35 131.35,429.47 126,422 121.13,415.21 119.44,406.5 119.25,398.22"]; "CGemv{inplace}" [height=0.5, pos="472,194", shape=ellipse, width=2.0569]; "name=x TensorType(float64, matrix)" -> "CGemv{inplace}" [label="2 TensorType(float64, matrix)", lp="387,326", pos="e,417.53,206.33 264.19,439.95 272.46,435.26 280.19,429.37 286,422 330.4,365.66 274.09,319.94 319,264 341.06,236.53 376.41,219.61 \ 407.58,209.41"]; "AllocEmpty{dtype='float64'}" -> "CGemv{inplace}" [color=red, label="0 TensorType(float64, vector)", lp="201.5,238", pos="e,398.78,197.07 111.67,263.77 109.42,252.76 108.91,238.92 117,230 134.92,210.23 289.58,201.22 388.77,197.44"]; "CGemv{inplace}" -> "Elemwise{Composite{GT(scalar_sigmoid((-((-i0) - i1))), i2)}}" [label="0 TensorType(float64, vector)", lp="733.5,150", pos="e,736.34,122.9 515.74,179.33 551.4,168.44 603.18,153.22 649,142 673.96,135.89 701.14,130.03 726.39,124.9"]; "val=1.0 TensorType(float64, scalar)" [fillcolor=limegreen, height=0.5, pos="437,282", shape=box, style=filled, width=3.0278]; "val=1.0 TensorType(float64, scalar)" -> "CGemv{inplace}" [label="1 TensorType(float64, scalar)", lp="541.5,238", pos="e,465.05,212.08 444.08,263.6 449,251.51 455.65,235.18 461.22,221.49"]; "name=w TensorType(float64, vector)" [fillcolor=limegreen, height=0.5, pos="677,282", shape=box, style=filled, width=3.1389]; "name=w TensorType(float64, vector)" -> "CGemv{inplace}" [label="3 TensorType(float64, vector)", lp="733.5,238", pos="e,540.12,201.21 665.1,263.77 656.39,252.47 643.58,238.3 629,230 605.11,216.4 576.39,208.09 550.07,203"]; "val=0.0 TensorType(float64, scalar)" [fillcolor=limegreen, height=0.5, pos="917,282", shape=box, style=filled, width=3.0278]; "val=0.0 TensorType(float64, scalar)" -> "CGemv{inplace}" [label="4 TensorType(float64, scalar)", lp="944.5,238", pos="e,541.25,200.46 891.6,263.79 873.13,252.18 847.07,237.65 822,230 796.82,222.32 646.71,209.1 551.43,201.29"]; "TensorType(int8, vector)" [fillcolor=dodgerblue, height=0.5, pos="822,18", shape=box, style=filled, width=2.1736]; "Elemwise{Composite{GT(scalar_sigmoid((-((-i0) - i1))), i2)}}" -> "TensorType(int8, vector)" [label="TensorType(int8, vector)", lp="892.5,62", pos="e,822,36.084 822,87.597 822,75.746 822,59.817 822,46.292"]; "val=[ 0.5] TensorType(float32, (True,))" [fillcolor=limegreen, height=0.5, pos="822,194", shape=box, style=filled, width=3.2847]; "val=[ 0.5] TensorType(float32, (True,))" -> "Elemwise{Composite{GT(scalar_sigmoid((-((-i0) - i1))), i2)}}" [label="2 TensorType(float32, (True,))", lp="908.5,150", pos="e,822,124.08 822,175.6 822,163.75 822,147.82 822,134.29"]; }
\ No newline at end of file
<!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;
}
.tooltip {
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;
}
</style>
<div>
<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.dot';
// 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', 'tooltip')
.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 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';
}
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.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.fixed = true;
nodes.push(node);
dotGraph._nodes[nodeId] = node;
}
// 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 fillColor(f) {
return typeof(f) == 'undefined' ? 'white' : f;
}
nodes.each(function(d) {
sel = d3.select(this);
var shape;
if (d.value.shape == 'ellipse') {
shape = sel.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 {
shape = sel.append('rect')
.attr('class', 'nodeRect')
.attr('width', d.value.width)
.attr('height', d.value.height);
}
shape.attr('fill', fillColor(d.value.fillcolor));
});
nodes.on('dblclick', releaseNode);
// Add nodes text
var nodesText = nodes.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;})
.attr('contenteditable', "true")
.on('dblclick', releaseNode);
// Drag-start event handler
function dragStart(d) {
d3.event.sourceEvent.stopPropagation();
d.fixed = true;
}
// 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', dragStart);
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,3064,868"]; "InplaceDimShuffle{x}" [height=0.5, pos="508,546", shape=ellipse, width=2.5686]; "Elemwise{Composite{((-i0) - i1)}}[(0, 0)]" [fillcolor="#FFAABB", height=0.5, pos="1180,458", shape=ellipse, style=filled, width=4.6165]; "InplaceDimShuffle{x}" -> "Elemwise{Composite{((-i0) - i1)}}[(0, 0)]" [label="1 TensorType(float64, (True,))", lp="991.5,502", pos="e,1077.2,472.16 583.13,535.39 700.83,520.32 929.42,491.07 1067,473.46"]; "name=b TensorType(float64, scalar)" [fillcolor=limegreen, height=0.5, pos="199,654", shape=box, style=filled, width=3.0625]; "name=b TensorType(float64, scalar)" -> "InplaceDimShuffle{x}" [color=dodgerblue, label="TensorType(float64, scalar)", lp="478,600", pos="e,464.47,561.93 248.65,635.97 305.09,616.61 396.89,585.12 454.78,565.26"]; "Elemwise{Composite{(i0 - (i1 * i2))}}[(0, 0)]" [fillcolor="#FFAABB", height=0.5, pos="179,18", shape=ellipse, style=filled, width=4.9776]; "name=b TensorType(float64, scalar)" -> "Elemwise{Composite{(i0 - (i1 * i2))}}[(0, 0)]" [color=red, label="0 TensorType(float64, scalar)", lp="131.5,326", pos="e,115.8,34.997 136.27,635.88 94.787,620.32 48,592.64 48,547 48,547 48,547 48,105 48,72.701 76.173,51.864 106.39,38.804"]; "Shape_i{0}" [fillcolor=cyan, height=0.5, pos="2254,762", shape=ellipse, style=filled, width=1.4763]; "AllocEmpty{dtype='float64'}" [fillcolor="#FFAA22", height=0.5, pos="2189,654", shape=ellipse, style=filled, width=3.2589]; "Shape_i{0}" -> "AllocEmpty{dtype='float64'}" [label="TensorType(int64, scalar)", lp="2248,708", pos="e,2179.1,672.11 2210,751.54 2196.5,746.34 2183,738.32 2175,726 2166.4,712.82 2169.6,695.57 2175,681.36"]; "Elemwise{eq,no_inplace}" [fillcolor="#FFAABB", height=0.5, pos="2151,458", shape=ellipse, style=filled, width=2.9297]; "Shape_i{0}" -> "Elemwise{eq,no_inplace}" [label="1 TensorType(int64, scalar)", lp="2396,600", pos="e,2182.2,475.28 2292.5,749.53 2303.6,744.23 2314.5,736.66 2321,726 2337.7,698.44 2320.8,609.52 2304,582 2276.5,536.93 2226.3,501.37 \ 2190.9,480.32"]; "name=x TensorType(float64, matrix)" [fillcolor=limegreen, height=0.5, pos="2254,850", shape=box, style=filled, width=3.1181]; "name=x TensorType(float64, matrix)" -> "Shape_i{0}" [label="TensorType(float64, matrix)", lp="2334,806", pos="e,2254,780.08 2254,831.6 2254,819.75 2254,803.82 2254,790.29"]; "InplaceDimShuffle{1,0}" [height=0.5, pos="2630,708", shape=ellipse, width=2.779]; "name=x TensorType(float64, matrix)" -> "InplaceDimShuffle{1,0}" [color=dodgerblue, label="TensorType(float64, matrix)", lp="2537,806", pos="e,2602.5,725.41 2353.5,831.92 2375.1,827.08 2397.5,821.13 2418,814 2482.4,791.59 2552.4,754.11 2593.7,730.52"]; "CGemv{inplace}" [height=0.5, pos="1944,546", shape=ellipse, width=2.0569]; "name=x TensorType(float64, matrix)" -> "CGemv{inplace}" [label="2 TensorType(float64, matrix)", lp="1754,708", pos="e,1876.1,553.37 2141.5,835.48 1970.2,812.32 1656.8,758.98 1590,672 1580.3,659.31 1580.4,648.84 1590,636 1606.6,613.66 1623.9,627.8 \ 1650,618 1686.1,604.42 1692.1,593.2 1729,582 1773.5,568.51 1824.8,559.91 1866.1,554.61"]; "name=x.T TensorType(float64, matrix)" [height=0.5, pos="2876,600", width=4.2783]; "InplaceDimShuffle{1,0}" -> "name=x.T TensorType(float64, matrix)" [label="TensorType(float64, matrix)", lp="2877,654", pos="e,2840.7,617.58 2670.9,691.4 2686.1,685.49 2703.4,678.59 2719,672 2757.2,655.86 2800.1,636.37 2831.4,621.9"]; "CGemv{inplace} id=19" [height=0.5, pos="2157,106", shape=ellipse, width=2.7013]; "name=x.T TensorType(float64, matrix)" -> "CGemv{inplace} id=19" [label="2 TensorType(float64, matrix)", lp="2979,370", pos="e,2253.7,108.43 2881.2,581.84 2886.5,562.77 2894,530.98 2894,503 2894,503 2894,503 2894,193 2894,130.33 2468.2,113.25 2263.9,108.65"]; "Shape_i{0} id=3" [fillcolor=cyan, height=0.5, pos="1571,546", shape=ellipse, style=filled, width=2.002]; "Shape_i{0} id=3" -> "Elemwise{eq,no_inplace}" [label="0 TensorType(int64, scalar)", lp="1844,502", pos="e,2046.9,461.21 1625.2,534.09 1654.2,527.86 1690.3,519.41 1722,510 1741.9,504.08 1745.7,498.54 1766,494 1855.6,473.98 1959.5,465.36 \ 2036.7,461.68"]; "InplaceDimShuffle{x} id=7" [height=0.5, pos="1659,458", shape=ellipse, width=3.1172]; "Shape_i{0} id=3" -> "InplaceDimShuffle{x} id=7" [color=dodgerblue, label="TensorType(int64, scalar)", lp="1645,502", pos="e,1597.3,473.16 1566.9,527.95 1565.3,517.28 1565.3,503.77 1572,494 1576.3,487.74 1582,482.59 1588.3,478.37"]; "name=y TensorType(float64, vector)" [fillcolor=limegreen, height=0.5, pos="1081,654", shape=box, style=filled, width=3.0903]; "name=y TensorType(float64, vector)" -> "Shape_i{0} id=3" [label="TensorType(float64, vector)", lp="1478,600", pos="e,1518.5,558.36 1159.7,635.97 1256.8,614.98 1419.7,579.74 1508.5,560.51"]; "Elemwise{sub,no_inplace}" [fillcolor="#FFAABB", height=0.5, pos="519,370", shape=ellipse, style=filled, width=3.0624]; "name=y TensorType(float64, vector)" -> "Elemwise{sub,no_inplace}" [label="1 TensorType(float64, vector)", lp="443.5,502", pos="e,471.35,386.34 969.54,651.53 773.46,648.4 385.48,639.5 365,618 333.32,584.73 310.57,554.44 395,440 411.59,417.51 437.83,401.4 461.9,\ 390.44"]; "Elemwise{Composite{((i0 * i1 * i2 * i3) + ((scalar_sigmoid((-i4)) *..." [fillcolor="#FFAABB", height=0.5, pos="1579,194", shape=ellipse, style=filled, width=7.3955]; "name=y TensorType(float64, vector)" -> "Elemwise{Composite{((i0 * i1 * i2 * i3) + ((scalar_sigmoid((-i4)) *..." [label="3 TensorType(float64, vector)", lp="2062.5,414", pos="e,1809.4,203.06 1192.5,650.77 1312.4,647.33 1494.8,638.79 1561,618 1655.4,588.35 1659.2,541.57 1746,494 1842.7,441 1874,442.62 1978,\ 406 1980.2,405.21 2302.6,301.93 2304,300 2366.8,213.53 2226.9,237.1 2185,230 2116.5,218.37 1957.6,209.44 1819.7,203.5"]; "Elemwise{Composite{((i0 * scalar_softplus(i1)) - (i2 * i3 * scalar_..." [fillcolor="#FFAABB", height=0.5, pos="964,282", shape=ellipse, style=filled, width=7.3087]; "name=y TensorType(float64, vector)" -> "Elemwise{Composite{((i0 * scalar_softplus(i1)) - (i2 * i3 * scalar_..." [label="0 TensorType(float64, vector)", lp="815.5,458", pos="e,805.95,296.4 969.3,640.75 866.87,626.32 731,597.63 731,547 731,547 731,547 731,369 731,345.49 727.5,333.69 745,318 754.35,309.62 \ 773.13,303.25 795.95,298.39"]; "Elemwise{sub,no_inplace}" -> "Elemwise{Composite{((i0 * i1 * i2 * i3) + ((scalar_sigmoid((-i4)) *..." [label="5 TensorType(float64, vector)", lp="607.5,282", pos="e,1343.6,202.42 513.52,351.82 507.28,328.56 500.62,287.28 523,264 550.73,235.15 1030.1,213.6 1333.3,202.78"]; "Elemwise{sub,no_inplace}" -> "Elemwise{Composite{((i0 * scalar_softplus(i1)) - (i2 * i3 * scalar_..." [label="3 TensorType(float64, vector)", lp="632.5,326", pos="e,778.18,294.77 524.07,351.81 528.44,340.21 535.99,325.68 548,318 557.92,311.66 664.92,302.74 767.9,295.49"]; "val=[ 1.] TensorType(float64, (True,))" [fillcolor=limegreen, height=0.5, pos="519,458", shape=box, style=filled, width=3.1944]; "val=[ 1.] TensorType(float64, (True,))" -> "Elemwise{sub,no_inplace}" [label="0 TensorType(float64, (True,))", lp="605.5,414", pos="e,519,388.08 519,439.6 519,427.75 519,411.82 519,398.29"]; "AllocEmpty{dtype='float64'}" -> "CGemv{inplace}" [color=red, label="0 TensorType(float64, vector)", lp="2219.5,600", pos="e,2016.8,549.67 2158.7,636.57 2150.5,631.29 2141.9,624.97 2135,618 2121.6,604.53 2127.6,592.78 2112,582 2087.2,564.9 2055.8,555.85 \ 2026.9,551.15"]; "Assert{msg='Theano Assert failed!'}" [height=0.5, pos="2151,282", shape=ellipse, width=4.013]; "Elemwise{eq,no_inplace}" -> "Assert{msg='Theano Assert failed!'}" [label="1 TensorType(int8, scalar)", lp="2225.5,370", pos="e,2151,300.07 2151,440 2151,409.85 2151,346.79 2151,310.43"]; "Elemwise{Cast{float64}}" [fillcolor="#FFAABB", height=0.5, pos="1747,370", shape=ellipse, style=filled, width=2.9207]; "InplaceDimShuffle{x} id=7" -> "Elemwise{Cast{float64}}" [label="TensorType(int64, (True,))", lp="1812.5,414", pos="e,1742.7,388.24 1699.4,441.12 1708.7,436.06 1717.9,429.72 1725,422 1731.3,415.17 1736,406.27 1739.4,397.81"]; "CGemv{inplace}" -> "Elemwise{Composite{((-i0) - i1)}}[(0, 0)]" [color=red, label="0 TensorType(float64, vector)", lp="2020.5,502", pos="e,1328.9,466.09 1941.4,527.81 1938.6,516.21 1933.1,501.68 1922,494 1886.9,469.7 1580.7,478.01 1538,476 1472.9,472.93 1401.2,469.53 \ 1339.2,466.58"]; "val=1.0 TensorType(float64, scalar)" [fillcolor=limegreen, height=0.5, pos="1708,654", shape=box, style=filled, width=3.0278]; "val=1.0 TensorType(float64, scalar)" -> "CGemv{inplace}" [label="1 TensorType(float64, scalar)", lp="1856.5,600", pos="e,1873.1,551.52 1719,635.79 1730.4,619.32 1749.9,595.1 1773,582 1800.2,566.56 1833.3,557.88 1863.1,553.02"]; "name=w TensorType(float64, vector)" [fillcolor=limegreen, height=0.5, pos="2597,654", shape=box, style=filled, width=3.1389]; "name=w TensorType(float64, vector)" -> "CGemv{inplace}" [label="3 TensorType(float64, vector)", lp="2590.5,600", pos="e,2017.7,548.11 2536.3,635.87 2525.5,631.16 2514.9,625.28 2506,618 2491.3,605.99 2499.3,591.66 2483,582 2444.9,559.49 2169.9,551.15 \ 2028.1,548.32"]; "name=w TensorType(float64, vector)" -> "CGemv{inplace} id=19" [color=red, label="0 TensorType(float64, vector)", lp="2773.5,370", pos="e,2247.8,112.55 2653.2,635.79 2661.5,631.15 2669.2,625.32 2675,618 2695,592.83 2689,579.16 2689,547 2689,547 2689,547 2689,193 2689,\ 149.8 2412.1,124.17 2257.8,113.24"]; "val=0.0 TensorType(float64, scalar)" [fillcolor=limegreen, height=0.5, pos="1944,654", shape=box, style=filled, width=3.0278]; "val=0.0 TensorType(float64, scalar)" -> "CGemv{inplace}" [label="4 TensorType(float64, scalar)", lp="2027.5,600", pos="e,1944,564.34 1944,635.97 1944,619.38 1944,593.88 1944,574.43"]; "Elemwise{inv,no_inplace}" [fillcolor="#FFAABB", height=0.5, pos="1879,282", shape=ellipse, style=filled, width=3.0304]; "Elemwise{Cast{float64}}" -> "Elemwise{inv,no_inplace}" [label="TensorType(float64, (True,))", lp="1836.5,326", pos="e,1793.6,293.26 1745.3,351.9 1745.2,340.94 1746.9,327.12 1755,318 1763,308.98 1773.1,302.21 1784.1,297.13"]; "Elemwise{Cast{float64}}" -> "Elemwise{Composite{((i0 * i1 * i2 * i3) + ((scalar_sigmoid((-i4)) *..." [label="6 TensorType(float64, (True,))", lp="1674.5,282", pos="e,1574.7,212.06 1736.9,351.97 1729.1,340.46 1717.3,325.95 1703,318 1657.8,292.88 1623.3,337.83 1588,300 1568.8,279.46 1569.4,245.81 \ 1573,222.14"]; sigmoid [fillcolor="#FFAABB", height=0.5, pos="1925,370", shape=ellipse, style=filled, width=1.1152]; "Elemwise{Composite{((-i0) - i1)}}[(0, 0)]" -> sigmoid [label="TensorType(float64, vector)", lp="1642,414", pos="e,1892.7,380.92 1334.4,451.28 1415.9,446.46 1506.6,437.71 1544,422 1554.2,417.72 1552.7,410.1 1563,406 1624.6,381.39 1795.5,398.57 \ 1861,388 1868.2,386.84 1875.7,385.22 1883,383.43"]; "Elemwise{neg,no_inplace}" [fillcolor="#FFAABB", height=0.5, pos="913,370", shape=ellipse, style=filled, width=3.0624]; "Elemwise{Composite{((-i0) - i1)}}[(0, 0)]" -> "Elemwise{neg,no_inplace}" [label="TensorType(float64, vector)", lp="993,414", pos="e,908.16,388.2 1019.9,453.04 972.64,448.31 929.37,439.18 914,422 908.29,415.62 906.75,406.78 907.05,398.26"]; "Elemwise{Composite{((-i0) - i1)}}[(0, 0)]" -> "Elemwise{Composite{((i0 * i1 * i2 * i3) + ((scalar_sigmoid((-i4)) *..." [label="4 TensorType(float64, vector)", lp="1614.5,326", pos="e,1571.2,212.21 1301.4,445.69 1384.1,435.49 1483.9,417.46 1514,388 1536.8,365.67 1520.5,348.47 1530,318 1540.6,284.05 1556.3,246.22 \ 1567,221.59"]; "Elemwise{Composite{((-i0) - i1)}}[(0, 0)]" -> "Elemwise{Composite{((i0 * scalar_softplus(i1)) - (i2 * i3 * scalar_..." [color=red, label="1 TensorType(float64, vector)", lp="1179.5,370", pos="e,1074.2,298.37 1147.5,440.33 1128.4,428.56 1105.9,410.82 1095,388 1088.1,373.55 1088.1,366.46 1095,352 1100.4,340.58 1111.6,345.42 \ 1117,334 1120,327.57 1121.4,323.56 1117,318 1111.6,311.21 1099.4,305.63 1084.1,301.08"]; "Elemwise{inv,no_inplace}" -> "Elemwise{Composite{((i0 * i1 * i2 * i3) + ((scalar_sigmoid((-i4)) *..." [label="2 TensorType(float64, (True,))", lp="1842.5,238", pos="e,1636.9,211.61 1827.1,266.12 1777.2,251.82 1701.5,230.13 1646.9,214.46"]; sigmoid -> "Assert{msg='Theano Assert failed!'}" [color=dodgerblue, label="0 TensorType(float64, vector)", lp="2026.5,326", pos="e,2051.2,295.04 1926.3,351.82 1928,340.54 1932.2,326.37 1942,318 1950.2,310.97 1995,303.01 2041,296.46"]; "Elemwise{Composite{GT(scalar_sigmoid(i0), i1)}}" [fillcolor="#FFAABB", height=0.5, pos="277,282", shape=ellipse, style=filled, width=5.59]; "Elemwise{neg,no_inplace}" -> "Elemwise{Composite{GT(scalar_sigmoid(i0), i1)}}" [label="0 TensorType(float64, vector)", lp="845.5,326", pos="e,422.14,294.49 845.06,355.7 818.58,349.91 788.13,342.5 761,334 742.73,328.28 739.65,322.36 721,318 621.58,294.78 593.78,308.02 \ 492,300 472.68,298.48 452.39,296.87 432.3,295.29"]; "Elemwise{neg,no_inplace}" -> "Elemwise{Composite{((i0 * scalar_softplus(i1)) - (i2 * i3 * scalar_..." [label="4 TensorType(float64, vector)", lp="1028.5,326", pos="e,954.04,300.02 923.28,351.93 926.7,346.23 930.53,339.85 934,334 938.88,325.79 944.17,316.81 948.94,308.71"]; "Assert{msg='Theano Assert failed!'}" -> "Elemwise{Composite{((i0 * i1 * i2 * i3) + ((scalar_sigmoid((-i4)) *..." [color=red, label="0 TensorType(float64, vector)", lp="2096.5,238", pos="e,1753.4,207.65 2093.6,265.39 2049.9,254.04 1988,239.12 1933,230 1878.2,220.93 1818.3,213.91 1763.5,208.62"]; "TensorType(int8, vector)" [fillcolor=dodgerblue, height=0.5, pos="488,194", shape=box, style=filled, width=2.1736]; "Elemwise{Composite{GT(scalar_sigmoid(i0), i1)}}" -> "TensorType(int8, vector)" [label="TensorType(int8, vector)", lp="429.5,238", pos="e,410.68,212.04 300.38,263.89 316.26,252.93 338.1,239.1 359,230 372.22,224.24 386.63,219.22 400.87,214.91"]; "val=[ 0.5] TensorType(float32, (True,))" [fillcolor=limegreen, height=0.5, pos="272,370", shape=box, style=filled, width=3.2847]; "val=[ 0.5] TensorType(float32, (True,))" -> "Elemwise{Composite{GT(scalar_sigmoid(i0), i1)}}" [label="1 TensorType(float32, (True,))", lp="361.5,326", pos="e,276.01,300.08 273.01,351.6 273.7,339.75 274.63,323.82 275.41,310.29"]; "Sum{acc_dtype=float64}" [height=0.5, pos="179,106", shape=ellipse, width=2.8658]; "Elemwise{Composite{((i0 * i1 * i2 * i3) + ((scalar_sigmoid((-i4)) *..." -> "Sum{acc_dtype=float64}" [label="TensorType(float64, vector)", lp="259,150", pos="e,173.93,124.01 1351.4,184.61 1265.7,181.63 1167.4,178.41 1078,176 1053.1,175.33 197.64,175.65 180,158 173.79,151.79 172.24,142.73 \ 172.68,133.97"]; "Elemwise{Composite{((i0 * i1 * i2 * i3) + ((scalar_sigmoid((-i4)) *..." -> "CGemv{inplace} id=19" [label="3 TensorType(float64, vector)", lp="2004.5,150", pos="e,2083.8,117.89 1683.7,177.43 1795.6,160.77 1970.8,134.7 2073.7,119.39"]; "val=[-1.] TensorType(float64, (True,))" [fillcolor=limegreen, height=0.5, pos="1389,370", shape=box, style=filled, width=3.2222]; "val=[-1.] TensorType(float64, (True,))" -> "Elemwise{Composite{((i0 * i1 * i2 * i3) + ((scalar_sigmoid((-i4)) *..." [label="1 TensorType(float64, (True,))", lp="1432.5,282", pos="e,1485.7,210.92 1371.9,351.66 1352.4,329.66 1325.6,291.3 1346,264 1362.2,242.24 1421.1,224.92 1475.6,213.07"]; "val=[-1.] TensorType(float64, (True,))" -> "Elemwise{Composite{((i0 * scalar_softplus(i1)) - (i2 * i3 * scalar_..." [label="2 TensorType(float64, (True,))", lp="1260.5,326", pos="e,1085.4,297.98 1272.9,352.33 1227.5,345.39 1184,338.03 1174,334 1162.5,329.33 1162.5,322.81 1151,318 1133.5,310.67 1114.4,304.87 \ 1095.4,300.27"]; "TensorType(float64, vector) id=26" [fillcolor=dodgerblue, height=0.5, pos="964,194", shape=box, style=filled, width=2.9236]; "Elemwise{Composite{((i0 * scalar_softplus(i1)) - (i2 * i3 * scalar_..." -> "TensorType(float64, vector) id=26" [label="TensorType(float64, vector)", lp="1043,238", pos="e,964,212.08 964,263.6 964,251.75 964,235.82 964,222.29"]; "Sum{acc_dtype=float64}" -> "Elemwise{Composite{(i0 - (i1 * i2))}}[(0, 0)]" [label="2 TensorType(float64, scalar)", lp="262.5,62", pos="e,179,36.084 179,87.597 179,75.746 179,59.817 179,46.292"]; "val=-0.01 TensorType(float64, scalar)" [fillcolor=limegreen, height=0.5, pos="276,194", shape=box, style=filled, width=3.1944]; "val=-0.01 TensorType(float64, scalar)" -> "CGemv{inplace} id=19" [label="1 TensorType(float64, scalar)", lp="965.5,150", pos="e,2059.6,107.51 391.14,176.83 394.12,176.53 397.08,176.26 400,176 1023,121.19 1774.1,109.92 2049.3,107.6"]; "val=0.9998 TensorType(float64, scalar)" [fillcolor=limegreen, height=0.5, pos="2157,194", shape=box, style=filled, width=3.3125]; "val=0.9998 TensorType(float64, scalar)" -> "CGemv{inplace} id=19" [label="4 TensorType(float64, scalar)", lp="2240.5,150", pos="e,2157,124.08 2157,175.6 2157,163.75 2157,147.82 2157,134.29"]; "val=0.01 TensorType(float64, scalar)" [fillcolor=limegreen, height=0.5, pos="413,106", shape=box, style=filled, width=3.1181]; "val=0.01 TensorType(float64, scalar)" -> "Elemwise{Composite{(i0 - (i1 * i2))}}[(0, 0)]" [label="1 TensorType(float64, scalar)", lp="458.5,62", pos="e,285.55,32.604 396.38,87.768 384.5,76.465 367.56,62.293 350,54 332.97,45.956 314.12,39.755 295.35,34.975"]; }
\ No newline at end of file
<!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;
}
.tooltip {
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;
}
</style>
<div>
<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='train.dot';
// 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', 'tooltip')
.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 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';
}
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.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.fixed = true;
nodes.push(node);
dotGraph._nodes[nodeId] = node;
}
// 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 fillColor(f) {
return typeof(f) == 'undefined' ? 'white' : f;
}
nodes.each(function(d) {
sel = d3.select(this);
var shape;
if (d.value.shape == 'ellipse') {
shape = sel.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 {
shape = sel.append('rect')
.attr('class', 'nodeRect')
.attr('width', d.value.width)
.attr('height', d.value.height);
}
shape.attr('fill', fillColor(d.value.fillcolor));
});
nodes.on('dblclick', releaseNode);
// Add nodes text
var nodesText = nodes.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;})
.attr('contenteditable', "true")
.on('dblclick', releaseNode);
// Drag-start event handler
function dragStart(d) {
d3.event.sourceEvent.stopPropagation();
d.fixed = true;
}
// 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', dragStart);
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>
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论