pypharm 1.2.7__py3-none-any.whl → 1.2.8__py3-none-any.whl

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.
PyPharm/__init__.py CHANGED
@@ -1 +1 @@
1
- from .models import BaseCompartmentModel, MagicCompartmentModelWith
1
+ from .models import BaseCompartmentModel, MagicCompartmentModel, ReleaseCompartmentModel
PyPharm/models.py CHANGED
@@ -1,5 +1,6 @@
1
1
  import numpy as np
2
- from scipy.integrate import solve_ivp
2
+ from scipy.integrate import solve_ivp, RK45
3
+ from scipy.integrate._ivp.rk import rk_step, SAFETY, MAX_FACTOR, MIN_FACTOR
3
4
  from scipy.optimize import minimize
4
5
  from .country_optimization import CountriesAlgorithm
5
6
  from .country_optimization_v2 import CountriesAlgorithm_v2
@@ -236,7 +237,7 @@ class BaseCompartmentModel:
236
237
  return x
237
238
 
238
239
 
239
- class MagicCompartmentModelWith(BaseCompartmentModel):
240
+ class MagicCompartmentModel(BaseCompartmentModel):
240
241
 
241
242
  need_magic_optimization = False
242
243
 
@@ -274,49 +275,185 @@ class MagicCompartmentModelWith(BaseCompartmentModel):
274
275
 
275
276
  class ReleaseCompartmentModel(BaseCompartmentModel):
276
277
 
277
- def __init__(self, release_parameters, v, *args, **kwargs):
278
+ need_v_release_optimization = False
279
+
280
+ class ReleaseRK45(RK45):
281
+
282
+ def __init__(self, fun, t0, y0, t_bound, release_function, compartment_number, c0, max_step=np.inf,
283
+ rtol=1e-3, atol=1e-6, vectorized=False,
284
+ first_step=None, **extraneous):
285
+ super().__init__(fun, t0, y0, t_bound, max_step=max_step,
286
+ rtol=rtol, atol=atol, vectorized=vectorized,
287
+ first_step=first_step, **extraneous)
288
+ self.release_function = release_function
289
+ self.compartment_number = compartment_number
290
+ self.c0 = c0
291
+ self.old_release_correction = 0
292
+
293
+ def _step_impl(self):
294
+ result = super()._step_impl()
295
+ release_correction = self.release_function(self.t, self.c0)
296
+ self.y[self.compartment_number] += release_correction - self.old_release_correction
297
+ self.old_release_correction = release_correction
298
+ return result
299
+
300
+ def __init__(self, v_release, release_parameters, release_compartment, release_function=None, *args, **kwargs):
301
+ """
302
+ Камерная модель с высвобождением для описания фармакокинетики системы
303
+
304
+ Неизвестные параметры при необходимости задаются как None
305
+ например configuration_matrix = [[0, 1], [None, 0]]
306
+
307
+ Args:
308
+ configuration_matrix: Настроечная матрица модели, отображающая константы перехода между матрицами
309
+ outputs: Вектор констант перехода во вне камер
310
+ volumes: Объемы камер
311
+ v_release: Объем гепотетической камеры из которой происходит высвобождение
312
+ release_parameters: Параметры функции высвобождения
313
+ release_compartment: Номер камеры в которую происходит высвобождение
314
+ release_function: Функция высвобождения по умолчанию f(t,m,b,c) = c0 * c * t ** b / (t ** b + m)
315
+ """
278
316
  super().__init__(*args, **kwargs)
279
317
  self.release_parameters = np.array(release_parameters)
280
318
  self.release_parameters_target_count = 0
281
319
  if np.any(self.release_parameters == None):
282
320
  self.release_parameters_target = np.where(self.release_parameters == None)
283
321
  self.release_parameters_target_count = np.sum(self.release_parameters == None)
284
- self.v = v
322
+ self.v_release = v_release
323
+ if self.v_release is None:
324
+ self.need_v_release_optimization = True
325
+ self.release_compartment = release_compartment
326
+ self.release_function = release_function
285
327
 
286
- def _runge_kutta(self, y, x, dx):
287
- k1 = dx * self._сompartment_model(x, y)
288
- k2 = dx * self._сompartment_model(x + 0.5 * dx, y + 0.5 * k1)
289
- k3 = dx * self._сompartment_model(x + 0.5 * dx, y + 0.5 * k2)
290
- k4 = dx * self._сompartment_model(x + dx, y + k3)
291
- return y + (k1 + 2 * k2 + 2 * k3 + k4) / 6
328
+ def load_data_from_list(self, x):
329
+ super().load_data_from_list(x)
330
+ s = self.configuration_matrix_target_count + self.outputs_target_count + self.volumes_target_count
331
+ if self.release_parameters_target:
332
+ self.release_parameters[self.release_parameters_target] = x[s:s + self.release_parameters_target_count]
333
+ if self.need_v_release_optimization:
334
+ self.v_release = x[s + self.release_parameters_target_count]
292
335
 
