mxlpy 0.23.0__py3-none-any.whl → 0.25.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.
@@ -1,27 +1,39 @@
1
- """Parameter Fitting Module for Metabolic Models.
1
+ """Parameter local fitting Module for Metabolic Models.
2
2
 
3
- This module provides functions foru fitting model parameters to experimental data,
4
- including both steadyd-state and time-series data fitting capabilities.e
5
-
6
- Functions:
7
- fit_steady_state: Fits parameters to steady-state experimental data
8
- fit_time_course: Fits parameters to time-series experimental data
3
+ This module provides functions for fitting model parameters to experimental data,
4
+ including both steadyd-state and time-series data fitting capabilities.
9
5
  """
10
6
 
11
7
  from __future__ import annotations
12
8
 
13
9
  import logging
10
+ from collections.abc import Callable
14
11
  from copy import deepcopy
15
12
  from dataclasses import dataclass
16
13
  from functools import partial
17
- from typing import TYPE_CHECKING, Protocol
14
+ from typing import TYPE_CHECKING, Literal
18
15
 
19
- import numpy as np
20
16
  from scipy.optimize import minimize
21
17
 
22
18
  from mxlpy import parallel
23
- from mxlpy.simulator import Simulator
24
- from mxlpy.types import Array, ArrayLike, Callable, IntegratorType, cast
19
+ from mxlpy.types import IntegratorType, cast
20
+
21
+ from .common import (
22
+ Bounds,
23
+ CarouselFit,
24
+ FitResult,
25
+ InitialGuess,
26
+ LossFn,
27
+ MinResult,
28
+ ProtocolResidualFn,
29
+ ResidualFn,
30
+ SteadyStateResidualFn,
31
+ TimeSeriesResidualFn,
32
+ _protocol_time_course_residual,
33
+ _steady_state_residual,
34
+ _time_course_residual,
35
+ rmse,
36
+ )
25
37
 
26
38
  if TYPE_CHECKING:
27
39
  import pandas as pd
@@ -32,60 +44,19 @@ if TYPE_CHECKING:
32
44
  LOGGER = logging.getLogger(__name__)
33
45
 
34
46
  __all__ = [
35
- "Bounds",
36
- "CarouselFit",
37
- "FitResult",
38
- "InitialGuess",
39
47
  "LOGGER",
40
- "LossFn",
41
- "MinResult",
42
- "MinimizeFn",
43
- "ProtocolResidualFn",
44
- "ResidualFn",
45
- "SteadyStateResidualFn",
46
- "TimeSeriesResidualFn",
48
+ "Minimizer",
49
+ "ScipyMinimizer",
47
50
  "carousel_protocol_time_course",
48
51
  "carousel_steady_state",
49
52
  "carousel_time_course",
50
53
  "protocol_time_course",
51
- "rmse",
52
54
  "steady_state",
53
55
  "time_course",
54
56
  ]
55
57
 
56
58
 
57
- @dataclass
58
- class MinResult:
59
- """Result of a minimization operation."""
60
-
61
- parameters: dict[str, float]
62
- residual: float
63
-
64
-
65
- @dataclass
66
- class FitResult:
67
- """Result of a fit operation."""
68
-
69
- model: Model
70
- best_pars: dict[str, float]
71
- loss: float
72
-
73
-
74
- @dataclass
75
- class CarouselFit:
76
- """Result of a carousel fit operation."""
77
-
78
- fits: list[FitResult]
79
-
80
- def get_best_fit(self) -> FitResult:
81
- """Get the best fit from the carousel."""
82
- return min(self.fits, key=lambda x: x.loss)
83
-
84
-
85
- type InitialGuess = dict[str, float]
86
- type ResidualFn = Callable[[Array], float]
87
- type Bounds = dict[str, tuple[float | None, float | None]]
88
- type MinimizeFn = Callable[
59
+ type Minimizer = Callable[
89
60
  [
90
61
  ResidualFn,
91
62
  InitialGuess,
@@ -93,248 +64,68 @@ type MinimizeFn = Callable[
93
64
  ],
94
65
  MinResult | None,
95
66
  ]
96
- type LossFn = Callable[
97
- [
98
- pd.DataFrame | pd.Series,
99
- pd.DataFrame | pd.Series,
100
- ],
101
- float,
102
- ]
103
-
104
67
 
105
- def rmse(
106
- y_pred: pd.DataFrame | pd.Series,
107
- y_true: pd.DataFrame | pd.Series,
108
- ) -> float:
109
- """Calculate root mean square error between model and data."""
110
- return cast(float, np.sqrt(np.mean(np.square(y_pred - y_true))))
111
68
 
69
+ @dataclass
70
+ class ScipyMinimizer:
71
+ """Local multivariate minimization using scipy.optimize.
112
72
 
