Stacked on #29 (base branch is feature/insulin-profile, not main) — this PR should be merged after #29, or retargeted to main once #29 lands.
reporting.py: new classify_bolus() (splits bolus treatments into food/correction/SMB), effective_basal_series() (profile-scheduled basal rate overridden by active temp basal), target_glucose_series() (pump target as a step function), and glucose_min_max().
ui_common.py: new shared Plotly trace-building helpers — add_basal_area_trace, add_carb_bars_trace, add_bolus_marker_traces, add_target_line_trace — each parametrized by an x_col so they work both with real timestamps (Live) and hour-of-day floats (Dagoverzicht's per-day subplots).
pages/4_Dagoverzicht.py: each day's subplot now overlays the basal-rate area (secondary y-axis), carb bars, bolus dots (sized by units, food/correction labeled, SMB unlabeled), and the profile's target-glucose line, alongside the existing glucose line. Manual per-row title annotations replace make_subplots' subplot_titles to avoid colliding with the new shared legend.
pages/1_Live.py: same overlays added to the rolling live chart; the existing insulin markers are replaced by the categorized/sized bolus markers for consistency. Basal/target series are computed per calendar day and concatenated to correctly span a rolling window that crosses midnight.
Every overlay layer uses its own color and alpha (so nothing fully occludes what's behind it) and is properly attributed in the legend, per the request's spec.
Note on a pre-existing issue found during testing: the Live page's "48 uur" period option doesn't actually refresh the chart to show 48h of data (still shows ~24h) — verified this reproduces identically on the unmodified main version of this page, so it predates this PR and is unrelated to these changes. Flagging it here rather than silently leaving it; happy to file it separately if useful.
Test plan
ruff check . passes
pytest tests/ -v passes (122 tests, +26 new: classify_bolus/effective_basal_series/target_glucose_series/glucose_min_max in test_reporting.py, overlay trace helpers in test_ui_common.py)
Manually launched the app against the real configured Nightscout instance and verified both pages render real basal/bolus/carb/target overlays correctly (screenshots inspected): legend fully attributed and deduplicated across Dagoverzicht's stacked days, correct axis titles on both primary (mmol/L) and secondary (Basaal E/uur · KH g) axes, alpha blending visible, bolus dose labels legible, target line tracks the real profile.
## Summary
Stacked on #29 (base branch is `feature/insulin-profile`, not `main`) — this PR should be merged after #29, or retargeted to `main` once #29 lands.
- `reporting.py`: new `classify_bolus()` (splits bolus treatments into food/correction/SMB), `effective_basal_series()` (profile-scheduled basal rate overridden by active temp basal), `target_glucose_series()` (pump target as a step function), and `glucose_min_max()`.
- `ui_common.py`: new shared Plotly trace-building helpers — `add_basal_area_trace`, `add_carb_bars_trace`, `add_bolus_marker_traces`, `add_target_line_trace` — each parametrized by an `x_col` so they work both with real timestamps (Live) and hour-of-day floats (Dagoverzicht's per-day subplots).
- `pages/4_Dagoverzicht.py`: each day's subplot now overlays the basal-rate area (secondary y-axis), carb bars, bolus dots (sized by units, food/correction labeled, SMB unlabeled), and the profile's target-glucose line, alongside the existing glucose line. Manual per-row title annotations replace `make_subplots`' `subplot_titles` to avoid colliding with the new shared legend.
- `pages/1_Live.py`: same overlays added to the rolling live chart; the existing insulin markers are replaced by the categorized/sized bolus markers for consistency. Basal/target series are computed per calendar day and concatenated to correctly span a rolling window that crosses midnight.
Every overlay layer uses its own color and alpha (so nothing fully occludes what's behind it) and is properly attributed in the legend, per the request's spec.
**Note on a pre-existing issue found during testing:** the Live page's "48 uur" period option doesn't actually refresh the chart to show 48h of data (still shows ~24h) — verified this reproduces identically on the unmodified `main` version of this page, so it predates this PR and is unrelated to these changes. Flagging it here rather than silently leaving it; happy to file it separately if useful.
## Test plan
- [x] `ruff check .` passes
- [x] `pytest tests/ -v` passes (122 tests, +26 new: `classify_bolus`/`effective_basal_series`/`target_glucose_series`/`glucose_min_max` in `test_reporting.py`, overlay trace helpers in `test_ui_common.py`)
- [x] Manually launched the app against the real configured Nightscout instance and verified both pages render real basal/bolus/carb/target overlays correctly (screenshots inspected): legend fully attributed and deduplicated across Dagoverzicht's stacked days, correct axis titles on both primary (mmol/L) and secondary (Basaal E/uur · KH g) axes, alpha blending visible, bolus dose labels legible, target line tracks the real profile.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Overlay the full insulin picture onto the interactive glucose charts:
basal rate as a semi-transparent step-area (profile schedule overridden
by active temp basal), bolus doses as size-scaled dots split into
food/correction/SMB categories (food and correction labeled with units,
SMB left unlabeled), carbs as bars, and the pump's target glucose as a
line — each with its own color, alpha, and legend entry. Shared trace-
building helpers live in ui_common.py so both pages (and the PDF report
in a follow-up PR) render identically.
Builds on the pump profile work in #29 (profile_data.py, load_profile()).
pd.Timedelta(days=1) triggers a DeprecationWarning about NumPy's
"generic" timedelta unit in this pandas version; pd.Timedelta(1, unit="D")
is equivalent and warning-free.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Stacked on #29 (base branch is
feature/insulin-profile, notmain) — this PR should be merged after #29, or retargeted tomainonce #29 lands.reporting.py: newclassify_bolus()(splits bolus treatments into food/correction/SMB),effective_basal_series()(profile-scheduled basal rate overridden by active temp basal),target_glucose_series()(pump target as a step function), andglucose_min_max().ui_common.py: new shared Plotly trace-building helpers —add_basal_area_trace,add_carb_bars_trace,add_bolus_marker_traces,add_target_line_trace— each parametrized by anx_colso they work both with real timestamps (Live) and hour-of-day floats (Dagoverzicht's per-day subplots).pages/4_Dagoverzicht.py: each day's subplot now overlays the basal-rate area (secondary y-axis), carb bars, bolus dots (sized by units, food/correction labeled, SMB unlabeled), and the profile's target-glucose line, alongside the existing glucose line. Manual per-row title annotations replacemake_subplots'subplot_titlesto avoid colliding with the new shared legend.pages/1_Live.py: same overlays added to the rolling live chart; the existing insulin markers are replaced by the categorized/sized bolus markers for consistency. Basal/target series are computed per calendar day and concatenated to correctly span a rolling window that crosses midnight.Every overlay layer uses its own color and alpha (so nothing fully occludes what's behind it) and is properly attributed in the legend, per the request's spec.
Note on a pre-existing issue found during testing: the Live page's "48 uur" period option doesn't actually refresh the chart to show 48h of data (still shows ~24h) — verified this reproduces identically on the unmodified
mainversion of this page, so it predates this PR and is unrelated to these changes. Flagging it here rather than silently leaving it; happy to file it separately if useful.Test plan
ruff check .passespytest tests/ -vpasses (122 tests, +26 new:classify_bolus/effective_basal_series/target_glucose_series/glucose_min_maxintest_reporting.py, overlay trace helpers intest_ui_common.py)🤖 Generated with Claude Code