293
- def release_function(self, t, c0):
336
+ def _default_release_function(self, t, c0):
294
337
  """
295
338
  Функция для поправки на высвобождение
296
339
  """
297
- m, b, c = self.release_parametrs
340
+ m, b, c = self.release_parameters
298
341
  return c0 * c * t ** b / (t ** b + m)
299
342
 
300
- def __call__(self, t_max, c0=None, d=None, compartment_number=None, max_step=0.01, t_eval=None):
343
+ def get_release_function(self):
344
+ if self.release_function is not None:
345
+ return lambda t, c0: self.release_function(t, c0, *self.release_parameters)
346
+ else:
347
+ return self._default_release_function
348
+
349
+ def __call__(self, t_max, c0=None, d=None, max_step=0.01, t_eval=None, **kwargs):
350
+ """
351
+ Расчет кривых концентраций по фармакокинетической модели
352
+
353
+ Args:
354
+ t_max: Предельное время расчета
355
+ c0: Начальная концентрация в камере из которой высвобождается вещество
356
+ d: Вводимая доза
357
+ max_step: Максимальный шаг при решении СДУ
358
+ t_eval: Временные точки, в которых необходимо молучить решение
359
+
360
+ Returns:
361
+ Результат работы решателя scipy solve_ivp
362
+ """
301
363
  if not self._optim:
302
364
  assert (not any([self.configuration_matrix_target, self.outputs_target, self.volumes_target])), \
303
365
  "It is impossible to make a calculation with unknown parameters"
304
- assert any([c0 is not None, d, compartment_number is not None]), "Need to set c0 or d and compartment_number"
366
+ assert any([c0 is not None, d]), "Need to set c0 or d and compartment_number"
305
367
  if c0 is None:
368
+ assert d, "Need to set d"
369
+ c0 = d / self.v_release
370
+ ts = [0, t_max]
371
+ y0 = np.zeros(self.outputs.shape)
372
+ self.last_result = solve_ivp(
373
+ fun=self._сompartment_model if
374
+ not self.numba_option
375
+ else lambda t, c: self._numba_сompartment_model(t, c,
376
+ self.configuration_matrix.astype(
377
+ np.float64),
378
+ self.outputs.astype(
379
+ np.float64),
380
+ self.volumes.astype(
381
+ np.float64)),
382
+ t_span=ts,
383
+ y0=y0,
384
+ max_step=max_step,
385
+ t_eval=t_eval,
386
+ method=self.ReleaseRK45,
387
+ release_function=self.get_release_function(),
388
+ compartment_number=self.release_compartment,
389
+ c0=c0
390
+ )
391
+ return self.last_result
392
+
393
+ def _target_function(self, x, max_step=0.01, metric='R2'):
394
+ """
395
+ Функция расчета значения целевой функции
396
+
397
+ Args:
398
+ x: Значение искомых параметров модели
399
+ max_step: Максимальный шаг при решении СДУ
400
+
401
+ Returns:
402
+ Значение целевой функции, характеризующее отклонение от эксперементальных данных
403
+ """
404
+ self.load_data_from_list(x)
405
+ c0 = self.c0
406
+ if c0 is None:
407
+ c0 = self.d / self.v_release
408
+ self(
409
+ t_max=np.max(self.teoretic_x),
410
+ c0=c0,
411
+ t_eval=self.teoretic_x,
412
+ max_step=max_step
413
+ )
414
+ target_results = self.last_result.y[tuple(self.know_compartments), :]
415
+ if metric == 'R2':
416
+ return np.sum(np.sum(self.w * ((target_results - self.teoretic_y) ** 2), axis=1) / np.sum((self.teoretic_avg - self.teoretic_y) ** 2, axis=1))
417
+ elif metric == 'norm':
418
+ return np.linalg.norm(target_results - self.teoretic_y)
419
+ else:
420
+ return np.sum(np.sum(self.w * ((target_results - self.teoretic_y) ** 2), axis=1) / np.sum((self.teoretic_avg - self.teoretic_y) ** 2, axis=1))
421
+
422
+ def load_optimization_data(self, teoretic_x, teoretic_y, know_compartments, w = None, c0=None, d=None, compartment_number=None):
423
+ """
424
+ Функция загрузки в модель эксперементальных данных
425
+
426
+ Args:
427
+ teoretic_x: Вектор временных точек теоретических значений
428
+ teoretic_y: Матрица с теоретическими значениями
429
+ know_compartments: Вектор с номерами камер, по которым есть данные
430
+ c0: Начальная концентрация в камере из которой высвобождается вещество
431
+ d: Вводимая доза
432
+
433
+ Returns:
434
+ None
435
+ """
436
+ self.teoretic_x = np.array(teoretic_x)
437
+ self.teoretic_y = np.array(teoretic_y)
438
+ self.know_compartments = know_compartments
439
+ self.teoretic_avg = np.average(self.teoretic_y, axis=1)
440
+ self.teoretic_avg = np.repeat(self.teoretic_avg, self.teoretic_x.size)
441
+ self.teoretic_avg = np.reshape(self.teoretic_avg, self.teoretic_y.shape)
442
+ assert any([c0, d, compartment_number is not None]), "Need to set c0 or d and compartment_number"
443
+ if not c0:
306
444
  assert all([d, compartment_number is not None]), "Need to set d and compartment_number"
