mxlpy 0.25.0__py3-none-any.whl → 0.26.0__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.
mxlpy/fit/global_.py DELETED
@@ -1,534 +0,0 @@
1
- """Parameter global fitting Module for Metabolic Models.
2
-
3
- This module provides functions for fitting model parameters to experimental data,
4
- including both steadyd-state and time-series data fitting capabilities.
5
- """
6
-
7
- from __future__ import annotations
8
-
9
- import logging
10
- from collections.abc import Callable
11
- from copy import deepcopy
12
- from functools import partial
13
- from typing import TYPE_CHECKING
14
-
15
- from scipy.optimize import basinhopping
16
-
17
- from mxlpy import parallel
18
- from mxlpy.types import IntegratorType, cast
19
-
20
- from .common import (
21
- CarouselFit,
22
- FitResult,
23
- InitialGuess,
24
- LossFn,
25
- MinResult,
26
- ProtocolResidualFn,
27
- ResidualFn,
28
- SteadyStateResidualFn,
29
- TimeSeriesResidualFn,
30
- _protocol_time_course_residual,
31
- _steady_state_residual,
32
- _time_course_residual,
33
- rmse,
34
- )
35
-
36
- if TYPE_CHECKING:
37
- import pandas as pd
38
-
39
- from mxlpy.carousel import Carousel
40
- from mxlpy.model import Model
41
-
42
- LOGGER = logging.getLogger(__name__)
43
-
44
- __all__ = [
45
- "LOGGER",
46
- "Minimizer",
47
- "carousel_protocol_time_course",
48
- "carousel_steady_state",
49
- "carousel_time_course",
50
- "protocol_time_course",
51
- "steady_state",
52
- "time_course",
53
- ]
54
-
55
-
56
- type Minimizer = Callable[
57
- [
58
- ResidualFn,
59
- InitialGuess,
60
- ],
61
- MinResult | None,
62
- ]
63
-
64
-
65
- def _default_minimizer(
66
- residual_fn: ResidualFn,
67
- p0: dict[str, float],
68
- ) -> MinResult | None:
69
- res = basinhopping(
70
- residual_fn,
71
- x0=list(p0.values()),
72
- )
73
- if res.success:
74
- return MinResult(
75
- parameters=dict(
76
- zip(
77
- p0,
78
- res.x,
79
- strict=True,
80
- ),
81
- ),
82
- residual=res.fun,
83
- )
84
-
85
- LOGGER.warning("Minimisation failed.")
86
- return None
87
-
88
-
89
- def _carousel_steady_state_worker(
90
- model: Model,
91
- p0: dict[str, float],
92
- data: pd.Series,
93
- y0: dict[str, float] | None,
94
- integrator: IntegratorType | None,
95
- loss_fn: LossFn,
96
- minimizer: Minimizer,
97
- residual_fn: SteadyStateResidualFn,
98
- ) -> FitResult | None:
99
- model_pars = model.get_parameter_values()
100
-
101
- return steady_state(
102
- model,
103
- p0={k: v for k, v in p0.items() if k in model_pars},
104
- y0=y0,
105
- data=data,
106
- minimizer=minimizer,
107
- residual_fn=residual_fn,
108
- integrator=integrator,
109
- loss_fn=loss_fn,
110
- )
111
-
112
-
113
- def _carousel_time_course_worker(
114
- model: Model,
115
- p0: dict[str, float],
116
- data: pd.DataFrame,
117
- y0: dict[str, float] | None,
118
- integrator: IntegratorType | None,
119
- loss_fn: LossFn,
120
- minimizer: Minimizer,
121
- residual_fn: TimeSeriesResidualFn,
122
- ) -> FitResult | None:
123
- model_pars = model.get_parameter_values()
124
- return time_course(
125
- model,
126
- p0={k: v for k, v in p0.items() if k in model_pars},
127
- y0=y0,
128
- data=data,
129
- minimizer=minimizer,
130
- residual_fn=residual_fn,
131
- integrator=integrator,
132
- loss_fn=loss_fn,
133
- )
134
-
135
-
136
- def _carousel_protocol_worker(
137
- model: Model,
138
- p0: dict[str, float],
139
- data: pd.DataFrame,
140
- protocol: pd.DataFrame,
141
- y0: dict[str, float] | None,
142
- integrator: IntegratorType | None,
143
- loss_fn: LossFn,
144
- minimizer: Minimizer,
145
- residual_fn: ProtocolResidualFn,
146
- ) -> FitResult | None:
147
- model_pars = model.get_parameter_values()
148
- return protocol_time_course(
149
- model,
150
- p0={k: v for k, v in p0.items() if k in model_pars},
151
- y0=y0,
152
- protocol=protocol,
153
- data=data,
154
- minimizer=minimizer,
155
- residual_fn=residual_fn,
156
- integrator=integrator,
157
- loss_fn=loss_fn,
158
- )
159
-
160
-
161
- def steady_state(
162
- model: Model,
163
- *,
164
- p0: dict[str, float],
165
- data: pd.Series,
166
- y0: dict[str, float] | None = None,
167
- minimizer: Minimizer = _default_minimizer,
168
- residual_fn: SteadyStateResidualFn = _steady_state_residual,
169
- integrator: IntegratorType | None = None,
170
- loss_fn: LossFn = rmse,
171
- ) -> FitResult | None:
172
- """Fit model parameters to steady-state experimental data.
173
-
174
- Examples:
175
- >>> steady_state(model, p0, data)
176
- {'k1': 0.1, 'k2': 0.2}
177
-
178
- Args:
179
- model: Model instance to fit
180
- data: Experimental steady state data as pandas Series
181
- p0: Initial parameter guesses as {parameter_name: value}
182
- y0: Initial conditions as {species_name: value}
183
- minimizer: Function to minimize fitting error
184
- residual_fn: Function to calculate fitting error
185
- integrator: ODE integrator class
186
- loss_fn: Loss function to use for residual calculation
187
- bounds: Mapping of bounds per parameter
188
-
189
- Returns:
190
- dict[str, float]: Fitted parameters as {parameter_name: fitted_value}
191
-
192
- Note:
193
- Uses L-BFGS-B optimization with bounds [1e-6, 1e6] for all parameters
194
-
195
- """
196
- par_names = list(p0.keys())
197
-
198
- # Copy to restore
199
- p_orig = model.get_parameter_values()
200
-
201
- fn = cast(
202
- ResidualFn,
203
- partial(
204
- residual_fn,
205
- data=data,
206
- model=model,
207
- y0=y0,
208
- par_names=par_names,
209
- integrator=integrator,
210
- loss_fn=loss_fn,
211
- ),
212
- )
213
- min_result = minimizer(fn, p0)
214
- # Restore original model
215
- model.update_parameters(p_orig)
216
- if min_result is None:
217
- return min_result
218
-
219
- return FitResult(
220
- model=deepcopy(model).update_parameters(min_result.parameters),
221
- best_pars=min_result.parameters,
222
- loss=min_result.residual,
223
- )
224
-
225
-
226
- def time_course(
227
- model: Model,
228
- *,
229
- p0: dict[str, float],
230
- data: pd.DataFrame,
231
- y0: dict[str, float] | None = None,
232
- minimizer: Minimizer = _default_minimizer,
233
- residual_fn: TimeSeriesResidualFn = _time_course_residual,
234
- integrator: IntegratorType | None = None,
235
- loss_fn: LossFn = rmse,
236
- ) -> FitResult | None:
237
- """Fit model parameters to time course of experimental data.
238
-
239
- Examples:
240
- >>> time_course(model, p0, data)
241
- {'k1': 0.1, 'k2': 0.2}
242
-
243
- Args:
244
- model: Model instance to fit
245
- data: Experimental time course data
246
- p0: Initial parameter guesses as {parameter_name: value}
247
- y0: Initial conditions as {species_name: value}
248
- minimizer: Function to minimize fitting error
249
- residual_fn: Function to calculate fitting error
250
- integrator: ODE integrator class
251
- loss_fn: Loss function to use for residual calculation
252
- bounds: Mapping of bounds per parameter
253
-
254
- Returns:
255
- dict[str, float]: Fitted parameters as {parameter_name: fitted_value}
256
-
257
- Note:
258
- Uses L-BFGS-B optimization with bounds [1e-6, 1e6] for all parameters
259
-
260
- """
261
- par_names = list(p0.keys())
262
- p_orig = model.get_parameter_values()
263
-
264
- fn = cast(
265
- ResidualFn,
266
- partial(
267
- residual_fn,
268
- data=data,
269
- model=model,
270
- y0=y0,
271
- par_names=par_names,
272
- integrator=integrator,
273
- loss_fn=loss_fn,
274
- ),
275
- )
276
-
277
- min_result = minimizer(fn, p0)
278
- # Restore original model
279
- model.update_parameters(p_orig)
280
- if min_result is None:
281
- return min_result
282
-
283
- return FitResult(
284
- model=deepcopy(model).update_parameters(min_result.parameters),
285
- best_pars=min_result.parameters,
286
- loss=min_result.residual,
287
- )
288
-
289
-
290
- def protocol_time_course(
291
- model: Model,
292
- *,
293
- p0: dict[str, float],
294
- data: pd.DataFrame,
295
- protocol: pd.DataFrame,
296
- y0: dict[str, float] | None = None,
297
- minimizer: Minimizer = _default_minimizer,
298
- residual_fn: ProtocolResidualFn = _protocol_time_course_residual,
299
- integrator: IntegratorType | None = None,
300
- loss_fn: LossFn = rmse,
301
- ) -> FitResult | None:
302
- """Fit model parameters to time course of experimental data.
303
-
304
- Time points of protocol time course are taken from the data.
305
-
306
- Examples:
307
- >>> time_course(model, p0, data)
308
- {'k1': 0.1, 'k2': 0.2}
309
-
310
- Args:
311
- model: Model instance to fit
312
- p0: Initial parameter guesses as {parameter_name: value}
313
- data: Experimental time course data
314
- protocol: Experimental protocol
315
- y0: Initial conditions as {species_name: value}
316
- minimizer: Function to minimize fitting error
317
- residual_fn: Function to calculate fitting error
318
- integrator: ODE integrator class
319
- loss_fn: Loss function to use for residual calculation
320
- time_points_per_step: Number of time points per step in the protocol
321
- bounds: Mapping of bounds per parameter
322
-
323
- Returns:
324
- dict[str, float]: Fitted parameters as {parameter_name: fitted_value}
325
-
326
- Note:
327
- Uses L-BFGS-B optimization with bounds [1e-6, 1e6] for all parameters
328
-
329
- """
330
- par_names = list(p0.keys())
331
- p_orig = model.get_parameter_values()
332
-
333
- fn = cast(
334
- ResidualFn,
335
- partial(
336
- residual_fn,
337
- data=data,
338
- model=model,
339
- y0=y0,
340
- par_names=par_names,
341
- integrator=integrator,
342
- loss_fn=loss_fn,
343
- protocol=protocol,
344
- ),
345
- )
346
-
347
- min_result = minimizer(fn, p0)
348
- # Restore original model
349
- model.update_parameters(p_orig)
350
- if min_result is None:
351
- return min_result
352
-
353
- return FitResult(
354
- model=deepcopy(model).update_parameters(min_result.parameters),
355
- best_pars=min_result.parameters,
356
- loss=min_result.residual,
357
- )
358
-
359
-
360
- def carousel_steady_state(
361
- carousel: Carousel,
362
- *,
363
- p0: dict[str, float],
364
- data: pd.Series,
365
- y0: dict[str, float] | None = None,
366
- minimizer: Minimizer = _default_minimizer,
367
- residual_fn: SteadyStateResidualFn = _steady_state_residual,
368
- integrator: IntegratorType | None = None,
369
- loss_fn: LossFn = rmse,
370
- ) -> CarouselFit:
371
- """Fit model parameters to steady-state experimental data over a carousel.
372
-
373
- Examples:
374
- >>> carousel_steady_state(carousel, p0=p0, data=data)
375
-
376
- Args:
377
- carousel: Model carousel to fit
378
- p0: Initial parameter guesses as {parameter_name: value}
379
- data: Experimental time course data
380
- protocol: Experimental protocol
381
- y0: Initial conditions as {species_name: value}
382
- minimizer: Function to minimize fitting error
383
- residual_fn: Function to calculate fitting error
384
- integrator: ODE integrator class
385
- loss_fn: Loss function to use for residual calculation
386
- time_points_per_step: Number of time points per step in the protocol
387
- bounds: Mapping of bounds per parameter
388
-
389
- Returns:
390
- dict[str, float]: Fitted parameters as {parameter_name: fitted_value}
391
-
392
- Note:
393
- Uses L-BFGS-B optimization with bounds [1e-6, 1e6] for all parameters
394
-
395
- """
396
- return CarouselFit(
397
- [
398
- fit
399
- for i in parallel.parallelise(
400
- partial(
401
- _carousel_steady_state_worker,
402
- p0=p0,
403
- data=data,
404
- y0=y0,
405
- integrator=integrator,
406
- loss_fn=loss_fn,
407
- minimizer=minimizer,
408
- residual_fn=residual_fn,
409
- ),
410
- inputs=list(enumerate(carousel.variants)),
411
- )
412
- if (fit := i[1]) is not None
413
- ]
414
- )
415
-
416
-
417
- def carousel_time_course(
418
- carousel: Carousel,
419
- *,
420
- p0: dict[str, float],
421
- data: pd.DataFrame,
422
- y0: dict[str, float] | None = None,
423
- minimizer: Minimizer = _default_minimizer,
424
- residual_fn: TimeSeriesResidualFn = _time_course_residual,
425
- integrator: IntegratorType | None = None,
426
- loss_fn: LossFn = rmse,
427
- ) -> CarouselFit:
428
- """Fit model parameters to time course of experimental data over a carousel.
429
-
430
- Time points are taken from the data.
431
-
432
- Examples:
433
- >>> carousel_time_course(carousel, p0=p0, data=data)
434
-
435
- Args:
436
- carousel: Model carousel to fit
437
- p0: Initial parameter guesses as {parameter_name: value}
438
- data: Experimental time course data
439
- protocol: Experimental protocol
440
- y0: Initial conditions as {species_name: value}
441
- minimizer: Function to minimize fitting error
442
- residual_fn: Function to calculate fitting error
443
- integrator: ODE integrator class
444
- loss_fn: Loss function to use for residual calculation
445
- time_points_per_step: Number of time points per step in the protocol
446
- bounds: Mapping of bounds per parameter
447
-
448
- Returns:
449
- dict[str, float]: Fitted parameters as {parameter_name: fitted_value}
450
-
451
- Note:
452
- Uses L-BFGS-B optimization with bounds [1e-6, 1e6] for all parameters
453
-
454
- """
455
- return CarouselFit(
456
- [
457
- fit
458
- for i in parallel.parallelise(
459
- partial(
460
- _carousel_time_course_worker,
461
- p0=p0,
462
- data=data,
463
- y0=y0,
464
- integrator=integrator,
465
- loss_fn=loss_fn,
466
- minimizer=minimizer,
467
- residual_fn=residual_fn,
468
- ),
469
- inputs=list(enumerate(carousel.variants)),
470
- )
471
- if (fit := i[1]) is not None
472
- ]
473
- )
474
-
475
-
476
- def carousel_protocol_time_course(
477
- carousel: Carousel,
478
- *,
479
- p0: dict[str, float],
480
- data: pd.DataFrame,
481
- protocol: pd.DataFrame,
482
- y0: dict[str, float] | None = None,
483
- minimizer: Minimizer = _default_minimizer,
484
- residual_fn: ProtocolResidualFn = _protocol_time_course_residual,
485
- integrator: IntegratorType | None = None,
486
- loss_fn: LossFn = rmse,
487
- ) -> CarouselFit:
488
- """Fit model parameters to time course of experimental data over a protocol.
489
-
490
- Time points of protocol time course are taken from the data.
491
-
492
- Examples:
493
- >>> carousel_steady_state(carousel, p0=p0, data=data)
494
-
495
- Args:
496
- carousel: Model carousel to fit
497
- p0: Initial parameter guesses as {parameter_name: value}
498
- data: Experimental time course data
499
- protocol: Experimental protocol
500
- y0: Initial conditions as {species_name: value}
501
- minimizer: Function to minimize fitting error
502
- residual_fn: Function to calculate fitting error
503
- integrator: ODE integrator class
504
- loss_fn: Loss function to use for residual calculation
505
- time_points_per_step: Number of time points per step in the protocol
506
- bounds: Mapping of bounds per parameter
507
-
508
- Returns:
509
- dict[str, float]: Fitted parameters as {parameter_name: fitted_value}
510
-
511
- Note:
512
- Uses L-BFGS-B optimization with bounds [1e-6, 1e6] for all parameters
513
-
514
- """
515
- return CarouselFit(
516
- [
517
- fit
518
- for i in parallel.parallelise(
519
- partial(
520
- _carousel_protocol_worker,
521
- p0=p0,
522
- data=data,
523
- protocol=protocol,
524
- y0=y0,
525
- integrator=integrator,
526
- loss_fn=loss_fn,
527
- minimizer=minimizer,
528
- residual_fn=residual_fn,
529
- ),
530
- inputs=list(enumerate(carousel.variants)),
531
- )
532
- if (fit := i[1]) is not None
533
- ]
534
- )