Skip to content

Commit 3ea1748

Browse files
GiacomoGiacomo
authored andcommitted
[master] added few options to fasten things up during replay. v 0.0.5
1 parent 991e3b4 commit 3ea1748

File tree

8 files changed

+252
-113
lines changed

8 files changed

+252
-113
lines changed

py_replay_bg/environment/__init__.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ class Environment:
1919
A string to be attached as suffix to the resulting output files' name.
2020
save_workspace: bool
2121
A boolean that specifies whether or not to save the results of ReplayBG in the results/workspaces directory.
22+
analyze_results : bool
23+
A flag that specifies whether to analyze the resulting trace or not. Setting this flag to False will fasten
24+
ReplayBG and it is recommended if ReplayBG will be a component of a bigger framework (e.g., to be used in an
25+
iterative process).
2226
scenario: str, {'single-meal', 'multi-meal'}
2327
A string that specifies whether the given scenario refers to a single-meal scenario or a multi-meal scenario.
2428
bolus_source : str, {'data', or 'dss'}
@@ -47,7 +51,8 @@ class Environment:
4751
None
4852
"""
4953

50-
def __init__(self, modality, save_name, save_folder, save_suffix='', save_workspace=False, scenario='single_meal',
54+
def __init__(self, modality, save_name, save_folder, save_suffix='', save_workspace=False, analyze_results=True,
55+
scenario='single_meal',
5156
bolus_source='data', basal_source='data', cho_source='data', seed=1,
5257
parallelize=False, n_processes=None, plot_mode=True, verbose=True):
5358
"""
@@ -66,6 +71,10 @@ def __init__(self, modality, save_name, save_folder, save_suffix='', save_worksp
6671
A string to be attached as suffix to the resulting output files' name.
6772
save_workspace: bool, optional, default : False
6873
A boolean that specifies whether or not to save the results of ReplayBG in the results/workspaces directory.
74+
analyze_results : bool, optional, default : True
75+
A flag that specifies whether to analyze the resulting trace or not. Setting this flag to False will fasten
76+
ReplayBG and it is recommended if ReplayBG will be a component of a bigger framework (e.g., to be used in an
77+
iterative process).
6978
scenario: str, {'single-meal', 'multi-meal'}, optional, default : 'single-meal'
7079
A string that specifies whether the given scenario refers to a single-meal scenario or a multi-meal scenario.
7180
bolus_source : str, {'data', or 'dss'}, optional, default : 'data'
@@ -120,6 +129,9 @@ def __init__(self, modality, save_name, save_folder, save_suffix='', save_worksp
120129
# Set the save workspace flag
121130
self.save_workspace = save_workspace
122131

132+
# Set the analyze results flag
133+
self.analyze_results = analyze_results
134+
123135
# Single-meal or multi-meal scenario?
124136
self.scenario = scenario
125137

py_replay_bg/identification/mcmc.py

Lines changed: 39 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@ class MCMC:
3737
Number of steps to use for the main chain.
3838
thin_factor: int
3939
Chain thin factor to use.
40-
to_sample: int
41-
Number of samples to generate via the copula.
4240
save_chains: bool
4341
A flag that specifies whether to save the resulting mcmc chains and copula samplers.
4442
callback_ncheck: int
@@ -52,7 +50,6 @@ class MCMC:
5250

5351
def __init__(self, model,
5452
n_steps=10000,
55-
to_sample=1000,
5653
save_chains=False,
5754
callback_ncheck=100):
5855
"""
@@ -64,8 +61,6 @@ def __init__(self, model,
6461
An object that represents the physiological model hyperparameters to be used by ReplayBG.
6562
n_steps: int, optional, default : 10000
6663
Number of steps to use for the main chain.
67-
to_sample: int, optional, default : 1000
68-
Number of samples to generate via the copula.
6964
save_chains: bool, optional, default : False
7065
A flag that specifies whether to save the resulting mcmc chains and copula samplers.
7166
callback_ncheck: int, optional, default : 100
@@ -103,9 +98,6 @@ def __init__(self, model,
10398
# Chain thin factor to use
10499
self.thin_factor = int(np.ceil(n_steps / 1000))
105100

106-
# Number of samples to generate via the copula
107-
self.to_sample = to_sample
108-
109101
# Save the chains?
110102
self.save_chains = save_chains
111103

@@ -159,7 +151,7 @@ def identify(self, data, rbg_data, rbg):
159151

160152
posterior_func = self.model.log_posterior_single_meal if self.model.is_single_meal else self.model.log_posterior_multi_meal
161153
sampler = zeus.EnsembleSampler(self.n_walkers, self.n_dim, posterior_func, args=[rbg_data],
162-
verbose=rbg.environment.verbose, pool=pool, maxsteps=10)
154+
verbose=rbg.environment.verbose, pool=pool, maxsteps=1000)
163155
sampler.run_mcmc(start, self.n_steps, callbacks=[cb0, cb1, cb2])
164156
sampler.summary # Print summary diagnostics
165157

@@ -175,32 +167,35 @@ def identify(self, data, rbg_data, rbg):
175167
draws = dict()
176168
for up in range(len(rbg.model.unknown_parameters)):
177169
draws[rbg.model.unknown_parameters[up]] = dict()
178-
draws[rbg.model.unknown_parameters[up]]['samples'] = np.empty(self.to_sample)
170+
draws[rbg.model.unknown_parameters[up]]['samples_1000'] = np.empty(1000)
171+
draws[rbg.model.unknown_parameters[up]]['samples_100'] = np.empty(100)
172+
draws[rbg.model.unknown_parameters[up]]['samples_10'] = np.empty(10)
179173
draws[rbg.model.unknown_parameters[up]]['chain'] = chain[:, up]
180174

181-
if rbg.environment.verbose:
182-
print('Extracting samples from copula')
183-
184-
to_be_sampled = [True] * self.to_sample
185-
while any(to_be_sampled):
175+
to_sample = [1000, 100, 10]
176+
for nr in to_sample:
177+
if rbg.environment.verbose:
178+
print('Extracting samples from copula - ' + str(nr) + ' realizations')
186179

187-
#Get the idxs of the missing samples
188-
tbs = np.where(to_be_sampled)[0]
180+
to_be_sampled = [True] * nr
181+
while any(to_be_sampled):
189182

190-
#Get the new samples
191-
samples = distributions.sample(len(tbs)).to_numpy()
183+
#Get the idxs of the missing samples
184+
tbs = np.where(to_be_sampled)[0]
192185

193-
#For each sample...
194-
for i in range(0, len(tbs)):
186+
#Get the new samples
187+
samples = distributions.sample(len(tbs)).to_numpy()
195188

196-
#...check if it is ok. If so...
197-
if self.model.check_copula_extraction(samples[i]):
189+
#For each sample...
190+
for i in range(0, len(tbs)):
198191

199-
# ...flag it and fill the final vector
200-
to_be_sampled[tbs[i]] = False
201-
for up in range(len(rbg.model.unknown_parameters)):
202-
draws[rbg.model.unknown_parameters[up]]['samples'][tbs[i]] = samples[i,up]
192+
#...check if it is ok. If so...
193+
if self.model.check_copula_extraction(samples[i]):
203194

195+
# ...flag it and fill the final vector
196+
to_be_sampled[tbs[i]] = False
197+
for up in range(len(rbg.model.unknown_parameters)):
198+
draws[rbg.model.unknown_parameters[up]]['samples_'+str(nr)][tbs[i]] = samples[i,up]
204199

205200
# Check physiological plausibility
206201
draws['physiological_plausibility'] = self.__check_physiological_plausibility(draws, data, rbg)
@@ -253,15 +248,15 @@ def __check_physiological_plausibility(self, draws, data, rbg):
253248
"""
254249

255250
if rbg.environment.verbose:
256-
print('Running physiological plausibility checks...')
251+
print('Running physiological plausibility checks (only on the 1000 samples)...')
257252

258253
# Initialize the return vector
259254
physiological_plausibility = dict()
260255

261-
physiological_plausibility['test_1'] = np.full((self.to_sample,), True)
262-
physiological_plausibility['test_2'] = np.full((self.to_sample,), True)
263-
physiological_plausibility['test_3'] = np.full((self.to_sample,), True)
264-
physiological_plausibility['test_4'] = np.full((self.to_sample,), True)
256+
physiological_plausibility['test_1'] = np.full((1000,), True)
257+
physiological_plausibility['test_2'] = np.full((1000,), True)
258+
physiological_plausibility['test_3'] = np.full((1000,), True)
259+
physiological_plausibility['test_4'] = np.full((1000,), True)
265260

266261
rbg_fake = copy.copy(rbg)
267262
rbg_fake.model = copy.copy(rbg.model)
@@ -299,9 +294,9 @@ def __check_physiological_plausibility(self, draws, data, rbg):
299294

300295
# Test 1: "if no insulin is injected, BG must go above 300 mg/dl in 1000 min"
301296
if rbg.environment.verbose:
302-
iterations = tqdm(range(self.to_sample), desc='Test 1 of 4')
297+
iterations = tqdm(range(1000), desc='Test 1 of 4')
303298
else:
304-
iterations = range(0, self.to_sample)
299+
iterations = range(0, 1000)
305300

306301
# Set simulation data
307302
data_fake_test_1 = copy.copy(data_fake)
@@ -312,7 +307,7 @@ def __check_physiological_plausibility(self, draws, data, rbg):
312307

313308
# set the model parameters
314309
for p in rbg_fake.model.unknown_parameters:
315-
setattr(rbg_fake.model.model_parameters,p,draws[p]['samples'][r])
310+
setattr(rbg_fake.model.model_parameters,p,draws[p]['samples_1000'][r])
316311
rbg_fake.model.model_parameters.kgri = rbg_fake.model.model_parameters.kempt
317312

318313
if (rbg_fake.sensors.cgm.model == 'CGM'):
@@ -326,9 +321,9 @@ def __check_physiological_plausibility(self, draws, data, rbg):
326321

327322
# Test 2: "if a bolus of 15 U is injected, BG should drop below 100 mg/dl"
328323
if rbg.environment.verbose:
329-
iterations = tqdm(range(self.to_sample), desc='Test 2 of 4')
324+
iterations = tqdm(range(1000), desc='Test 2 of 4')
330325
else:
331-
iterations = range(0, self.to_sample)
326+
iterations = range(0, 1000)
332327

333328
# Set simulation data
334329
data_fake_test_2 = copy.copy(data_fake)
@@ -351,7 +346,7 @@ def __check_physiological_plausibility(self, draws, data, rbg):
351346

352347
# set the model parameters
353348
for p in rbg_fake.model.unknown_parameters:
354-
setattr(rbg_fake.model.model_parameters, p, draws[p]['samples'][r])
349+
setattr(rbg_fake.model.model_parameters, p, draws[p]['samples_1000'][r])
355350
rbg_fake.model.model_parameters.kgri = rbg_fake.model.model_parameters.kempt
356351

357352
if (rbg_fake.sensors.cgm.model == 'CGM'):
@@ -365,9 +360,9 @@ def __check_physiological_plausibility(self, draws, data, rbg):
365360

366361
# Test 3: "it exists a basal insulin value such that glucose stays between 90 and 160 mg/dl",
367362
if rbg.environment.verbose:
368-
iterations = tqdm(range(self.to_sample), desc='Test 3 of 4')
363+
iterations = tqdm(range(1000), desc='Test 3 of 4')
369364
else:
370-
iterations = range(0, self.to_sample)
365+
iterations = range(0, 1000)
371366

372367
# Set simulation data
373368
data_fake_test_3 = copy.copy(data_fake)
@@ -384,7 +379,7 @@ def __check_physiological_plausibility(self, draws, data, rbg):
384379

385380
# set the model parameters
386381
for p in rbg_fake.model.unknown_parameters:
387-
setattr(rbg_fake.model.model_parameters, p, draws[p]['samples'][r])
382+
setattr(rbg_fake.model.model_parameters, p, draws[p]['samples_1000'][r])
388383
rbg_fake.model.model_parameters.kgri = rbg_fake.model.model_parameters.kempt
389384

390385
if (rbg_fake.sensors.cgm.model == 'CGM'):
@@ -418,9 +413,9 @@ def __check_physiological_plausibility(self, draws, data, rbg):
418413

419414
# Test 4: "a variation of basal insulin of 0.01 U/h does not vary basal glucose more than 20 mg/dl"
420415
if rbg.environment.verbose:
421-
iterations = tqdm(range(self.to_sample), desc='Test 4 of 4')
416+
iterations = tqdm(range(1000), desc='Test 4 of 4')
422417
else:
423-
iterations = range(0, self.to_sample)
418+
iterations = range(0, 1000)
424419

425420
# Set simulation data
426421
data_fake_test_4 = copy.copy(data_fake)
@@ -433,7 +428,7 @@ def __check_physiological_plausibility(self, draws, data, rbg):
433428

434429
# set the model parameters
435430
for p in rbg_fake.model.unknown_parameters:
436-
setattr(rbg_fake.model.model_parameters,p,draws[p]['samples'][r])
431+
setattr(rbg_fake.model.model_parameters,p,draws[p]['samples_1000'][r])
437432
rbg_fake.model.model_parameters.kgri = rbg_fake.model.model_parameters.kempt
438433

439434
if (rbg_fake.sensors.cgm.model == 'CGM'):

py_replay_bg/input_validation/__init__.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -271,30 +271,30 @@ def validate(self):
271271
raise Exception("'n_steps' input must be an integer.'")
272272

273273

274-
class ToSampleValidator:
274+
class SaveChainsValidator:
275275
"""
276-
Class for validating the 'to_sample' input parameter of ReplayBG.
276+
Class for validating the 'save_chains' input parameter of ReplayBG.
277277
"""
278278

279-
def __init__(self, to_sample):
280-
self.to_sample = to_sample
279+
def __init__(self, save_chains):
280+
self.save_chains = save_chains
281281

282282
def validate(self):
283-
if not isinstance(self.to_sample, int):
284-
raise Exception("'to_sample' input must be an integer.'")
283+
if not isinstance(self.save_chains, bool):
284+
raise Exception("'save_chains' input must be a boolean.'")
285285

286286

287-
class SaveChainsValidator:
287+
class AnalyzeResultsValidator:
288288
"""
289-
Class for validating the 'save_chains' input parameter of ReplayBG.
289+
Class for validating the 'analyze_results' input parameter of ReplayBG.
290290
"""
291291

292-
def __init__(self, save_chains):
293-
self.save_chains = save_chains
292+
def __init__(self, analyze_results):
293+
self.analyze_results = analyze_results
294294

295295
def validate(self):
296-
if not isinstance(self.save_chains, bool):
297-
raise Exception("'save_chains' input must be a boolean.'")
296+
if not isinstance(self.analyze_results, bool):
297+
raise Exception("'analyze_results' input must be a boolean.'")
298298

299299

300300
class CRValidator:
@@ -550,7 +550,7 @@ def __init__(self, modality, data, bw, scenario, save_name, save_suffix,
550550
yts, glucose_model, pathology, exercise, seed,
551551
bolus_source, basal_source, cho_source,
552552
cgm_model,
553-
n_steps, to_sample, save_chains,
553+
n_steps, save_chains, analyze_results,
554554
CR, CF, GT,
555555
meal_generator_handler, meal_generator_handler_params,
556556
bolus_calculator_handler, bolus_calculator_handler_params,
@@ -578,8 +578,8 @@ def __init__(self, modality, data, bw, scenario, save_name, save_suffix,
578578
self.cgm_model = cgm_model
579579

580580
self.n_steps = n_steps
581-
self.to_sample = to_sample
582581
self.save_chains = save_chains
582+
self.analyze_results = analyze_results
583583

584584
self.CR = CR
585585
self.CF = CF
@@ -654,12 +654,12 @@ def validate(self):
654654
# Validate the 'n_steps' input
655655
NStepsValidator(n_steps=self.n_steps).validate()
656656

657-
# Validate the 'to_sample' input
658-
ToSampleValidator(to_sample=self.to_sample).validate()
659-
660657
# Validate the 'save_chains' input
661658
SaveChainsValidator(save_chains=self.save_chains).validate()
662659

660+
# Validate the 'analyze_results' input
661+
AnalyzeResultsValidator(analyze_results=self.analyze_results).validate()
662+
663663
# Validate the 'CR' input
664664
CRValidator(CR=self.CR).validate()
665665

0 commit comments

Comments
 (0)