Commit Graph

20 Commits

Author SHA1 Message Date
Andrew Charlwood ea6b9065bf feat: Trust Comparison 6-chart dashboard with real data (Task 10.8)
- Add 3 new visualization functions to plotly_generator.py:
  create_trust_market_share_figure, create_trust_heatmap_figure,
  create_trust_duration_figure
- Replace 6 placeholder callbacks in trust_comparison.py with real
  implementations using trust-comparison queries + figure builders
- Cost Waterfall reuses existing figure function via key mapping
- Dosing reuses existing create_dosing_figure with group_by="trust"
- Cost Effectiveness reuses existing function scoped to directorate
- All 6 charts respond to date filter and chart type toggle
- Validated with both directory (RHEUMATOLOGY) and indication (asthma)
2026-02-06 22:23:47 +00:00
Andrew Charlwood 10739ca84d feat: Trust Comparison landing page + directorate selector (Task 10.7)
- Add get_directorate_summary() query for per-directorate patient/drug counts
- Create trust_comparison.py with landing grid and 6-chart dashboard layout
- Wire directorate card clicks and back button through app-state callbacks
- Add TC landing and dashboard CSS per Phase 10 design spec
- Placeholder charts for 6 dashboard graphs (filled in Task 10.8)
- Chart type toggle clears selected directorate when switching modes
2026-02-06 22:15:10 +00:00
Andrew Charlwood 9d4e32910d feat: add 5 trust-comparison query functions for Phase 10.6
New per-trust-within-directorate queries:
- get_trust_market_share: drugs by trust within a directorate
- get_trust_cost_waterfall: cost per patient by trust
- get_trust_dosing: drug dosing intervals by trust
- get_trust_heatmap: trust x drug matrix for one directorate
- get_trust_durations: drug durations by trust

Also verified existing get_pathway_costs(directory=X) works for
directorate-scoped Cost Effectiveness (no new function needed).

Thin wrappers added in dash_app/data/queries.py.
2026-02-06 22:04:43 +00:00
Andrew Charlwood 11b5cc5b81 feat: header fraction KPIs replacing KPI row (Task 10.3)
Remove KPI card row, add 3 inline fraction KPIs to header bar:
filtered/total patients, drugs, cost. Breadcrumb removed.
KPI callback refactored for 6 output IDs (3 filtered + 3 total).
total_cost added to load_initial_data() reference data.
2026-02-06 21:45:13 +00:00
Andrew Charlwood 965fc8c3d2 feat: add Treatment Duration bar chart (Task 9.9) 2026-02-06 20:12:01 +00:00
Andrew Charlwood 0af76e68e0 feat: add Directorate × Drug Heatmap chart (Task 9.8) 2026-02-06 20:04:19 +00:00
Andrew Charlwood 02fe4b4e28 feat: add Dosing Interval Comparison chart (Task 9.7) 2026-02-06 19:58:28 +00:00
Andrew Charlwood 4ffcdf4268 feat: add Drug Switching Sankey diagram (Task 9.6) 2026-02-06 19:50:43 +00:00
Andrew Charlwood 73a8d1a49f feat: add Cost Waterfall bar chart (Task 9.5) 2026-02-06 19:44:37 +00:00
Andrew Charlwood 4ef7239eed feat: add Pathway Cost Effectiveness lollipop chart (Task 9.4)
- Create create_cost_effectiveness_figure() in plotly_generator.py
  Horizontal lollipop chart with dot size by patient count,
  colour gradient green→amber→red by cost, retention annotations
- Fix calculate_retention_rate() to accept both 'value' and 'patients' keys
- Add _render_cost_effectiveness() dispatch in chart.py callbacks
- Wire into tab switching for active_tab='cost-effectiveness'
2026-02-06 19:38:54 +00:00
Andrew Charlwood f8960a3064 feat: add First-Line Market Share chart (Task 9.3)
- create_market_share_figure() in src/visualization/plotly_generator.py
- Horizontal stacked bar chart: directorates × drugs with patient %
- Wire into tab dispatch via _render_market_share() helper in chart.py
- Responds to date, chart type, trust, and directorate filters
2026-02-06 19:28:20 +00:00
Andrew Charlwood d98cd4fd69 feat: add 7 analytics chart query functions (Task 9.2)
New query functions in src/data_processing/pathway_queries.py:
- get_drug_market_share: Level 3 drug nodes grouped by directory
- get_pathway_costs: Level 4+ pathway nodes with cost_pp_pa
- get_cost_waterfall: Directorate cost per patient from level 3 aggregation
- get_drug_transitions: Sankey source/target drug transitions with ordinal line labels
- get_dosing_intervals: Parsed average_spacing by trust/directory
- get_drug_directory_matrix: Directory x drug pivot with patient/cost metrics
- get_treatment_durations: Weighted avg_days by drug within directorates