113
- class SteadyStateResidualFn(Protocol):
114
- """Protocol for steady state residual functions."""
73
+ See Also
74
+ --------
75
+ https://docs.scipy.org/doc/scipy/reference/optimize.html#local-multivariate-optimization
115
76
 
116
- def __call__(
117
- self,
118
- par_values: Array,
119
- # This will be filled out by partial
120
- par_names: list[str],
121
- data: pd.Series,
122
- model: Model,
123
- y0: dict[str, float] | None,
124
- integrator: IntegratorType,
125
- loss_fn: LossFn,
126
- ) -> float:
127
- """Calculate residual error between model steady state and experimental data."""
128
- ...
129
-
130
-
131
- class TimeSeriesResidualFn(Protocol):
132
- """Protocol for time series residual functions."""
77
+ """
133
78
 
134
- def __call__(
135
- self,
136
- par_values: Array,
137
- # This will be filled out by partial
138
- par_names: list[str],
139
- data: pd.DataFrame,
140
- model: Model,
141
- y0: dict[str, float] | None,
142
- integrator: IntegratorType,
143
- loss_fn: LossFn,
144
- ) -> float:
145
- """Calculate residual error between model time course and experimental data."""
146
- ...
147
-
148
-
149
- class ProtocolResidualFn(Protocol):
150
- """Protocol for time series residual functions."""
79
+ tol: float = 1e-6
80
+ method: Literal[
81
+ "Nelder-Mead",
82
+ "Powell",
83
+ "CG",
84
+ "BFGS",
85
+ "Newton-CG",
86
+ "L-BFGS-B",
87
+ "TNC",
88
+ "COBYLA",
89
+ "COBYQA",
90
+ "SLSQP",
91
+ "trust-constr",
92
+ "dogleg",
93
+ "trust-ncg",
94
+ "trust-exact",
95
+ "trust-krylov",
96
+ ] = "L-BFGS-B"
151
97
 
152
98
  def __call__(
153
99
  self,
154
- par_values: Array,
155
- # This will be filled out by partial
156
- par_names: list[str],
157
- data: pd.DataFrame,
158
- model: Model,
159
- y0: dict[str, float] | None,
160
- integrator: IntegratorType,
161
- loss_fn: LossFn,
162
- protocol: pd.DataFrame,
163
- ) -> float:
164
- """Calculate residual error between model time course and experimental data."""
165
- ...
166
-
167
-
168
- def _default_minimize_fn(
169
- residual_fn: ResidualFn,
170
- p0: dict[str, float],
171
- bounds: Bounds,
172
- ) -> MinResult | None:
173
- res = minimize(
174
- residual_fn,
175
- x0=list(p0.values()),
176
- bounds=[bounds.get(name, (1e-6, 1e6)) for name in p0],
177
- method="L-BFGS-B",
178
- )
179
- if res.success:
180
- return MinResult(
181
- parameters=dict(
182
- zip(
183
- p0,
184
- res.x,
185
- strict=True,
186
- ),
187
- ),
188
- residual=res.fun,
100
+ residual_fn: ResidualFn,
101
+ p0: dict[str, float],
102
+ bounds: Bounds,
103
+ ) -> MinResult | None:
104
+ """Call minimzer."""
105
+ res = minimize(
106
+ residual_fn,
107
+ x0=list(p0.values()),
108
+ bounds=[bounds.get(name, (1e-6, 1e6)) for name in p0],
109
+ method=self.method,
110
+ tol=self.tol,
189
111
  )
190
-
191
- LOGGER.warning("Minimisation failed.")
192
- return None
193
-
194
-
195
- def _steady_state_residual(
196
- par_values: Array,
197
- # This will be filled out by partial
198
- par_names: list[str],
199
- data: pd.Series,
200
- model: Model,
201
- y0: dict[str, float] | None,
202
- integrator: IntegratorType,
203
- loss_fn: LossFn,
204
- ) -> float:
205
- """Calculate residual error between model steady state and experimental data.
206
-
207
- Args:
208
- par_values: Parameter values to test
209
- data: Experimental steady state data
210
- model: Model instance to simulate
211
- y0: Initial conditions
212
- par_names: Names of parameters being fit
213
- integrator: ODE integrator class to use
214
- loss_fn: Loss function to use for residual calculation
215
-
216
- Returns:
217
- float: Root mean square error between model and data
218
-
219
- """
220
- res = (
221
- Simulator(
222
- model.update_parameters(
223
- dict(
112
+ if res.success:
113
+ return MinResult(
114
+ parameters=dict(
224
115
  zip(
225
- par_names,
226
- par_values,
116
+ p0,
117
+ res.x,
227
118
  strict=True,
228
- )
229
- )
230
- ),
231
- y0=y0,
232
- integrator=integrator,
233
- )
234
- .simulate_to_steady_state()
235
- .get_result()
236
- )
237
- if res is None:
238
- return cast(float, np.inf)
239
-
240
- return loss_fn(
241
- res.get_combined().loc[:, cast(list, data.index)],
242
- data,
243
- )
244
-
245
-
246
- def _time_course_residual(
247
- par_values: ArrayLike,
248
- # This will be filled out by partial
249
- par_names: list[str],
250
- data: pd.DataFrame,
251
- model: Model,
252
- y0: dict[str, float] | None,
253
- integrator: IntegratorType,
254
- loss_fn: LossFn,
255
- ) -> float:
256
- """Calculate residual error between model time course and experimental data.
257
-
258
- Args:
259
- par_values: Parameter values to test
260
- data: Experimental time course data
261
- model: Model instance to simulate
262
- y0: Initial conditions
263
- par_names: Names of parameters being fit
264
- integrator: ODE integrator class to use
265
- loss_fn: Loss function to use for residual calculation
266
-
267
- Returns:
268
- float: Root mean square error between model and data
269
-
270
- """
271
- res = (
272
- Simulator(
273
- model.update_parameters(dict(zip(par_names, par_values, strict=True))),
274
- y0=y0,
275
- integrator=integrator,
276
- )
277
- .simulate_time_course(cast(list, data.index))
278
- .get_result()
279
- )
280
- if res is None:
281
- return cast(float, np.inf)
282
- results_ss = res.get_combined()
283
-
284
- return loss_fn(
285
- results_ss.loc[:, cast(list, data.columns)],
286
- data,
287
- )
288
-
289
-
290
- def _protocol_time_course_residual(
291
- par_values: ArrayLike,
292
- # This will be filled out by partial
293
- par_names: list[str],
294
- data: pd.DataFrame,
295
- model: Model,
296
- y0: dict[str, float] | None,
297
- integrator: IntegratorType,
298
- loss_fn: LossFn,
299
- protocol: pd.DataFrame,
300
- ) -> float:
301
- """Calculate residual error between model time course and experimental data.
302
-
303
- Args:
304
- par_values: Parameter values to test
305
- data: Experimental time course data
306
- model: Model instance to simulate
307
- y0: Initial conditions
308
- par_names: Names of parameters being fit
309
- integrator: ODE integrator class to use
310
- loss_fn: Loss function to use for residual calculation
311
- protocol: Experimental protocol
312
- time_points_per_step: Number of time points per step in the protocol
119
+ ),
120
+ ),
121
+ residual=res.fun,
122
+ )
313
123
 
