Public
Edited
Jun 4, 2023
Insert cell
md`# Network VAST CHALLENGE Alvaro`
Insert cell
chart = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);

svg.append('rect')
.attr('width', '100%')
.attr('height', '100%')
.attr('fill', 'white')
.on('click', function() {
// Restore nodes and links to normal opacity.
d3.selectAll('.link').style('stroke-opacity', '0.6');
d3.selectAll('.node').style('opacity', '1');
});
var container = svg.append('g');
// Call zoom for svg container.
svg.call(zoom(container));

var link = container.append("g")
.attr("class", "links")
.selectAll("line");
var node = container.append("g")
.attr("class", "nodes")
.selectAll("circle");

// Make object of all neighboring nodes.
var linkedByIndex = {};
json.links.forEach(function(d) {
linkedByIndex[d.source.index + ',' + d.target.index] = 1;
linkedByIndex[d.target.index + ',' + d.source.index] = 1;
});

// A function to test if two nodes are neighboring.
function neighboring(a, b) {
return linkedByIndex[a.source.index + ',' + b.source.index];
}

return Object.assign(svg.node(), {
update(nodes,links) {

link = link.data(links, function(d) { return d.source.index + ", " + d.target.index;});
link.exit().remove();
var linkEnter = link.enter().append("line")
.attr('class', 'link')
.attr('stroke', 'gray');
link = linkEnter.merge(link);

node = node.data(nodes);
node.exit().remove();
var nodeEnter = node.enter().append("circle")
// Use degree centrality from NetworkX in json.
.attr('r', function(d, i) { return degreeSize(d.degree); })
// Color by group, a result of modularity calculation in NetworkX.
.attr("fill", function(d) { return color(d.group); })
.attr('class', 'node')
// On click, toggle ego networks for the selected node.
.on('click', function(d, i) {
// Ternary operator restyles links and nodes if they are adjacent.
d3.selectAll('.link').style('stroke-opacity', function (l) {
return l.target == d || l.source == d ? 1 : 0.1;
});
d3.selectAll('.node').style('opacity', function (n) {
return neighboring(d, n) ? 1 : 0.1;
});
d3.select(this).style('opacity', 1);
})
.call(drag(simulation));
node = nodeEnter.merge(node);
node.append("title")
.text(function(d) { return d.name; });

simulation
.nodes(nodes)
.on("tick", ticked);

simulation.force("link")
.links(links);
simulation.alpha(1).restart();

function ticked() {
link
.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });

node
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
}
}
});
}
Insert cell
// A slider (using only d3 and HTML5) that removes nodes below the input threshold.
slider = {

let min = d3.min(json.links, function(d) {return d.weight; });
let max = d3.max(json.links, function(d) {return d.weight; })
let slider = html`
<label for="threshold">Edge Weight Threshold: ${min}</label>
<input type="range" min="${min}" max="${max}" style="width:75%;"></input>`;
let label = slider.querySelector('label');
let range = slider.querySelector('input');
range.value = min
range.oninput = () => {
let threshold = range.valueAsNumber
label.innerHTML = `Edge Weight Threshold: ${threshold}`
let newLinks = json.links.filter(l => l.weight > threshold);
chart.update(json.nodes,newLinks);
};
return slider;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
json = FileAttachment("archivo_alvaro@1.json").json();
Insert cell
chart.update(json.nodes,json.links)
Insert cell
d3 = require("d3@4")
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more