pyR0compute 0.1.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.
@@ -0,0 +1,39 @@
1
+ """pyR0compute: symbolic computation of the basic reproduction number R0.
2
+
3
+ Implements the next-generation matrix method of van den Driessche & Watmough
4
+ (2002) for compartmental ODE models. Write the model, say which compartments
5
+ are infected, and every other symbol is treated as a parameter::
6
+
7
+ from pyr0compute import R0Model
8
+
9
+ model = R0Model('''
10
+ dS/dt = Lambda - beta*S*I - mu*S
11
+ dI/dt = beta*S*I - (gamma + mu)*I
12
+ dR/dt = gamma*I - mu*R
13
+ ''', infected=["I"])
14
+
15
+ model.R0 # Lambda*beta/(mu*(gamma + mu))
16
+ """
17
+
18
+ from .compat import GeneralEpidemiologicalModel
19
+ from .exceptions import (
20
+ DiseaseFreeEquilibriumError,
21
+ ModelSpecificationError,
22
+ NextGenerationError,
23
+ R0ComputeError,
24
+ )
25
+ from .model import R0Model
26
+ from .parsing import parse_expression
27
+
28
+ __version__ = "0.1.0"
29
+
30
+ __all__ = [
31
+ "R0Model",
32
+ "GeneralEpidemiologicalModel",
33
+ "parse_expression",
34
+ "R0ComputeError",
35
+ "ModelSpecificationError",
36
+ "DiseaseFreeEquilibriumError",
37
+ "NextGenerationError",
38
+ "__version__",
39
+ ]
pyr0compute/compat.py ADDED
@@ -0,0 +1,79 @@
1
+ """Backward-compatible interface of the original notebook."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Optional, Sequence
6
+
7
+ import sympy as sp
8
+
9
+ from .model import R0Model
10
+
11
+ __all__ = ["GeneralEpidemiologicalModel"]
12
+
13
+
14
+ class GeneralEpidemiologicalModel(R0Model):
15
+ """Interface of the original ``pyR0compute_examples.ipynb`` notebook.
16
+
17
+ Existing code keeps working, with two differences: the equations no longer
18
+ need to list the infected compartments first, and ``parameters`` is
19
+ optional (it is detected automatically). New code should use
20
+ :class:`R0Model`.
21
+
22
+ Parameters
23
+ ----------
24
+ variables, parameters, equations, infected_indices
25
+ As in the original notebook; ``infected_indices`` are positions in
26
+ ``variables``.
27
+ new_infection_terms
28
+ Optional list aligned with ``variables`` (zeros for uninfected).
29
+ equilibrium_point
30
+ Optional disease-free equilibrium aligned with ``variables``.
31
+ total_population
32
+ Accepted for compatibility; not needed.
33
+ verbose
34
+ Print the step-by-step report when :meth:`calculate_R0` is called
35
+ (default ``True``, like the original).
36
+ """
37
+
38
+ def __init__(
39
+ self,
40
+ variables: Sequence[sp.Symbol],
41
+ parameters: Optional[Sequence[sp.Symbol]],
42
+ equations: Sequence[sp.Expr],
43
+ infected_indices: Sequence[int],
44
+ new_infection_terms: Optional[Sequence[sp.Expr]] = None,
45
+ equilibrium_point: Optional[Sequence[sp.Expr]] = None,
46
+ total_population=None,
47
+ verbose: bool = True,
48
+ **kwargs,
49
+ ) -> None:
50
+ dfe = None
51
+ if equilibrium_point is not None:
52
+ dfe = dict(zip(variables, list(equilibrium_point)))
53
+ self._legacy_verbose = verbose
54
+ super().__init__(
55
+ equations=list(equations),
56
+ infected=list(infected_indices),
57
+ variables=list(variables),
58
+ parameters=list(parameters) if parameters else None,
59
+ new_infections=list(new_infection_terms) if new_infection_terms is not None else None,
60
+ dfe=dfe,
61
+ **kwargs,
62
+ )
63
+
64
+ def identify_F_V_terms(self):
65
+ """Return the vectors of new-infection and transition terms."""
66
+ F = sp.Matrix([self.new_infections[v] for v in self.infected])
67
+ V = sp.Matrix([self.transitions[v] for v in self.infected])
68
+ return F, V
69
+
70
+ def calculate_next_generation_matrices(self):
71
+ """Return ``(F, V)`` evaluated at the disease-free equilibrium."""
72
+ return self.F, self.V
73
+
74
+ def calculate_R0(self):
75
+ """Return R0 (printing the report if ``verbose``)."""
76
+ R0 = self.R0
77
+ if self._legacy_verbose:
78
+ print(self.report())
79
+ return R0
@@ -0,0 +1,17 @@
1
+ """Exceptions raised by pyR0compute."""
2
+
3
+
4
+ class R0ComputeError(ValueError):
5
+ """Base class for all pyR0compute errors."""
6
+
7
+
8
+ class ModelSpecificationError(R0ComputeError):
9
+ """The model (equations, variables, infected compartments...) is ill-defined."""
10
+
11
+
12
+ class DiseaseFreeEquilibriumError(R0ComputeError):
13
+ """The disease-free equilibrium could not be determined unambiguously."""
14
+
15
+
16
+ class NextGenerationError(R0ComputeError):
17
+ """The next-generation matrix or its spectral radius could not be computed."""