307
- c0 = d / self.v
308
- t = 0
309
- old_release_correction = 0
310
- result_x = np.array([])
311
- result_y = np.array([])
312
- y = np.zeros(self.outputs.size)
313
- while t <= t_max:
314
- np.append(result_x, t)
315
- np.append(result_y, y)
316
- release_correction = self.release_function(t + max_step, c0)
317
- y = self._runge_kutta(y, t, max_step)
318
- y[compartment_number] += release_correction - old_release_correction
319
- #y[0] = breeding_function(dx, t12, y[0]) # делаем поправочку на распад
320
- old_release_correction = release_correction
321
- t += max_step
322
- return result_x, result_y
445
+ self.d = d
446
+ self.c0 = None
447
+ else:
448
+ self.c0 = np.array(c0)
449
+ self.w = np.ones(self.teoretic_y.shape) if w is None else np.array(w)
450
+
451
+ def optimize(self, method=None, max_step=0.01, **kwargs):
452
+ x = super().optimize(method, max_step, **kwargs)
453
+ s = self.configuration_matrix_target_count + self.outputs_target_count + self.volumes_target_count
454
+ if self.release_parameters_target:
455
+ self.release_parameters[self.release_parameters_target] = x[s:s + self.release_parameters_target_count]
456
+ if self.need_v_release_optimization:
457
+ self.v_release = x[s:s + self.release_parameters_target_count + 1]
458
+ self.need_v_release_optimization = False
459
+ return x
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pypharm
3
- Version: 1.2.7
3
+ Version: 1.2.8
4
4
  Summary: Module for solving pharmacokinetic problems
5
5
  Home-page: https://github.com/Krash13/PyPharm
6
6
  Author: Krash13
@@ -139,3 +139,71 @@ model.optimize(
139
139
  )