314
- Returns:
315
- float: Root mean square error between model and data
124
+ LOGGER.warning("Minimisation failed due to %s", res.message)
125
+ return None
316
126
 
317
- """
318
- res = (
319
- Simulator(
320
- model.update_parameters(dict(zip(par_names, par_values, strict=True))),
321
- y0=y0,
322
- integrator=integrator,
323
- )
324
- .simulate_protocol_time_course(
325
- protocol=protocol,
326
- time_points=data.index,
327
- )
328
- .get_result()
329
- )
330
- if res is None:
331
- return cast(float, np.inf)
332
- results_ss = res.get_combined()
333
127
 
334
- return loss_fn(
335
- results_ss.loc[:, cast(list, data.columns)],
336
- data,
337
- )
128
+ _default_minimizer = ScipyMinimizer()
338
129
 
339
130
 
340
131
  def _carousel_steady_state_worker(
@@ -344,7 +135,7 @@ def _carousel_steady_state_worker(
344
135
  y0: dict[str, float] | None,
345
136
  integrator: IntegratorType | None,
346
137
  loss_fn: LossFn,
347
- minimize_fn: MinimizeFn,
138
+ minimizer: Minimizer,
348
139
  residual_fn: SteadyStateResidualFn,
349
140
  bounds: Bounds | None,
350
141
  ) -> FitResult | None:
@@ -355,7 +146,7 @@ def _carousel_steady_state_worker(
355
146
  p0={k: v for k, v in p0.items() if k in model_pars},
356
147
  y0=y0,
357
148
  data=data,
358
- minimize_fn=minimize_fn,
149
+ minimizer=minimizer,
359
150
  residual_fn=residual_fn,
360
151
  integrator=integrator,
361
152
  loss_fn=loss_fn,
@@ -370,7 +161,7 @@ def _carousel_time_course_worker(
370
161
  y0: dict[str, float] | None,
371
162
  integrator: IntegratorType | None,
372
163
  loss_fn: LossFn,
373
- minimize_fn: MinimizeFn,
164
+ minimizer: Minimizer,
374
165
  residual_fn: TimeSeriesResidualFn,
375
166
  bounds: Bounds | None,
376
167
  ) -> FitResult | None:
@@ -380,7 +171,7 @@ def _carousel_time_course_worker(
380
171
  p0={k: v for k, v in p0.items() if k in model_pars},
381
172
  y0=y0,
382
173
  data=data,
383
- minimize_fn=minimize_fn,
174
+ minimizer=minimizer,
384
175
  residual_fn=residual_fn,
385
176
  integrator=integrator,
386
177
  loss_fn=loss_fn,
@@ -396,7 +187,7 @@ def _carousel_protocol_worker(
396
187
  y0: dict[str, float] | None,
397
188
  integrator: IntegratorType | None,
398
189
  loss_fn: LossFn,
399
- minimize_fn: MinimizeFn,
190
+ minimizer: Minimizer,
400
191
  residual_fn: ProtocolResidualFn,
401
192
  bounds: Bounds | None,
402
193
  ) -> FitResult | None:
@@ -407,7 +198,7 @@ def _carousel_protocol_worker(
407
198
  y0=y0,
408
199
  protocol=protocol,
409
200
  data=data,
410
- minimize_fn=minimize_fn,
201
+ minimizer=minimizer,
411
202
  residual_fn=residual_fn,
412
203
  integrator=integrator,
413
204
  loss_fn=loss_fn,
@@ -421,7 +212,7 @@ def steady_state(
421
212
  p0: dict[str, float],
422
213
  data: pd.Series,
423
214
  y0: dict[str, float] | None = None,
424
- minimize_fn: MinimizeFn = _default_minimize_fn,
215
+ minimizer: Minimizer = _default_minimizer,
425
216
  residual_fn: SteadyStateResidualFn = _steady_state_residual,
426
217
  integrator: IntegratorType | None = None,
427
218
  loss_fn: LossFn = rmse,
@@ -438,7 +229,7 @@ def steady_state(
438
229
  data: Experimental steady state data as pandas Series
439
230
  p0: Initial parameter guesses as {parameter_name: value}
440
231
  y0: Initial conditions as {species_name: value}
441
- minimize_fn: Function to minimize fitting error
232
+ minimizer: Function to minimize fitting error
442
233
  residual_fn: Function to calculate fitting error
443
234
  integrator: ODE integrator class
444
235
  loss_fn: Loss function to use for residual calculation
@@ -468,7 +259,7 @@ def steady_state(
468
259
  loss_fn=loss_fn,
469
260
  ),
470
261
  )
471
- min_result = minimize_fn(fn, p0, {} if bounds is None else bounds)
262
+ min_result = minimizer(fn, p0, {} if bounds is None else bounds)
472
263
  # Restore original model
473
264
  model.update_parameters(p_orig)
474
265
  if min_result is None:
@@ -487,7 +278,7 @@ def time_course(
487
278
  p0: dict[str, float],
488
279
  data: pd.DataFrame,
489
280
  y0: dict[str, float] | None = None,
490
- minimize_fn: MinimizeFn = _default_minimize_fn,
281
+ minimizer: Minimizer = _default_minimizer,
491
282
  residual_fn: TimeSeriesResidualFn = _time_course_residual,
492
283
  integrator: IntegratorType | None = None,
493
284
  loss_fn: LossFn = rmse,
@@ -504,7 +295,7 @@ def time_course(
504
295
  data: Experimental time course data
505
296
  p0: Initial parameter guesses as {parameter_name: value}
506
297
  y0: Initial conditions as {species_name: value}
507
- minimize_fn: Function to minimize fitting error
298
+ minimizer: Function to minimize fitting error
508
299
  residual_fn: Function to calculate fitting error
509
300
  integrator: ODE integrator class
510
301
  loss_fn: Loss function to use for residual calculation
@@ -533,7 +324,7 @@ def time_course(
533
324
  ),
534
325
  )
535
326
 
536
- min_result = minimize_fn(fn, p0, {} if bounds is None else bounds)
327
+ min_result = minimizer(fn, p0, {} if bounds is None else bounds)
537
328
  # Restore original model
538
329
  model.update_parameters(p_orig)
539
330
  if min_result is None:
@@ -553,7 +344,7 @@ def protocol_time_course(
553
344
  data: pd.DataFrame,
554
345
  protocol: pd.DataFrame,
555
346
  y0: dict[str, float] | None = None,
556
- minimize_fn: MinimizeFn = _default_minimize_fn,
347
+ minimizer: Minimizer = _default_minimizer,
557
348
  residual_fn: ProtocolResidualFn = _protocol_time_course_residual,
558
349
  integrator: IntegratorType | None = None,
559
350
  loss_fn: LossFn = rmse,
@@ -561,6 +352,8 @@ def protocol_time_course(
561
352
  ) -> FitResult | None:
562
353
  """Fit model parameters to time course of experimental data.
