Spaces:
Sleeping
Sleeping
| """Adjacency matrix template — network family. | |
| d3-graph-gallery.com has no dedicated adjacency-matrix example (no | |
| `/graph/matrix_basic.html` or sibling page — confirmed 404, and the site's | |
| network/arc/chord section pages link only to force graphs, arc diagrams, | |
| and chord diagrams). The closest real sibling on that site for a grid of | |
| colored cells is the general heatmap example — | |
| https://d3-graph-gallery.com/graph/heatmap_style.html (d3 v4: d3.scaleBand() | |
| row/column axes, d3.scaleSequential(d3.interpolateInferno) cell coloring, | |
| cells loaded from a remote CSV via d3.csv()). Here the row/column bands are | |
| keyed by `data.nodes` ids (not a remote CSV), and cell values come from an | |
| NxN matrix built dynamically from `data.links` (same source/target-id | |
| lookup approach as network_chord.py) rather than a hardcoded/loaded table. | |
| """ | |
| from __future__ import annotations | |
| from app.agents.d3.registry import D3Template, register | |
| from app.agents.d3.templates._graph import GraphData, GraphNode, GraphLink | |
| _HTML = """<!-- Adapted from d3-graph-gallery.com (Yan Holtz) — https://d3-graph-gallery.com/graph/heatmap_style.html (no adjacency-matrix example exists on this site; closest sibling grid-of-cells chart substituted, see module docstring) --> | |
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <meta charset="utf-8"> | |
| <script src="https://d3js.org/d3.v7.min.js"></script> | |
| <style> | |
| html, body { margin: 0; padding: 0; width: 100vw; height: 100vh; background: #FAF7F2; color: #1A3557; font-family: Georgia, 'Libre Caslon Text', serif; overflow: hidden; } | |
| #my_dataviz { width: 100vw; height: 100vh; } | |
| .chart-title { fill: #1A3557; font-size: 18px; text-anchor: middle; } | |
| .axis text { fill: #1A3557; font-size: 11px; } | |
| .axis path, .axis line { display: none; } | |
| .cell { stroke: #FAF7F2; } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="my_dataviz"></div> | |
| <script> | |
| const data = __DATA__; | |
| const margin = {top: 110, right: 30, bottom: 20, left: 110}, | |
| width = 960 - margin.left - margin.right, | |
| height = 600 - margin.top - margin.bottom; | |
| const svg = d3.select("#my_dataviz") | |
| .append("svg") | |
| .attr("viewBox", `0 0 ${width + margin.left + margin.right} ${height + margin.top + margin.bottom}`) | |
| .attr("preserveAspectRatio", "xMidYMid meet") | |
| .style("width", "100%") | |
| .style("height", "100%") | |
| .append("g") | |
| .attr("transform", `translate(${margin.left},${margin.top})`); | |
| svg.append("text") | |
| .attr("class", "chart-title") | |
| .attr("x", width / 2) | |
| .attr("y", -70) | |
| .text(data.title); | |
| const ids = data.nodes.map(d => d.id); | |
| const index = new Map(ids.map((id, i) => [id, i])); | |
| const n = ids.length; | |
| const matrix = Array.from({length: n}, () => new Array(n).fill(0)); | |
| data.links.forEach(link => { | |
| const i = index.get(link.source); | |
| const j = index.get(link.target); | |
| if (i === undefined || j === undefined) return; | |
| matrix[i][j] += link.value; | |
| matrix[j][i] += link.value; | |
| }); | |
| const x = d3.scaleBand().range([0, width]).domain(ids).padding(0.05); | |
| const y = d3.scaleBand().range([0, height]).domain(ids).padding(0.05); | |
| svg.append("g") | |
| .attr("class", "axis") | |
| .call(d3.axisTop(x).tickSize(0)) | |
| .selectAll("text") | |
| .attr("transform", "translate(6,-8) rotate(-30)") | |
| .style("text-anchor", "start"); | |
| svg.append("g") | |
| .attr("class", "axis") | |
| .call(d3.axisLeft(y).tickSize(0)); | |
| const maxValue = d3.max(matrix.flat()) || 1; | |
| const color = d3.scaleSequential(d3.interpolateBlues).domain([0, maxValue]); | |
| const cells = []; | |
| matrix.forEach((row, i) => row.forEach((v, j) => cells.push({ row: ids[i], col: ids[j], value: v }))); | |
| svg.selectAll(".cell") | |
| .data(cells) | |
| .join("rect") | |
| .attr("class", "cell") | |
| .attr("x", d => x(d.col)) | |
| .attr("y", d => y(d.row)) | |
| .attr("width", x.bandwidth()) | |
| .attr("height", y.bandwidth()) | |
| .attr("rx", 3) | |
| .style("fill", d => d.value === 0 ? "#EFE9DF" : color(d.value)); | |
| </script> | |
| </body> | |
| </html> | |
| """ | |
| golden_sample = GraphData( | |
| title="Demo", | |
| nodes=[ | |
| GraphNode(id="A", group="x"), | |
| GraphNode(id="B", group="x"), | |
| GraphNode(id="C", group="y"), | |
| ], | |
| links=[ | |
| GraphLink(source="A", target="B", value=2), | |
| GraphLink(source="B", target="C", value=1), | |
| ], | |
| ) | |
| register( | |
| D3Template( | |
| id="network_adjacency_matrix", | |
| family="network", | |
| title="Adjacency matrix", | |
| when_to_use="Show which named entities connect to which, and how strongly, as a grid of colored cells.", | |
| data_requirements="A list of nodes (id, optional group) and weighted links (source id, target id, value).", | |
| schema=GraphData, | |
| html_template=_HTML, | |
| golden_sample=golden_sample, | |
| ) | |
| ) | |