add Samenvatting and AGP Profiel pages (FR2, FR3, FR9)
Wires reporting.py's stats into two new pages: a summary panel (data completeness, GMI, %CV, 5-band time-in-range vs. consensus targets) and the standard AGP percentile chart (5th-95th and 25th-75th bands plus median, aggregated by time-of-day across the selected period). Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
@@ -202,3 +202,27 @@ def summarize_events(events: pd.DataFrame, period_days: float) -> dict[str, floa
|
||||
"total_minutes": round(total_minutes, 1),
|
||||
"events_per_week": round(len(events) / period_days * 7, 1),
|
||||
}
|
||||
|
||||
|
||||
AGP_PERCENTILE_COLUMNS = ["minute_of_day", "p5", "p25", "p50", "p75", "p95"]
|
||||
|
||||
|
||||
def agp_percentile_bands(glucose: pd.DataFrame, bin_minutes: int = 30) -> pd.DataFrame:
|
||||
"""Aggregeer glucosewaarden per tijdstip-van-de-dag naar percentielbanden.
|
||||
|
||||
Groepeert alle metingen in de periode naar hun tijd-van-de-dag (in bins
|
||||
van `bin_minutes`), en berekent per bin de 5e/25e/50e/75e/95e percentiel
|
||||
— de standaard AGP-percentielgrafiek over een samengesteld 24-uursbeeld
|
||||
(Danne et al. 2017, Diabetes Care 40(12):1631-1640).
|
||||
"""
|
||||
if glucose.empty:
|
||||
return pd.DataFrame(columns=AGP_PERCENTILE_COLUMNS)
|
||||
|
||||
df = glucose.copy()
|
||||
minute_of_day = df["timestamp"].dt.hour * 60 + df["timestamp"].dt.minute
|
||||
df["bin"] = (minute_of_day // bin_minutes) * bin_minutes
|
||||
|
||||
grouped = df.groupby("bin")["mmol"].quantile([0.05, 0.25, 0.5, 0.75, 0.95]).unstack()
|
||||
grouped.columns = ["p5", "p25", "p50", "p75", "p95"]
|
||||
grouped = grouped.reset_index().rename(columns={"bin": "minute_of_day"})
|
||||
return grouped[AGP_PERCENTILE_COLUMNS].sort_values("minute_of_day").reset_index(drop=True)
|
||||
|
||||
Reference in New Issue
Block a user