docs: update progress.txt with iteration 28 (Task 9.6 complete — Sankey diagram)

This commit is contained in:
Andrew Charlwood
2026-02-06 19:51:44 +00:00
parent 4ffcdf4268
commit b1136ad7bf
+56
View File
@@ -1510,6 +1510,62 @@ Console error: `WARN: Multiple implied roots, cannot build icicle hierarchy of t
### Blocked items:
- None
## Iteration 28 — 2026-02-06
### Task: Phase 9 — Task 9.6 (Drug Switching Sankey chart — Tab 5)
### Why this task:
- Tasks 9.19.5 complete. Task 9.6 is next in sequence.
- Progress.txt from iteration 27 explicitly recommended this task.
- Sankey is a well-defined chart type with pre-existing query function (`get_drug_transitions()`).
### Status: COMPLETE
### What was done:
- **Created `create_sankey_figure(data, title)` in `src/visualization/plotly_generator.py`** (~130 lines):
- Plotly `go.Sankey` diagram: nodes = drugs with ordinal suffixes (e.g., "ADALIMUMAB (1st)"), links = patient transitions
- Nodes coloured by base drug name — same drug gets same colour across treatment lines (1st, 2nd, 3rd)
- Link colours use source node colour at 40% opacity for visual flow
- NHS colour palette (15 colours cycling), Source Sans 3 font
- Custom hover: node shows drug name + total patients, link shows source → target + patient count
- Dynamic height: scales with number of unique drug bases
- `arrangement="snap"` for clean node positioning
- **Added `_render_sankey(app_state, title)` helper in `dash_app/callbacks/chart.py`**:
- Extracts filter params (date_filter_id, chart_type, single directory/trust)
- Calls `get_drug_transitions()` wrapper then `create_sankey_figure()`
- Handles empty data and exceptions gracefully
- **Wired into `update_chart` dispatch**: `active_tab == "sankey"` → `_render_sankey()`
### Validation results:
- Tier 1 (Code): `from dash_app.app import app` — OK
- Tier 1 (App starts): `python run_dash.py` → "Dash is running on http://127.0.0.1:8050/" — no errors
- Tier 3 (Functional):
- Directory chart: 49 nodes, 65 links — renders correctly
- Indication chart: 34 nodes, 35 links — renders correctly
- RHEUMATOLOGY filter: 24 nodes, 27 links — filters correctly
- NNUH trust filter: 38 nodes, 47 links — filters correctly
- Date filter (2yr_12mo): 13 nodes, 12 links — filters correctly
- Empty data: returns empty figure — handled correctly
- Icicle, market share, cost effectiveness, cost waterfall — no regressions
### Files changed:
- `src/visualization/plotly_generator.py` — Added: `create_sankey_figure()` (~130 lines)
- `dash_app/callbacks/chart.py` — Added: `_render_sankey()` helper + dispatch branch
- `IMPLEMENTATION_PLAN.md` — Task 9.6 marked [x]
### Committed: 4ffcdf4 "feat: add Drug Switching Sankey diagram (Task 9.6)"
### Patterns discovered:
- Sankey node colouring by base drug name (stripping ordinal suffix) provides visual continuity — users can track the same drug across treatment lines by colour.
- `hex_to_rgba()` helper for link transparency is a reusable pattern. Using 35% opacity keeps links readable without obscuring overlapping flows.
- `arrangement="snap"` works better than "perpendicular" for this data shape — it allows Plotly to optimally position nodes vertically.
- The `_render_sankey(app_state, title)` pattern matches `_render_market_share()` and `_render_cost_waterfall()` — all take app_state and title, query independently from SQLite.
### Next iteration should:
- Start Task 9.7 — Dosing Interval Comparison chart (Tab 6)
- Sub-steps:
1. Create figure function in `src/visualization/plotly_generator.py` — `create_dosing_figure(data, title)`
2. Build horizontal grouped bar chart from `get_dosing_intervals()` data
3. Uses `parse_average_spacing()` to extract weekly interval numbers from HTML strings
4. Y-axis = trust or directorate, X-axis = weekly interval, grouped by drug
5. Wire into `update_chart` via `_render_dosing()` helper
6. Responds to drug filter, date filter, chart type toggle
- Read `get_dosing_intervals()` in pathway_queries.py for exact data shape
- Read `parse_average_spacing()` in `src/data_processing/parsing.py` for HTML parsing logic
### Blocked items:
- None
## Iteration 27 — 2026-02-06
### Task: Phase 9 — Task 9.5 (Cost Waterfall chart — Tab 4)
### Why this task: