Add NetworkPlot: node-edge graph with FR, KK, and circle layouts#8
Conversation
|
@claude review this jawn |
|
Claude finished @gabo515's task in 3m 18s —— View job Code Review
Solid implementation overall — the feature is well-scoped, integrates cleanly with the existing render pipeline, and the test coverage is genuinely good. Here are the issues worth addressing, roughly in priority order. Bugs / Correctness1. Group legend color inconsistency when nodes have explicit colors ( The Concretely: // Current — group adopts the explicit node color:
let c = node.color.clone()
.unwrap_or_else(|| fallback[gi % fallback.len()].to_string());
group_map.push((g.clone(), c));
// Better — group always uses palette; explicit color remains a node-level override:
let c = fallback[gi % fallback.len()].to_string();
group_map.push((g.clone(), c));2. Non-square matrix can panic (
for i in 0..n {
if i >= matrix.len() { continue; } // <-- add this
let j_start = if self.directed { 0 } else { i + 1 };
for j in j_start..n {
if j == i || j >= matrix[i].len() { continue; }Design / API3. let positions = net.compute_positions();For KK layout on a graph with even 200 nodes this involves an O(n³) Dijkstra pass plus 200 outer × n inner Newton iterations. Every call to 4. #[arg(long, default_value = "force")]
pub layout: String,A 5. No
Minor / Polish6. Dead In undirected mode 7.
8. Label width uses character count, breaks for Unicode/CJK ( node.label.len() as f64 * 0.6 * font_size as f64
9. let w_min = net.edges.iter().map(|e| e.weight).fold(f64::INFINITY, f64::min);
let w_max = net.edges.iter().map(|e| e.weight).fold(f64::NEG_INFINITY, f64::max);When Tests10. let arrow_count = svg.matches("<path").count();
assert!(arrow_count >= 3, ...);Self-loop arcs, node diamonds/triangles, and edge paths all use DocsThe docs page is detailed and well-written. One small issue: the description at Overall: The architecture is clean, the Barnes-Hut quadtree is a nice addition for large-graph scalability, and the builder API is consistent with the rest of the library. The bugs above (#1 and #2) are the only ones that could produce unexpected results for normal users. Everything else is polish. |
6a116ea to
11d4fbf
Compare
New plot type for network/graph visualization. Layout algorithms: - Fruchterman-Reingold force-directed (default), with Barnes-Hut O(n log n) approximation for n > 256 - Kamada-Kawai stress-based layout using all-pairs shortest paths - Circle layout Features: - Edge-list and adjacency-matrix input (order-independent with with_directed via deferred matrix resolution) - Directed (arrowheads) and undirected edges - Weighted edges mapped to stroke width - Self-loops as outward-facing bezier arcs - Antiparallel edges automatically curved to avoid overlap - Edge labels at midpoints - Per-node color, size, group, and shape (circle/square/triangle/diamond) - Node shapes use circumradius factor for correct edge clearance - Group-based legend with category10 palette - Label repulsion to avoid overlap, clamped to plot bounds - Pinned node positions preserved through normalization - Center gravity for disconnected component handling CLI: kuva network (edge-list and --matrix modes, --layout force/kk/circle, --directed, --labels, --repel-labels, etc.) Includes 18 unit tests, 6 CLI integration tests, 5 smoke tests, terminal smoke test, examples, doc assets, full documentation pages, gallery entry, CLI reference, man page, and changelog.
11d4fbf to
fc1fd9c
Compare
Description
New plot type: node-edge network/graph diagram with three layout algorithms (Fruchterman-Reingold with Barnes-Hut, Kamada-Kawai, circle), four node shapes, edge labels, antiparallel edge curving, label repulsion, and full CLI support.
Type of change
Checklist
Library (new plot type)
src/plot/network.rs— struct + builder methodssrc/plot/mod.rs—pub mod+ re-exportsrc/render/plots.rs—Plotenum variant +bounds()/colorbar_info()/set_color()src/render/render.rs—add_network(), added torender_multiple()match,skip_axesfor pixel-spacesrc/render/layout.rs—auto_from_plots()extended for legend sizingTests
tests/network_basic.rs— 18 tests: basic, directed, circle, self-loop, matrix, groups+legend, weighted, node sizes, disconnected, pinned positions, explicit colors, single-node self-loop, matrix+directed order, KK layout, edge labels, node shapes, antiparallel curving, label repulsiontests/cli_basic.rs— 6 CLI tests: SVG output, content verification, matrix mode, KK layout, directed+weighted+group, bad layout errorcargo test --features cli,full— all 139 existing tests still passcargo clippy --features cli,full -- -D warnings— cleanCLI
src/bin/kuva/network.rs— Args struct +run()src/bin/kuva/main.rs— module, Commands variant, match armscripts/smoke_tests.sh— 5 invocations (basic, directed+weighted+legend, circle, KK, matrix)scripts/terminal_plots.sh— terminal rendering testdocs/src/cli/network.md— subcommand docs with full flags tabledocs/src/cli/index.md— subcommand table entryman/kuva.1— regeneratedDocumentation
examples/network.rs— 3 variants (basic, directed, grouped)scripts/gen_docs.sh— invocation addeddocs/src/plots/network.md— full docs page with embedded SVGs and complete API referencedocs/src/SUMMARY.md— links added (Plot Types + CLI)docs/src/gallery.md— gallery card addedREADME.md— plot count 30 → 31Housekeeping
CHANGELOG.md— entry added under[Unreleased]src/prelude.rs—NetworkPlot,NetworkNode,NetworkEdge,NetworkLayout,NodeShapere-exported