chart = {
const wtcut = 0;
const links = data.links.map(d => Object.create(d));
const nodes = data.nodes.map(d => Object.create(d));
const simulation = d3.forceSimulation(nodes)
.force('x', d3.forceX().strength(2).x(d =>width/(maxLayer+4) * (d.LayerNum+1)))
.force('y', d3.forceY().strength(0.7).y(height / 2))
.force("link", d3.forceLink(links).strength(0).id(d => d.id))
.force("charge", d3.forceManyBody().strength(-40000/data['nodes'].length))
.force("center", d3.forceCenter(width / 2-100, height / 2));
const svg = d3.select(DOM.svg(width, height));
var newLinks = links.filter( function(d) { return 0.5 <= Math.abs(d.weight)/maxwt && Math.abs(d.weight)/maxwt <= 1;} );
var link = svg.append("g")
.attr("class","link")
.selectAll(".link")
.data(newLinks)
.join("line")
.attr("class", "link")
.attr("stroke", d => d.weight> 0? "#FF374C":"#6495ED")
.attr("stroke-opacity", d => Math.abs(d.weight)/maxwt)
.attr("stroke-width", d => Math.abs(d.weight)>wtcut? Math.abs(d.weight)/maxwt*4 : 0);
link.append("title")
.text( d => "From: L-" + d.source.LayerNum + " ,N-" + d.source.NodeNum + " to: L-" + d.target.LayerNum + ", N-" + d.target.NodeNum + " Weight: " +d.weight);
const node = svg.append("g")
.attr("stroke", "#fff")
.attr("stroke-width", 1.5)
.selectAll("circle")
.data(nodes)
.join("circle")
.attr("id", d => "node_"+d.id)
.attr("r", d => Math.abs(d.valueScaled)*10+3)
.attr("fill", d => d.valueScaled> 0? "#FF8C00":"#00CED1")
//.attr("fill", color)
//.attr("opacity", d => Math.abs(d.valueScaled)*0.6)
.call(drag(simulation))
//draw the link selection box
const bar = svg.append("g")
bar.append("rect")
.attr(x)
var temp1 = 0.5;
var temp2 = maxwt;
bar.append("text")
.attr("id","slt_info")
.attr("x", 100 )
.attr("y",height*9/10 - 40)
.attr("font-family", "sans-serif")
.attr("font-size", "10px")
.text("Selecting "+ newLinks.length + " links with weight between "+ temp1.toFixed(2) +" and " + temp2.toFixed(2));
var x = d3.scaleLinear()
.domain([0.0, 1])
.range([100, width*2/3]);
var brush = d3.brushX()
.extent([[100, height*9/10 - 32], [width*2/3, height*9/10]])
//.on("start brush end", brushed);
.on("start brush", brushed)
.on("end", brushended);
const axis = bar.append("g")
.attr("transform", "translate(0," + height*9/10 + ")")
.call(d3.axisBottom(x));
var dot = bar.append("g")
.selectAll(".dot")
.data(links)
.enter()
.append("circle")
.attr("class","dot")
.attr("cx", d=>x(Math.abs(d.weight)/maxwt))
.attr("cy", d => d.weight> 0? height*9/10 -10 : height*9/10 -20)
.attr("fill", d => d.weight>= 0? "#FF374C":"#6495ED")
.attr("r", 1.5)
.attr("fill-opacity", d=> Math.abs(d.weight)/maxwt)
//draw link-selector
var temp = 0.5*maxwt;
bar.append("g")
.call(brush)
.call(brush.move, [x(0.5),x(1.0)])
//.selectAll(".overlay")
//.each(function(d) { d.type = "selection"; }) // Treat overlay interaction as move.
//.on("mousedown touchstart", brushclicked); // Recenter before brushing.
//function brushclicked() {
//var cx = d3.mouse(this)[0];
//d3.select(this.parentNode).call(brush.move, cx > x(1.0) ? [x(0.0), x(1.1)] : cx < x(-0) ? [x(-0.0), x(1.0)] : [cx, x(1.0)]);
//}
function brushed() {
var extent = d3.event.selection;
var newLinks = links.filter( function(d) { return extent[0] <= x(Math.abs(d.weight)/maxwt) && x(Math.abs(d.weight)/maxwt) <= extent[1];});
svg.selectAll(".link").remove();
link = svg.append("g")
.attr("class","link")
.selectAll(".link")
.data(newLinks)
.join("line")
.attr("class", "link")
.attr("stroke", d => d.weight> 0? "#FF374C":"#6495ED")
.attr("stroke-opacity", d => Math.abs(d.weight)/maxwt)
.attr("stroke-width", d => Math.abs(d.weight)>wtcut? Math.abs(d.weight)/maxwt*4 : 0)
.attr("x1", d => d.source.x)
.attr("y1", d => d.source.y)
.attr("x2", d => d.target.x)
.attr("y2", d => d.target.y)
link.append("title")
.text( d => "From: L-" + d.source.LayerNum + " ,N-" + d.source.NodeNum + " to: L-" + d.target.LayerNum + ", N-" + d.target.NodeNum + " Weight: " +d.weight);
if(document.getElementById("slt_info"))
{
var temp1 = x.invert(extent[0])*maxwt;
var temp2 = x.invert(extent[1])*maxwt;
document.getElementById("slt_info").textContent = "Selecting "+ newLinks.length + " links with weight between "+ temp1.toFixed(2) +" and " + temp2.toFixed(2);
}
}
function brushended(){
return 0;
}
//done with selection box
//draw the legend
const leg = svg.append("g")
leg.append("rect")
.attr("x", width*9/10 - 100)
.attr("y", height/2 - 160)
.attr("width", 80)
.attr("height", 320)
.attr("fill", "gray")
.attr("fill-opacity",0.2)
for(let i = 0; i<5; i++)
{
leg.append("circle")
.attr("cx", width*9/10 - 80)
.attr("cy", height/2 + i*30 - 135)
.attr("r", (5-i) *10/5 + 3)
.attr("fill", "#FF8C00")
var circle_text = (5-i)/5;
leg.append("text")
.attr("x", width*9/10 - 30)
.attr("y", height/2 +i*30 - 135 + 4)
.attr("text-anchor","end")
.attr("font-family", "sans-serif")
.attr("font-size", "12px")
.text(circle_text.toFixed(2))
}
for(let i = 0; i<5; i++)
{
leg.append("circle")
.attr("cx", width*9/10 -80)
.attr("cy", height/2 + i*30 + 15)
.attr("r", (i+1) *10/5 + 3)
.attr("fill", "#00CED1")
var circle_text = -(i+1)/5;
leg.append("text")
.attr("x", width*9/10 - 30)
.attr("y", height/2 + i*30 + 15 + 4)
.attr("text-anchor","end")
.attr("font-family", "sans-serif")
.attr("font-size", "12px")
.text(circle_text.toFixed(2))
}
leg.append("rect")
.attr("x", width*9/10)
.attr("y", height/2 - 160)
.attr("width", 80)
.attr("height", 320)
.attr("fill", "gray")
.attr("fill-opacity",0.2)
for(let i = 0; i<5; i++)
{
leg.append("line")
.attr("x1", width*9/10 + 10)
.attr("y1", height/2 +i*30 - 135)
.attr("x2", width*9/10 + 30)
.attr("y2", height/2 +i*30 - 135)
.attr("stroke", "#FF374C")
.attr("stroke-opacity", d => (5-i)/maxwt)
.attr("stroke-width", (5-i)/maxwt*4);
var line_text = (5-i);
leg.append("text")
.attr("x", width*9/10+70)
.attr("y", height/2 +i*30 - 135 + 4)
.attr("text-anchor","end")
.attr("font-family", "sans-serif")
.attr("font-size", "12px")
.text(line_text.toFixed(2))
}
for(let i = 0; i<5; i++)
{
leg.append("line")
.attr("x1", width*9/10 + 10)
.attr("y1", height/2 +i*30 + 15)
.attr("x2", width*9/10 + 30)
.attr("y2", height/2 +i*30 + 15)
.attr("stroke", "#6495ED")
.attr("stroke-opacity", d => (i+1)/maxwt)
.attr("stroke-width", (i+1)/maxwt*4);
var line_text = -(i+1);
leg.append("text")
.attr("x", width*9/10+70)
.attr("y", height/2 +i*30 + 15 + 4)
.attr("text-anchor","end")
.attr("font-family", "sans-serif")
.attr("font-size", "12px")
.text(line_text.toFixed(2))
}
node.append("title")
.attr("id", d => "title_" + d.id)
.text(d => ['layer:'+d.LayerNum, ' node:'+d.NodeNum, ' value:'+d.value]);
simulation.on("tick", () => {
link
.attr("x1", d => d.source.x)
.attr("y1", d => d.source.y)
.attr("x2", d => d.target.x)
.attr("y2", d => d.target.y);
node
.attr("cx", d => d.x)
.attr("cy", d => d.y);
});
invalidation.then(() => simulation.stop());
return svg.node();
}