pypharm 1.2.6__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
@@ -125,7 +126,7 @@ class BaseCompartmentModel:
125
126
  if self.volumes_target:
126
127
  self.volumes[self.volumes_target] = x[self.configuration_matrix_target_count + self.outputs_target_count:self.configuration_matrix_target_count + self.outputs_target_count + self.volumes_target_count]
127
128
 
128
- def _target_function(self, x, max_step=0.01):
129
+ def _target_function(self, x, max_step=0.01, metric='R2'):
129
130
  """
130
131
  Функция расчета значения целевой функции
131
132
 
@@ -148,7 +149,13 @@ class BaseCompartmentModel:
148
149
  max_step=max_step
149
150
  )
150
151
  target_results = self.last_result.y[tuple(self.know_compartments), :]
151
- 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))
152
+ if metric == 'R2':
153
+ 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))
154
+ elif metric == 'norm':
155
+ return np.linalg.norm(target_results - self.teoretic_y)
156
+ else:
157
+ 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))
158
+
152
159
 
153
160
  def load_optimization_data(self, teoretic_x, teoretic_y, know_compartments, w = None, c0=None, d=None, compartment_number=None):
154
161
  """
@@ -181,7 +188,7 @@ class BaseCompartmentModel:
181
188
  self.c0 = np.array(c0)
182
189
  self.w = np.ones(self.teoretic_y.shape) if w is None else np.array(w)
183
190
 
184
- def optimize(self, method=None, max_step=0.01, **kwargs):
191
+ def optimize(self, method=None, max_step=0.01, metric='R2', **kwargs):
185
192
  """
186
193
  Функция оптимизации модели
187
194
 
@@ -194,7 +201,7 @@ class BaseCompartmentModel:
194
201
  None
195
202
  """
196
203
  self._optim = True
197
- f = lambda x: self._target_function(x, max_step=max_step)
204
+ f = lambda x: self._target_function(x, max_step=max_step, metric=metric)
198
205
  if method == 'country_optimization':
199
206
  CA = CountriesAlgorithm(
200
207
  f=f,
@@ -230,7 +237,7 @@ class BaseCompartmentModel:
230
237
  return x
231
238
 
232
239
 
233
- class MagicCompartmentModelWith(BaseCompartmentModel):
240
+ class MagicCompartmentModel(BaseCompartmentModel):
234
241
 
235
242
  need_magic_optimization = False
236
243
 
@@ -268,49 +275,185 @@ class MagicCompartmentModelWith(BaseCompartmentModel):
268
275
 
269
276
  class ReleaseCompartmentModel(BaseCompartmentModel):
270
277
 
271
- 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
+ """
272
316
  super().__init__(*args, **kwargs)
273
317
  self.release_parameters = np.array(release_parameters)
274
318
  self.release_parameters_target_count = 0
275
319
  if np.any(self.release_parameters == None):
276
320
  self.release_parameters_target = np.where(self.release_parameters == None)
277
321
  self.release_parameters_target_count = np.sum(self.release_parameters == None)
278
- 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
279
327
 
280
- def _runge_kutta(self, y, x, dx):
281
- k1 = dx * self._сompartment_model(x, y)
282
- k2 = dx * self._сompartment_model(x + 0.5 * dx, y + 0.5 * k1)
283
- k3 = dx * self._сompartment_model(x + 0.5 * dx, y + 0.5 * k2)
284
- k4 = dx * self._сompartment_model(x + dx, y + k3)
285
- 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]
286
335
 
287
- def release_function(self, t, c0):
336
+ def _default_release_function(self, t, c0):
288
337
  """
289
338
  Функция для поправки на высвобождение
290
339
  """
291
- m, b, c = self.release_parametrs
340
+ m, b, c = self.release_parameters
292
341
  return c0 * c * t ** b / (t ** b + m)
293
342
 
294
- 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
+ """
295
363
  if not self._optim:
296
364
  assert (not any([self.configuration_matrix_target, self.outputs_target, self.volumes_target])), \
297
365
  "It is impossible to make a calculation with unknown parameters"
298
- 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"
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
299
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:
300
444
  assert all([d, compartment_number is not None]), "Need to set d and compartment_number"
301
- c0 = d / self.v
302
- t = 0
303
- old_release_correction = 0
304
- result_x = np.array([])
305
- result_y = np.array([])
306
- y = np.zeros(self.outputs.size)
307
- while t <= t_max:
308
- np.append(result_x, t)
309
- np.append(result_y, y)
310
- release_correction = self.release_function(t + max_step, c0)
311
- y = self._runge_kutta(y, t, max_step)
312
- y[compartment_number] += release_correction - old_release_correction
313
- #y[0] = breeding_function(dx, t12, y[0]) # делаем поправочку на распад
314
- old_release_correction = release_correction
315
- t += max_step
316
- 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.6
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=zMfISbTMdI0oS9ERFF1hPD0OyRAFFza-K1JHwvhs7Jk,15102
5
- pypharm-1.2.6.dist-info/METADATA,sha256=WvI96qqUHixmSqdfkeZPju1Ph1N-x050eHHYG7rtNxM,4003
6
- pypharm-1.2.6.dist-info/WHEEL,sha256=OqRkF0eY5GHssMorFjlbTIq072vpHpF60fIQA6lS9xA,92
7
- pypharm-1.2.6.dist-info/top_level.txt,sha256=yybfSkKw8q1G3aEcnlfVL7_L9ufGFSAYZnpc7q6oYJk,8
8
- pypharm-1.2.6.dist-info/RECORD,,