Skip to content

Commit 591b54a

Browse files
anth-volkclaude
andcommitted
Fix overview stage ordering and edge label positioning
- Add ELK partition support to force sequential stage ordering in Overview - Fix edge label placement bug (was using array index instead of visual midpoint) - Add z-index to edge labels so they render above nodes - Increase between-layer spacing for better label readability Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 465dbcb commit 591b54a

3 files changed

Lines changed: 40 additions & 18 deletions

File tree

docs/pipeline-diagrams/src/components/edges/ElkEdge.jsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,9 @@ export default function ElkEdge({
3030
.map((p, i) => `${i === 0 ? "M" : "L"} ${p.x} ${p.y}`)
3131
.join(" ");
3232

33-
// Label at midpoint of the path
34-
const mid = Math.floor(points.length / 2);
35-
labelX = points[mid].x;
36-
labelY = points[mid].y;
33+
// Label at visual midpoint between start and end of the edge
34+
labelX = (points[0].x + points[points.length - 1].x) / 2;
35+
labelY = (points[0].y + points[points.length - 1].y) / 2;
3736
} else {
3837
// Fallback to smoothstep
3938
const [path, lx, ly] = getSmoothStepPath({
@@ -66,6 +65,7 @@ export default function ElkEdge({
6665
position: "absolute",
6766
transform: `translate(-50%, -50%) translate(${labelX}px, ${labelY}px)`,
6867
pointerEvents: "all",
68+
zIndex: 1000,
6969
}}
7070
className="nodrag nopan"
7171
>

docs/pipeline-diagrams/src/hooks/useElkLayout.js

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const ELK_OPTIONS = {
88
"elk.direction": "DOWN",
99
"elk.edgeRouting": "ORTHOGONAL",
1010
"elk.spacing.nodeNode": "60",
11-
"elk.layered.spacing.nodeNodeBetweenLayers": "80",
11+
"elk.layered.spacing.nodeNodeBetweenLayers": "120",
1212
"elk.layered.spacing.edgeNodeBetweenLayers": "30",
1313
"elk.spacing.edgeEdge": "20",
1414
"elk.spacing.edgeNode": "30",
@@ -77,16 +77,33 @@ export default function useElkLayout(initialNodes, initialEdges) {
7777
hasRun.current = true;
7878

7979
async function runLayout() {
80+
// Check if any node specifies a partition for forced ordering
81+
const usePartitioning = initialNodes.some(
82+
(n) => n.data?.elkPartition != null,
83+
);
84+
85+
const layoutOptions = { ...ELK_OPTIONS };
86+
if (usePartitioning) {
87+
layoutOptions["elk.partitioning.activate"] = "true";
88+
}
89+
8090
const graph = {
8191
id: "root",
82-
layoutOptions: ELK_OPTIONS,
92+
layoutOptions,
8393
children: initialNodes.map((node) => {
8494
const size = estimateNodeSize(node);
85-
return {
95+
const child = {
8696
id: node.id,
8797
width: size.width,
8898
height: size.height,
8999
};
100+
if (node.data?.elkPartition != null) {
101+
child.layoutOptions = {
102+
"elk.partitioning.partition":
103+
String(node.data.elkPartition),
104+
};
105+
}
106+
return child;
90107
}),
91108
edges: initialEdges.map((edge) => ({
92109
id: edge.id,

docs/pipeline-diagrams/src/stages/Overview.jsx

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,61 +8,62 @@ import {
88
} from "../constants/edgeStyles";
99

1010
const nodes = [
11-
// Stage nodes (vertical column, x=400, 200px gaps)
11+
// Stage nodes — elkPartition forces sequential layer ordering
1212
{
1313
id: "stage0",
1414
type: "process",
15-
data: { label: "Stage 0: Raw Data Download" },
15+
data: { label: "Stage 0: Raw Data Download", elkPartition: 0 },
1616
},
1717
{
1818
id: "stage1",
1919
type: "process",
20-
data: { label: "Stage 1: Base Dataset Construction" },
20+
data: { label: "Stage 1: Base Dataset Construction", elkPartition: 1 },
2121
},
2222
{
2323
id: "stage2",
2424
type: "process",
25-
data: { label: "Stage 2: Extended CPS (PUF Clone)" },
25+
data: { label: "Stage 2: Extended CPS (PUF Clone)", elkPartition: 2 },
2626
},
2727
{
2828
id: "stage3",
2929
type: "process",
30-
data: { label: "Stage 3: Stratified CPS" },
30+
data: { label: "Stage 3: Stratified CPS", elkPartition: 3 },
3131
},
3232
{
3333
id: "stage4",
3434
type: "process",
35-
data: { label: "Stage 4: Source Imputation" },
35+
data: { label: "Stage 4: Source Imputation", elkPartition: 4 },
3636
},
3737
{
3838
id: "stage5",
3939
type: "process",
40-
data: { label: "Stage 5: Matrix Build" },
40+
data: { label: "Stage 5: Matrix Build", elkPartition: 5 },
4141
},
4242
{
4343
id: "stage6",
4444
type: "process",
45-
data: { label: "Stage 6: Weight Fitting (L0)" },
45+
data: { label: "Stage 6: Weight Fitting (L0)", elkPartition: 6 },
4646
},
4747
{
4848
id: "stage7",
4949
type: "process",
50-
data: { label: "Stage 7: Local Area H5 Build" },
50+
data: { label: "Stage 7: Local Area H5 Build", elkPartition: 7 },
5151
},
5252
{
5353
id: "stage8",
5454
type: "process",
55-
data: { label: "Stage 8: Validation & Promotion" },
55+
data: { label: "Stage 8: Validation & Promotion", elkPartition: 8 },
5656
},
5757

58-
// Annotation nodes
58+
// Annotation nodes — partitioned near associated stages
5959
{
6060
id: "modal1",
6161
type: "external",
6262
data: {
6363
label: "Modal (CPU)",
6464
subtitle: "65GB RAM, 8 CPU",
6565
details: ["Stages 5-6 build phase"],
66+
elkPartition: 5,
6667
},
6768
},
6869
{
@@ -72,6 +73,7 @@ const nodes = [
7273
label: "Modal (GPU)",
7374
subtitle: "T4/A10/A100/H100",
7475
details: ["Stage 6 fit phase"],
76+
elkPartition: 6,
7577
},
7678
},
7779
{
@@ -81,6 +83,7 @@ const nodes = [
8183
label: "Modal (Workers)",
8284
subtitle: "8 containers, 16GB each",
8385
details: ["Stage 7 parallel build"],
86+
elkPartition: 7,
8487
},
8588
},
8689
{
@@ -90,6 +93,7 @@ const nodes = [
9093
label: "HuggingFace Hub",
9194
subtitle: "policyengine/policyengine-us-data",
9295
details: ["Download + Upload at every stage"],
96+
elkPartition: 0,
9397
},
9498
},
9599
{
@@ -99,6 +103,7 @@ const nodes = [
99103
label: "Local Machine",
100104
subtitle: "make data / make pipeline",
101105
details: ["Stages 0-3 run locally"],
106+
elkPartition: 1,
102107
},
103108
},
104109
];

0 commit comments

Comments
 (0)