159 lines
5.2 KiB
JavaScript
159 lines
5.2 KiB
JavaScript
|
var colorTable = [
|
||
|
'#2124FF', // input
|
||
|
'#FF2718', // output
|
||
|
'#1F22C1', // logistic sigmoid
|
||
|
'#EE8A2A', // tanh
|
||
|
'#B17516', // identity
|
||
|
'#B1B0AA', // hlim
|
||
|
'#2CB11F', // relu
|
||
|
'#C5B12C', // softsign
|
||
|
'#E685E7', // sinusoid
|
||
|
'#257580', // gaussian
|
||
|
'#B0484B', // softplus
|
||
|
'#4CB148', // bent_identity
|
||
|
'#000000' // GATE
|
||
|
];
|
||
|
|
||
|
var NODE_RADIUS = 7;
|
||
|
var REPEL_FORCE = 10;
|
||
|
var LINK_DISTANCE = 100;
|
||
|
|
||
|
var drawGraph = function(graph, panel, activation) {
|
||
|
var d3cola = cola.d3adaptor()
|
||
|
.avoidOverlaps(true)
|
||
|
.size([$('.best').width(), $('.best').height()]);
|
||
|
|
||
|
var svg = d3.select(panel);
|
||
|
|
||
|
d3.selectAll(panel + "> *").remove();
|
||
|
|
||
|
// define arrow markers for graph links
|
||
|
svg.append('svg:defs').append('svg:marker')
|
||
|
.attr('id', 'end-arrow')
|
||
|
.attr('viewBox', '0 -5 10 10')
|
||
|
.attr('refX', 6)
|
||
|
.attr('markerWidth', 5)
|
||
|
.attr('markerHeight', 5)
|
||
|
.attr('orient', 'auto')
|
||
|
.append('svg:path')
|
||
|
.attr('d', 'M0,-5L10,0L0,5')
|
||
|
.attr('fill', '#000');
|
||
|
|
||
|
graph.nodes.forEach(function (v) { v.height = v.width = 2 * NODE_RADIUS; });
|
||
|
|
||
|
d3cola
|
||
|
.nodes(graph.nodes)
|
||
|
.links(graph.links)
|
||
|
.symmetricDiffLinkLengths(REPEL_FORCE)
|
||
|
.linkDistance(LINK_DISTANCE)
|
||
|
.start(10, 15, 20);
|
||
|
|
||
|
var path = svg.selectAll(".link")
|
||
|
.data(graph.links)
|
||
|
.enter().append('svg:path')
|
||
|
.attr('class', 'link')
|
||
|
.style("stroke-width", function (d) {
|
||
|
if(activation){
|
||
|
return 1.5;
|
||
|
} else {
|
||
|
return 1.5 + Math.sqrt(d.weight * 5);
|
||
|
}
|
||
|
})
|
||
|
.style("stroke", function (d) {
|
||
|
if(activation){
|
||
|
return activationColor(d.source.activation * d.weight, graph.main.maxActivation * graph.main.maxWeight);
|
||
|
} else if(d.gate){
|
||
|
if(d.source.activation){
|
||
|
return activationColor(d.source.activation, graph.main.maxActivation);
|
||
|
} else{
|
||
|
return 'rgb(255,0,0)';
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
var node = svg.selectAll(".node")
|
||
|
.data(graph.nodes)
|
||
|
.enter().append("circle")
|
||
|
.attr("class", "node")
|
||
|
.attr("r", function(d) { return NODE_RADIUS; })
|
||
|
.style("fill", function (d) {
|
||
|
if(activation){
|
||
|
return activationColor(d.activation, graph.main.maxActivation);
|
||
|
} else {
|
||
|
return colorTable[d.type];
|
||
|
}
|
||
|
|
||
|
})
|
||
|
.call(d3cola.drag);
|
||
|
|
||
|
node.append("title")
|
||
|
.text(function (d) { return d.id; });
|
||
|
|
||
|
var label = svg.selectAll(".label")
|
||
|
.data(graph.nodes)
|
||
|
.enter().append("text")
|
||
|
.attr("class", "label")
|
||
|
.text(function (d) { return '(' + d.index + ') ' + d.name; })
|
||
|
.call(d3cola.drag)
|
||
|
|
||
|
d3cola.on("tick", function () {
|
||
|
// draw directed edges with proper padding from node centers
|
||
|
path.attr('d', function (d) {
|
||
|
var deltaX = d.target.x - d.source.x,
|
||
|
deltaY = d.target.y - d.source.y,
|
||
|
dist = Math.sqrt(deltaX * deltaX + deltaY * deltaY),
|
||
|
normX = deltaX / dist,
|
||
|
normY = deltaY / dist;
|
||
|
|
||
|
if(isNaN(normX)) normX = 0;
|
||
|
if(isNaN(normY)) normY = 0;
|
||
|
|
||
|
sourcePadding = NODE_RADIUS,
|
||
|
targetPadding = NODE_RADIUS + 2,
|
||
|
sourceX = d.source.x + (sourcePadding * normX),
|
||
|
sourceY = d.source.y + (sourcePadding * normY),
|
||
|
targetX = d.target.x - (targetPadding * normX),
|
||
|
targetY = d.target.y - (targetPadding * normY);
|
||
|
|
||
|
// Defaults for normal edge.
|
||
|
drx = 0,
|
||
|
dry = 0,
|
||
|
xRotation = 0, // degrees
|
||
|
largeArc = 0, // 1 or 0
|
||
|
sweep = 1; // 1 or 0
|
||
|
|
||
|
// Self edge.
|
||
|
if (d.source.x === d.target.x && d.source.y === d.target.y) {
|
||
|
drx = dist;
|
||
|
dry = dist;
|
||
|
// Fiddle with this angle to get loop oriented.
|
||
|
xRotation = -45;
|
||
|
|
||
|
// Needs to be 1.
|
||
|
largeArc = 1;
|
||
|
|
||
|
// Change sweep to change orientation of loop.
|
||
|
//sweep = 0;
|
||
|
|
||
|
// Make drx and dry different to get an ellipse
|
||
|
// instead of a circle.
|
||
|
drx = 20;
|
||
|
dry = 20;
|
||
|
|
||
|
// For whatever reason the arc collapses to a point if the beginning
|
||
|
// and ending points of the arc are the same, so kludge it.
|
||
|
targetX = targetX + 1;
|
||
|
targetY = targetY + 1;
|
||
|
}
|
||
|
return 'M' + sourceX + ',' + sourceY + "A" + drx + "," + dry + " " + xRotation + "," + largeArc + "," + sweep + " " + targetX + ',' + targetY;
|
||
|
});
|
||
|
|
||
|
node.attr("cx", function (d) { return d.x; })
|
||
|
.attr("cy", function (d) { return d.y; })
|
||
|
|
||
|
label
|
||
|
.attr("x", function (d) { return d.x + 10; })
|
||
|
.attr("y", function (d) { return d.y - 10; });
|
||
|
});
|
||
|
};
|