Thin wrappers added in dash_app/data/queries.py for all 7 functions.
2026-02-06 19:21:10 +00:00
Andrew Charlwood fe2d048a21 feat: add parsing utilities and 8-tab chart infrastructure (Task 9.1)
- Create src/data_processing/parsing.py with parse_average_spacing(),
  parse_pathway_drugs(), and calculate_retention_rate()
- Add 8-tab bar to chart_card.py (Icicle, Market Share, Cost Effectiveness,
  Cost Waterfall, Sankey, Dosing, Heatmap, Duration)
- Add active-tab dcc.Store and tab switching callback in chart.py
- Remove Chart Views section from sidebar (now in tab bar)
- Lazy rendering: only active tab's chart is computed
2026-02-06 19:13:19 +00:00
Andrew Charlwood de08d4b520 fix: prune empty ancestor nodes and update KPIs for filtered views (Section 8)
- Add _prune_empty_ancestors() to remove directorate/trust nodes with no
  matching children when drug or directorate filters are active (e.g.,
  filtering by Immunoglobulin no longer shows empty Ophthalmology box)
- Sum level-3 drug nodes for KPI values when entity filters are active
  instead of using the root node's pre-computed unfiltered totals
2026-02-06 16:25:56 +00:00
Andrew Charlwood 00627a7299 fix: preserve ancestor nodes in drug/directorate filters to prevent broken icicle hierarchy (Task 7.2)
Drug filter WHERE clause used `drug_sequence IS NULL` to keep ancestor nodes,
but levels 0-2 have empty string '' not NULL. Changed to level-based gating:
- Drug filter: `(level < 3 OR drug_sequence LIKE ...)`
- Directorate filter: `(level < 2 OR directory IN (...) OR directory IS NULL OR directory = '')`
- Trust filter was already correct (had `OR trust_name = ''`)
2026-02-06 15:24:09 +00:00
Andrew Charlwood e877268805 feat: add data freshness indicator with relative time and patient count (Task 5.3) 2026-02-06 14:21:45 +00:00
Andrew Charlwood f0505ee43e feat: add trust selection to drawer with filter wiring (Task 5.1) 2026-02-06 14:09:36 +00:00
Andrew Charlwood 40ce7fc5f9 feat: add icicle chart rendering with NHS colorscale and dynamic titles (Task 3.4)
- Add create_icicle_from_nodes() to src/visualization/plotly_generator.py
  accepting list-of-dicts from dcc.Store with NHS blue gradient colorscale,
  10-field customdata, and matching text/hover templates from Reflex version
- Add update_chart callback to dash_app/callbacks/chart.py rendering
  go.Icicle figure from chart-data store with dynamic subtitle
- Title generation helper mirrors Reflex _generate_pathway_chart_title()
2026-02-06 13:44:13 +00:00
Andrew Charlwood b71748fa7d feat: add shared pathway query functions for Dash data access (Task 1.1)
Extract load_data() and load_pathway_data() logic from Reflex AppState
into standalone functions in src/data_processing/pathway_queries.py.
Create thin dash_app/data/queries.py wrapper with DB_PATH resolution.
2026-02-06 13:02:34 +00:00
Andrew Charlwood 76838887e6 refactor: reorganize repository to src/ layout
Move 6 packages (core, config, data_processing, analysis, visualization, cli)
into src/ to reduce root clutter. Merge tools/data.py into
data_processing/transforms.py. Move docs to docs/.

Path resolution via .pth file (setup_dev.py), pytest pythonpath config,
and sys.path bootstrap in rxconfig.py and CLI entry points.

Clean up pyproject.toml deps (remove stale pins, add snowflake-connector-python).
Fix tomllib import for Python 3.10 compatibility.

All 113 tests pass.
2026-02-06 12:03:48 +00:00