Skip to content

Analyzing Results

ReplayBG analyzes twinning and replay outputs by integrating AGATA (py_agata), a dedicated toolbox for glucose data analysis. The two helpers live in py_replay_bg.utils.agata_analysis and run AGATA on the resulting glucose traces, optionally printing a compact summary and folding the metrics back into the saved pickle.

analyze_replay

Runs AGATA's full glucose-profile analysis on a replay's output — and, when the replay used a sensor, also on the noisy measurement trace.

from py_replay_bg.utils.agata_analysis import analyze_replay

analysis = analyze_replay(replay_results, ts=5, verbose=True)
Parameter Meaning
replay_results The dict returned by replay() (must contain output).
ts AGATA glucose sampling cadence in minutes (default 5). The output is downsampled to this cadence.
integration_ts Minutes per integration step (default 1, = environment.ts).
glycemic_target Glycemic target set forwarded to AGATA (default "diabetes").
verbose Print a compact metric summary.
path / save_name When path is given, add the analysis to replay_results in place under an analysis key and re-save it to <path>/replay_<save_name>.pkl.

Returns a dict with key output (the AGATA profile of the model output) and, when a sensor was used, measurement (the profile of the sensor trace).

analyze_twin

Simulates the fitted model forward to get the predicted trace, runs the profile analysis on it, and computes the comprehensive fit-error metric set against the reference CGM (rbg_data.y).

from py_replay_bg.utils.agata_analysis import analyze_twin

analysis = analyze_twin(twin_results, rbg_data, model, verbose=True)
Parameter Meaning
twin_results The dict returned by twin() (must contain theta).
rbg_data The data object that was twinned: provides the reference CGM y, the inputs u, tsteps and yts.
model A model instance. It is reset with the twin's theta (plus the first observed glucose and the t=0 input row) and simulated forward, so its state is overwritten.
integration_ts Minutes per integration step (default 1, = environment.ts); the AGATA cadence is rbg_data.yts * integration_ts.
glycemic_target Glycemic target set forwarded to AGATA (default "diabetes").
verbose Print a compact metric summary (default False).
path / save_name When path is given, re-save twin_results plus rbg_data and the new analysis key to <path>/twin_<save_name>.pkl (twin_results itself is not modified).

Returns a dict with:

  • profile — the AGATA glucose profile of the fitted trace,
  • error — the fit-error metrics: rmse, mard, cod, Clarke EGA zones (clarke), and g_rmse.

What AGATA computes

analyze_glucose_profile returns a rich set of standardized glucose metrics, grouped as:

  • variability — mean/median/std glucose, CV, range, IQR, AUC, GMI, CONGA, J-index, MAGE, MODD, and more;
  • time_in_ranges — time in target, and in (level 1/2) hypo- and hyperglycemia;
  • risk — ADRR, LBGI, HBGI, BGRI, GRI;
  • glycemic_transformation — GRADE scores, IGC, hypo/hyper index, MR index;
  • events — hypo/hyperglycemic events (start/end/duration/frequency);
  • data_quality — days of observation and missing-glucose percentage.

The verbose=True printout gives a curated subset (mean/std/CV glucose, GMI, time-in-target, time hypo/hyper, LBGI/HBGI) plus, for analyze_twin, the fit-error block (RMSE, MARD, COD, gRMSE, Clarke A/B/C/D/E).

Typical workflow

Continuing from Getting Started (df, rbg, rbg_data, model and unknown_parameters_prior already defined):

from py_replay_bg.data.multi_meal_t1d_data import MultiMealT1DData
from py_replay_bg.model.multi_meal_t1d import MultiMealT1DModel
from py_replay_bg.utils.numba_dicts import to_typed_f64_dict
from py_replay_bg.utils.agata_analysis import analyze_twin, analyze_replay

# 1. Twin, then analyze the fit and fold the metrics into the saved pickle.
result = rbg.twin(rbg_data=rbg_data, model=model,
                  unknown_parameters_prior=unknown_parameters_prior,
                  path='results', save_name='my_twin')
analyze_twin(result, rbg_data, model, verbose=True,
             path='results', save_name='my_twin')

# 2. Replay two scenarios and compare their glycemic metrics. replay() uses the
#    model's construction-time theta0, so rebuild each model with the twin.
theta0 = to_typed_f64_dict(result['theta'])
model = MultiMealT1DModel(u2ss=rbg_data.u2ss, tsteps=rbg_data.tsteps,
                          theta0=theta0, t_start=rbg_data.t_start)
baseline = rbg.replay(rbg_data=rbg_data, model=model)

df_whatif = df.copy()
df_whatif['bolus'] = df_whatif['bolus'] * 0.7      # e.g. cut every bolus by 30%
rbg_data_whatif = MultiMealT1DData(data=df_whatif, environment=rbg.environment)
model_whatif = MultiMealT1DModel(u2ss=rbg_data_whatif.u2ss, tsteps=rbg_data_whatif.tsteps,
                                 theta0=theta0, t_start=rbg_data_whatif.t_start)
whatif = rbg.replay(rbg_data=rbg_data_whatif, model=model_whatif)

analyze_replay(baseline, ts=5, verbose=True)
analyze_replay(whatif,   ts=5, verbose=True)

For the metric definitions and the complete list of indices, see the AGATA documentation.