140
140
  ```
141
141
 
142
+ При оптимизации, вектор неизвестных это
143
+ x = [configuration_matrix (неизвестные), outputs(неизвестные), volumes(неизвестные)]
144
+
145
+ **4) Модель MagicCompartmentModel**
146
+
147
+ Данная модель необходима нам для тех случаев,
148
+ когда мы не знаем как именно стоит переводить входные
149
+ единицы измерения в выходные.
150
+
151
+ В модель добавляется 2 дополнительных параметра:
152
+
153
+ * magic_coefficient - множитель преобразования входных единиц в выходные;
154
+ * exclude_compartments - список номеров камер, которые не
155
+ подвергнутся преобразованию.
156
+
157
+ ```python
158
+ from PyPharm import MagicCompartmentModel
159
+
160
+ model = MagicCompartmentModel([[0, 0.4586], [0.1919, 0]], [0.0309, 0], volumes=[228, 629], magic_coefficient=None, exclude_compartments=[2])
161
+
162
+ res = model(90, d=5700, compartment_number=0)
163
+ ```
164
+
165
+ Параметр magic_coefficient может быть задан None,
166
+ в таком случае он будет подвергнут оптимизации, в таком
167
+ случае он будет браться из последнего значения в векторе
168
+ переменных.
169
+ Если оба параметра не заданы, то модель выраздается
170
+ в простую BaseCompartmentModel.
171
+
172
+ **5) Модель MagicCompartmentModel**
173
+
174
+ Данная модель учитывает поправку на высвобождение
175
+ ЛВ в модель вводятся дополнительные параметры:
176
+ * v_release - Объем гепотетической камеры из которой происходит высвобождение
177
+ * release_parameters - Параметры функции высвобождения
178
+ * release_compartment - Номер камеры в которую происходит высвобождение
179
+ * release_function - Функция высвобождения по умолчанию f(t,m,b,c) = c0 * c * t ** b / (t ** b + m)
180
+
181
+ При этом d и c0 теперь везде носят характер параметров камеры,
182
+ из которой происходит высвобождение
183
+ ```python
184
+ from PyPharm import ReleaseCompartmentModel
185
+ import matplotlib.pyplot as plt
186
+
187
+ model = ReleaseCompartmentModel(
188
+ 6.01049235e+00,
189
+ [4.56683781e-03, 1.36845756e+00, 5.61175978e-01],
190
+ 0,
191
+ configuration_matrix=[[0, 1.18292665e+01], [3.02373800e-01, 0]],
192
+ outputs=[5.00000000e+00, 0],
193
+ volumes=[1.98530383e+01, 3.81007392e+02],
194
+ numba_option=True
195
+ )
196
+ teoretic_t = [5/60, 0.25, 0.5, 1, 2, 4, 24, 48]
197
+ teoretic_c = [[3558.19, 508.49, 230.95, 52.05, 44.97, 36.52, 17.89, 10.36]]
198
+ d = 5 * 0.02 * 1000000
199
+ res = model(48, d=d)
200
+ plt.plot(teoretic_t, teoretic_c[0], 'r*')
201
+ plt.plot(res.t, res.y[0])
202
+ plt.grid()
203
+ plt.show()
204
+ ```
205
+ Параметры release_parameters и v_release могут подвергаться оптимизации
206
+ в таком случае, искомое нужно просто задать как None. Тогда вектор неизвестных это
207
+ x = [configuration_matrix (неизвестные), outputs(неизвестные), volumes(неизвестные), release_parameters(неизвестные), v_release]
208
+
209
+
@@ -0,0 +1,8 @@
1
+ PyPharm/__init__.py,sha256=hxhMRlWpLMARQV-ZNYkmvhQ9gCYI18an75vlySWjA6s,90
2
+ PyPharm/country_optimization.py,sha256=nbg5kuJcOhMMfPR0_1O8KUzyqHApUcnqgs_I2I0Z1Gs,20008
3
+ PyPharm/country_optimization_v2.py,sha256=3d2mt15DXdr1V3soIJS51xuCv6uzH8pirah1RnI5--8,13156
4
+ PyPharm/models.py,sha256=T3MWl4chohFkaWJ4VsJYf-ZA6MgGyiosUmLhfoY8Q9o,23011
5
+ pypharm-1.2.8.dist-info/METADATA,sha256=3VAJKZu8pZPmXUGlZDJLSBzH2GimXfMJXaSDdEVOUBo,7466
6
+ pypharm-1.2.8.dist-info/WHEEL,sha256=OqRkF0eY5GHssMorFjlbTIq072vpHpF60fIQA6lS9xA,92
7
+ pypharm-1.2.8.dist-info/top_level.txt,sha256=yybfSkKw8q1G3aEcnlfVL7_L9ufGFSAYZnpc7q6oYJk,8
8
+ pypharm-1.2.8.dist-info/RECORD,,
@@ -1,8 +0,0 @@
1
- PyPharm/__init__.py,sha256=w8UUsamzw4OEa0eHiwC7k4u3TKNM_OAzP2X7KB-OtYo,69
2
- PyPharm/country_optimization.py,sha256=nbg5kuJcOhMMfPR0_1O8KUzyqHApUcnqgs_I2I0Z1Gs,20008
3
- PyPharm/country_optimization_v2.py,sha256=3d2mt15DXdr1V3soIJS51xuCv6uzH8pirah1RnI5--8,13156
4
- PyPharm/models.py,sha256=NogyRiNxdBT7tWvbjciMcVNwhJEiEXWH-s_KAByuN2M,15449
5
- pypharm-1.2.7.dist-info/METADATA,sha256=mOXSET6arxZBSW1kj54eNQsPUjLxYFK_q_4vUUBtRFk,4003
6
- pypharm-1.2.7.dist-info/WHEEL,sha256=OqRkF0eY5GHssMorFjlbTIq072vpHpF60fIQA6lS9xA,92
7
- pypharm-1.2.7.dist-info/top_level.txt,sha256=yybfSkKw8q1G3aEcnlfVL7_L9ufGFSAYZnpc7q6oYJk,8
8
- pypharm-1.2.7.dist-info/RECORD,,