Skip to content

Commit ee9f35e

Browse files
authored
Merge pull request #45 from lcossu/snack_overrides
Manually override absorption rates and delay of snacks and hypo treatments
2 parents 1170804 + 76ea5a2 commit ee9f35e

File tree

5 files changed

+144
-5
lines changed

5 files changed

+144
-5
lines changed

docs/documentation/replaying.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ rbg.replay(data: pd.DataFrame,
5050
n_replay: int = 1000,
5151
sensors: list | None = None,
5252
sensor_cgm: CGM = Vettoretti19CGM,
53+
snack_absorption=snack_absorption,
54+
snack_absorption_delay=snack_absorption_delay,
55+
hypotreatment_absorption=hypotreatment_absorption,
5356
) -> Dict:
5457
```
5558
### Input parameters
@@ -119,6 +122,9 @@ replay simulations. Ignored if twinning_method is 'map'.
119122
- `sensors`: , optional, default: `None`: A `list[Sensors]` to be used in each of the replay simulations. Its length
120123
must coincide with the selected `n_replay`. Used when working with intervals. If `None` new sensors will be used.
121124
- `sensor_cgm`, optional, default: `Vettoretti19CGM`: The class of the CGM error model to be used during the replay simulation.
125+
- `snack_absorption`, optional, default: `None`: A value to override the identified snack absorption rate.
126+
- `snack_absorption_delay`, optional, default: `None`: A value to override the identified snack absorption delay (between 0 and 60 minutes)
127+
- `hypotreatment_absorption`, optional, default: `None`: A value to override the identified hypotreatment absorption rate.
122128

123129
::: tip REMEMBER
124130
The total length of the simulation, `simulation_length`, is defined in minutes and determined by ReplayBG automatically
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import os
2+
import numpy as np
3+
4+
from utils import load_test_data, load_patient_info
5+
6+
from py_replay_bg.py_replay_bg import ReplayBG
7+
from py_replay_bg.visualizer import Visualizer
8+
from py_replay_bg.analyzer import Analyzer
9+
10+
# Set verbosity
11+
verbose = True
12+
plot_mode = False
13+
14+
# Set other parameters for twinning
15+
blueprint = 'multi-meal'
16+
save_folder = os.path.join(os.path.abspath(''), '..', '..', '..')
17+
18+
# load patient_info
19+
patient_info = load_patient_info()
20+
p = np.where(patient_info['patient'] == 1)[0][0]
21+
# Set bw and u2ss
22+
bw = float(patient_info.bw.values[p])
23+
24+
# Instantiate ReplayBG
25+
rbg = ReplayBG(blueprint=blueprint, save_folder=save_folder,
26+
yts=5, exercise=False,
27+
seed=1,
28+
verbose=verbose, plot_mode=plot_mode)
29+
30+
# Load data and set save_name
31+
data = load_test_data(day=1)
32+
save_name = 'data_day_' + str(1)
33+
34+
print("Replaying " + save_name)
35+
36+
# Replay the twin with the same input data used for twinning
37+
replay_results = rbg.replay(data=data, bw=bw, save_name=save_name,
38+
twinning_method='map',
39+
save_workspace=True,
40+
save_suffix='_replay_map', snack_absorption=.5, snack_absorption_delay=60)
41+
42+
# Visualize and analyze results
43+
Visualizer.plot_replay_results(replay_results, data=data)
44+
analysis = Analyzer.analyze_replay_results(replay_results, data=data)
45+
print('Mean glucose: %.2f mg/dl' % analysis['median']['glucose']['variability']['mean_glucose'])
46+
print('TIR: %.2f %%' % analysis['median']['glucose']['time_in_ranges']['time_in_target'])
47+
print('N Days: %.2f days' % analysis['median']['glucose']['data_quality']['number_days_of_observation'])

py_replay_bg/input_validation/__init__.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,3 +609,51 @@ def __init__(self, yts):
609609
def validate(self):
610610
if not isinstance(self.yts, int):
611611
raise Exception("'yts' input must be an integer.'")
612+
613+
614+
class SnackAbsorptionValidator:
615+
"""
616+
Validates the 'snack_absorption' parameter.
617+
"""
618+
619+
def __init__(self, snack_absorption):
620+
self.snack_absorption = snack_absorption
621+
622+
def validate(self):
623+
if self.snack_absorption is not None:
624+
if not isinstance(self.snack_absorption, float):
625+
raise Exception("'snack_absorption' input must be a float.'")
626+
if not (0 <= self.snack_absorption <= 1):
627+
raise Exception("'snack_absorption' input must be between 0 and 1.'")
628+
629+
630+
class SnackAbsorptionDelayValidator:
631+
"""
632+
Validates the 'snack_absorption_delay' parameter.
633+
"""
634+
635+
def __init__(self, snack_absorption_delay):
636+
self.snack_absorption_delay = snack_absorption_delay
637+
638+
def validate(self):
639+
if self.snack_absorption_delay is not None:
640+
if not isinstance(self.snack_absorption_delay, int):
641+
raise Exception("'snack_absorption_delay' input must be a integer.'")
642+
if not (0 <= self.snack_absorption_delay <= 60):
643+
raise Exception("'snack_absorption_delay' input must be between 0 and 60.'")
644+
645+
646+
class HypotreatmentAbsorptionValidator:
647+
"""
648+
Validates the 'hypotreatment_absorption' parameter.
649+
"""
650+
651+
def __init__(self, hypotreatment_absorption):
652+
self.hypotreatment_absorption = hypotreatment_absorption
653+
654+
def validate(self):
655+
if self.hypotreatment_absorption is not None:
656+
if not isinstance(self.hypotreatment_absorption, float):
657+
raise Exception("'hypotreatment_absorption' input must be a float.'")
658+
if not (0 <= self.hypotreatment_absorption <= 1):
659+
raise Exception("'hypotreatment_absorption' input must be between 0 and 1.'")

py_replay_bg/input_validation/input_validator_replay.py

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,9 @@ def __init__(self,
119119
sensors: list,
120120
blueprint: str,
121121
exercise: bool,
122+
snack_absorption: float,
123+
snack_absorption_delay: int,
124+
hypotreatment_absorption: float,
122125
):
123126
self.data = data
124127
self.bw = bw
@@ -147,7 +150,9 @@ def __init__(self,
147150
self.sensors = sensors
148151
self.blueprint = blueprint
149152
self.exercise = exercise
150-
153+
self.snack_absorption = snack_absorption
154+
self.snack_absorption_delay = snack_absorption_delay
155+
self.hypotreatment_absorption = hypotreatment_absorption
151156

152157
def validate(self):
153158
"""
@@ -156,7 +161,8 @@ def validate(self):
156161

157162
# Validate the 'data' input
158163
DataValidator(modality='replay', data=self.data, blueprint=self.blueprint, exercise=self.exercise,
159-
bolus_source=self.bolus_source, basal_source=self.basal_source, cho_source=self.cho_source).validate()
164+
bolus_source=self.bolus_source, basal_source=self.basal_source,
165+
cho_source=self.cho_source).validate()
160166

161167
# Validate the 'bw' input
162168
BWValidator(bw=self.bw).validate()
@@ -192,7 +198,8 @@ def validate(self):
192198
BolusCalculatorHandlerValidator(bolus_calculator_handler=self.bolus_calculator_handler).validate()
193199

194200
# Validate the 'bolus_calculator_handler_params' input
195-
BolusCalculatorHandlerParamsValidator(bolus_calculator_handler_params=self.bolus_calculator_handler_params).validate()
201+
BolusCalculatorHandlerParamsValidator(
202+
bolus_calculator_handler_params=self.bolus_calculator_handler_params).validate()
196203

197204
# Validate the 'basal_handler' input
198205
BasalHandlerValidator(basal_handler=self.basal_handler).validate()
@@ -207,7 +214,8 @@ def validate(self):
207214
HypotreatmentsHandlerValidator(hypotreatments_handler=self.hypotreatments_handler).validate()
208215

209216
# Validate the 'hypotreatments_handler_params' input
210-
HypotreatmentsHandlerParamsValidator(hypotreatments_handler_params=self.hypotreatments_handler_params).validate()
217+
HypotreatmentsHandlerParamsValidator(
218+
hypotreatments_handler_params=self.hypotreatments_handler_params).validate()
211219

212220
# Validate the 'enable_correction_boluses' input
213221
EnableCorrectionBolusesValidator(enable_correction_boluses=self.enable_correction_boluses).validate()
@@ -216,7 +224,8 @@ def validate(self):
216224
CorrectionBolusesHandlerValidator(correction_boluses_handler=self.correction_boluses_handler).validate()
217225

218226
# Validate the 'correction_boluses_handler_params' input
219-
CorrectionBolusesHandlerParamsValidator(correction_boluses_handler_params=self.correction_boluses_handler_params).validate()
227+
CorrectionBolusesHandlerParamsValidator(
228+
correction_boluses_handler_params=self.correction_boluses_handler_params).validate()
220229

221230
# Validate the 'save_suffix' input
222231
SaveSuffixValidator(save_suffix=self.save_suffix).validate()
@@ -229,3 +238,12 @@ def validate(self):
229238

230239
# Validate the 'sensors' input
231240
SensorsValidator(sensors=self.sensors).validate()
241+
242+
# Validate the 'snack_absorption' input
243+
SnackAbsorptionValidator(snack_absorption=self.snack_absorption).validate()
244+
245+
# Validate the 'snack_absorption_delay' input
246+
SnackAbsorptionDelayValidator(snack_absorption_delay=self.snack_absorption_delay).validate()
247+
248+
# Validate the 'hypotreatment_absorption' input
249+
HypotreatmentAbsorptionValidator(hypotreatment_absorption=self.hypotreatment_absorption).validate()

py_replay_bg/py_replay_bg.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,9 @@ def replay(self,
300300
n_replay: int = 1000,
301301
sensors: list | None = None,
302302
sensor_cgm: CGM = Vettoretti19CGM,
303+
snack_absorption: float = None,
304+
snack_absorption_delay: int = None,
305+
hypotreatment_absorption: float = None,
303306
) -> Dict:
304307
"""
305308
Runs ReplayBG according to the chosen modality.
@@ -375,6 +378,13 @@ def replay(self,
375378
sensor_cgm: CGM, optional, default: Vettoretti19CGM
376379
The class representing the sensors to be used in each of the replay simulations.
377380
381+
snack_absorption: float, optional, default: None
382+
The absorption rate to be used for snacks (kabs_S in the model). If None, the value identified during twinning is used.
383+
snack_absorption_delay: int, optional, default: None
384+
The absorption delay in minutes to be used for snacks (beta_S in the model). If None, the value identified during twinning is used.
385+
hypotreatment_absorption: float, optional, default: None
386+
The absorption rate to be used for hypotreatments (kabs_H in the model). If None, the value identified during twinning is used.
387+
378388
Returns
379389
-------
380390
replay_results: dict
@@ -445,6 +455,9 @@ def replay(self,
445455
sensors=sensors,
446456
exercise=self.environment.exercise,
447457
blueprint=self.environment.blueprint,
458+
snack_absorption=snack_absorption,
459+
snack_absorption_delay=snack_absorption_delay,
460+
hypotreatment_absorption=hypotreatment_absorption,
448461
).validate()
449462

450463
if self.environment.verbose:
@@ -460,6 +473,13 @@ def replay(self,
460473
draws = twinning_results['draws']
461474
u2ss = twinning_results['u2ss']
462475

476+
if snack_absorption is not None:
477+
draws['kabs_S'] = snack_absorption
478+
if snack_absorption_delay is not None:
479+
draws['beta_S'] = snack_absorption_delay
480+
if hypotreatment_absorption is not None:
481+
draws['kabs_H'] = hypotreatment_absorption
482+
463483
if self.environment.blueprint == 'single-meal':
464484
model = T1DModelSingleMeal(data=data, bw=bw, u2ss=u2ss, x0=x0,
465485
previous_data_name=previous_data_name,

0 commit comments

Comments
 (0)