Skip to content

Commit b6029f5

Browse files
committed
[master] v 0.1.1
1 parent ca95d2d commit b6029f5

File tree

17 files changed

+383
-55
lines changed

17 files changed

+383
-55
lines changed
61.6 KB
Binary file not shown.

dist/py_replay_bg-0.1.1.tar.gz

55.1 KB
Binary file not shown.

py_replay_bg.egg-info/PKG-INFO

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Metadata-Version: 2.1
22
Name: py_replay_bg
3-
Version: 0.1.0
3+
Version: 0.1.1
44
Summary: ReplayBG is a digital twin-based methodology to assess new strategies for type 1 diabetes management.
55
Author-email: Giacomo Cappon <cappongiacomo@gmail.com>
66
Project-URL: Homepage, https://github.com/gcappon/py_replay_bg
@@ -51,7 +51,7 @@ Requires-Dist: pillow==10.2.0
5151
Requires-Dist: pkginfo==1.10.0
5252
Requires-Dist: plotly==5.20.0
5353
Requires-Dist: pluggy==1.4.0
54-
Requires-Dist: py-agata==0.0.5
54+
Requires-Dist: py-agata==0.0.6
5555
Requires-Dist: Pygments==2.17.2
5656
Requires-Dist: pyparsing==3.1.2
5757
Requires-Dist: pyproject_hooks==1.0.0

py_replay_bg.egg-info/SOURCES.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ py_replay_bg/dss/default_dss_handlers.py
1515
py_replay_bg/environment/__init__.py
1616
py_replay_bg/example/code/quick-start.py
1717
py_replay_bg/identification/__init__.py
18+
py_replay_bg/identification/map.py
1819
py_replay_bg/identification/mcmc.py
1920
py_replay_bg/input_validation/__init__.py
2021
py_replay_bg/model/__init__.py
@@ -25,6 +26,7 @@ py_replay_bg/tests/__init__.py
2526
py_replay_bg/tests/test_plot_replay_bg_intervals.py
2627
py_replay_bg/tests/test_replay_bg.py
2728
py_replay_bg/tests/test_replay_bg_intervals.py
29+
py_replay_bg/tests/test_replay_bg_intervals_map.py
2830
py_replay_bg/utils/__init__.py
2931
py_replay_bg/utils/stats.py
3032
py_replay_bg/visualizer/__init__.py

py_replay_bg.egg-info/requires.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ pillow==10.2.0
3636
pkginfo==1.10.0
3737
plotly==5.20.0
3838
pluggy==1.4.0
39-
py-agata==0.0.5
39+
py-agata==0.0.6
4040
Pygments==2.17.2
4141
pyparsing==3.1.2
4242
pyproject_hooks==1.0.0

