Skip to content

feat(#1532): modernize dj.Diagram rendering style - #1534

Open
dimitri-yatsenko wants to merge 15 commits into
masterfrom
fix/1532-diagram-restyle
Open

feat(#1532): modernize dj.Diagram rendering style#1534
dimitri-yatsenko wants to merge 15 commits into
masterfrom
fix/1532-diagram-restyle

Conversation

@dimitri-yatsenko

@dimitri-yatsenko dimitri-yatsenko commented Aug 10, 2026

Copy link
Copy Markdown
Member

Modernizes dj.Diagram rendering — parts 2–4 of #1532 (the style work; the edge-weight correctness fix is #1533, on which this is stacked). Docs companion: datajoint/datajoint-docs#247 (spec) and #248 (regenerated notebook diagrams).

What changed

Palette & typography

  • Each tier gets a readable fill / stroke / text triple in place of the old alpha-blended primaries. Shapes stay load-bearing: Manual & Lookup = rounded rectangle (Lookup gray, Manual-sized), Imported & Computed = ellipse, Part = neutral rounded box.
  • Explicit Helvetica (no more Times fallback); rounded node corners; generous label margins.

Master–part entity grouping

  • A master and its parts are enclosed in a subtle rounded shaded cluster (no dashed frame); schema clusters are rounded + dashed.
  • Part labels drop the master prefix (Scan, not Acquisition.Scan) — the enclosure carries membership.
  • Parts share the master's rank. (Forcing exact below/right placement inside the cluster proved unreliable in Graphviz once a part has its own child, so within-cluster ordering is left to the layout engine — see commit history.)
  • Parts keep a box (not boxless) so platform nodes are clickable targets that open the table.

Edges

  • Renamed-FK edges use a desaturated amber (#C77D3A), ordinary edges a translucent slate; both share one alpha per theme, so a renamed edge sits at the same visual density as the rest, differing only in hue. LR + no arrowheads (already the config default).

Themes — new display.diagram_theme (DJ_DIAGRAM_THEME):

  • light (default), dark (deep-slate background, light text, brighter strokes), and auto — a single SVG that adapts to the viewer's light/dark mode via an injected prefers-color-scheme block.

Naming

  • Scrub "ERD" from the codebase (test_erd.pytest_diagram.py, identifiers, a comment) — DataJoint diagrams are not ERDs.
  • Rename the internal node attribute distinguishedintroduces_dimension, matching the documented "schema dimension"/"axis" vocabulary.

Tests

  • test_diagram_style.py — style-contract (visual-regression) guard: renders a fixed schema per theme and asserts the palette, thick/thin edge weights, entity cluster, dark background, and adaptive media block (no fragile geometry pinning).
  • test_diagram.py — entity-cluster + prefix-dropped label test.
  • Robustness fix: master↔part detection handles both node-naming schemes (class Master.Part and raw schema.master__part).
  • All diagram suites green on MySQL 8.0 and PostgreSQL 15.

Notes for reviewers

Line weight is binary and encodes cardinality only: thick when the foreign key
constitutes the child's entire primary key (1:1), thin when the child has
primary-key attributes beyond those the FK contributes (multi-valued) — newly
declared or inherited from another FK. penwidth already followed this via multi;
remove the misleading master-part conflation in the layout weight and drive it
from the same predicate so the two never diverge.

Rename-safe: multi compares the child's referencing columns to the child primary
key (both child-column space), so a renamed FK that is the child's whole PK is
correctly 1:1/thick. Adds a guardrail test (1:1, multi, master-part, renamed-1:1).
Replace the alpha-blended Graphviz-default look with a readable, modern palette
and typography (parts 2 and 4 of #1532):

- Tier palette: each tier gets a fill / stroke / text triple (Manual green,
  Lookup slate, Imported blue, Computed red, Part near-white) in place of the
  alpha-blended primaries. Shape stays load-bearing and unchanged.
- Rounded corners + generous label margins on box tiers; explicit Helvetica
  font (no more Times fallback).
- Renamed-FK edges use a desaturated amber (#C77D3A) instead of vivid #FF8800;
  ordinary edges a light translucent slate.
- Left-to-right, no arrowheads (already the config default).

Entity-group clustering (master+parts) and a visual-regression fixture follow.
@dimitri-yatsenko dimitri-yatsenko added the enhancement Indicates new improvements label Aug 10, 2026
Enclose each master and its parts in a nested, unlabeled entity cluster; part
labels drop the master prefix (`C`, not `B.C`) since the enclosure carries
membership. Master and its parts share a rank (horizontal = derivation, vertical
= containment), except a part that depends on a sibling part, which is left off
the rank so the intra-group chain descends.

Also rename the diagram test module test_erd.py -> test_diagram.py and its
identifiers, and scrub 'ERD' from a code comment: DataJoint diagrams are not
ERDs. Adds a test asserting the entity cluster and the prefix-dropped part label.
@dimitri-yatsenko
dimitri-yatsenko force-pushed the fix/1532-diagram-restyle branch from c3c5665 to 5906776 Compare August 10, 2026 19:46
Schema clusters get rounded corners (style rounded,dashed). Master-part entity
clusters drop the dashed frame for a quiet rounded shaded background (#F3F5F8,
borderless) so the grouping reads subtly and doesn't compete with the schema box.
Add a diagram color theme option (dj.config display.diagram_theme = light|dark).
Refactor make_dot styling into theme-independent structure (_TIER_STRUCTURE) plus
per-theme color sets (_DIAGRAM_THEMES): tier fill/stroke/text triples, background,
edge colors, and cluster colors. The dark theme uses a deep-slate background with
light text and brighter strokes.

Edges share one alpha per theme, so a renamed (amber) edge sits at the same
visual density as ordinary edges — differing only in hue — and both are given
more contrast than the first pass. Also fix a single-underscore config.override
example in the docstring (needs double underscore for nested keys).
Add theme='auto': render the diagram in light colors and inject a
prefers-color-scheme style block so a single SVG adapts to the viewer's light or
dark mode (the two palettes are collision-free, so a per-color attribute-selector
override is unambiguous). Exposed via Diagram.svg_string(); make_svg/_repr_svg_
use it. make_dot() gains an optional theme override.

Also brighten the dark-theme entity-cluster fill so the master-part grouping box
reads against the dark background.
Match Lookup's box size to Manual (fontsize/size), so a Lookup reads as a gray
rectangle the same size as a Manual table rather than a smaller subtle box. Part
rendering unchanged (neutral subtle box, per design review).
A part inherits its master's tier and has no tier-shape of its own, but it keeps
a neutral subtle box (not a tier shape) so platform nodes are clickable targets
that open the table. Comment this so it isn't reverted to boxless.
Add invisible ordering edges through each entity's same-rank group (master then
parts) so parts are placed below the master in LR and to its right in TB, rather
than leaving the within-rank order to Graphviz's heuristic.
The prior ordering edges were being overridden: inside the entity cluster, the
master is anchored by its derivation-chain edges and the real master->part FK
edge forced the part above (LR). Fix by (a) marking master->part FK edges
constraint=false so they don't vote on within-rank order, and (b) adding an
invisible ordering edge whose direction depends on rankdir — reversed
(part->master) for LR to put parts below, forward (master->part) for TB to put
parts to the right. Both recipes verified empirically.
Remove the constraint=false on master->part FK edges and the invisible ordering
edges. They ordered simple parts (below in LR / right in TB) but could not do so
reliably when a part has its own child part (the child edge + cluster crossing-
minimization override the flat-edge order), and the special-casing was brittle.
Keep the entity clustering and shared rank; leave within-cluster placement to
Graphviz.
Add a style-contract test that renders a fixed schema per theme and asserts the
palette (per-tier fill/stroke), thick/thin edge weights, entity cluster, dark
background, and adaptive prefers-color-scheme block — catching palette/weight/
theme regressions without pinning fragile SVG geometry.

Also make master<->part detection in make_dot robust to both node-naming schemes
(class 'Master.Part' and raw 'schema.master__part'), using the actual node keys
for predecessor lookups instead of reconstructing them — the old code crashed on
raw-table-name graphs.
Make 'auto' (adaptive light/dark SVG) the default diagram_theme, so rendered
diagrams adapt to the viewer's appearance out of the box. Also set the schema
cluster label to Helvetica — it previously fell back to Graphviz's Times default
while the node labels were already sans.
@dimitri-yatsenko

Copy link
Copy Markdown
Member Author

@ttngu207 @MilagrosMarin — for a concrete example of the new diagram style on a real pipeline (not the synthetic test schema), see the LC-MS demo rendered with this branch: https://github.com/datajoint/lcms-demo/tree/viz/diagram-restyle-1534 — the README there renders docs/pipeline.svg with the modernized palette, master-part entity clustering, corrected edge weights, sans typography, and the adaptive (light/dark) theme (datajoint/lcms-demo#3).

Set labelloc=t, labeljust=r on the schema cluster so the schema/module label
sits in the top-right corner rather than top-center.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Indicates new improvements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant