pypharm 1.4.2__tar.gz → 1.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pypharm
3
- Version: 1.4.2
3
+ Version: 1.5.0
4
4
  Summary: Module for solving pharmacokinetic problems
5
5
  Home-page: https://github.com/Krash13/PyPharm
6
6
  Author: Krash13
@@ -0,0 +1,81 @@
1
+ MODEL_CONST = {
2
+ 'human':{
3
+ 'adipose': {'V':143, 'Q': 60 * 3.7},
4
+ 'bone': {'V':124, 'Q': 60 * 3.6} ,
5
+ 'brain': {'V':20.7, 'Q': 60 * 10} ,
6
+ 'gut': {'V':23.6, 'Q': 60 * 13} ,
7
+ 'heart': {'V':3.8, 'Q': 60 * 2.14},
8
+ 'kidney': {'V':4.4, 'Q': 60 * 15.7} ,
9
+ 'liver': {'V':24.1, 'Q': 60 * 21} ,
10
+ 'lung': {'V':16.7, 'Q': 60 * 71} ,
11
+ 'muscle': {'V':429, 'Q': 60 * 10.7} ,
12
+ 'pancreas': {'V':1.2, 'Q': 60 * 1.9} ,
13
+ 'skin': {'V':111, 'Q': 60 * 4.3} ,
14
+ 'spleen': {'V':2.7, 'Q': 60 * 1.1},
15
+ 'stomach': {'V':2.2, 'Q': 60 * 0.56},
16
+ 'teaster': {'V':0.51, 'Q': 60 * 0.04},
17
+ 'arterial_blood': {'V':25.7} ,
18
+ 'venous_blood': {'V':51.4}
19
+ },
20
+ 'rat':{
21
+ 'adipose': {'V':40, 'Q': 60 * 1.6},
22
+ 'bone': {'V':53.2, 'Q': 60 * 10.12},
23
+ 'brain': {'V':6.8, 'Q': 60 * 5.32} ,
24
+ 'gut': {'V':40, 'Q': 60 * 52} ,
25
+ 'heart': {'V':3.2, 'Q': 60 * 15.68},
26
+ 'kidney': {'V':9.2, 'Q': 60 * 36.92},
27
+ 'liver': {'V':41.2, 'Q': 60 * 80} ,
28
+ 'lung': {'V':4, 'Q': 60 * 203.2} ,
29
+ 'muscle': {'V':487.6, 'Q': 60 * 30} ,
30
+ 'pancreas': {'V':5.2, 'Q': 60 * 4} ,
31
+ 'skin': {'V':160, 'Q': 60 * 20} ,
32
+ 'spleen': {'V':2.4, 'Q': 60 * 5} ,
33
+ 'stomach': {'V':4.4, 'Q': 60 * 8.2} ,
34
+ 'teaster': {'V':10, 'Q': 60 * 1.8} ,
35
+ 'arterial_blood': {'V':22.4} ,
36
+ # 'arterial_blood': {'V':22.4, 'Q': 60 * 10.8} ,
37
+ 'venous_blood': {'V':45.2}
38
+ },
39
+ 'mouse': {
40
+ 'adipose': {'V': 1000 * 1e-3 / 0.02, 'Q': 60 * 4e-5 * 1000 / 0.02},
41
+ 'bone': {'V': 1000 * 1.58e-3 / 0.02, 'Q': 60 * 2.53e-4 * 1000 / 0.02},
42
+ 'brain': {'V': 1000 * 1.7e-4 / 0.02, 'Q': 60 * 1.3e-4 * 1000 / 0.02},
43
+ 'gut': {'V': 1000 * 6.27e-4 / 0.02, 'Q': 60 * 5e-4 * 1000 / 0.02},
44
+ 'heart': {'V': 1000 * 9.5e-5 / 0.02, 'Q': 60 * 2.8e-4 * 1000 / 0.02},
45
+ 'kidney': {'V': 1000 * 3.4e-4 / 0.02, 'Q': 60 * 1.3e-3 * 1000 / 0.02},
46
+ 'liver': {'V': 1000 * 1e-3/ 0.02, 'Q' : 60 * 3.5e-4 * 1000 / 0.02},
47
+ 'lung': {'V': 1000 * 1e-4 / 0.02, 'Q': 60 * 5.47e-3 * 1000 / 0.02},
48
+ 'muscle': {'V': 1000 * 0.01e-1 / 0.02, 'Q': 60 * 9.1e-4 * 1000 / 0.02},
49
+ 'pancreas': {'V': 1000 * 1.3e-4 / 0.02, 'Q': 60 * 5.2e-5 * 1000 / 0.02},
50
+ 'skin': {'V': 1000 * 2.9e-3 / 0.02, 'Q': 60 * 4.1e-4 * 1000 / 0.02},
51
+ 'spleen': {'V': 1000 * 1e-4 / 0.02, 'Q': 60 * 9e-5 * 1000 / 0.02},
52
+ 'stomach': {'V': 1000 * 1.1e-4 / 0.02, 'Q': 60 * 1.1e-4 * 1000 / 0.02},
53
+ 'teaster': {'V': 1, 'Q': 1},
54
+ 'arterial_blood': {'V': 1000 * 2.28e-4 / 0.02},
55
+ # 'arterial_blood': {'V':22.4, 'Q': 60 * 10.8} ,
56
+ 'venous_blood': {'V': 1000 * 5.25e-4 / 0.02}
57
+ }
58
+ }
59
+
60
+ class ORGAN_NAMES:
61
+
62
+ LUNG = 'lung'
63
+ HEART = 'heart'
64
+ BRAIN = 'brain'
65
+ MUSCLE = 'muscle'
66
+ ADIPOSE = 'adipose'
67
+ SKIN = 'skin'
68
+ BONE = 'bone'
69
+ KIDNEY = 'kidney'
70
+ LIVER = 'liver'
71
+ GUT = 'gut'
72
+ SPLEEN = 'spleen'
73
+ STOMACH = 'stomach'
74
+ PANCREAS = 'pancreas'
75
+ VENOUS = 'venous_blood'
76
+ ARTERIAL = 'arterial_blood'
77
+
78
+ class ANIMALS:
79
+ HUMAN = 'human'
80
+ RAT = 'rat'
81
+ MOUSE = 'mouse'
@@ -4,9 +4,9 @@ import numpy as np
4
4
  from scipy.integrate import solve_ivp, RK45
5
5
  from scipy.integrate import simps
6
6
  from scipy.optimize import minimize
7
- from ..algorithms.country_optimization import CountriesAlgorithm
8
- from ..algorithms.country_optimization_v2 import CountriesAlgorithm_v2
9
- from ..algorithms.genetic_optimization import GeneticAlgorithm
7
+ from PyPharm.algorithms.country_optimization import CountriesAlgorithm
8
+ from PyPharm.algorithms.country_optimization_v2 import CountriesAlgorithm_v2
9
+ from PyPharm.algorithms.genetic_optimization import GeneticAlgorithm
10
10
  from numba import njit
11
11
  import matplotlib.pyplot as plt
12
12
 
@@ -127,7 +127,8 @@ class BaseCompartmentModel:
127
127
  t_span=ts,
128
128
  y0=c0,
129
129
  max_step=max_step,
130
- t_eval=t_eval
130
+ t_eval=t_eval,
131
+ method='LSODA'
131
132
  )
132
133
  return self.last_result
133
134
 
@@ -0,0 +1,672 @@
1
+ import inspect
2
+ from numbalsoda import lsoda_sig, lsoda
3
+ import numpy as np
4
+ from scipy.integrate import solve_ivp, LSODA
5
+ from scipy.optimize import minimize
6
+ from PyPharm.algorithms.country_optimization import CountriesAlgorithm
7
+ from PyPharm.algorithms.country_optimization_v2 import CountriesAlgorithm_v2
8
+ from PyPharm.algorithms.genetic_optimization import GeneticAlgorithm
9
+ from PyPharm.constants import MODEL_CONST, ORGAN_NAMES, ANIMALS
10
+ from numba import njit, types, cfunc
11
+ from numba.typed import Dict
12
+ import matplotlib.pyplot as plt
13
+
14
+
15
+
16
+ class PBPKmod:
17
+
18
+ _organs = ['lung', 'heart', 'brain', 'muscle', 'adipose', 'skin', 'bone', 'kidney',
19
+ 'liver', 'gut', 'spleen', 'stomach', 'pancreas', 'venous_blood', 'arterial_blood']
20
+ _cl_organs = ['kidney', 'liver']
21
+
22
+ def __init__(self, know_k=None, know_cl=None, numba_option=False, lsoda_option=False):
23
+
24
+ self.know_k = know_k if know_k is not None else {}
25
+ self.know_cl = know_cl if know_cl is not None else {}
26
+ self._optim = False
27
+ self.numba_option = numba_option
28
+ self.lsoda_option = lsoda_option
29
+ if numba_option or lsoda_option:
30
+ self.cnst_v_dict = {}
31
+ for key in MODEL_CONST:
32
+ cnst_v = Dict.empty(
33
+ key_type=types.unicode_type,
34
+ value_type=types.float64
35
+ )
36
+ for k, v in MODEL_CONST[key].items():
37
+ cnst_v[k] = v['V']
38
+ self.cnst_v_dict[key] = cnst_v
39
+ self.cnst_q_dict = {}
40
+ for key in MODEL_CONST:
41
+ cnst_q = Dict.empty(
42
+ key_type=types.unicode_type,
43
+ value_type=types.float64
44
+ )
45
+ for k, v in MODEL_CONST[key].items():
46
+ if v.get('Q'):
47
+ cnst_q[k] = v['Q']
48
+ self.cnst_q_dict[key] = cnst_q
49
+
50
+ def load_optimization_data(self, time_exp, dict_c_exp, start_c_in_venous, animal=ANIMALS.MOUSE):
51
+ self.time_exp = time_exp
52
+ self.dict_c_exp = dict_c_exp
53
+ self.start_c_in_venous = start_c_in_venous
54
+ self.animal = animal
55
+
56
+ def _get_sol_difurs(self):
57
+ return self(max(self.time_exp), self.start_c_in_venous, self.animal)
58
+
59
+ def fitness(self, k_cl):
60
+
61
+ self.k_cl = k_cl
62
+
63
+ sol_difurs = self._get_sol_difurs()
64
+ # Список для хранения результатов
65
+ present_organs_indices = []
66
+
67
+ # Проверяем, какие ключи из 'organs' есть в 'dict_n'
68
+ for organ in self._organs:
69
+ if organ in self.dict_c_exp:
70
+ index = self._organs.index(organ) # Получаем индекс органа в списке organs
71
+ present_organs_indices.append((organ, index))
72
+
73
+ rez_err = 0
74
+ for organ, index in present_organs_indices:
75
+ mean_y = sum(sol_difurs[index]) / len(sol_difurs[index])
76
+ a = [(sol_difurs[index][self.time_exp[i]] - self.dict_c_exp[organ][i]) ** 2 for i in range(len(self.dict_c_exp[organ]))]
77
+ a = sum(a)
78
+ b = [(mean_y - self.dict_c_exp[organ][i]) ** 2 for i in
79
+ range(len(self.dict_c_exp[organ]))]
80
+ b = sum(b)
81
+ rez_err += a / b
82
+ # rez_err += sum([abs(sol_difurs[:, index][self.time_exp[i]] - self.dict_c_exp[organ][i]) for i in
83
+ # range(len(self.dict_c_exp[organ]))])
84
+
85
+ return rez_err
86
+ def _get_result(self, fun, t, max_time, K_CL, animal=ANIMALS.MOUSE):
87
+ if not self.lsoda_option:
88
+ return solve_ivp(
89
+ fun=fun,
90
+ t_span=[0, max_time],
91
+ y0=self.y0,
92
+ t_eval=t,
93
+ method=LSODA,
94
+ )
95
+ else:
96
+ return lsoda(
97
+ funcptr=fun,
98
+ u0=np.array(self.y0, dtype=np.float64),
99
+ t_eval=np.array(t, dtype=np.float64),
100
+ data=np.array(K_CL, dtype=np.float64),
101
+ )
102
+
103
+ def _prepare_result(self, t, res):
104
+ if not self.lsoda_option:
105
+ self._res = res.y
106
+ else:
107
+ res = res.T
108
+ self._res = res
109
+ self.last_result = {
110
+ 't': t * 60
111
+ }
112
+ if not self.lsoda_option:
113
+ for organ in self._organs:
114
+ index = self._organs.index(organ)
115
+ self.last_result[organ] = res.y[index]
116
+ else:
117
+ for organ in self._organs:
118
+ index = self._organs.index(organ)
119
+ self.last_result[organ] = res[index]
120
+
121
+ def __call__(self, max_time, start_c_in_venous, animal=ANIMALS.MOUSE, step=1.0):
122
+ self.y0 = [0 for _ in range(15)] # всего в модели 15 органов
123
+ self.y0[-2] = start_c_in_venous
124
+ t = np.linspace(0, max_time, max_time + 1 if self._optim else int(1 / step * max_time) + 1) / 60
125
+
126
+ if not hasattr(self, 'k_cl'):
127
+ self.k_cl = []
128
+
129
+ full_k = []
130
+ i = 0
131
+ for name in self._organs:
132
+ know_k = self.know_k.get(name)
133
+ if know_k is not None:
134
+ full_k.append(know_k)
135
+ else:
136
+ full_k.append(self.k_cl[i])
137
+ i += 1
138
+ full_cl = []
139
+
140
+ for name in self._cl_organs:
141
+ know_k = self.know_cl.get(name)
142
+ if know_k is not None:
143
+ full_cl.append(know_k)
144
+ else:
145
+ full_cl.append(self.k_cl[i])
146
+ i += 1
147
+ if not self.numba_option and not self.lsoda_option:
148
+ res = self._get_result(
149
+ fun=lambda time, y: self.fullPBPKmodel(y, time, [*full_k, *full_cl], animal),
150
+ t=t,
151
+ max_time=max_time,
152
+ K_CL=[*full_k, *full_cl],
153
+ animal=animal
154
+ )
155
+ elif self.lsoda_option:
156
+ cnst_v = self.cnst_v_dict[animal]
157
+ cnst_q = self.cnst_q_dict[animal]
158
+ res, success = self._get_result(
159
+ fun=self.lsoda_fullPBPK_for_optimization.address,
160
+ t=t,
161
+ max_time=max_time,
162
+ K_CL=[*full_k, *full_cl, *[cnst_q[key] for key in cnst_q.keys()], *[cnst_v[key] for key in cnst_v.keys()]],
163
+ animal=animal
164
+ )
165
+ else:
166
+ k_cl = np.array([*full_k, *full_cl])
167
+ cnst_v = self.cnst_v_dict[animal]
168
+ cnst_q = self.cnst_q_dict[animal]
169
+ function = lambda time, c: self.numba_fullPBPK_for_optimization(
170
+ y=c,
171
+ t=time,
172
+ K_CL=k_cl.astype(np.float64),
173
+ cnst_q=cnst_q,
174
+ cnst_v=cnst_v
175
+ )
176
+ res = self._get_result(
177
+ fun=function,
178
+ t=t,
179
+ max_time=max_time,
180
+ K_CL=[*full_k, *full_cl],
181
+ animal=animal
182
+ )
183
+ self._prepare_result(t, res)
184
+ return self._res
185
+
186
+ def plot_last_result(self, organ_names=[], left=None, right=None, user_names={}, theoretic_data={}, y_lims={}):
187
+ if hasattr(self, 'last_result'):
188
+ for name in organ_names:
189
+ if theoretic_data.get(name):
190
+ plt.plot(theoretic_data[name]['x'], theoretic_data[name]['y'], '*r')
191
+ plt.plot(
192
+ self.last_result['t'],
193
+ self.last_result.get(name),
194
+ )
195
+ plt.title(user_names.get(name, name))
196
+ plt.xlim(left=left, right=right)
197
+ if y_lims.get(name):
198
+ plt.ylim(y_lims.get(name))
199
+ plt.grid()
200
+ plt.show()
201
+
202
+ def optimize(self, method=None, user_method=None, method_is_func=True,
203
+ optimization_func_name='__call__', **kwargs):
204
+ """
205
+ Функция оптимизации модели
206
+
207
+ Args:
208
+ method: Метод оптимизации, любой доступный minimize + 'country_optimization' и 'country_optimization_v2'
209
+ max_step: Максимальный шаг при решении СДУ
210
+ **kwargs: Дополнительные именованные аргументы
211
+
212
+ Returns:
213
+ None
214
+ """
215
+ self._optim = True
216
+ f = lambda x: self.fitness(x)
217
+ if user_method is not None:
218
+ if method_is_func:
219
+ x = user_method(f, **kwargs)
220
+ else:
221
+ optimization_obj = user_method(f, **kwargs)
222
+ x = getattr(optimization_obj, optimization_func_name)()
223
+ else:
224
+ if method == 'country_optimization':
225
+ CA = CountriesAlgorithm(
226
+ f=f,
227
+ memory_list=getattr(self, 'memory', None),
228
+ **kwargs
229
+ )
230
+ CA.start()
231
+ x = CA.countries[0].population[0].x
232
+ elif method == 'country_optimization_v2':
233
+ CA = CountriesAlgorithm_v2(
234
+ f=f,
235
+ **kwargs
236
+ )
237
+ CA.start()
238
+ x = CA.countries[0].population[0].x
239
+ elif method == 'GA':
240
+ CA = GeneticAlgorithm(
241
+ f=f,
242
+ **kwargs
243
+ )
244
+ x = CA.start()
245
+ else:
246
+ res = minimize(
247
+ fun=f,
248
+ method=method,
249
+ **kwargs
250
+ )
251
+ x = res.x
252
+ self._optim = False
253
+ return x
254
+
255
+ def update_know_params(self, k_cl=None):
256
+ if k_cl:
257
+ i = 0
258
+ for name in self._organs:
259
+ know_k = self.know_k.get(name)
260
+ if know_k is None:
261
+ self.know_k[name] = k_cl[i]
262
+ i += 1
263
+ for name in self._cl_organs:
264
+ know_cl = self.know_cl.get(name)
265
+ if know_cl is None:
266
+ self.know_cl[name] = k_cl[i]
267
+ i += 1
268
+
269
+ def get_unknown_params(self):
270
+ result = []
271
+ for name in self._organs:
272
+ know_k = self.know_k.get(name)
273
+ if know_k is None:
274
+ result.append(f"k_{name}")
275
+ for name in self._cl_organs:
276
+ know_cl = self.know_cl.get(name)
277
+ if know_cl is None:
278
+ result.append(f"cl_{name}")
279
+ return result
280
+
281
+ def fullPBPKmodel(self, y, t, K_CL, animal=ANIMALS.MOUSE): # V, Q, K, CL):
282
+ # 15 органов
283
+ cnst = MODEL_CONST[animal]
284
+ C_lung, C_heart, C_brain, C_muscle, C_fat, C_skin, C_bone, \
285
+ C_kidney, C_liver, C_gut, C_spleen, C_stomach, C_pancreas, C_V, C_A = y
286
+
287
+ K_lung, K_heart, K_brain, K_muscle, K_fat, K_skin, K_bone, \
288
+ K_kidney, K_liver, K_gut, K_spleen, K_stomach, K_pancreas, K_liver_cl, K_kidney_cl = K_CL[:15]
289
+ CL_kidney, CL_liver = K_CL[15:]
290
+
291
+ dC_lung_dt = cnst['lung']['Q'] * (C_V - C_lung / K_lung) / cnst['lung']['V']
292
+ dC_heart_dt = cnst['heart']['Q'] * (C_A - C_heart / K_heart) / cnst['heart']['V']
293
+ dC_brain_dt = cnst['brain']['Q'] * (C_A - C_brain / K_brain) / cnst['brain']['V']
294
+ dC_muscle_dt = cnst['muscle']['Q'] * (C_A - C_muscle / K_muscle) / cnst['muscle']['V']
295
+ dC_fat_dt = cnst['adipose']['Q'] * (C_A - C_fat / K_fat) / cnst['adipose']['V']
296
+ dC_skin_dt = cnst['skin']['Q'] * (C_A - C_skin / K_skin) / cnst['skin']['V']
297
+ dC_bone_dt = cnst['bone']['Q'] * (C_A - C_bone / K_bone) / cnst['bone']['V']
298
+ # Kidney V(Kidney)*dC(Kidney)/dt = Q(Kidney)*C(A)-Q(Kidney)*CV(Kidney)-CL(Kidney,int)*CV(Kidney,int)?
299
+ dC_kidney_dt = (cnst['kidney']['Q'] * (C_A - C_kidney / K_kidney) - CL_kidney * C_kidney / K_kidney_cl) / \
300
+ cnst['kidney']['V'] # ???
301
+
302
+ # Liver V(Liver)*dC(Liver)/dt = (Q(Liver)-Q(Spleen)-Q(Gut)-Q(Pancreas)-Q(Stomach))*C(A) + Q(Spleen)*CV(Spleen) +
303
+ # + Q(Gut)*CV(Gut) + Q(Pancreas)*CV(Pancreas) + Q(Stomach)*CV(Stomach) -
304
+ # - Q(Liver)*CV(Liver) - CL(Liver,int)*CV(Liver,int)? # тут скорее всего нужно вычитать потоки из друг друга дополнительно по крови что бы сохранить массовый баланс
305
+ Q_liver_in_from_art = cnst['liver']['Q'] - cnst['gut']['Q'] - cnst['spleen']['Q'] - \
306
+ cnst['pancreas']['Q'] - cnst['stomach']['Q']
307
+ dC_liver_dt = (
308
+ Q_liver_in_from_art * C_A + cnst['gut']['Q'] * C_gut / K_gut
309
+ + cnst['spleen']['Q'] * C_spleen / K_spleen
310
+ + cnst['stomach']['Q'] * C_stomach / K_stomach
311
+ + cnst['pancreas']['Q'] * C_pancreas / K_pancreas
312
+ - cnst['liver']['Q'] * C_liver / K_liver
313
+ - CL_liver * C_liver / K_liver_cl # ???
314
+ ) / cnst['liver']['V']
315
+
316
+ dC_gut_dt = cnst['gut']['Q'] * (C_A - C_gut / K_gut) / cnst['gut']['V']
317
+ dC_spleen_dt = cnst['spleen']['Q'] * (C_A - C_spleen / K_spleen) / cnst['spleen']['V']
318
+ dC_stomach_dt = cnst['stomach']['Q'] * (C_A - C_stomach / K_stomach) / cnst['stomach']['V']
319
+ dC_pancreas_dt = cnst['pancreas']['Q'] * (C_A - C_pancreas / K_pancreas) / cnst['pancreas']['V']
320
+
321
+ dC_venouse_dt = (
322
+ cnst['heart']['Q'] * C_heart / K_heart
323
+ + cnst['brain']['Q'] * C_brain / K_brain
324
+ + cnst['muscle']['Q'] * C_muscle / K_muscle
325
+ + cnst['skin']['Q'] * C_skin / K_skin
326
+ + cnst['adipose']['Q'] * C_fat / K_fat
327
+ + cnst['bone']['Q'] * C_bone / K_bone
328
+ + cnst['kidney']['Q'] * C_kidney / K_kidney
329
+ + cnst['liver']['Q'] * C_liver / K_liver
330
+ - cnst['lung']['Q'] * C_V
331
+ ) / cnst['venous_blood']['V']
332
+
333
+ dC_arterial_dt = cnst['lung']['Q'] * (C_lung / K_lung - C_A) / cnst['arterial_blood']['V']
334
+
335
+ y_new = [dC_lung_dt, dC_heart_dt, dC_brain_dt, dC_muscle_dt, dC_fat_dt, dC_skin_dt, dC_bone_dt, \
336
+ dC_kidney_dt, dC_liver_dt, dC_gut_dt, dC_spleen_dt, dC_stomach_dt, dC_pancreas_dt, dC_venouse_dt,
337
+ dC_arterial_dt]
338
+ return y_new
339
+
340
+ @staticmethod
341
+ @njit
342
+ def numba_fullPBPK_for_optimization(y, t, K_CL, cnst_q, cnst_v):
343
+ C_lung, C_heart, C_brain, C_muscle, C_fat, C_skin, C_bone, \
344
+ C_kidney, C_liver, C_gut, C_spleen, C_stomach, C_pancreas, C_V, C_A = y
345
+
346
+ K_lung, K_heart, K_brain, K_muscle, K_fat, K_skin, K_bone, \
347
+ K_kidney, K_liver, K_gut, K_spleen, K_stomach, K_pancreas, K_liver_cl, K_kidney_cl = K_CL[:15]
348
+ CL_kidney, CL_liver = K_CL[15:]
349
+
350
+ dC_lung_dt = cnst_q['lung'] * (C_V - C_lung / K_lung) / cnst_v['lung']
351
+ dC_heart_dt = cnst_q['heart'] * (C_A - C_heart / K_heart) / cnst_v['heart']
352
+ dC_brain_dt = cnst_q['brain'] * (C_A - C_brain / K_brain) / cnst_v['brain']
353
+ dC_muscle_dt = cnst_q['muscle'] * (C_A - C_muscle / K_muscle) / cnst_v['muscle']
354
+ dC_fat_dt = cnst_q['adipose'] * (C_A - C_fat / K_fat) / cnst_v['adipose']
355
+ dC_skin_dt = cnst_q['skin'] * (C_A - C_skin / K_skin) / cnst_v['skin']
356
+ dC_bone_dt = cnst_q['bone'] * (C_A - C_bone / K_bone) / cnst_v['bone']
357
+ # Kidney V(Kidney)*dC(Kidney)/dt = Q(Kidney)*C(A)-Q(Kidney)*CV(Kidney)-CL(Kidney,int)*CV(Kidney,int)?
358
+ dC_kidney_dt = (cnst_q['kidney'] * (C_A - C_kidney / K_kidney) - CL_kidney * C_kidney / K_kidney_cl) / \
359
+ cnst_v['kidney'] # ???
360
+
361
+ # Liver V(Liver)*dC(Liver)/dt = (Q(Liver)-Q(Spleen)-Q(Gut)-Q(Pancreas)-Q(Stomach))*C(A) + Q(Spleen)*CV(Spleen) +
362
+ # + Q(Gut)*CV(Gut) + Q(Pancreas)*CV(Pancreas) + Q(Stomach)*CV(Stomach) -
363
+ # - Q(Liver)*CV(Liver) - CL(Liver,int)*CV(Liver,int)? # тут скорее всего нужно вычитать потоки из друг друга дополнительно по крови что бы сохранить массовый баланс
364
+ Q_liver_in_from_art = cnst_q['liver'] - cnst_q['gut'] - cnst_q['spleen'] - \
365
+ cnst_q['pancreas'] - cnst_q['stomach']
366
+ dC_liver_dt = (
367
+ Q_liver_in_from_art * C_A + cnst_q['gut'] * C_gut / K_gut
368
+ + cnst_q['spleen'] * C_spleen / K_spleen
369
+ + cnst_q['stomach'] * C_stomach / K_stomach
370
+ + cnst_q['pancreas'] * C_pancreas / K_pancreas
371
+ - cnst_q['liver'] * C_liver / K_liver
372
+ - CL_liver * C_liver / K_liver_cl # ???
373
+ ) / cnst_v['liver']
374
+
375
+ dC_gut_dt = cnst_q['gut'] * (C_A - C_gut / K_gut) / cnst_v['gut']
376
+ dC_spleen_dt = cnst_q['spleen'] * (C_A - C_spleen / K_spleen) / cnst_v['spleen']
377
+ dC_stomach_dt = cnst_q['stomach'] * (C_A - C_stomach / K_stomach) / cnst_v['stomach']
378
+ dC_pancreas_dt = cnst_q['pancreas'] * (C_A - C_pancreas / K_pancreas) / cnst_v['pancreas']
379
+
380
+ dC_venouse_dt = (
381
+ cnst_q['heart'] * C_heart / K_heart
382
+ + cnst_q['brain'] * C_brain / K_brain
383
+ + cnst_q['muscle'] * C_muscle / K_muscle
384
+ + cnst_q['skin'] * C_skin / K_skin
385
+ + cnst_q['adipose'] * C_fat / K_fat
386
+ + cnst_q['bone'] * C_bone / K_bone
387
+ + cnst_q['kidney'] * C_kidney / K_kidney
388
+ + cnst_q['liver'] * C_liver / K_liver
389
+ - cnst_q['lung'] * C_V
390
+ ) / cnst_v['venous_blood']
391
+
392
+ dC_arterial_dt = cnst_q['lung'] * (C_lung / K_lung - C_A) / cnst_v['arterial_blood']
393
+
394
+ y_new = np.array([dC_lung_dt, dC_heart_dt, dC_brain_dt, dC_muscle_dt, dC_fat_dt, dC_skin_dt, dC_bone_dt, \
395
+ dC_kidney_dt, dC_liver_dt, dC_gut_dt, dC_spleen_dt, dC_stomach_dt, dC_pancreas_dt, dC_venouse_dt,
396
+ dC_arterial_dt]).astype(np.float64)
397
+ return y_new
398
+
399
+ @staticmethod
400
+ @cfunc(lsoda_sig)
401
+ def lsoda_fullPBPK_for_optimization(t, y, y_new, data):
402
+
403
+ C_lung = y[0]
404
+ C_heart = y[1]
405
+ C_brain = y[2]
406
+ C_muscle = y[3]
407
+ C_fat = y[4]
408
+ C_skin = y[5]
409
+ C_bone = y[6]
410
+ C_kidney = y[7]
411
+ C_liver = y[8]
412
+ C_gut = y[9]
413
+ C_spleen = y[10]
414
+ C_stomach = y[11]
415
+ C_pancreas = y[12]
416
+ C_V = y[13]
417
+ C_A = y[14]
418
+
419
+ K_lung = data[0]
420
+ K_heart = data[1]
421
+ K_brain = data[2]
422
+ K_muscle = data[3]
423
+ K_fat = data[4]
424
+ K_skin = data[5]
425
+ K_bone = data[6]
426
+ K_kidney = data[7]
427
+ K_liver = data[8]
428
+ K_gut = data[9]
429
+ K_spleen = data[10]
430
+ K_stomach = data[11]
431
+ K_pancreas = data[12]
432
+ K_liver_cl = data[13]
433
+ K_kidney_cl = data[14]
434
+ CL_kidney = data[15]
435
+ CL_liver = data[16]
436
+
437
+ cnst_q_adipose = data[17]
438
+ cnst_q_bone = data[18]
439
+ cnst_q_brain = data[19]
440
+ cnst_q_gut = data[20]
441
+ cnst_q_heart = data[21]
442
+ cnst_q_kidney = data[22]
443
+ cnst_q_liver = data[23]
444
+ cnst_q_lung = data[24]
445
+ cnst_q_muscle = data[25]
446
+ cnst_q_pancreas = data[26]
447
+ cnst_q_skin = data[27]
448
+ cnst_q_spleen = data[28]
449
+ cnst_q_stomach = data[29]
450
+ cnst_q_teaster = data[30]
451
+
452
+ cnst_v_adipose = data[31]
453
+ cnst_v_bone = data[32]
454
+ cnst_v_brain = data[33]
455
+ cnst_v_gut = data[34]
456
+ cnst_v_heart = data[35]
457
+ cnst_v_kidney = data[36]
458
+ cnst_v_liver = data[37]
459
+ cnst_v_lung = data[38]
460
+ cnst_v_muscle = data[39]
461
+ cnst_v_pancreas = data[40]
462
+ cnst_v_skin = data[41]
463
+ cnst_v_spleen = data[42]
464
+ cnst_v_stomach = data[43]
465
+ cnst_v_teaster = data[44]
466
+ cnst_v_arterial_blood = data[45]
467
+ cnst_v_venous_blood = data[46]
468
+
469
+ dC_lung_dt = cnst_q_lung * (C_V - C_lung / K_lung) / cnst_v_lung
470
+ dC_heart_dt = cnst_q_heart * (C_A - C_heart / K_heart) / cnst_v_heart
471
+ dC_brain_dt = cnst_q_brain * (C_A - C_brain / K_brain) / cnst_v_brain
472
+ dC_muscle_dt = cnst_q_muscle * (C_A - C_muscle / K_muscle) / cnst_v_muscle
473
+ dC_fat_dt = cnst_q_adipose * (C_A - C_fat / K_fat) / cnst_v_adipose
474
+ dC_skin_dt = cnst_q_skin * (C_A - C_skin / K_skin) / cnst_v_skin
475
+ dC_bone_dt = cnst_q_bone * (C_A - C_bone / K_bone) / cnst_v_bone
476
+ # Kidney V(Kidney)*dC(Kidney)/dt = Q(Kidney)*C(A)-Q(Kidney)*CV(Kidney)-CL(Kidney,int)*CV(Kidney,int)?
477
+ dC_kidney_dt = (cnst_q_kidney * (C_A - C_kidney / K_kidney) - CL_kidney * C_kidney / K_kidney_cl) / \
478
+ cnst_v_kidney # ???
479
+
480
+ # Liver V(Liver)*dC(Liver)/dt = (Q(Liver)-Q(Spleen)-Q(Gut)-Q(Pancreas)-Q(Stomach))*C(A) + Q(Spleen)*CV(Spleen) +
481
+ # + Q(Gut)*CV(Gut) + Q(Pancreas)*CV(Pancreas) + Q(Stomach)*CV(Stomach) -
482
+ # - Q(Liver)*CV(Liver) - CL(Liver,int)*CV(Liver,int)? # тут скорее всего нужно вычитать потоки из друг друга дополнительно по крови что бы сохранить массовый баланс
483
+ Q_liver_in_from_art = cnst_q_liver - cnst_q_gut - cnst_q_spleen - \
484
+ cnst_q_pancreas - cnst_q_stomach
485
+ dC_liver_dt = (
486
+ Q_liver_in_from_art * C_A + cnst_q_gut * C_gut / K_gut
487
+ + cnst_q_spleen * C_spleen / K_spleen
488
+ + cnst_q_stomach * C_stomach / K_stomach
489
+ + cnst_q_pancreas * C_pancreas / K_pancreas
490
+ - cnst_q_liver * C_liver / K_liver
491
+ - CL_liver * C_liver / K_liver_cl # ???
492
+ ) / cnst_v_liver
493
+
494
+ dC_gut_dt = cnst_q_gut * (C_A - C_gut / K_gut) / cnst_v_gut
495
+ dC_spleen_dt = cnst_q_spleen * (C_A - C_spleen / K_spleen) / cnst_v_spleen
496
+ dC_stomach_dt = cnst_q_stomach * (C_A - C_stomach / K_stomach) / cnst_v_stomach
497
+ dC_pancreas_dt = cnst_q_pancreas * (C_A - C_pancreas / K_pancreas) / cnst_v_pancreas
498
+
499
+ dC_venouse_dt = (
500
+ cnst_q_heart * C_heart / K_heart
501
+ + cnst_q_brain * C_brain / K_brain
502
+ + cnst_q_muscle * C_muscle / K_muscle
503
+ + cnst_q_skin * C_skin / K_skin
504
+ + cnst_q_adipose * C_fat / K_fat
505
+ + cnst_q_bone * C_bone / K_bone
506
+ + cnst_q_kidney * C_kidney / K_kidney
507
+ + cnst_q_liver * C_liver / K_liver
508
+ - cnst_q_lung * C_V
509
+ ) / cnst_v_venous_blood
510
+
511
+ dC_arterial_dt = cnst_q_lung * (C_lung / K_lung - C_A) / cnst_v_arterial_blood
512
+ y_new[0] = dC_lung_dt
513
+ y_new[1] = dC_heart_dt
514
+ y_new[2] = dC_brain_dt
515
+ y_new[3] = dC_muscle_dt
516
+ y_new[4] = dC_fat_dt
517
+ y_new[5] = dC_skin_dt
518
+ y_new[6] = dC_bone_dt
519
+ y_new[7] = dC_kidney_dt
520
+ y_new[8] = dC_liver_dt
521
+ y_new[9] = dC_gut_dt
522
+ y_new[10] = dC_spleen_dt
523
+ y_new[11] = dC_stomach_dt
524
+ y_new[12] = dC_pancreas_dt
525
+ y_new[13] = dC_venouse_dt
526
+ y_new[14] = dC_arterial_dt
527
+
528
+ # y_new = [dC_lung_dt, dC_heart_dt, dC_brain_dt, dC_muscle_dt, dC_fat_dt, dC_skin_dt, dC_bone_dt, \
529
+ # dC_kidney_dt, dC_liver_dt, dC_gut_dt, dC_spleen_dt, dC_stomach_dt, dC_pancreas_dt, dC_venouse_dt,
530
+ # dC_arterial_dt]
531
+
532
+
533
+ class ReleasePBPKmod(PBPKmod):
534
+
535
+ @staticmethod
536
+ def ode_release(solver, t, y0, release_function, d, v, is_lsoda=False):
537
+ result = []
538
+ new_y0 = y0
539
+ old_release_correction = 0
540
+ for i in range(1, len(t)):
541
+ if is_lsoda:
542
+ res, _ = solver(new_y0, t[i - 1], t[i])
543
+ y = res.T
544
+ else:
545
+ res = solver(new_y0, t[i - 1], t[i])
546
+ y = res.y
547
+ release_correction = release_function(t[i], d)
548
+ plus_release = release_correction - old_release_correction
549
+ all_corrections = plus_release
550
+ y[-2][1] += all_corrections / v
551
+ old_release_correction = release_correction
552
+ if i == 1:
553
+ result.append([y[i][0] for i in range(y.shape[0])])
554
+ new_y0 = np.array([y[i][1] for i in range(y.shape[0])])
555
+ result.append(new_y0)
556
+ return np.array(result).T
557
+
558
+ def __init__(self, release_parameters: dict=None, release_function: callable=None, know_k=None, know_cl=None, numba_option=False, lsoda_option=False):
559
+ super().__init__(
560
+ know_k=know_k, know_cl=know_cl, numba_option=numba_option, lsoda_option=lsoda_option
561
+ )
562
+ self.release_function = release_function
563
+ if release_parameters is None:
564
+ self.release_parameters = {}
565
+ else:
566
+ self.release_parameters = release_parameters
567
+ self.know_release_parameters = set(self.release_parameters.keys())
568
+
569
+ @staticmethod
570
+ def _default_release_function(t, d, m, b, c):
571
+ """
572
+ Функция для поправки на высвобождение
573
+ """
574
+ return d * c * t ** b / (t ** b + m)
575
+
576
+ def get_release_function(self):
577
+ return lambda t, d: self._get_release_function()(t, d, **self.release_parameters)
578
+
579
+ def _get_release_function(self):
580
+ if self.release_function is not None:
581
+ return self.release_function
582
+ else:
583
+ return self._default_release_function
584
+
585
+ @property
586
+ def _release_parameters_list(self) -> list[str]:
587
+ method = self._get_release_function()
588
+ arguments = inspect.getfullargspec(method).args
589
+ return [arg for arg in arguments if arg not in {'t', 'd'}]
590
+
591
+ def get_unknown_params(self):
592
+ result = super().get_unknown_params()
593
+ arguments = self._release_parameters_list
594
+ for arg in arguments:
595
+ know_arg = self.release_parameters.get(arg)
596
+ if know_arg is None:
597
+ result.append(f"release_{arg}")
598
+ return result
599
+
600
+ def update_know_params(self, k_cl=None, release_parameters=None):
601
+ super().update_know_params(k_cl)
602
+ if release_parameters is not None:
603
+ self.release_parameters = release_parameters
604
+ self.know_release_parameters = set(self.release_parameters.keys())
605
+
606
+ def _get_sol_difurs(self):
607
+ return self(max(self.time_exp), self.d, self.animal)
608
+
609
+ def fitness(self, x):
610
+
611
+ n = len(self._organs) + len(self._cl_organs) - len(self.know_cl) - len(self.know_k)
612
+ self.k_cl = x[:n]
613
+ i = 0
614
+ for arg in self._release_parameters_list:
615
+ if not arg in self.know_release_parameters:
616
+ self.release_parameters[arg] = x[n + i]
617
+ i += 1
618
+ return super().fitness(self.k_cl)
619
+
620
+ def _get_result(self, fun, t, max_time, K_CL, animal):
621
+ if not self.lsoda_option:
622
+ solver = lambda y0, t_left, t_right: solve_ivp(
623
+ fun=fun,
624
+ t_span=[t_left, t_right],
625
+ y0=y0,
626
+ t_eval=np.array([t_left, t_right]),
627
+ method=LSODA
628
+ )
629
+ return self.ode_release(solver, t, self.y0, d=self.d, v=self.v, release_function=self.get_release_function())
630
+ else:
631
+ solver = lambda y0, t_left, t_right: lsoda(
632
+ funcptr=fun,
633
+ u0=np.array(y0, dtype=np.float64),
634
+ t_eval=np.array([t_left, t_right], dtype=np.float64),
635
+ data=np.array(K_CL, dtype=np.float64),
636
+ )
637
+ return self.ode_release(solver, t, self.y0, d=self.d, v=self.v,
638
+ release_function=self.get_release_function(), is_lsoda=True), True
639
+
640
+ def _prepare_result(self, t, res):
641
+ self._res = res
642
+ self.last_result = {
643
+ 't': t * 60
644
+ }
645
+ for organ in self._organs:
646
+ index = self._organs.index(organ)
647
+ self.last_result[organ] = res[index]
648
+
649
+ def __call__(self, max_time, d, animal=ANIMALS.MOUSE, step=1.0):
650
+ self.d = d
651
+ const = MODEL_CONST[animal]
652
+ self.v = const['venous_blood']['V']
653
+ return super().__call__(
654
+ max_time=max_time,
655
+ start_c_in_venous=0,
656
+ animal=animal,
657
+ step=step
658
+ )
659
+
660
+ def optimize(self, method=None, user_method=None, method_is_func=True,
661
+ optimization_func_name='__call__', **kwargs):
662
+
663
+ return super().optimize(
664
+ method=method, user_method=user_method, method_is_func=method_is_func,
665
+ optimization_func_name=optimization_func_name, **kwargs
666
+ )
667
+
668
+ def load_optimization_data(self, time_exp, dict_c_exp, d, animal=ANIMALS.MOUSE):
669
+ self.time_exp = time_exp
670
+ self.dict_c_exp = dict_c_exp
671
+ self.d = d
672
+ self.animal = animal
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pypharm
3
- Version: 1.4.2
3
+ Version: 1.5.0
4
4
  Summary: Module for solving pharmacokinetic problems
