docs: final integration verification + CLAUDE.md update for two-view architecture (Task 10.11)

This commit is contained in:
Andrew Charlwood
2026-02-06 22:55:22 +00:00
parent 552b949ed9
commit 5f890f2d93
3 changed files with 203 additions and 84 deletions
+126 -64
View File
@@ -112,24 +112,27 @@ The refresh command:
├── dash_app/ # Dash web application
│ ├── app.py # Dash app, layout root, dcc.Store, register_callbacks
│ ├── assets/
│ │ └── nhs.css # NHS design system CSS (from 01_nhs_classic.html)
│ │ └── nhs.css # NHS design system CSS
│ ├── data/
│ │ ├── queries.py # Thin wrapper calling src/data_processing/pathway_queries.py
│ │ └── card_browser.py # DimSearchTerm.csv → directorate tree for drawer
│ │ └── card_browser.py # DimSearchTerm.csv → directorate tree for modals
│ ├── components/
│ │ ├── header.py # Top header bar with data freshness indicator
│ │ ├── sidebar.py # Left navigation with drawer triggers
│ │ ├── kpi_row.py # 4 KPI cards (patients, drugs, cost, match rate)
│ │ ├── filter_bar.py # Chart type toggle pills + date filter dropdowns
│ │ ├── chart_card.py # Chart area with tabs + dcc.Graph + loading spinner
│ │ ├── drawer.py # dmc.Drawer with drug/trust chips + directorate cards
│ │ ├── header.py # Top header bar with fraction KPIs + data freshness
│ │ ├── sidebar.py # Left nav: Patient Pathways + Trust Comparison
│ │ ├── sub_header.py # Global filter bar (date dropdowns + chart type toggle)
│ │ ├── filter_bar.py # Patient Pathways filter buttons (drugs, trusts, directorates)
│ │ ├── chart_card.py # Chart area with Icicle/Sankey tabs + dcc.Graph
│ │ ├── modals.py # dmc.Modal dialogs for drug/trust/directorate selection
│ │ ├── trust_comparison.py # Trust Comparison landing page + 6-chart dashboard
│ │ └── footer.py # Page footer
│ ├── callbacks/
│ │ ├── __init__.py # register_callbacks(app)
│ │ ├── filters.py # Reference data loading + filter state management
│ │ ├── chart.py # Tab switching, pathway data loading, 8-chart dispatch
│ │ ├── drawer.py # Drawer open/close + drug/trust selection
│ │ ── kpi.py # KPI card value updates
│ │ ├── chart.py # Tab switching, pathway data loading, chart dispatch
│ │ ├── modals.py # Modal open/close + drug/trust/directorate selection
│ │ ── navigation.py # Sidebar view switching + Trust Comparison navigation
│ │ ├── trust_comparison.py # 6 Trust Comparison chart callbacks
│ │ └── kpi.py # Header fraction KPI updates
│ └── utils/
│ └── __init__.py
@@ -264,6 +267,9 @@ Refactored from the original 267-line `generate_graph()` function:
- **create_dosing_figure(data, title, group_by)** - Grouped horizontal bar chart: dosing intervals by drug or trust
- **create_heatmap_figure(data, title, metric)** - Matrix heatmap: directorate × drug with patient/cost/cost_pp_pa colouring
- **create_duration_figure(data, title, show_directory)** - Horizontal bar chart: average treatment duration in days per drug
- **create_trust_market_share_figure(data, title)** - Trust Comparison: horizontal stacked bars grouped by trust, drugs as segments
- **create_trust_heatmap_figure(data, title, metric)** - Trust Comparison: trust × drug matrix with NHS blue colorscale
- **create_trust_duration_figure(data, title)** - Trust Comparison: grouped horizontal bars with one trace per trust
- **save_figure_html()** - Save interactive HTML file
- **open_figure_in_browser()** - Open chart in default browser
@@ -285,43 +291,70 @@ Shared query functions used by the Dash app (via thin wrappers in `dash_app/data
- **get_dosing_intervals(db_path, filter_id, chart_type, drug, trust)** - Level 3 nodes with parsed average_spacing intervals
- **get_drug_directory_matrix(db_path, filter_id, chart_type, trust)** - Level 3 nodes pivoted as directory × drug matrix
- **get_treatment_durations(db_path, filter_id, chart_type, directory, trust)** - Level 3 nodes with avg_days by drug
- **get_trust_market_share(db_path, filter_id, chart_type, directory)** - Trust Comparison: drugs by trust within a single directorate
- **get_trust_cost_waterfall(db_path, filter_id, chart_type, directory)** - Trust Comparison: one bar per trust showing cost_pp within directorate
- **get_trust_dosing(db_path, filter_id, chart_type, directory)** - Trust Comparison: drug dosing intervals broken down by trust
- **get_trust_heatmap(db_path, filter_id, chart_type, directory)** - Trust Comparison: trust × drug matrix for one directorate
- **get_trust_durations(db_path, filter_id, chart_type, directory)** - Trust Comparison: drug durations by trust within directorate
- **get_directorate_summary(db_path, filter_id, chart_type, directory)** - Summary stats for a directorate (total patients, drugs, cost)
### Dash Application (`dash_app/`)
**State Management** via 3 `dcc.Store` components:
- **app-state** (session): `chart_type`, `initiated`, `last_seen`, `date_filter_id`, `selected_drugs`, `selected_directorates`, `selected_trusts`
**Two-View Architecture:**
The application is split into two analytical perspectives, selectable via the sidebar:
- **Patient Pathways**: Pathway-focused analysis (Icicle + Sankey charts) with drug/trust/directorate filters
- **Trust Comparison**: Per-directorate analysis comparing drugs across trusts (6 charts for a selected directorate)
**State Management** via 4 `dcc.Store` components:
- **app-state** (session): `chart_type`, `initiated`, `last_seen`, `date_filter_id`, `selected_drugs`, `selected_directorates`, `selected_trusts`, `active_view` ("patient-pathways" | "trust-comparison"), `selected_comparison_directorate` (null | directorate name)
- **chart-data** (memory): `nodes[]`, `unique_patients`, `total_drugs`, `total_cost`, `last_updated`
- **reference-data** (session): `available_drugs`, `available_directorates`, `available_indications`, `available_trusts`, `total_patients`, `last_updated`
- **active-tab** (memory): Currently selected chart tab within Patient Pathways ("icicle" | "sankey")
**Callback Chain** (unidirectional):
```
Page Load → load_reference_data → reference-data store + header indicators
→ update_app_state → app-state store (default filters)
→ load_pathway_data → chart-data store
├→ update_kpis → KPI cards
└→ update_chart → dcc.Graph (dispatches by active-tab)
├→ update_kpis → header fraction KPIs
└→ update_chart → dcc.Graph (Icicle or Sankey)
Filter change → update_app_state → app-state → load_pathway_data → (chain above)
Drawer selection → all-drugs-chips/trust-chips → update_app_state → (chain above)
Tab click → switch_tab → active-tab store → update_chart → dcc.Graph (lazy: only active tab computed)
Modal selection → drug/trust chips → update_app_state → (chain above)
Tab click → switch_tab → active-tab store → update_chart → dcc.Graph (lazy rendering)
Sidebar click → switch_view → active_view in app-state → show/hide views
Trust Comparison:
Landing page → directorate button click → selected_comparison_directorate → 6 chart callbacks
Back button → clear selected_comparison_directorate → return to landing
```
**Key Components:**
- **Header** (`header.py`): NHS branding, data freshness indicator (patient count + relative time)
- **Sidebar** (`sidebar.py`): Navigation with Pathway Overview link (chart views moved to tab bar in chart_card.py)
- **Filter Bar** (`filter_bar.py`): Chart type toggle pills (By Directory / By Indication) + date filter dropdowns
- **KPI Row** (`kpi_row.py`): 4 cards — Unique Patients, Drug Types, Total Cost, Indication Match Rate (~93%)
- **Chart Card** (`chart_card.py`): 8-tab chart area (Icicle, Market Share, Cost Effectiveness, Cost Waterfall, Sankey, Dosing, Heatmap, Duration) with `dcc.Loading` spinner, dynamic subtitle, and `dcc.Store(id="active-tab")`
- **Drawer** (`drawer.py`): `dmc.Drawer` with drug chips (`dmc.ChipGroup`), trust chips, directorate accordion with indication sub-items and drug fragment badges
- **Header** (`header.py`): NHS branding, fraction KPIs (X/X patients, X/X drugs, £X/£X cost), data freshness indicator
- **Sidebar** (`sidebar.py`): 2 navigation items — "Patient Pathways" (default), "Trust Comparison"
- **Sub-Header** (`sub_header.py`): Global filter bar — date dropdowns (Initiated, Last Seen) + chart type toggle pills (By Directory / By Indication). Constant across both views.
- **Filter Bar** (`filter_bar.py`): Patient Pathways-only filter buttons — Drugs (with count badge), Trusts (with count badge), Directorates (with count badge), Clear All. Only visible on Patient Pathways view.
- **Chart Card** (`chart_card.py`): 2-tab chart area (Icicle, Sankey) with `dcc.Loading` spinner, dynamic subtitle, and `dcc.Store(id="active-tab")`
- **Modals** (`modals.py`): 3 `dmc.Modal` dialogs for drug selection (ChipGroup), trust selection (ChipGroup), directorate browser (Accordion with indication sub-items and drug fragment badges)
- **Trust Comparison** (`trust_comparison.py`): Landing page (directorate/indication button grid) + 6-chart dashboard (Market Share, Cost Waterfall, Dosing, Heatmap, Duration, Cost Effectiveness)
- **Footer** (`footer.py`): NHS Norfolk and Waveney ICB branding
**Drawer Drug Browser:**
- "All Drugs" section: flat `dmc.ChipGroup` with 42 drugs from pathway_nodes level 3
- "Trusts" section: `dmc.ChipGroup` with 7 trusts
- "By Directorate" section: nested `dmc.Accordion` — 19 directorates → indications → drug fragment `dmc.Badge` items
**Filter Modals:**
- Drug Modal: flat `dmc.ChipGroup` with 42 drugs from pathway_nodes level 3
- Trust Modal: `dmc.ChipGroup` with 7 trusts
- Directorate Modal: nested `dmc.Accordion` — 19 directorates → indications → drug fragment `dmc.Badge` items
- Clicking a drug fragment badge selects all full drug names containing that fragment (substring match)
- "Clear All Filters" button resets drug and trust selections
**Trust Comparison Dashboard (6 Charts):**
All scoped to a single selected directorate, comparing drugs across trusts:
1. **Market Share**: Drug breakdown per trust (stacked bars per trust)
2. **Cost Waterfall**: Per-trust cost within directorate
3. **Dosing**: Drug dosing intervals by trust
4. **Heatmap**: Trust × drug matrix
5. **Duration**: Drug durations by trust
6. **Cost Effectiveness**: Pathway costs within directorate (NOT split by trust)
### Data Transformations (`data_processing/transforms.py`)
Core data transformation functions used by the pipeline:
@@ -389,30 +422,48 @@ Core data transformation functions used by the pipeline:
[Dash App: python run_dash.py]
┌──────────────────────────────────────────┐
Filter Bar + Drawer (toggle pills, │
date dropdowns, drug/trust chips)
Global Sub-Header (date dropdowns, │
chart type toggle pills)
│ → Triggers update_app_state callback │
└──────────────────────────────────────────┘
┌──────────────────────────────────────────┐
│ load_pathway_data callback
→ Input: app-state dcc.Store
│ → Calls pathway_queries.load_pathway_
nodes() with filters
→ Output: chart-data dcc.Store
└──────────────────────────────────────────┘
├──────────────────────────────┐
▼ ▼
────────────────────┐ ┌──────────────────────
│ update_kpis │ │ update_chart
→ 4 KPI cards → create_icicle_
→ formatted from_nodes()
counts/costs │ │ → 10-field custom-
└────────────────────┘ │ data + NHS blue
│ → dcc.Graph figure
└──────────────────────┘
├─── Patient Pathways View ─────────────────────────────┐
│ │
┌──────────────────────────────────────────┐
│ │ Filter Bar (Drugs/Trusts/Directorates) │
Modal selections → app-state │
│ └──────────────────────────────────────────┘
│ ▼ │
┌──────────────────────────────────────────┐ │
│ │ load_pathway_data callback │ │
│ │ → chart-data store │ │
│ └──────────────────────────────────────────┘ │
│ │
├──────────────────────────────┐
│ ┌────────────────────┐ ┌──────────────────────┐
│ │ update_kpis │ │ update_chart │
→ header KPIs │ → Icicle or Sankey │
└────────────────────┘ └──────────────────────┘
│ │
├─── Trust Comparison View ─────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────┐ │
│ │ Landing Page │ │
│ │ → Directorate/Indication buttons │ │
│ │ → Click → selected_comparison_dir │ │
│ └──────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────┐ │
│ │ 6-Chart Dashboard │ │
│ │ → Market Share, Cost Waterfall, Dosing │ │
│ │ → Heatmap, Duration, Cost Effectiveness│ │
│ │ → All per-trust within one directorate │ │
│ └──────────────────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────┘
```
### Reference Data Files (`data/`)
@@ -493,22 +544,32 @@ The input data (CSV/Parquet) must contain columns including:
## Output
8 interactive chart tabs in a single Dash application:
1. **Icicle** — Hierarchical pathway view (Directory: Trust → Directorate → Drug → Pathway; Indication: Trust → GP Diagnosis → Drug → Pathway)
2. **Market Share** — Horizontal stacked bars showing drug market share by directorate/indication
3. **Cost Effectiveness** — Lollipop chart of pathway cost per patient per annum with retention annotations
4. **Cost Waterfall** — Waterfall chart of directorate-level cost_pp_pa
5. **Sankey** — Drug switching flows across 1st → 2nd → 3rd treatment lines
6. **Dosing** — Grouped bar chart of dosing intervals by drug or trust
7. **Heatmap** — Directorate × Drug matrix coloured by patient count, cost, or cost_pp_pa
8. **Duration** — Horizontal bar chart of average treatment duration per drug
Two-view Dash application with distinct analytical perspectives:
All charts support:
**Patient Pathways View** (2 tabs):
1. **Icicle** — Hierarchical pathway view (Directory: Trust → Directorate → Drug → Pathway; Indication: Trust → GP Diagnosis → Drug → Pathway)
2. **Sankey** — Drug switching flows across 1st → 2nd → 3rd treatment lines
Patient Pathways supports:
- Directory / Indication toggle
- Date filter combinations (6 options)
- Trust, drug, and directorate filters
- Trust, drug, and directorate filters via modals
- Lazy rendering (only active tab computed)
**Trust Comparison View** (6 charts in dashboard):
Landing page with directorate/indication buttons → 6-chart dashboard for selected directorate:
1. **Market Share** — Drug breakdown per trust (stacked bars)
2. **Cost Waterfall** — Per-trust cost within directorate
3. **Dosing** — Drug dosing intervals by trust
4. **Heatmap** — Trust × drug matrix
5. **Duration** — Drug durations by trust
6. **Cost Effectiveness** — Pathway costs within directorate (not split by trust)
Trust Comparison supports:
- Directory / Indication toggle (changes landing page buttons)
- Date filter combinations (6 options)
- All 6 charts scoped to selected directorate
## Testing
```bash
@@ -564,13 +625,14 @@ The pre-computed pathway architecture introduces these changes:
- **Benefit**: Sub-50ms filter response time vs multi-minute calculations
### State Management (Dash)
- State lives in 3 `dcc.Store` components: `app-state`, `chart-data`, `reference-data`
- State lives in 4 `dcc.Store` components: `app-state`, `chart-data`, `reference-data`, `active-tab`
- Filter state: `chart_type`, `initiated`, `last_seen`, `date_filter_id`, `selected_drugs`, `selected_directorates`, `selected_trusts`
- Chart type toggle: "By Directory" / "By Indication" pills in filter bar
- Dynamic subtitle: "Trust → Directorate → Drug → Pathway" or "Trust → Indication → Drug → Pathway"
- Drug/trust selection via `dmc.ChipGroup` in right-side drawer
- View state: `active_view` ("patient-pathways" | "trust-comparison"), `selected_comparison_directorate` (null | directorate name)
- Chart type toggle: "By Directory" / "By Indication" pills in global sub-header
- Drug/trust/directorate selection via `dmc.Modal` dialogs (Patient Pathways only)
- Fraction KPIs in header (X/X patients, X/X drugs, £X/£X cost)
### Icicle Chart
### Icicle Chart (Patient Pathways)
- Full 10-field customdata structure (value, colour, cost, costpp, first_seen, last_seen, first_seen_parent, last_seen_parent, average_spacing, cost_pp_pa)
- NHS blue gradient colorscale: Heritage Blue #003087 → Pale Blue #E3F2FD
- Treatment statistics (average_spacing, cost_pp_pa) in hover tooltips
+20 -20
View File
@@ -566,14 +566,14 @@ Additionally: KPI row removed, fraction KPIs moved to header, global filter sub-
- **Checkpoint**: All new components styled consistently with NHS design system
### 10.11 Final integration + documentation
- [ ] Verify all views work: Patient Pathways (Icicle + Sankey), Trust Comparison (landing + 6-chart dashboard)
- [ ] Verify global filters (date, chart type) affect both views
- [ ] Verify Patient Pathways filters (drug, trust, directorate) only affect Patient Pathways
- [ ] Verify Trust Comparison directorate selector works for all directorates and indications
- [ ] Verify no regressions in Icicle and Sankey charts
- [ ] Test with both "directory" and "indication" chart types
- [ ] Update CLAUDE.md with new architecture (two views, state management, callback chains)
- [ ] `python run_dash.py` starts cleanly
- [x] Verify all views work: Patient Pathways (Icicle + Sankey), Trust Comparison (landing + 6-chart dashboard)
- [x] Verify global filters (date, chart type) affect both views
- [x] Verify Patient Pathways filters (drug, trust, directorate) only affect Patient Pathways
- [x] Verify Trust Comparison directorate selector works for all directorates and indications
- [x] Verify no regressions in Icicle and Sankey charts
- [x] Test with both "directory" and "indication" chart types
- [x] Update CLAUDE.md with new architecture (two views, state management, callback chains)
- [x] `python run_dash.py` starts cleanly
- **Checkpoint**: Full application works end-to-end, documentation updated ✓
---
@@ -611,18 +611,18 @@ All tasks marked `[x]` AND:
- [x] `python run_dash.py` starts cleanly with all tabs
### Phase 10 Completion Criteria
- [ ] Sidebar has "Patient Pathways" + "Trust Comparison" navigation items
- [ ] Patient Pathways view shows Icicle + Sankey tabs only
- [ ] Trust Comparison landing page shows directorate/indication buttons
- [ ] Trust Comparison dashboard renders 6 charts for selected directorate (Market Share, Cost Waterfall, Dosing, Heatmap, Duration, Cost Effectiveness)
- [ ] All 6 Trust Comparison charts show per-trust breakdown within selected directorate (except Cost Effectiveness which is directorate-scoped, no trust split)
- [ ] KPI row removed — fraction KPIs (X/X patients, drugs, cost) in header
- [ ] Global filter sub-header (date + chart type) is prominent and constant across both views
- [ ] Drug/trust/directorate filters only visible on Patient Pathways
- [ ] Chart type toggle affects Trust Comparison (indication mode shows indication buttons)
- [ ] Date filter changes update both views
- [ ] Icicle + Sankey have no regressions
- [ ] `python run_dash.py` starts cleanly
- [x] Sidebar has "Patient Pathways" + "Trust Comparison" navigation items
- [x] Patient Pathways view shows Icicle + Sankey tabs only
- [x] Trust Comparison landing page shows directorate/indication buttons
- [x] Trust Comparison dashboard renders 6 charts for selected directorate (Market Share, Cost Waterfall, Dosing, Heatmap, Duration, Cost Effectiveness)
- [x] All 6 Trust Comparison charts show per-trust breakdown within selected directorate (except Cost Effectiveness which is directorate-scoped, no trust split)
- [x] KPI row removed — fraction KPIs (X/X patients, drugs, cost) in header
- [x] Global filter sub-header (date + chart type) is prominent and constant across both views
- [x] Drug/trust/directorate filters only visible on Patient Pathways
- [x] Chart type toggle affects Trust Comparison (indication mode shows indication buttons)
- [x] Date filter changes update both views
- [x] Icicle + Sankey have no regressions
- [x] `python run_dash.py` starts cleanly
---
+57
View File
@@ -2475,3 +2475,60 @@ Console error: `WARN: Multiple implied roots, cannot build icicle hierarchy of t
- This is the FINAL task — if all checks pass, the project is complete
### Blocked items:
- None
## Iteration 43 — 2026-02-06
### Task: 10.11 — Final integration + documentation
### Why this task:
- This is the ONLY remaining task — all others are marked [x]
- Task 10.10 (CSS cleanup + polish) was completed in iteration 42
- Progress.txt from iteration 42 explicitly recommended Task 10.11 as the FINAL task
### Status: COMPLETE
### What was done:
- **Programmatic verification of Patient Pathways view**:
- Reference data loads: 42 drugs, 14 directorates, 32 indications, 7 trusts
- Directory mode (all_6mo): 293 nodes, 11,118 patients, 39 drugs, ~£130.6M
- Indication mode (all_6mo): 438 nodes, 11,252 patients
- Icicle figure renders: 1 trace, type=icicle
- Sankey figure renders: 2 drug transitions, 1 trace
- Drug filter (ADALIMUMAB): 91 nodes, levels [0,1,2,3,4,5] — hierarchy intact
- Trust filter (Cambridge): 15 nodes, levels [0,1,2,3,4] — hierarchy intact
- **Programmatic verification of Trust Comparison view**:
- Trust Market Share (RHEUMATOLOGY): 42 rows, 6 trusts, 17 drugs
- Trust Cost Waterfall: 6 rows (one per trust)
- Trust Dosing: 40 rows
- Trust Heatmap: 6 trusts × 17 drugs
- Trust Durations: 40 rows
- Cost Effectiveness (RHEUMATOLOGY): 38 pathway rows
- Indication mode (asthma): 3 rows, 2 trusts, 2 drugs
- All 3 trust-specific figure builders render correctly
- **Callback/layout verification**:
- 20 callbacks registered (correct)
- 2 sidebar nav items: Patient Pathways, Trust Comparison
- 2 chart tabs: Icicle, Sankey
- 4 dcc.Store components: app-state, chart-data, reference-data, active-tab
- All 6 date filter IDs return data (all_6mo through 2yr_12mo)
- **Both chart types verified**: directory and indication modes work for both views
- **CLAUDE.md updated** with two-view architecture:
- Package structure updated (removed kpi_row.py, drawer.py; added modals.py, sub_header.py, trust_comparison.py, navigation.py, trust_comparison callbacks)
- State management updated to 4 stores with active_view and selected_comparison_directorate
- Callback chain updated with two-view flow diagram
- Key components updated (header fraction KPIs, 2-item sidebar, sub-header, filter bar, modals, trust comparison)
- Output section updated to describe two-view architecture
- Added trust-comparison visualization and query functions
- **All Phase 10 completion criteria marked [x]** in IMPLEMENTATION_PLAN.md
- **All tasks in IMPLEMENTATION_PLAN.md are [x]** — no remaining [ ], [~], or [B] items
### Validation results:
- Tier 1 (Code): `from dash_app.app import app` — OK, 20 callbacks
- Tier 1 (App starts): `python run_dash.py` — "Dash is running on http://127.0.0.1:8050/" — no errors
- Tier 3 (Functional): All data queries verified programmatically for both views, both chart types, drug/trust filters
### Files changed:
- `CLAUDE.md` — Updated with two-view architecture
- `IMPLEMENTATION_PLAN.md` — Task 10.11 and Phase 10 completion criteria marked [x]
### Committed: [pending]
### Patterns discovered:
- Programmatic verification (running queries and figure builders via `python -c`) is more reliable than manual browser testing for an amnesiac loop
- The final integration task is primarily verification + documentation — no code changes needed when previous iterations were thorough
### Next iteration should:
- N/A — ALL TASKS COMPLETE. The project is finished.
### Blocked items:
- None