feat: add Dosing Interval Comparison chart (Task 9.7)
This commit is contained in:
@@ -1623,3 +1623,60 @@ Console error: `WARN: Multiple implied roots, cannot build icicle hierarchy of t
|
||||
- Note: Sankey has ordinal suffixes (e.g., "ADALIMUMAB (1st)") to prevent self-loops
|
||||
### Blocked items:
|
||||
- None
|
||||
|
||||
## Iteration 29 — 2026-02-06
|
||||
### Task: Phase 9 — Task 9.7 (Dosing Interval Comparison chart — Tab 6)
|
||||
### Why this task:
|
||||
- Tasks 9.1–9.6 complete. Task 9.7 is next in sequence.
|
||||
- Progress.txt from iteration 28 explicitly recommended this task.
|
||||
- Uses existing `get_dosing_intervals()` query and `parse_average_spacing()` parsing.
|
||||
### Status: COMPLETE
|
||||
### What was done:
|
||||
- **Created `create_dosing_figure(data, title, group_by)` in `src/visualization/plotly_generator.py`** (~180 lines):
|
||||
- Two modes via `group_by` parameter:
|
||||
- **"drug" (overview)**: Weighted average weekly interval per drug, one horizontal bar per drug sorted by patient count. Bars coloured by interval (NHS blue gradient — darker = more frequent dosing). Patient count annotations on right side.
|
||||
- **"trust" (per-drug comparison)**: Grouped horizontal bars per trust, one trace per directory. Enables cross-trust dosing comparison for a specific drug.
|
||||
- Hover shows: drug/trust, interval, avg doses, avg treatment weeks, patient count
|
||||
- Dynamic height, NHS design aesthetic (Source Sans 3, transparent, clean grid)
|
||||
- Helper functions: `_dosing_by_drug()` and `_dosing_by_trust()` for clean separation
|
||||
- **Added `_render_dosing(app_state, title)` helper in `dash_app/callbacks/chart.py`**:
|
||||
- Extracts filter params (date_filter_id, chart_type, single drug/trust)
|
||||
- Auto-selects `group_by`: "trust" when single drug selected, "drug" for overview
|
||||
- Calls `get_dosing_intervals()` wrapper then `create_dosing_figure()`
|
||||
- Handles empty data and exceptions gracefully
|
||||
- **Wired into `update_chart` dispatch**: `active_tab == "dosing"` → `_render_dosing()`
|
||||
### Validation results:
|
||||
- Tier 1 (Code): `from dash_app.app import app` — OK, 11 callbacks registered
|
||||
- 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 overview: 124 rows → 36 drugs, intervals 4.3–52.4 weeks — renders correctly
|
||||
- Indication chart: 219 rows → 37 drugs — renders correctly
|
||||
- ADALIMUMAB single drug: 14 rows → 4 directory traces, per-trust comparison — renders correctly
|
||||
- NNUH trust filter: single trust reduces data — filters correctly
|
||||
- Date filter (2yr_12mo): 89 rows → 29 drugs — filters correctly
|
||||
- Empty data: returns empty figure — handled correctly
|
||||
- Icicle still works: 293 nodes, 11,118 patients — no regression
|
||||
- Market share, cost effectiveness, cost waterfall, Sankey — no regressions
|
||||
### Files changed:
|
||||
- `src/visualization/plotly_generator.py` — Added: `create_dosing_figure()`, `_dosing_by_drug()`, `_dosing_by_trust()` (~180 lines)
|
||||
- `dash_app/callbacks/chart.py` — Added: `_render_dosing()` helper + dispatch branch
|
||||
- `IMPLEMENTATION_PLAN.md` — Task 9.7 marked [x]
|
||||
### Committed: [pending]
|
||||
### Patterns discovered:
|
||||
- Dosing chart benefits from two distinct modes: overview (all drugs, weighted averages) and comparison (single drug, per-trust). The `group_by` parameter makes this clean without separate figure functions.
|
||||
- Trust names are very long (e.g., "NORFOLK AND NORWICH UNIVERSITY HOSPITALS NHS FOUNDATION TRUST") — stripping " NHS FOUNDATION TRUST" and " HOSPITALS" suffixes greatly improves y-axis readability.
|
||||
- Weighted average by patient count is the right aggregation for dosing intervals — it prevents small patient groups from skewing the displayed interval.
|
||||
- Bar colour gradient by interval value provides immediate visual cue: darker blue = more frequent dosing, lighter = less frequent.
|
||||
### Next iteration should:
|
||||
- Start Task 9.8 — Directorate × Drug Heatmap chart (Tab 7)
|
||||
- Sub-steps:
|
||||
1. Create figure function in `src/visualization/plotly_generator.py` — `create_heatmap_figure(data, title, metric)`
|
||||
2. Build Plotly heatmap from `get_drug_directory_matrix()` data
|
||||
3. Rows = directorates (sorted by total patients), Columns = drugs (sorted by frequency)
|
||||
4. Cell colour = patient count (default), with possible toggle for cost or cost_pp_pa
|
||||
5. Wire into `update_chart` via `_render_heatmap()` helper
|
||||
6. Responds to trust filter, date filter, chart type toggle
|
||||
- Read `get_drug_directory_matrix()` in pathway_queries.py for exact data shape
|
||||
- Data returns: `{directories: [...], drugs: [...], matrix: {dir: {drug: {patients, cost, cost_pp_pa}}}}`
|
||||
### Blocked items:
|
||||
- None
|
||||
|
||||
Reference in New Issue
Block a user