Add pump profile fetching and Insulineprofiel page
willemjan/glucose-dashboard/pipeline/head This commit looks good
willemjan/glucose-dashboard/pipeline/head This commit looks good
Fetch and parse the latest-used Nightscout profile (basal schedule, ISF, carb ratio, DIA, targets) and show it as a new dashboard page: a list of basal/ISF/carb-ratio segments plus a bar chart of basal rate by hour of day. This is the data foundation for treatment overlays on the glucose charts and the redesigned PDF report in follow-up PRs.
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
import pandas as pd
|
||||
import plotly.graph_objects as go
|
||||
import requests
|
||||
import streamlit as st
|
||||
|
||||
from auth import require_auth
|
||||
from nightscout_client import NightscoutConfigError
|
||||
from profile_data import segments_table, segments_to_hourly_bars, total_daily_basal
|
||||
from ui_common import get_colors, load_profile
|
||||
|
||||
st.set_page_config(page_title="Glucose dashboard — Insulineprofiel", page_icon="📊", layout="wide")
|
||||
require_auth()
|
||||
|
||||
st.title("Insulineprofiel")
|
||||
st.caption("Het meest recent gebruikte pompprofiel: basaalschema, ISF, koolhydraatratio en DIA.")
|
||||
|
||||
try:
|
||||
profile = load_profile()
|
||||
except NightscoutConfigError as exc:
|
||||
st.error(str(exc))
|
||||
st.stop()
|
||||
except (requests.RequestException, ValueError) as exc:
|
||||
st.error(f"Kon geen profiel ophalen van Nightscout: {exc}")
|
||||
st.stop()
|
||||
|
||||
if not profile:
|
||||
st.info("Geen pompprofiel gevonden op deze Nightscout-instantie.")
|
||||
st.stop()
|
||||
|
||||
colors = get_colors()
|
||||
|
||||
col1, col2 = st.columns(2)
|
||||
col1.metric("DIA (werkingsduur insuline)", f"{profile['dia']:.1f} uur")
|
||||
col2.caption(f"Profielnaam: {profile['name'] or '—'}")
|
||||
|
||||
st.subheader("Basaalschema")
|
||||
bars = segments_to_hourly_bars(profile["basal"])
|
||||
fig = go.Figure(
|
||||
go.Scatter(
|
||||
x=[b["hour"] for b in bars],
|
||||
y=[b["value"] for b in bars],
|
||||
mode="lines",
|
||||
line={"shape": "hv", "color": colors["basal"], "width": 2},
|
||||
fill="tozeroy",
|
||||
fillcolor=colors["basal"],
|
||||
opacity=0.7,
|
||||
name="Basaal",
|
||||
hovertemplate="%{x:.0f}:00 · %{y:.2f} E/uur<extra></extra>",
|
||||
)
|
||||
)
|
||||
fig.update_layout(
|
||||
paper_bgcolor="rgba(0,0,0,0)",
|
||||
plot_bgcolor="rgba(0,0,0,0)",
|
||||
font_color=colors["text"],
|
||||
height=320,
|
||||
margin={"l": 10, "r": 10, "t": 10, "b": 10},
|
||||
xaxis={"title": "Uur van de dag", "range": [0, 24], "dtick": 2, "gridcolor": colors["grid"]},
|
||||
yaxis={"title": "E/uur", "gridcolor": colors["grid"], "rangemode": "tozero"},
|
||||
showlegend=False,
|
||||
)
|
||||
st.plotly_chart(fig, width="stretch")
|
||||
|
||||
basal_rows = segments_table(profile["basal"])
|
||||
st.dataframe(
|
||||
pd.DataFrame(basal_rows).rename(
|
||||
columns={"start": "Van", "end": "Tot", "value": "Basaalsnelheid (E/uur)"}
|
||||
),
|
||||
width="stretch",
|
||||
hide_index=True,
|
||||
)
|
||||
|
||||
col_isf, col_ratio = st.columns(2)
|
||||
with col_isf:
|
||||
st.subheader("Insulinegevoeligheid (ISF)")
|
||||
isf_rows = segments_table(profile["sens"])
|
||||
st.dataframe(
|
||||
pd.DataFrame(isf_rows).rename(
|
||||
columns={"start": "Van", "end": "Tot", "value": "ISF (mmol/L per E)"}
|
||||
),
|
||||
width="stretch",
|
||||
hide_index=True,
|
||||
)
|
||||
|
||||
with col_ratio:
|
||||
st.subheader("Koolhydraatratio")
|
||||
ratio_rows = segments_table(profile["carbratio"])
|
||||
st.dataframe(
|
||||
pd.DataFrame(ratio_rows).rename(
|
||||
columns={"start": "Van", "end": "Tot", "value": "Ratio (g koolhydraten per E)"}
|
||||
),
|
||||
width="stretch",
|
||||
hide_index=True,
|
||||
)
|
||||
|
||||
st.caption(
|
||||
f"Totale dagelijkse basaal: {total_daily_basal(profile['basal']):.1f} E "
|
||||
"(volgens profielschema, exclusief tijdelijke aanpassingen)."
|
||||
)
|
||||
Reference in New Issue
Block a user