add Dagoverzicht, Hypo Events, and Hyper Events pages (FR4, FR5, FR6)
Dagoverzicht stacks one glucose trace per calendar day (small multiples via a shared 0-24h x-axis). The two event pages share a new render_event_level() helper in ui_common.py so Level 1/Level 2 hypo and hyper are rendered identically: count/avg/longest/events-per-week metrics, a time-of-day histogram, and a table of individual events. Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
@@ -10,9 +10,12 @@ from __future__ import annotations
|
||||
|
||||
from datetime import date, datetime, timedelta, timezone
|
||||
|
||||
import pandas as pd
|
||||
import plotly.graph_objects as go
|
||||
import streamlit as st
|
||||
|
||||
from nightscout_client import fetch_entries_range, fetch_treatments_range
|
||||
from reporting import detect_events, summarize_events
|
||||
|
||||
MMOL_HOVERTEMPLATE = "%{x|%d-%m %H:%M} · %{y:.1f} mmol/L<extra></extra>"
|
||||
|
||||
@@ -93,3 +96,54 @@ def load_range_data(start: date, end: date):
|
||||
glucose = fetch_entries_range(start, end)
|
||||
treatments = fetch_treatments_range(start, end)
|
||||
return glucose, treatments
|
||||
|
||||
|
||||
def render_event_level(
|
||||
glucose: pd.DataFrame,
|
||||
threshold: float,
|
||||
direction: str,
|
||||
level_name: str,
|
||||
period_days: int,
|
||||
colors: dict,
|
||||
) -> None:
|
||||
"""Render de metrics/tabel/tijdstip-histogram voor één hypo-/hyperniveau.
|
||||
|
||||
Gedeeld tussen de Hypo Events- en Hyper Events-pagina's (FR5/FR6), die
|
||||
elk twee niveaus (Level 1/Level 2) op dezelfde manier tonen.
|
||||
"""
|
||||
events = detect_events(glucose, threshold, direction)
|
||||
summary = summarize_events(events, period_days)
|
||||
|
||||
st.subheader(level_name)
|
||||
cols = st.columns(4)
|
||||
cols[0].metric("Aantal events", summary["count"])
|
||||
cols[1].metric("Gem. duur", f"{summary['avg_duration_minutes']:.0f} min")
|
||||
cols[2].metric("Langste event", f"{summary['longest_duration_minutes']:.0f} min")
|
||||
cols[3].metric("Events/week", f"{summary['events_per_week']:.1f}")
|
||||
|
||||
if events.empty:
|
||||
st.info("Geen events gevonden in deze periode.")
|
||||
return
|
||||
|
||||
bar_color = colors["low"] if direction == "below" else colors["high"]
|
||||
hours = events["start"].dt.hour
|
||||
hour_counts = hours.value_counts().reindex(range(24), fill_value=0).sort_index()
|
||||
fig = go.Figure(go.Bar(x=list(hour_counts.index), y=hour_counts.to_numpy(), marker_color=bar_color))
|
||||
fig.update_layout(
|
||||
paper_bgcolor="rgba(0,0,0,0)",
|
||||
plot_bgcolor="rgba(0,0,0,0)",
|
||||
font_color=colors["text"],
|
||||
height=220,
|
||||
margin={"l": 10, "r": 10, "t": 10, "b": 10},
|
||||
xaxis={"title": "Uur van de dag", "dtick": 2, "gridcolor": colors["grid"]},
|
||||
yaxis={"title": "Aantal events", "gridcolor": colors["grid"]},
|
||||
)
|
||||
st.plotly_chart(fig, width="stretch")
|
||||
|
||||
display = events.copy()
|
||||
display["start"] = display["start"].dt.strftime("%d-%m-%Y %H:%M")
|
||||
display["end"] = display["end"].dt.strftime("%d-%m-%Y %H:%M")
|
||||
display = display.rename(
|
||||
columns={"start": "Start", "end": "Einde", "duration_minutes": "Duur (min)"}
|
||||
)
|
||||
st.dataframe(display, width="stretch", hide_index=True)
|
||||
|
||||
Reference in New Issue
Block a user