563
354
 
355
+ Time points of protocol time course are taken from the data.
356
+
564
357
  Examples:
565
358
  >>> time_course(model, p0, data)
566
359
  {'k1': 0.1, 'k2': 0.2}
@@ -571,7 +364,7 @@ def protocol_time_course(
571
364
  data: Experimental time course data
572
365
  protocol: Experimental protocol
573
366
  y0: Initial conditions as {species_name: value}
574
- minimize_fn: Function to minimize fitting error
367
+ minimizer: Function to minimize fitting error
575
368
  residual_fn: Function to calculate fitting error
576
369
  integrator: ODE integrator class
577
370
  loss_fn: Loss function to use for residual calculation
@@ -602,7 +395,7 @@ def protocol_time_course(
602
395
  ),
603
396
  )
604
397
 
605
- min_result = minimize_fn(fn, p0, {} if bounds is None else bounds)
398
+ min_result = minimizer(fn, p0, {} if bounds is None else bounds)
606
399
  # Restore original model
607
400
  model.update_parameters(p_orig)
608
401
  if min_result is None:
@@ -621,7 +414,7 @@ def carousel_steady_state(
621
414
  p0: dict[str, float],
622
415
  data: pd.Series,
623
416
  y0: dict[str, float] | None = None,
624
- minimize_fn: MinimizeFn = _default_minimize_fn,
417
+ minimizer: Minimizer = _default_minimizer,
625
418
  residual_fn: SteadyStateResidualFn = _steady_state_residual,
626
419
  integrator: IntegratorType | None = None,
627
420
  loss_fn: LossFn = rmse,
@@ -638,7 +431,7 @@ def carousel_steady_state(
638
431
  data: Experimental time course data
639
432
  protocol: Experimental protocol
640
433
  y0: Initial conditions as {species_name: value}
641
- minimize_fn: Function to minimize fitting error
434
+ minimizer: Function to minimize fitting error
642
435
  residual_fn: Function to calculate fitting error
643
436
  integrator: ODE integrator class
644
437
  loss_fn: Loss function to use for residual calculation
@@ -663,7 +456,7 @@ def carousel_steady_state(
663
456
  y0=y0,
664
457
  integrator=integrator,
665
458
  loss_fn=loss_fn,
666
- minimize_fn=minimize_fn,
459
+ minimizer=minimizer,
667
460
  residual_fn=residual_fn,
668
461
  bounds=bounds,
669
462
  ),
@@ -680,7 +473,7 @@ def carousel_time_course(
680
473
  p0: dict[str, float],
681
474
  data: pd.DataFrame,
682
475
  y0: dict[str, float] | None = None,
683
- minimize_fn: MinimizeFn = _default_minimize_fn,
476
+ minimizer: Minimizer = _default_minimizer,
684
477
  residual_fn: TimeSeriesResidualFn = _time_course_residual,
685
478
  integrator: IntegratorType | None = None,
686
479
  loss_fn: LossFn = rmse,
@@ -688,8 +481,10 @@ def carousel_time_course(
688
481
  ) -> CarouselFit:
689
482
  """Fit model parameters to time course of experimental data over a carousel.
690
483
 
484
+ Time points are taken from the data.
485
+
691
486
  Examples:
692
- >>> carousel_steady_state(carousel, p0=p0, data=data)
487
+ >>> carousel_time_course(carousel, p0=p0, data=data)
693
488
 
694
489
  Args:
695
490
  carousel: Model carousel to fit
@@ -697,7 +492,7 @@ def carousel_time_course(
697
492
  data: Experimental time course data
698
493
  protocol: Experimental protocol
699
494
  y0: Initial conditions as {species_name: value}
700
- minimize_fn: Function to minimize fitting error
495
+ minimizer: Function to minimize fitting error
701
496
  residual_fn: Function to calculate fitting error
702
497
  integrator: ODE integrator class
703
498
  loss_fn: Loss function to use for residual calculation
@@ -722,7 +517,7 @@ def carousel_time_course(
722
517
  y0=y0,
723
518
  integrator=integrator,
724
519
  loss_fn=loss_fn,
725
- minimize_fn=minimize_fn,
520
+ minimizer=minimizer,
726
521
  residual_fn=residual_fn,
727
522
  bounds=bounds,
728
523
  ),
@@ -740,7 +535,7 @@ def carousel_protocol_time_course(
740
535
  data: pd.DataFrame,
741
536
  protocol: pd.DataFrame,
742
537
  y0: dict[str, float] | None = None,
743
- minimize_fn: MinimizeFn = _default_minimize_fn,
538
+ minimizer: Minimizer = _default_minimizer,
744
539
  residual_fn: ProtocolResidualFn = _protocol_time_course_residual,
745
540
  integrator: IntegratorType | None = None,
746
541
  loss_fn: LossFn = rmse,
@@ -748,6 +543,8 @@ def carousel_protocol_time_course(
748
543
  ) -> CarouselFit:
749
544
  """Fit model parameters to time course of experimental data over a protocol.
750
545
 
546
+ Time points of protocol time course are taken from the data.
547
+
751
548
  Examples:
752
549
  >>> carousel_steady_state(carousel, p0=p0, data=data)
753
550
 
@@ -757,7 +554,7 @@ def carousel_protocol_time_course(
757
554
  data: Experimental time course data
758
555
  protocol: Experimental protocol
759
556
  y0: Initial conditions as {species_name: value}
760
- minimize_fn: Function to minimize fitting error
557
+ minimizer: Function to minimize fitting error
761
558
  residual_fn: Function to calculate fitting error
762
559
  integrator: ODE integrator class
763
560
  loss_fn: Loss function to use for residual calculation
@@ -783,7 +580,7 @@ def carousel_protocol_time_course(
783
580
  y0=y0,
784
581
  integrator=integrator,
785
582
  loss_fn=loss_fn,
786
- minimize_fn=minimize_fn,
583
+ minimizer=minimizer,
787
584
  residual_fn=residual_fn,
788
585
  bounds=bounds,
789
586
  ),
mxlpy/identify.py CHANGED
@@ -9,8 +9,9 @@ import numpy as np
9
9
  import pandas as pd
10
10
  from tqdm import tqdm
11
11
 
12
- from mxlpy import fit
12
+ from mxlpy import fit_local
13
13
  from mxlpy.distributions import LogNormal, sample
14
+ from mxlpy.fit.common import LossFn, rmse
14
15
  from mxlpy.parallel import parallelise
15
16
 
16
17
  if TYPE_CHECKING:
@@ -26,9 +27,9 @@ def _mc_fit_time_course_worker(
26
27
  p0: pd.Series,
27
28
  model: Model,
28
29
  data: pd.DataFrame,
29
- loss_fn: fit.LossFn,
30
+ loss_fn: fit_local.LossFn,
30
31
  ) -> float:
31
- fit_result = fit.time_course(
32
+ fit_result = fit_local.time_course(
32
33
  model=model,
33
34
  p0=p0.to_dict(),
34
35
  data=data,
@@ -45,7 +46,7 @@ def profile_likelihood(
45
46
  parameter_name: str,
46
47
  parameter_values: Array,
47
48
  n_random: int = 10,
48
- loss_fn: fit.LossFn = fit.rmse,
49
+ loss_fn: LossFn = rmse,
49
50
  ) -> pd.Series:
50
51
  """Estimate the profile likelihood of model parameters given data.
51
52