Public
Edited
Dec 7, 2022
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
sigma = import('https://cdn.skypack.dev/sigma@2.4.0?min')
Insert cell
Insert cell
Insert cell
graph = {
const sourceCSV = d3.csvParse(
await FileAttachment("styles (1).csv").text(),
d3.autoType
)

const graph = new Graph({type: 'undirected'});

// Create nodes: images
sourceCSV.forEach(row => {
let nid = row.image_url;
if (!graph.hasNode(nid)) {
let nodeColor = "#666666"
if (row.style == "cubisme") {
nodeColor = "#6666FF";
} else if (row.style == "impressionnisme") {
nodeColor = "#33FF33";
}
graph.addNode(nid, {
label: "img "+row.style,
kind: "image",
style: row.style,
color: nodeColor,
size: 3,
});
}
})

// Create nodes: cluster
sourceCSV.forEach(row => {
let nid = row.numero_cluster;
if (!graph.hasNode(nid)) {
graph.addNode(nid, {
label: "Cluster",
kind: "cluster",
numero_cluster: row.numero_cluster,
color: 'red',
size: 4,
});
}
})

// Create nodes: City
sourceCSV.forEach(row => {
let nid = row.City;
if (!graph.hasNode(nid)) {
graph.addNode(nid, {
label: row.City,
kind: "city",
size: 10,
});
}
})

// Create links: part of
sourceCSV.forEach(row => {
let sourceid = row.image_url;
let targetid = row.numero_cluster;
if (!graph.hasEdge(sourceid, targetid)) {
graph.addEdge(sourceid, targetid, {
kind: "part of",
color: "#00FFFF",
});
}
})

// Create links: is in
sourceCSV.forEach(row => {
let sourceid = row.image_url;
let targetid = row.City;
if (!graph.hasEdge(sourceid, targetid)) {
graph.addEdge(sourceid, targetid, {
kind: "is in",
color: "#FFFF00",
});
}
})

applyLayout(graph);
return graph;
}
Insert cell
graph.getNodeAttributes(graph.nodes()[0])
Insert cell
Insert cell
{
// Copy the graph to keep the original untouched
const g = graph.copy();

// Set node size and color
const nodeRadius = 4;
// Create canvas
const canvas = document.createElement('canvas');
canvas.width = 800;
canvas.height = 400;
const ctx = canvas.getContext('2d');

/// Scale node coordinates
// Extents
var xExtent = d3.extent(
g.nodes()
.map(nid => {
let n = g.getNodeAttributes(nid)
return n.x
})
);
var yExtent = d3.extent(
g.nodes()
.map(nid => {
let n = g.getNodeAttributes(nid)
return n.y
})
);
let xRange = [0, canvas.width];
let yRange = [0, canvas.height];
// Compare the ratios (range / domain)
const ratioX = (xExtent[1]-xExtent[0]) / canvas.width;
const ratioY = (yExtent[1]-yExtent[0]) / canvas.height;
if (ratioX < ratioY) {
// L'axe X est le plus étiré
const xMiddle = canvas.width / 2;
const newRange = canvas.height;
xRange = [xMiddle - (newRange/2), xMiddle + (newRange/2)];
} else {
// L'axe Y est le plus étiré
const yMiddle = canvas.height / 2;
const newRange = canvas.width;
yRange = [yMiddle - (newRange/2), yMiddle + (newRange/2)];
}
// Adapter le range pour gérer la taille des noeuds
const margin = nodeRadius + 12;
xRange[0] += margin;
xRange[1] -= margin;
yRange[0] += margin;
yRange[1] -= margin;
// Flip axe Y
yRange.reverse();
// Build scales
var x = d3.scaleLinear()
.domain(xExtent)
.range(xRange);
var y = d3.scaleLinear()
.domain(yExtent)
.range(yRange);

/// Draw edges
// Iterate over the edges
g.edges().forEach(eid => {
// Get the node object for the source and the target
let ns = g.getNodeAttributes(g.source(eid));
let nt = g.getNodeAttributes(g.target(eid));
let e = g.getEdgeAttributes(eid);
// Set style
ctx.strokeStyle = e.color;
ctx.lineWidth = 1;
// Draw line
ctx.beginPath();
ctx.moveTo(x(ns.x), y(ns.y));
ctx.lineTo(x(nt.x), y(nt.y));
ctx.stroke();
})

/// Draw nodes
// Iterate over the nodes
g.nodes().forEach(nid => {
// Get the node object (has coordinates and attributes)
let n = g.getNodeAttributes(nid);

// Set style
ctx.fillStyle = n.color;
// Draw circle
ctx.beginPath();
ctx.arc(x(n.x), y(n.y), nodeRadius, 0, 2 * Math.PI, false);
ctx.fill();
});

// Titre
let nodeKinds = {};
g.nodes().forEach(nid => {
let n = g.getNodeAttributes(nid);
nodeKinds[n.kind] = n.color;
});
ctx.textAlign = "left";
ctx.font = "24px sans-serif";
ctx.fillStyle = "#303040";
ctx.fillText(`Types de noeuds: ${
Object.keys(nodeKinds)
.map(kind => `${kind} (${ nodeKinds[kind] })`)
.join(", ")
}.`, 10, 30);
return canvas;
}
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