mxlpy 0.16.0__py3-none-any.whl → 0.17.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/__init__.py CHANGED
@@ -48,6 +48,7 @@ from . import (
48
48
  fns,
49
49
  mc,
50
50
  mca,
51
+ npe,
51
52
  plot,
52
53
  report,
53
54
  sbml,
@@ -66,7 +67,7 @@ from .scan import (
66
67
  )
67
68
  from .simulator import Simulator
68
69
  from .symbolic import SymbolicModel, to_symbolic_model
69
- from .types import Derived, IntegratorProtocol
70
+ from .types import Derived, IntegratorProtocol, unwrap
70
71
 
71
72
  with contextlib.suppress(ImportError):
72
73
  from .integrators import Assimulo
@@ -95,6 +96,7 @@ __all__ = [
95
96
  "make_protocol",
96
97
  "mc",
97
98
  "mca",
99
+ "npe",
98
100
  "plot",
99
101
  "report",
100
102
  "sbml",
@@ -104,6 +106,7 @@ __all__ = [
104
106
  "time_course",
105
107
  "time_course_over_protocol",
106
108
  "to_symbolic_model",
109
+ "unwrap",
107
110
  ]
108
111
 
109
112
 
mxlpy/fns.py CHANGED
@@ -37,52 +37,255 @@ __all__ = [
37
37
 
38
38
 
39
39
  def constant(x: Float) -> Float:
40
- """Constant function."""
40
+ """Return a constant value regardless of other model components.
41
+
42
+ Parameters
43
+ ----------
44
+ x
45
+ Value to return
46
+
47
+ Returns
48
+ -------
49
+ Float
50
+ The input value unchanged
51
+
52
+ Examples
53
+ --------
54
+ >>> constant(5.0)
55
+ 5.0
56
+
57
+ """
41
58
  return x
42
59
 
43
60
 
44
61
  def neg(x: Float) -> Float:
45
- """Negation function."""
62
+ """Calculate the negation of a value.
63
+
64
+ Parameters
65
+ ----------
66
+ x
67
+ Value to negate
68
+
69
+ Returns
70
+ -------
71
+ Float
72
+ Negative of the input value
73
+
74
+ Examples
75
+ --------
76
+ >>> neg(3.0)
77
+ -3.0
78
+ >>> neg(-2.5)
79
+ 2.5
80
+
81
+ """
46
82
  return -x
47
83
 
48
84
 
49
85
  def minus(x: Float, y: Float) -> Float:
50
- """Subtraction function."""
86
+ """Calculate the difference between two values.
87
+
88
+ Parameters
89
+ ----------
90
+ x
91
+ Minuend (value to subtract from)
92
+ y
93
+ Subtrahend (value to subtract)
94
+
95
+ Returns
96
+ -------
97
+ Float
98
+ Difference between x and y (x - y)
99
+
100
+ Examples
101
+ --------
102
+ >>> minus(5.0, 3.0)
103
+ 2.0
104
+ >>> minus(2.0, 5.0)
105
+ -3.0
106
+
107
+ """
51
108
  return x - y
52
109
 
53
110
 
54
111
  def mul(x: Float, y: Float) -> Float:
55
- """Multiplication function."""
112
+ """Calculate the product of two values.
113
+
114
+ Parameters
115
+ ----------
116
+ x
117
+ First factor
118
+ y
119
+ Second factor
120
+
121
+ Returns
122
+ -------
123
+ Float
124
+ Product of x and y (x * y)
125
+
126
+ Examples
127
+ --------
128
+ >>> mul(2.0, 3.0)
129
+ 6.0
130
+ >>> mul(0.5, 4.0)
131
+ 2.0
132
+
133
+ """
56
134
  return x * y
57
135
 
58
136
 
59
137
  def div(x: Float, y: Float) -> Float:
60
- """Division function."""
138
+ """Calculate the quotient of two values.
139
+
140
+ Parameters
141
+ ----------
142
+ x
143
+ Numerator
144
+ y
145
+ Denominator
146
+
147
+ Returns
148
+ -------
149
+ Float
150
+ Quotient of x and y (x / y)
151
+
152
+ Examples
153
+ --------
154
+ >>> div(6.0, 3.0)
155
+ 2.0
156
+ >>> div(5.0, 2.0)
157
+ 2.5
158
+
159
+ """
61
160
  return x / y
62
161
 
63
162
 
64
163
  def one_div(x: Float) -> Float:
65
- """Reciprocal function."""
164
+ """Calculate the reciprocal of a value.
165
+
166
+ Parameters
167
+ ----------
168
+ x
169
+ Value to find reciprocal of
170
+
171
+ Returns
172
+ -------
173
+ Float
174
+ Reciprocal of x (1 / x)
175
+
176
+ Examples
177
+ --------
178
+ >>> one_div(2.0)
179
+ 0.5
180
+ >>> one_div(4.0)
181
+ 0.25
182
+
183
+ """
66
184
  return 1.0 / x
67
185
 
68
186
 
69
187
  def neg_div(x: Float, y: Float) -> Float:
70
- """Negated division function."""
188
+ """Calculate the negative quotient of two values.
189
+
190
+ Parameters
191
+ ----------
192
+ x
193
+ Numerator
194
+ y
195
+ Denominator
196
+
197
+ Returns
198
+ -------
199
+ Float
200
+ Negative quotient of x and y (-x / y)
201
+
202
+ Examples
203
+ --------
204
+ >>> neg_div(6.0, 3.0)
205
+ -2.0
206
+ >>> neg_div(-6.0, 3.0)
207
+ 2.0
208
+
209
+ """
71
210
  return -x / y
72
211
 
73
212
 
74
213
  def twice(x: Float) -> Float:
75
- """Twice function."""
214
+ """Calculate twice the value.
215
+
216
+ Parameters
217
+ ----------
218
+ x
219
+ Value to double
220
+
221
+ Returns
222
+ -------
223
+ Float
224
+ Double of the input value (x * 2)
225
+
226
+ Examples
227
+ --------
228
+ >>> twice(3.5)
229
+ 7.0
230
+ >>> twice(-1.5)
231
+ -3.0
232
+
233
+ """
76
234
  return x * 2
77
235
 
78
236
 
79
237
  def add(x: Float, y: Float) -> Float:
80
- """Proportional function."""
238
+ """Calculate the sum of two values.
239
+
240
+ Parameters
241
+ ----------
242
+ x
243
+ First addend
244
+ y
245
+ Second addend
246
+
247
+ Returns
248
+ -------
249
+ Float
250
+ Sum of x and y (x + y)
251
+
252
+ Examples
253
+ --------
254
+ >>> add(2.0, 3.0)
255
+ 5.0
256
+ >>> add(-1.5, 3.5)
257
+ 2.0
258
+
259
+ """
81
260
  return x + y
82
261
 
83
262
 
84
263
  def proportional(x: Float, y: Float) -> Float:
85
- """Proportional function."""
264
+ """Calculate the product of two values.
265
+
266
+ Common in mass-action kinetics where x represents a rate constant
267
+ and y represents a substrate concentration.
268
+
269
+ Parameters
270
+ ----------
271
+ x
272
+ First factor (often rate constant)
273
+ y
274
+ Second factor (often concentration)
275
+
276
+ Returns
277
+ -------
278
+ Float
279
+ Product of x and y (x * y)
280
+
281
+ Examples
282
+ --------
283
+ >>> proportional(0.5, 2.0) # rate = 0.5 * [S]
284
+ 1.0
285
+ >>> proportional(0.1, 5.0)
286
+ 0.5
287
+
288
+ """
86
289
  return x * y
87
290
 
88
291
 
@@ -95,7 +298,32 @@ def moiety_1s(
95
298
  x: Float,
96
299
  x_total: Float,
97
300
  ) -> Float:
98
- """General moiety for one substrate."""
301
+ """Calculate conservation relationship for one substrate.
302
+
303
+ Used for creating derived variables that represent moiety conservation,
304
+ such as calculating the free form of a species when you know the total.
305
+
306
+ Parameters
307
+ ----------
308
+ x
309
+ Concentration of one form of the species
310
+ x_total
311
+ Total concentration of all forms
312
+
313
+ Returns
314
+ -------
315
+ Float
316
+ Concentration of the other form (x_total - x)
317
+
318
+ Examples
319
+ --------
320
+ >>> moiety_1s(0.3, 1.0) # If total is 1.0 and one form is 0.3, other is 0.7
321
+ 0.7
322
+ >>> # Example: If ATP + ADP = total_adenosine
323
+ >>> moiety_1s(0.8, 1.5) # [ADP] = total_adenosine - [ATP]
324
+ 0.7
325
+
326
+ """
99
327
  return x_total - x
100
328
 
101
329
 
@@ -104,7 +332,35 @@ def moiety_2s(
104
332
  x2: Float,
105
333
  x_total: Float,
106
334
  ) -> Float:
107
- """General moiety for two substrates."""
335
+ """Calculate conservation relationship for two substrates.
336
+
337
+ Used for creating derived variables that represent moiety conservation
338
+ across three species, where the third species concentration can be
339
+ calculated from the total and the other two species.
340
+
341
+ Parameters
342
+ ----------
343
+ x1
344
+ Concentration of first form of the species
345
+ x2
346
+ Concentration of second form of the species
347
+ x_total
348
+ Total concentration of all forms
349
+
350
+ Returns
351
+ -------
352
+ Float
353
+ Concentration of the third form (x_total - x1 - x2)
354
+
355
+ Examples
356
+ --------
357
+ >>> moiety_2s(0.3, 0.2, 1.0) # If total is 1.0, first form is 0.3, second is 0.2
358
+ 0.5
359
+ >>> # Example: If ATP + ADP + AMP = total_adenosine
360
+ >>> moiety_2s(0.5, 0.3, 1.0) # [AMP] = total_adenosine - [ATP] - [ADP]
361
+ 0.2
362
+
363
+ """
108
364
  return x_total - x1 - x2
109
365
 
110
366
 
@@ -114,22 +370,132 @@ def moiety_2s(
114
370
 
115
371
 
116
372
  def mass_action_1s(s1: Float, k: Float) -> Float:
117
- """Irreversible mass action reaction with one substrate."""
373
+ """Calculate irreversible mass action reaction rate with one substrate.
374
+
375
+ Rate = k * [S]
376
+
377
+ Parameters
378
+ ----------
379
+ s1
380
+ Substrate concentration
381
+ k
382
+ Rate constant
383
+
384
+ Returns
385
+ -------
386
+ Float
387
+ Reaction rate
388
+
389
+ Examples
390
+ --------
391
+ >>> mass_action_1s(2.0, 0.5) # Rate = 0.5 * [S]
392
+ 1.0
393
+ >>> # Example: Simple degradation reaction S -> ∅
394
+ >>> mass_action_1s(5.0, 0.2) # Rate = 0.2 * [S]
395
+ 1.0
396
+
397
+ """
118
398
  return k * s1
119
399
 
120
400
 
121
401
  def mass_action_1s_1p(s1: Float, p1: Float, kf: Float, kr: Float) -> Float:
122
- """Reversible mass action reaction with one substrate and one product."""
402
+ """Calculate reversible mass action reaction rate with one substrate and one product.
403
+
404
+ Rate = kf * [S] - kr * [P]
405
+
406
+ Parameters
407
+ ----------
408
+ s1
409
+ Substrate concentration
410
+ p1
411
+ Product concentration
412
+ kf
413
+ Forward rate constant
414
+ kr
415
+ Reverse rate constant
416
+
417
+ Returns
418
+ -------
419
+ Float
420
+ Net reaction rate (positive for forward direction)
421
+
422
+ Examples
423
+ --------
424
+ >>> # For reaction S ⇌ P
425
+ >>> mass_action_1s_1p(2.0, 1.0, 0.5, 0.2) # Rate = 0.5*[S] - 0.2*[P]
426
+ 0.8
427
+ >>> # At equilibrium, rates balance
428
+ >>> mass_action_1s_1p(2.0, 5.0, 0.5, 0.2) # Rate = 0.5*2 - 0.2*5
429
+ 0.0
430
+
431
+ """
123
432
  return kf * s1 - kr * p1
124
433
 
125
434
 
126
435
  def mass_action_2s(s1: Float, s2: Float, k: Float) -> Float:
127
- """Irreversible mass action reaction with two substrates."""
436
+ """Calculate irreversible mass action reaction rate with two substrates.
437
+
438
+ Rate = k * [S1] * [S2]
439
+
440
+ Parameters
441
+ ----------
442
+ s1
443
+ First substrate concentration
444
+ s2
445
+ Second substrate concentration
446
+ k
447
+ Rate constant
448
+
449
+ Returns
450
+ -------
451
+ Float
452
+ Reaction rate
453
+
454
+ Examples
455
+ --------
456
+ >>> mass_action_2s(2.0, 3.0, 0.5) # Rate = 0.5 * [S1] * [S2]
457
+ 3.0
458
+ >>> # Example: Bimolecular reaction S1 + S2 -> P
459
+ >>> mass_action_2s(1.0, 2.0, 0.25) # Rate = 0.25 * [S1] * [S2]
460
+ 0.5
461
+
462
+ """
128
463
  return k * s1 * s2
129
464
 
130
465
 
131
466
  def mass_action_2s_1p(s1: Float, s2: Float, p1: Float, kf: Float, kr: Float) -> Float:
132
- """Reversible mass action reaction with two substrates and one product."""
467
+ """Calculate reversible mass action reaction rate with two substrates and one product.
468
+
469
+ Rate = kf * [S1] * [S2] - kr * [P]
470
+
471
+ Parameters
472
+ ----------
473
+ s1
474
+ First substrate concentration
475
+ s2
476
+ Second substrate concentration
477
+ p1
478
+ Product concentration
479
+ kf
480
+ Forward rate constant
481
+ kr
482
+ Reverse rate constant
483
+
484
+ Returns
485
+ -------
486
+ Float
487
+ Net reaction rate (positive for forward direction)
488
+
489
+ Examples
490
+ --------
491
+ >>> # For reaction S1 + S2 ⇌ P
492
+ >>> mass_action_2s_1p(2.0, 1.5, 1.0, 0.5, 0.2) # Rate = 0.5*[S1]*[S2] - 0.2*[P]
493
+ 1.3
494
+ >>> # At equilibrium, rates balance
495
+ >>> mass_action_2s_1p(2.0, 1.0, 5.0, 0.5, 0.5) # Rate = 0.5*2*1 - 0.5*5
496
+ -1.5
497
+
498
+ """
133
499
  return kf * s1 * s2 - kr * p1
134
500
 
135
501
 
@@ -140,7 +506,34 @@ def mass_action_2s_1p(s1: Float, s2: Float, p1: Float, kf: Float, kr: Float) ->
140
506
 
141
507
 
142
508
  def michaelis_menten_1s(s1: Float, vmax: Float, km1: Float) -> Float:
143
- """Irreversible Michaelis-Menten equation for one substrate."""
509
+ """Calculate irreversible Michaelis-Menten reaction rate for one substrate.
510
+
511
+ Rate = Vmax * [S] / (Km + [S])
512
+
513
+ Parameters
514
+ ----------
515
+ s1
516
+ Substrate concentration
517
+ vmax
518
+ Maximum reaction velocity
519
+ km1
520
+ Michaelis constant (substrate concentration at half-maximal rate)
521
+
522
+ Returns
523
+ -------
524
+ Float
525
+ Reaction rate
526
+
527
+ Examples
528
+ --------
529
+ >>> michaelis_menten_1s(2.0, 10.0, 1.0) # When [S]=2*Km, rate = 2/3 * Vmax
530
+ 6.666666666666667
531
+ >>> michaelis_menten_1s(10.0, 5.0, 1.0) # When [S]>>Km, rate ≈ Vmax
532
+ 4.545454545454546
533
+ >>> michaelis_menten_1s(0.1, 5.0, 1.0) # When [S]<<Km, rate ≈ Vmax*[S]/Km
534
+ 0.45454545454545453
535
+
536
+ """
144
537
  return s1 * vmax / (s1 + km1)
145
538
 
146
539
 
@@ -162,7 +555,41 @@ def michaelis_menten_2s(
162
555
  km1: Float,
163
556
  km2: Float,
164
557
  ) -> Float:
165
- """Michaelis-Menten equation (ping-pong) for two substrates."""
558
+ """Calculate Michaelis-Menten reaction rate (ping-pong) for two substrates.
559
+
560
+ Rate = Vmax * [S1] * [S2] / ([S1]*[S2] + km1*[S2] + km2*[S1])
561
+
562
+ This follows ping-pong kinetics, appropriate for reactions with
563
+ multiple substrates where binding occurs in sequence.
564
+
565
+ Parameters
566
+ ----------
567
+ s1
568
+ First substrate concentration
569
+ s2
570
+ Second substrate concentration
571
+ vmax
572
+ Maximum reaction velocity
573
+ km1
574
+ Michaelis constant for first substrate
575
+ km2
576
+ Michaelis constant for second substrate
577
+
578
+ Returns
579
+ -------
580
+ Float
581
+ Reaction rate
582
+
583
+ Examples
584
+ --------
585
+ >>> michaelis_menten_2s(2.0, 2.0, 10.0, 1.0, 1.0) # Equal substrate concentrations
586
+ 5.0
587
+ >>> michaelis_menten_2s(0.1, 10.0, 5.0, 1.0, 2.0) # S1 is limiting
588
+ 0.4545454545454546
589
+ >>> michaelis_menten_2s(10.0, 0.2, 5.0, 1.0, 2.0) # S2 is limiting
590
+ 0.43478260869565216
591
+
592
+ """
166
593
  return vmax * s1 * s2 / (s1 * s2 + km1 * s2 + km2 * s1)
167
594
 
168
595
 
@@ -175,17 +602,82 @@ def michaelis_menten_3s(
175
602
  km2: Float,
176
603
  km3: Float,
177
604
  ) -> Float:
178
- """Michaelis-Menten equation (ping-pong) for three substrates."""
605
+ """Calculate Michaelis-Menten reaction rate (ping-pong) for three substrates.
606
+
607
+ Rate = Vmax * [S1] * [S2] * [S3] / ([S1]*[S2] + km1*[S2]*[S3] + km2*[S1]*[S3] + km3*[S1]*[S2])
608
+
609
+ This follows ping-pong kinetics, appropriate for reactions with
610
+ multiple substrates where binding occurs in sequence.
611
+
612
+ Parameters
613
+ ----------
614
+ s1
615
+ First substrate concentration
616
+ s2
617
+ Second substrate concentration
618
+ s3
619
+ Third substrate concentration
620
+ vmax
621
+ Maximum reaction velocity
622
+ km1
623
+ Michaelis constant for first substrate
624
+ km2
625
+ Michaelis constant for second substrate
626
+ km3
627
+ Michaelis constant for third substrate
628
+
629
+ Returns
630
+ -------
631
+ Float
632
+ Reaction rate
633
+
634
+ Examples
635
+ --------
636
+ >>> michaelis_menten_3s(2.0, 2.0, 2.0, 10.0, 1.0, 1.0, 1.0) # Equal substrate concentrations
637
+ 2.5
638
+ >>> michaelis_menten_3s(0.1, 10.0, 10.0, 5.0, 1.0, 2.0, 2.0) # S1 is limiting
639
+ 0.22727272727272727
640
+
641
+ """
179
642
  return (
180
643
  vmax * s1 * s2 * s3 / (s1 * s2 + km1 * s2 * s3 + km2 * s1 * s3 + km3 * s1 * s2)
181
644
  )
182
645
 
183
646
 
184
647
  ###############################################################################
185
- # Reactions: michaelis-menten type
648
+ # Reactions: diffusion type
186
649
  ###############################################################################
187
650
 
188
651
 
189
652
  def diffusion_1s_1p(inside: Float, outside: Float, k: Float) -> Float:
190
- """Diffusion reaction with one substrate and one product."""
653
+ """Calculate diffusion rate between two compartments.
654
+
655
+ Rate = k * ([outside] - [inside])
656
+
657
+ Positive rate indicates flow from outside to inside.
658
+
659
+ Parameters
660
+ ----------
661
+ inside
662
+ Concentration inside the compartment
663
+ outside
664
+ Concentration outside the compartment
665
+ k
666
+ Diffusion rate constant
667
+
668
+ Returns
669
+ -------
670
+ Float
671
+ Net diffusion rate
672
+
673
+ Examples
674
+ --------
675
+ >>> diffusion_1s_1p(1.0, 3.0, 0.5) # Flow into the compartment
676
+ 1.0
677
+ >>> diffusion_1s_1p(5.0, 2.0, 0.5) # Flow out of the compartment
678
+ -1.5
679
+ >>> diffusion_1s_1p(3.0, 3.0, 0.5) # No net flow at equilibrium
680
+ 0.0
681
+
682
+ """
191
683
  return k * (outside - inside)