py_replay_bg/environment/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ def __init__(self, modality, save_name, save_folder, save_suffix='', save_worksp
123123
os.mkdir(os.path.join(self.replay_bg_path, 'results'))
124124
if not (os.path.exists(os.path.join(self.replay_bg_path, 'results', 'draws'))):
125125
os.mkdir(os.path.join(self.replay_bg_path, 'results', 'draws'))
126+
if not (os.path.exists(os.path.join(self.replay_bg_path, 'results', 'map'))):
127+
os.mkdir(os.path.join(self.replay_bg_path, 'results', 'map'))
126128
if not (os.path.exists(os.path.join(self.replay_bg_path, 'results', 'logs'))):
127129
os.mkdir(os.path.join(self.replay_bg_path, 'results', 'logs'))
128130
if not (os.path.exists(os.path.join(self.replay_bg_path, 'results', 'mcmc_chains'))):

py_replay_bg/identification/map.py

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
import os
2+
3+
import matplotlib.pyplot as plt
4+
from matplotlib import pylab
5+
6+
7+
import numpy as np
8+
9+
from multiprocessing import Pool
10+
11+
import pickle
12+
13+
import copy
14+
import pandas as pd
15+
16+
from py_replay_bg.data import ReplayBGData
17+
18+
from datetime import datetime, timedelta
19+
20+
from tqdm import tqdm
21+
22+
from scipy.optimize import minimize
23+
24+
import warnings
25+
26+
# Suppress all RuntimeWarnings
27+
warnings.filterwarnings("ignore", category=RuntimeWarning)
28+
29+
class MAP:
30+
"""
31+
A class that orchestrates the identification process via MAP.
32+
"""
33+
34+
def __init__(self, model,
35+
max_iter: int = 100000):
36+
"""
37+
Constructs all the necessary attributes for the MCMC object.
38+
39+
Parameters
40+
----------
41+
model: Model
42+
An object that represents the physiological model hyperparameters to be used by ReplayBG.
43+
max_iter: int, optional, default : 1000
44+
Maximum number of iterations.
45+
46+
Returns
47+
-------
48+
None
49+
50+
Raises
51+
------
52+
None
53+
54+
See Also
55+
--------
56+
None
57+
58+
Examples
59+
--------
60+
None
61+
"""
62+
63+
# Physiological model to identify
64+
self.model = model
65+
66+
# Number of unknown parameters to identify
67+
self.n_dim = len(self.model.unknown_parameters)
68+
69+
# Number of times to re-run the procedure
70+
self.n_rerun = 64
71+
72+
# Maximum number of iterations
73+
self.max_iter = max_iter
74+
75+
# Maximum number of function evaluations
76+
self.max_fev = 1000000
77+
78+
def identify(self, data, rbg_data, rbg):
79+
"""
80+
Runs the identification procedure.
81+
82+
Parameters
83+
----------
84+
data: pd.DataFrame
85+
Pandas dataframe which contains the data to be used by the tool.
86+
rbg_data: ReplayBGData
87+
An object containing the data to be used during the identification procedure.
88+
rbg: ReplayBG
89+
The instance of ReplayBG.
90+
91+
Returns
92+
-------
93+
draws: dict
94+
A dictionary containing the chain and the samples obtained from the MCMC procedure and the copula sampling, respectively.
95+
96+
Raises
97+
------
98+
None
99+
100+
See Also
101+
--------
102+
None
103+
104+
Examples
105+
--------
106+
None
107+
"""
108+
109+
# Set the initial positions of the walkers.
110+
start = self.model.start_guess + self.model.start_guess_sigma * np.random.randn(self.n_rerun, self.n_dim)
111+
start[start < 0] = 0
112+
113+
# Set the pooler
114+
pool = None
115+
if rbg.environment.parallelize:
116+
pool = Pool(processes=rbg.environment.n_processes)
117+
118+
# Setup the options
119+
options = dict()
120+
options['maxiter'] = self.max_iter
121+
options['maxfev'] = self.max_fev
122+
options['disp'] = False
123+
124+
# Select the function to minimize
125+
neg_log_posterior_func = self.model.neg_log_posterior_single_meal if self.model.is_single_meal else self.model.neg_log_posterior_multi_meal
126+
127+
# Initialize results
128+
results = []
129+
130+
if pool is None:
131+
132+
if rbg.environment.verbose:
133+
iterator = tqdm(range(self.n_rerun))
134+
iterator.set_description("Min loss: %f" % np.nan)
135+
else:
136+
iterator = range(self.n_rerun)
137+
138+
# Initialize best
139+
best = -1
140+
141+
for r in iterator:
142+
result = run_map(start[r], neg_log_posterior_func, rbg_data, options)
143+
results.append(result)
144+
if best == -1 or result['fun'] < results[best]['fun']:
145+
best = r
146+
if rbg.environment.verbose:
147+
iterator.set_description("Min loss %f" % results[best]['fun'])
148+
149+
else:
150+
# Prepare input arguments as tuples for starmap
151+
args = [(start[r], neg_log_posterior_func, rbg_data, options) for r in range(self.n_rerun)]
152+
153+
# Initialize best
154+
best = -1
155+
156+
# Get results (verbosity not allowed for the moment)
157+
results = pool.starmap(run_map, args)
158+
159+
# Get best
160+
for r, result in enumerate(results):
161+
if best == -1 or result['fun'] < results[best]['fun']:
162+
best = r
163+
164+
draws = dict()
165+
for up in range(len(rbg.model.unknown_parameters)):
166+
draws[rbg.model.unknown_parameters[up]] = results[best]['x'][up]
167+
168+
# Save results
169+
identification_results = dict()
170+
identification_results['draws'] = draws
171+
172+
with open(os.path.join(rbg.environment.replay_bg_path, 'results', 'map',
173+
'map_' + rbg.environment.save_name + '.pkl'), 'wb') as file:
174+
pickle.dump(identification_results, file)
175+
176+
return draws
177+
178+
def run_map(start, func, rbg_data, options):
179+
result = minimize(func, start, method='Powell', args=(rbg_data,), options=options)
180+
ret = dict()
181+
ret['fun'] = result.fun
182+
ret['x'] = result.x
183+
return ret

py_replay_bg/input_validation/__init__.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,19 @@ def validate(self):
301301
raise Exception("'previous_data_name' input must be a string.'")
302302

303303

304+
class IdentificationMethodValidator:
305+
"""
306+
Class for validating the 'identification_method' input parameter of ReplayBG.
307+
"""
308+
309+
def __init__(self, identification_method):
310+
self.identification_method = identification_method
311+
312+
def validate(self):
313+
if not (self.identification_method == 'mcmc' or self.identification_method == 'map'):
314+
raise Exception("'cgm_model' input must be 'mcmc' or 'map'.")
315+
316+
304317
class NStepsValidator:
305318
"""
306319
Class for validating the 'n_steps' input parameter of ReplayBG.
@@ -595,6 +608,7 @@ def __init__(self, modality, data, bw, u2ss, scenario, save_name, save_suffix,
595608
cgm_model,
596609
X0,
597610
previous_data_name,
611+
identification_method,
598612
n_steps, save_chains, analyze_results,
599613
CR, CF, GT,
600614
meal_generator_handler, meal_generator_handler_params,
@@ -626,6 +640,8 @@ def __init__(self, modality, data, bw, u2ss, scenario, save_name, save_suffix,
626640
self.X0 = X0
627641
self.previous_data_name = previous_data_name
628642

643+
self.identification_method = identification_method
644+
629645
self.n_steps = n_steps
630646
self.save_chains = save_chains
631647
self.analyze_results = analyze_results
@@ -709,6 +725,9 @@ def validate(self):
709725
# Validate the 'previous_data_name' input
710726
PreviousDataNameValidator(previous_data_name=self.previous_data_name).validate()
711727

728+
# Validate the 'identification_method' input
729+
IdentificationMethodValidator(identification_method=self.identification_method).validate()
730+
712731
# Validate the 'n_steps' input
713732
NStepsValidator(n_steps=self.n_steps).validate()
714733

0 commit comments

Comments
 (0)