5
5
  Home-page: https://github.com/Krash13/PyPharm
6
6
  Author: Krash13
@@ -1,5 +1,6 @@
1
1
  numpy>=1.22.1
2
- scipy>=1.8.0
2
+ scipy<=1.13.0
3
3
  numba>=0.58.1
4
4
  matplotlib>=3.5.1
5
5
  graycode>=1.0.5
6
+ numbalsoda>=0.3.4
@@ -6,7 +6,7 @@ def readme():
6
6
 
7
7
  setup(
8
8
  name='pypharm',
9
- version='1.4.2',
9
+ version='1.5.0',
10
10
  author='Krash13',
11
11
  author_email='krasheninnikov.r.s@muctr.ru',
12
12
  description='Module for solving pharmacokinetic problems',
@@ -14,7 +14,8 @@ setup(
14
14
  long_description_content_type='text/markdown',
15
15
  url='https://github.com/Krash13/PyPharm',
16
16
  packages=find_packages(),
17
- install_requires=['numpy>=1.22.1', 'scipy>=1.8.0', 'numba>=0.58.1', 'matplotlib>=3.5.1', 'graycode>=1.0.5'],
17
+ install_requires=['numpy>=1.22.1', 'scipy<=1.13.0', 'numba>=0.58.1',
18
+ 'matplotlib>=3.5.1', 'graycode>=1.0.5', 'numbalsoda>=0.3.4'],
18
19
  classifiers=[
19
20
  'Programming Language :: Python :: 3.9',
20
21
  'License :: OSI Approved :: BSD License',
@@ -1,56 +0,0 @@
1
- MODEL_CONST = {
2
- 'human':{
3
- 'adipose': {'V':143, 'Q':3.7},
4
- 'bone': {'V':124, 'Q': 3.6} ,
5
- 'brain': {'V':20.7, 'Q': 10} ,
6
- 'gut': {'V':23.6, 'Q': 13} ,
7
- 'heart': {'V':3.8, 'Q': 2.14},
8
- 'kidney': {'V':4.4, 'Q': 15.7} ,
9
- 'liver': {'V':24.1, 'Q': 21} ,
10
- 'lung': {'V':16.7, 'Q': 71} ,
11
- 'muscle': {'V':429, 'Q': 10.7} ,
12
- 'pancreas': {'V':1.2, 'Q': 1.9} ,
13
- 'skin': {'V':111, 'Q': 4.3} ,
14
- 'spleen': {'V':2.7, 'Q': 1.1},
15
- 'stomach': {'V':2.2, 'Q':0.56},
16
- 'teaster': {'V':0.51, 'Q':0.04},
17
- 'arterial_blood': {'V':25.7} ,
18
- 'venous_blood': {'V':51.4}
19
- },
20
- 'rat':{
21
- 'adipose': {'V':40, 'Q':1.6},
22
- 'bone': {'V':53.2, 'Q': 10.12},
23
- 'brain': {'V':6.8, 'Q': 5.32} ,
24
- 'gut': {'V':40, 'Q': 52} ,
25
- 'heart': {'V':3.2, 'Q': 15.68},
26
- 'kidney': {'V':9.2, 'Q': 36.92},
27
- 'liver': {'V':41.2, 'Q': 80} ,
28
- 'lung': {'V':4, 'Q': 203.2} ,
29
- 'muscle': {'V':487.6, 'Q': 30} ,
30
- 'pancreas': {'V':5.2, 'Q': 4} ,
31
- 'skin': {'V':160, 'Q': 20} ,
32
- 'spleen': {'V':2.4, 'Q': 5} ,
33
- 'stomach': {'V':4.4, 'Q':8.2} ,
34
- 'teaster': {'V':10, 'Q':1.8} ,
35
- 'arterial_blood': {'V':22.4, 'Q':10.8} ,
36
- 'venous_blood': {'V':45.2}
37
- }
38
- }
39
-
40
- class ORGAN_NAMES:
41
-
42
- LUNG = 'lung'
43
- HEART = 'heart'
44
- BRAIN = 'brain'
45
- MUSCLE = 'muscle'
46
- ADIPOSE = 'adipose'
47
- SKIN = 'skin'
48
- BONE = 'bone'
49
- KIDNEY = 'kidney'
50
- LIVER = 'liver'
51
- GUT = 'gut'
52
- SPLEEN = 'spleen'
53
- STOMACH = 'stomach'
54
- PANCREAS = 'pancreas'
55
- VENOUS = 'venous_blood'
56
- ARTERIAL = 'arterial_blood'
@@ -1,369 +0,0 @@
1
- from multiprocessing import shared_memory
2
- import datetime
3
- import numpy as np
4
- from scipy.integrate import solve_ivp, RK45, odeint
5
- from scipy.integrate import simps
6
- from scipy.optimize import minimize
7
- from PyPharm.algorithms.country_optimization import CountriesAlgorithm
8
- from PyPharm.algorithms.country_optimization_v2 import CountriesAlgorithm_v2
9
- from PyPharm.algorithms.genetic_optimization import GeneticAlgorithm
10
- from PyPharm.constants import MODEL_CONST, ORGAN_NAMES
11
- from numba import njit, types
12
- from numba.typed import Dict
13
- import matplotlib.pyplot as plt
14
-
15
- cnst_rat = MODEL_CONST['rat']
16
- cnst_human = MODEL_CONST['human']
17
-
18
-
19
- class PBPKmod:
20
-
21
- _organs = ['lung', 'heart', 'brain', 'muscle', 'adipose', 'skin', 'bone', 'kidney',
22
- 'liver', 'gut', 'spleen', 'stomach', 'pancreas', 'venous_blood', 'arterial_blood']
23
- _cl_organs = ['kidney', 'liver']
24
-
25
- def __init__(self, know_k={}, know_cl={}, numba_option=False):
26
- self.know_k = know_k
27
- self.know_cl = know_cl
28
- self._optim = False
29
- self.numba_option = numba_option
30
- if numba_option:
31
- self.cnst_v_rat = Dict.empty(
32
- key_type=types.unicode_type,
33
- value_type=types.float64
34
- )
35
- for k, v in cnst_rat.items():
36
- self.cnst_v_rat[k] = v['V']
37
- self.cnst_v_human = Dict.empty(
38
- key_type=types.unicode_type,
39
- value_type=types.float64
40
- )
41
- for k, v in cnst_human.items():
42
- self.cnst_v_human[k] = v['V']
43
- self.cnst_q_rat = Dict.empty(
44
- key_type=types.unicode_type,
45
- value_type=types.float64
46
- )
47
- for k, v in cnst_rat.items():
48
- if v.get('Q'):
49
- self.cnst_q_rat[k] = v['Q']
50
- self.cnst_q_human = Dict.empty(
51
- key_type=types.unicode_type,
52
- value_type=types.float64
53
- )
54
- for k, v in cnst_human.items():
55
- if v.get('Q'):
56
- self.cnst_q_human[k] = v['Q']
57
-
58
- def load_optimization_data(self, time_exp, dict_c_exp, start_c_in_venous, is_human=False):
59
- self.time_exp = time_exp
60
- self.dict_c_exp = dict_c_exp
61
- self.start_c_in_venous = start_c_in_venous
62
- self.is_human = is_human
63
-
64
- def fitness(self, k_cl):
65
-
66
- self.k_cl = k_cl
67
-
68
- sol_difurs = self(max(self.time_exp), self.start_c_in_venous, self.is_human)
69
- # Список для хранения результатов
70
- present_organs_indices = []
71
-
72
- # Проверяем, какие ключи из 'organs' есть в 'dict_n'
73
- for organ in self._organs:
74
- if organ in self.dict_c_exp:
75
- index = self._organs.index(organ) # Получаем индекс органа в списке organs
76
- present_organs_indices.append((organ, index))
77
-
78
- rez_err = 0
79
- for organ, index in present_organs_indices:
80
- mean_y = sum(sol_difurs[:, index]) / len(sol_difurs[:, index])
81
- a = [(sol_difurs[:, index][self.time_exp[i]] - self.dict_c_exp[organ][i]) ** 2 for i in range(len(self.dict_c_exp[organ]))]
82
- a = sum(a)
83
- b = [(mean_y - self.dict_c_exp[organ][i]) ** 2 for i in
84
- range(len(self.dict_c_exp[organ]))]
85
- b = sum(b)
86
- rez_err += a / b
87
- # rez_err += sum([abs(sol_difurs[:, index][self.time_exp[i]] - self.dict_c_exp[organ][i]) for i in
88
- # range(len(self.dict_c_exp[organ]))])
89
-
90
- return rez_err
91
-
92
- def __call__(self, max_time, start_c_in_venous, is_human=False, step=1):
93
- self.y0 = [0 for _ in range(15)] # всего в модели 15 органов
94
- self.y0[-2] = start_c_in_venous
95
- t = np.linspace(0, max_time, max_time + 1 if self._optim else int(1 / step * max_time) + 1)
96
-
97
- if not hasattr(self, 'k_cl'):
98
- self.k_cl = []
99
-
100
- full_k = []
101
- i = 0
102
- for name in self._organs:
103
- know_k = self.know_k.get(name)
104
- if know_k is not None:
105
- full_k.append(know_k)
106
- else:
107
- full_k.append(self.k_cl[i])
108
- i += 1
109
- full_cl = []
110
-
111
- for name in self._cl_organs:
112
- know_k = self.know_cl.get(name)
113
- if know_k is not None:
114
- full_cl.append(know_k)
115
- else:
116
- full_cl.append(self.k_cl[i])
117
- i += 1
118
- if not self.numba_option:
119
- sol_difurs = odeint(
120
- self.fullPBPKmodel,
121
- self.y0,
122
- t,
123
- args=([*full_k, *full_cl], is_human)
124
- )
125
- else:
126
- k_cl = np.array([*full_k, *full_cl])
127
- if is_human:
128
- cnst_v = self.cnst_v_human
129
- cnst_q = self.cnst_q_human
130
- else:
131
- cnst_v = self.cnst_v_rat
132
- cnst_q = self.cnst_q_rat
133
- function = lambda c, t: self.numba_fullPBPK_for_optimization(
134
- y=c,
135
- t=t,
136
- K_CL=k_cl.astype(np.float64),
137
- cnst_q=cnst_q,
138
- cnst_v=cnst_v
139
- )
140
- sol_difurs = odeint(
141
- function,
142
- self.y0,
143
- t
144
- )
145
- if self._optim:
146
- return sol_difurs
147
-
148
- self.last_result = {
149
- 't': t
150
- }
151
- for organ in self._organs:
152
- index = self._organs.index(organ)
153
- self.last_result[organ] = np.array([sol_difurs[i][index] for i in range(t.size)])
154
- return self.last_result
155
-
156
- def plot_last_result(self, organ_names=[], left=None, right=None, user_names={}, theoretic_data={}, y_lims={}):
157
- if hasattr(self, 'last_result'):
158
- for name in organ_names:
159
- if theoretic_data.get(name):
160
- plt.plot(theoretic_data[name]['x'], theoretic_data[name]['y'], '*r')
161
- plt.plot(
162
- self.last_result['t'],
163
- self.last_result.get(name),
164
- )
165
- plt.title(user_names.get(name, name))
166
- plt.xlim(left=left, right=right)
167
- if y_lims.get(name):
168
- plt.ylim(y_lims.get(name))
169
- plt.grid()
170
- plt.show()
171
-
172
- def optimize(self, method=None, user_method=None, method_is_func=True,
173
- optimization_func_name='__call__', **kwargs):
174
- """
175
- Функция оптимизации модели
176
-
177
- Args:
178
- method: Метод оптимизации, любой доступный minimize + 'country_optimization' и 'country_optimization_v2'
179
- max_step: Максимальный шаг при решении СДУ
180
- **kwargs: Дополнительные именованные аргументы
181
-
182
- Returns:
183
- None
184
- """
185
- self._optim = True
186
- f = lambda x: self.fitness(x)
187
- if user_method is not None:
188
- if method_is_func:
189
- x = user_method(f, **kwargs)
190
- else:
191
- optimization_obj = user_method(f, **kwargs)
192
- x = getattr(optimization_obj, optimization_func_name)()
193
- else:
194
- if method == 'country_optimization':
195
- CA = CountriesAlgorithm(
196
- f=f,
197
- memory_list=getattr(self, 'memory', None),
198
- **kwargs
199
- )
200
- CA.start()
201
- x = CA.countries[0].population[0].x
202
- elif method == 'country_optimization_v2':
203
- CA = CountriesAlgorithm_v2(
204
- f=f,
205
- **kwargs
206
- )
207
- CA.start()
208
- x = CA.countries[0].population[0].x
209
- elif method == 'GA':
210
- CA = GeneticAlgorithm(
211
- f=f,
212
- **kwargs
213
- )
214
- x = CA.start()
215
- else:
216
- res = minimize(
217
- fun=f,
218
- method=method,
219
- **kwargs
220
- )
221
- x = res.x
222
- self._optim = False
223
- return x
224
-
225
- def update_know_params(self, k_cl):
226
- i = 0
227
- for name in self._organs:
228
- know_k = self.know_k.get(name)
229
- if know_k is None:
230
- self.know_k[name] = k_cl[i]
231
- i += 1
232
- for name in self._cl_organs:
233
- know_cl = self.know_cl.get(name)
234
- if know_cl is None:
235
- self.know_cl[name] = k_cl[i]
236
- i += 1
237
-
238
- def get_unknown_params(self):
239
- result = []
240
- for name in self._organs:
241
- know_k = self.know_k.get(name)
242
- if know_k is None:
243
- result.append(f"k_{name}")
244
- for name in self._cl_organs:
245
- know_cl = self.know_cl.get(name)
246
- if know_cl is None:
247
- result.append(f"cl_{name}")
248
- return result
249
-
250
- def fullPBPKmodel(self, y, t, K_CL, is_human=False): # V, Q, K, CL):
251
- # 15 органов
252
- if is_human:
253
- cnst = cnst_human
254
- else:
255
- cnst = cnst_rat
256
- C_lung, C_heart, C_brain, C_muscle, C_fat, C_skin, C_bone, \
257
- C_kidney, C_liver, C_gut, C_spleen, C_stomach, C_pancreas, C_V, C_A = y
258
-
259
- K_lung, K_heart, K_brain, K_muscle, K_fat, K_skin, K_bone, \
260
- K_kidney, K_liver, K_gut, K_spleen, K_stomach, K_pancreas, K_liver_cl, K_kidney_cl = K_CL[:15]
261
- CL_kidney, CL_liver = K_CL[15:]
262
-
263
- dC_lung_dt = cnst['lung']['Q'] * (C_V - C_lung / K_lung) / cnst['lung']['V']
264
- dC_heart_dt = cnst['heart']['Q'] * (C_A - C_heart / K_heart) / cnst['heart']['V']
265
- dC_brain_dt = cnst['brain']['Q'] * (C_A - C_brain / K_brain) / cnst['brain']['V']
266
- dC_muscle_dt = cnst['muscle']['Q'] * (C_A - C_muscle / K_muscle) / cnst['muscle']['V']
267
- dC_fat_dt = cnst['adipose']['Q'] * (C_A - C_fat / K_fat) / cnst['adipose']['V']
268
- dC_skin_dt = cnst['skin']['Q'] * (C_A - C_skin / K_skin) / cnst['skin']['V']
269
- dC_bone_dt = cnst['bone']['Q'] * (C_A - C_bone / K_bone) / cnst['bone']['V']
270
- # Kidney V(Kidney)*dC(Kidney)/dt = Q(Kidney)*C(A)-Q(Kidney)*CV(Kidney)-CL(Kidney,int)*CV(Kidney,int)?
271
- dC_kidney_dt = (cnst['kidney']['Q'] * (C_A - C_kidney / K_kidney) - CL_kidney * C_kidney / K_kidney_cl) / \
272
- cnst['kidney']['V'] # ???
273
-
274
- # Liver V(Liver)*dC(Liver)/dt = (Q(Liver)-Q(Spleen)-Q(Gut)-Q(Pancreas)-Q(Stomach))*C(A) + Q(Spleen)*CV(Spleen) +
275
- # + Q(Gut)*CV(Gut) + Q(Pancreas)*CV(Pancreas) + Q(Stomach)*CV(Stomach) -
276
- # - Q(Liver)*CV(Liver) - CL(Liver,int)*CV(Liver,int)? # тут скорее всего нужно вычитать потоки из друг друга дополнительно по крови что бы сохранить массовый баланс
277
- Q_liver_in_from_art = cnst['liver']['Q'] - cnst['gut']['Q'] - cnst['spleen']['Q'] - \
278
- cnst['pancreas']['Q'] - cnst['stomach']['Q']
279
- dC_liver_dt = (
280
- Q_liver_in_from_art * C_A + cnst['gut']['Q'] * C_gut / K_gut
281
- + cnst['spleen']['Q'] * C_spleen / K_spleen
282
- + cnst['stomach']['Q'] * C_stomach / K_stomach
283
- + cnst['pancreas']['Q'] * C_pancreas / K_pancreas
284
- - cnst['liver']['Q'] * C_liver / K_liver
285
- - CL_liver * C_liver / K_liver_cl # ???
286
- ) / cnst['liver']['V']
287
-
288
- dC_gut_dt = cnst['gut']['Q'] * (C_A - C_gut / K_gut) / cnst['gut']['V']
289
- dC_spleen_dt = cnst['spleen']['Q'] * (C_A - C_spleen / K_spleen) / cnst['spleen']['V']
290
- dC_stomach_dt = cnst['stomach']['Q'] * (C_A - C_stomach / K_stomach) / cnst['stomach']['V']
291
- dC_pancreas_dt = cnst['pancreas']['Q'] * (C_A - C_pancreas / K_pancreas) / cnst['pancreas']['V']
292
-
293
- dC_venouse_dt = (
294
- cnst['heart']['Q'] * C_heart / K_heart
295
- + cnst['brain']['Q'] * C_brain / K_brain
296
- + cnst['muscle']['Q'] * C_muscle / K_muscle
297
- + cnst['skin']['Q'] * C_skin / K_skin
298
- + cnst['adipose']['Q'] * C_fat / K_fat
299
- + cnst['bone']['Q'] * C_bone / K_bone
300
- + cnst['kidney']['Q'] * C_kidney / K_kidney
301
- + cnst['liver']['Q'] * C_liver / K_liver
302
- - cnst['lung']['Q'] * C_V
303
- ) / cnst['venous_blood']['V']
304
-
305
- dC_arterial_dt = cnst['lung']['Q'] * (C_lung / K_lung - C_A) / cnst['arterial_blood']['V']
306
-
307
- y_new = [dC_lung_dt, dC_heart_dt, dC_brain_dt, dC_muscle_dt, dC_fat_dt, dC_skin_dt, dC_bone_dt, \
308
- dC_kidney_dt, dC_liver_dt, dC_gut_dt, dC_spleen_dt, dC_stomach_dt, dC_pancreas_dt, dC_venouse_dt,
309
- dC_arterial_dt]
310
- return y_new
311
-
312
- @staticmethod
313
- @njit
314
- def numba_fullPBPK_for_optimization(y, t, K_CL, cnst_q, cnst_v):
315
- C_lung, C_heart, C_brain, C_muscle, C_fat, C_skin, C_bone, \
316
- C_kidney, C_liver, C_gut, C_spleen, C_stomach, C_pancreas, C_V, C_A = y
317
-
318
- K_lung, K_heart, K_brain, K_muscle, K_fat, K_skin, K_bone, \
319
- K_kidney, K_liver, K_gut, K_spleen, K_stomach, K_pancreas, K_liver_cl, K_kidney_cl = K_CL[:15]
320
- CL_kidney, CL_liver = K_CL[15:]
321
-
322
- dC_lung_dt = cnst_q['lung'] * (C_V - C_lung / K_lung) / cnst_v['lung']
323
- dC_heart_dt = cnst_q['heart'] * (C_A - C_heart / K_heart) / cnst_v['heart']
324
- dC_brain_dt = cnst_q['brain'] * (C_A - C_brain / K_brain) / cnst_v['brain']
325
- dC_muscle_dt = cnst_q['muscle'] * (C_A - C_muscle / K_muscle) / cnst_v['muscle']
326
- dC_fat_dt = cnst_q['adipose'] * (C_A - C_fat / K_fat) / cnst_v['adipose']
327
- dC_skin_dt = cnst_q['skin'] * (C_A - C_skin / K_skin) / cnst_v['skin']
328
- dC_bone_dt = cnst_q['bone'] * (C_A - C_bone / K_bone) / cnst_v['bone']
329
- # Kidney V(Kidney)*dC(Kidney)/dt = Q(Kidney)*C(A)-Q(Kidney)*CV(Kidney)-CL(Kidney,int)*CV(Kidney,int)?
330
- dC_kidney_dt = (cnst_q['kidney'] * (C_A - C_kidney / K_kidney) - CL_kidney * C_kidney / K_kidney_cl) / \
331
- cnst_v['kidney'] # ???
332
-
333
- # Liver V(Liver)*dC(Liver)/dt = (Q(Liver)-Q(Spleen)-Q(Gut)-Q(Pancreas)-Q(Stomach))*C(A) + Q(Spleen)*CV(Spleen) +
334
- # + Q(Gut)*CV(Gut) + Q(Pancreas)*CV(Pancreas) + Q(Stomach)*CV(Stomach) -
335
- # - Q(Liver)*CV(Liver) - CL(Liver,int)*CV(Liver,int)? # тут скорее всего нужно вычитать потоки из друг друга дополнительно по крови что бы сохранить массовый баланс
336
- Q_liver_in_from_art = cnst_q['liver'] - cnst_q['gut'] - cnst_q['spleen'] - \
337
- cnst_q['pancreas'] - cnst_q['stomach']
338
- dC_liver_dt = (
339
- Q_liver_in_from_art * C_A + cnst_q['gut'] * C_gut / K_gut
340
- + cnst_q['spleen'] * C_spleen / K_spleen
341
- + cnst_q['stomach'] * C_stomach / K_stomach
342
- + cnst_q['pancreas'] * C_pancreas / K_pancreas
343
- - cnst_q['liver'] * C_liver / K_liver
344
- - CL_liver * C_liver / K_liver_cl # ???
345
- ) / cnst_v['liver']
346
-
347
- dC_gut_dt = cnst_q['gut'] * (C_A - C_gut / K_gut) / cnst_v['gut']
348
- dC_spleen_dt = cnst_q['spleen'] * (C_A - C_spleen / K_spleen) / cnst_v['spleen']
349
- dC_stomach_dt = cnst_q['stomach'] * (C_A - C_stomach / K_stomach) / cnst_v['stomach']
350
- dC_pancreas_dt = cnst_q['pancreas'] * (C_A - C_pancreas / K_pancreas) / cnst_v['pancreas']
351
-
352
- dC_venouse_dt = (
353
- cnst_q['heart'] * C_heart / K_heart
354
- + cnst_q['brain'] * C_brain / K_brain
355
- + cnst_q['muscle'] * C_muscle / K_muscle
356
- + cnst_q['skin'] * C_skin / K_skin
357
- + cnst_q['adipose'] * C_fat / K_fat
358
- + cnst_q['bone'] * C_bone / K_bone
359
- + cnst_q['kidney'] * C_kidney / K_kidney
360
- + cnst_q['liver'] * C_liver / K_liver
361
- - cnst_q['lung'] * C_V
362
- ) / cnst_v['venous_blood']
363
-
364
- dC_arterial_dt = cnst_q['lung'] * (C_lung / K_lung - C_A) / cnst_v['arterial_blood']
365
-
366
- y_new = np.array([dC_lung_dt, dC_heart_dt, dC_brain_dt, dC_muscle_dt, dC_fat_dt, dC_skin_dt, dC_bone_dt, \
367
- dC_kidney_dt, dC_liver_dt, dC_gut_dt, dC_spleen_dt, dC_stomach_dt, dC_pancreas_dt, dC_venouse_dt,
368
- dC_arterial_dt]).astype(np.float64)
369
- return y_new
File without changes
File without changes
File without changes