Skip to content

Oncology

Oncology: tumour growth, the vessels that feed it, and the therapies that treat it.

AndrogenReceptorProstateElement(label, visual=None, *, N=1.5, AD=1.0, AI=0.0, UIP=0.0, UP=0.0, UT=40.0, UD=40.0, m1=0.0001, b2=22.4, b3=22.4, c1=0.0, psi1_n=0.0001202, psi1_d=0.001048, psi1_i=9.8e-05, phi1_n=0.0001281, phi1_d=0.00111, phi1_i=0.000279, psi2=12.355, phi2=49.587, psi3_n=0.008, psi3_d=0.15, psi3_i=0.01, psi4=62.162, Vc=5.56, v1=18.397, v2=63.753, v3=28.4, phi=12.0, age=60.0, du1=0.001515, du2=0.05635, du3=5.776, gamma_p=0.3125, KP=800.0, beta_n=0.0022622, beta_d=0.002, beta_i=0.003, sigma=10.0)

Bases: Element

Normal epithelium and prostate cancer cells driven by activated androgen receptors, with tissue and serum PSA.

The normal cells follow dN/dt = r1 N (1 - (N + c1 (AD + AI)) / b1) - d1 N, the dependent cells dAD/dt = r2 AD (1 - m1)(1 - L) - d2 AD, and the independent cells dAI/dt = r3 AI (1 - (c1 N + AD + AI) / b3) - d3 AI + m1 r2 AD (1 - L), where L = (c1 N + AD + AI) / b2. The rates are r_i = psi1_i UD^2 / (psi2^2 + UD^2) + phi1_i UT^2 / (phi2^2 + UT^2) and d_i = psi3_i / (psi4 + UD + UT) for the receptors activated by DHT, UD, and by testosterone, UT. The tissue PSA follows dUIP/dt = -du1 UIP Nf - gamma_p UIP (AD + AI)^2 / (KP + AD + AI) - du2 UIP + r4, with the production r4 = sum_i beta_i (UT + UD + sigma) X_i over the cell types, and the serum PSA gains the leaks and is cleared at du3. The capacity of the normal cells b1 and their share Nf = N / b1 follow the prostate volume v1 a^phi / (v2^phi + a^phi) + v3 at the age a, divided by the volume Vc of a billion cells.

The element holds the states and parameters and has no laws of its own: the interactions of prostate_androgen_receptor read its parameters.

Parameters:

Name Type Description Default
label str

The label of the prostate.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
N Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial normal epithelial cells.

1.5
AD Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial androgen-dependent cells.

1.0
AI Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial androgen-independent cells.

0.0
UIP Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial tissue PSA.

0.0
UP Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial serum PSA.

0.0
UT Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The concentration of receptors activated by testosterone.

40.0
UD Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The concentration of receptors activated by dihydrotestosterone.

40.0
m1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The fraction of the divisions of dependent cells that yields independent cells.

0.0001
b2 Annotated[float, ParameterSpec(domain=open(0, oo))]

The carrying capacity of the dependent cells.

22.4
b3 Annotated[float, ParameterSpec(domain=open(0, oo))]

The carrying capacity of the independent cells.

22.4
c1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The interaction between normal and cancer cells.

0.0
psi1_n Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The maximum growth of the normal cells driven by DHT.

0.0001202
psi1_d Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The maximum growth of the dependent cells driven by DHT.

0.001048
psi1_i Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The maximum growth of the independent cells driven by DHT.

9.8e-05
phi1_n Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The maximum growth of the normal cells driven by testosterone.

0.0001281
phi1_d Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The maximum growth of the dependent cells driven by testosterone.

0.00111
phi1_i Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The maximum growth of the independent cells driven by testosterone.

0.000279
psi2 Annotated[float, ParameterSpec(domain=open(0, oo))]

The DHT-activated receptors at which the growth is half way.

12.355
phi2 Annotated[float, ParameterSpec(domain=open(0, oo))]

The testosterone-activated receptors at which the growth is half way.

49.587
psi3_n Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death of the normal cells.

0.008
psi3_d Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death of the dependent cells.

0.15
psi3_i Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death of the independent cells.

0.01
psi4 Annotated[float, ParameterSpec(domain=open(0, oo))]

The activated receptors at which the death is halved.

62.162
Vc Annotated[float, ParameterSpec(domain=open(0, oo))]

The volume of a billion cells.

5.56
v1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The prostate volume that ageing adds.

18.397
v2 Annotated[float, ParameterSpec(domain=open(0, oo))]

The age at which half of that volume is added.

63.753
v3 Annotated[float, ParameterSpec(domain=open(0, oo))]

The prostate volume of a young man.

28.4
phi Annotated[float, ParameterSpec(domain=open(0, oo))]

The steepness of the growth of the prostate with age.

12.0
age Annotated[float, ParameterSpec(domain=open(0, oo))]

The age of the patient at the start.

60.0
du1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which tissue PSA leaks through normal epithelium.

0.001515
du2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The decay rate of tissue PSA.

0.05635
du3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The clearance rate of serum PSA.

5.776
gamma_p Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which tissue PSA leaks through cancer cells.

0.3125
KP Annotated[float, ParameterSpec(domain=open(0, oo))]

The cancer cells at which the leak per cell is half its maximum.

800.0
beta_n Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The PSA production of the normal cells.

0.0022622
beta_d Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The PSA production of the dependent cells.

0.002
beta_i Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The PSA production of the independent cells.

0.003
sigma Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The PSA production independent of the receptors.

10.0

Examples:

>>> from skcomplex.models.biology.oncology import AndrogenReceptorProstateElement
>>> AndrogenReceptorProstateElement('prostate').KP
800.0
Source code in src/skcomplex/models/biology/oncology/_androgen_receptor_prostate.py
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    N: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 1.5,
    AD: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    AI: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    UIP: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    UP: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    UT: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 40.0,
    UD: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 40.0,
    m1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0001,
    b2: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 22.4,
    b3: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 22.4,
    c1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    psi1_n: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0001202,
    psi1_d: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.001048,
    psi1_i: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 9.8e-05,
    phi1_n: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0001281,
    phi1_d: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.00111,
    phi1_i: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.000279,
    psi2: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 12.355,
    phi2: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 49.587,
    psi3_n: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.008,
    psi3_d: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.15,
    psi3_i: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.01,
    psi4: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 62.162,
    Vc: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 5.56,
    v1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 18.397,
    v2: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 63.753,
    v3: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 28.4,
    phi: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 12.0,
    age: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 60.0,
    du1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.001515,
    du2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.05635,
    du3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 5.776,
    gamma_p: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.3125,
    KP: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 800.0,
    beta_n: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0022622,
    beta_d: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.002,
    beta_i: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.003,
    sigma: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 10.0,
) -> None:
    super().__init__(label, visual=visual)
    self.N = N
    self.AD = AD
    self.AI = AI
    self.UIP = UIP
    self.UP = UP
    self.UT = UT
    self.UD = UD
    self.m1 = m1
    self.b2 = b2
    self.b3 = b3
    self.c1 = c1
    self.psi1_n = psi1_n
    self.psi1_d = psi1_d
    self.psi1_i = psi1_i
    self.phi1_n = phi1_n
    self.phi1_d = phi1_d
    self.phi1_i = phi1_i
    self.psi2 = psi2
    self.phi2 = phi2
    self.psi3_n = psi3_n
    self.psi3_d = psi3_d
    self.psi3_i = psi3_i
    self.psi4 = psi4
    self.Vc = Vc
    self.v1 = v1
    self.v2 = v2
    self.v3 = v3
    self.phi = phi
    self.age = age
    self.du1 = du1
    self.du2 = du2
    self.du3 = du3
    self.gamma_p = gamma_p
    self.KP = KP
    self.beta_n = beta_n
    self.beta_d = beta_d
    self.beta_i = beta_i
    self.sigma = sigma

AndrogenSuppressionElement(label, visual=None, *, AD=10.0, AI=0.14, U=20.0, r1=0.025, r2=0.006, b=9.1e-11, c1=0.9, c2=0.8, d1=0.064, m1=5e-05, U0=20.0, du=0.08, a=0.9)

Bases: Element

Androgen-dependent and androgen-independent prostate cancer cells under continuous androgen suppression.

The dependent cells follow dAD/dt = r1 U (1 - b (AD + c1 AI)) AD - (d1 + m1)(1 - U / U0) AD, the independent cells dAI/dt = r2 (1 - b (AI + c2 AD)) AI + m1 (1 - U / U0) AD, and the serum androgen du/dt = -du (U - U0) - U0 du a, which the drug efficacy a lowers to U0 (1 - a).

The element holds the states and parameters and has no laws of its own: the interactions of continuous_androgen_suppression read its parameters.

Parameters:

Name Type Description Default
label str

The label of the tumour.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
AD Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of androgen-dependent cells.

10.0
AI Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of androgen-independent cells.

0.14
U Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial serum androgen concentration.

20.0
r1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of the dependent cells per unit of androgen.

0.025
r2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of the independent cells.

0.006
b Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The reciprocal carrying capacity.

9.1e-11
c1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The competition of the independent cells on the dependent ones.

0.9
c2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The competition of the dependent cells on the independent ones.

0.8
d1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of the dependent cells under androgen deprivation.

0.064
m1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which androgen deprivation turns dependent cells independent.

5e-05
U0 Annotated[float, ParameterSpec(domain=open(0, oo))]

The normal androgen concentration.

20.0
du Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The elimination rate of the androgen.

0.08
a Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The efficacy of the suppression.

0.9

Examples:

>>> from skcomplex.models.biology.oncology import AndrogenSuppressionElement
>>> AndrogenSuppressionElement('tumour', a=0.6).a
0.6
Source code in src/skcomplex/models/biology/oncology/_androgen_suppression.py
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    AD: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 10.0,
    AI: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.14,
    U: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 20.0,
    r1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.025,
    r2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.006,
    b: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 9.1e-11,
    c1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.9,
    c2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.8,
    d1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.064,
    m1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 5e-05,
    U0: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 20.0,
    du: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.08,
    a: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.9,
) -> None:
    super().__init__(label, visual=visual)
    self.AD = AD
    self.AI = AI
    self.U = U
    self.r1 = r1
    self.r2 = r2
    self.b = b
    self.c1 = c1
    self.c2 = c2
    self.d1 = d1
    self.m1 = m1
    self.U0 = U0
    self.du = du
    self.a = a

AngiogenesisImmunotherapyTumourElement(label, visual=None, *, A=5000.0, Vb=625.0, E=0.1, c_an=0.0, q_an=0.0, R_an=0.0, c_im=0.0, q_im=0.0, R_im=0.0, v1=0.025, v2=0.2, a1=0.1, xi_s=8.7, xi_i=0.00873, a2=1.35, r1=3e-05, c1=0.0005, d1=0.37451, s_e=0.15, a3=0.1, alpha_an=0.4811, beta_an=0.0348, k12_an=0.223, k21_an=0.215, u50_an=11.4274, alpha_im=0.5827, beta_im=0.0271, k12_im=0.3, k21_im=0.2455, u50_im=7.1903, g=1.0, delta_r=0.01, u_theta=5.0, tox_an=10.0, tox_im=10.0, dose_an=15.0, dose_im=20.0, period=21.0, width=1 / 24, doses=6)

Bases: Element

Tumour with its vasculature and effector cells under bevacizumab and atezolizumab, with resistance.

The tumour A grows by the Hahnfeldt law toward its vascular capacity Vb and effector cells E kill it. The capacity is stimulated and inhibited by the tumour and destroyed by the antiangiogenic effect UAn, and the immunotherapy effect UIm boosts the effector cells. Each drug follows a two-compartment model with central amount c and peripheral amount q, in mg per kg, infused for width days every period days. Its effect is c^g / ((f U50)^g + c^g), where f = 1 + delta_r R and R integrates max(0, u_theta - c), so the drug loses potency while its concentration stays low. Volumes are in mm³, and time is in days.

The element holds the states and parameters and has no laws of its own: the interactions of angiogenesis_immunotherapy read its parameters.

Parameters:

Name Type Description Default
label str

The label of the tumour.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
A Annotated[float, StateSpec(domain=open(0, oo))]

The initial tumour volume.

5000.0
Vb Annotated[float, StateSpec(domain=open(0, oo))]

The initial vascular capacity.

625.0
E Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial effector cells, dimensionless.

0.1
c_an Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial central amount of the antiangiogenic drug.

0.0
q_an Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial peripheral amount of the antiangiogenic drug.

0.0
R_an Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial resistance integral of the antiangiogenic drug.

0.0
c_im Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial central amount of the immunotherapeutic drug.

0.0
q_im Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial peripheral amount of the immunotherapeutic drug.

0.0
R_im Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial resistance integral of the immunotherapeutic drug.

0.0
v1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth constant of the tumour.

0.025
v2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The spontaneous loss of vasculature.

0.2
a1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The kill rate of the tumour by effector cells.

0.1
xi_s Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The stimulation of the vasculature by the tumour.

8.7
xi_i Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The inhibition of the vasculature by the tumour.

0.00873
a2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The highest destruction rate of the vasculature by the antiangiogenic drug.

1.35
r1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The proliferation rate of effector cells.

3e-05
c1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The inverse of the tumour volume above which the tumour suppresses the effector cells.

0.0005
d1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of effector cells.

0.37451
s_e Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The influx of effector cells.

0.15
a3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The highest boost of effector cells by the immunotherapeutic drug.

0.1
alpha_an Annotated[float, ParameterSpec(domain=open(0, oo))]

The distribution rate of the antiangiogenic drug.

0.4811
beta_an Annotated[float, ParameterSpec(domain=open(0, oo))]

The elimination rate of the antiangiogenic drug.

0.0348
k12_an Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate from the central to the peripheral compartment of the antiangiogenic drug.

0.223
k21_an Annotated[float, ParameterSpec(domain=open(0, oo))]

The rate from the peripheral to the central compartment of the antiangiogenic drug.

0.215
u50_an Annotated[float, ParameterSpec(domain=open(0, oo))]

The amount of antiangiogenic drug of half effect before resistance.

11.4274
alpha_im Annotated[float, ParameterSpec(domain=open(0, oo))]

The distribution rate of the immunotherapeutic drug.

0.5827
beta_im Annotated[float, ParameterSpec(domain=open(0, oo))]

The elimination rate of the immunotherapeutic drug.

0.0271
k12_im Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate from the central to the peripheral compartment of the immunotherapeutic drug.

0.3
k21_im Annotated[float, ParameterSpec(domain=open(0, oo))]

The rate from the peripheral to the central compartment of the immunotherapeutic drug.

0.2455
u50_im Annotated[float, ParameterSpec(domain=open(0, oo))]

The amount of immunotherapeutic drug of half effect before resistance.

7.1903
g Annotated[float, ParameterSpec(domain=open(0, oo))]

The steepness of the drug effects.

1.0
delta_r Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The capacity of the tumour to resist the drugs.

0.01
u_theta Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The amount below which resistance develops.

5.0
tox_an Annotated[float, ParameterSpec(domain=open(0, oo))]

The amount of antiangiogenic drug at which its toxicity turns exponential.

10.0
tox_im Annotated[float, ParameterSpec(domain=open(0, oo))]

The amount of immunotherapeutic drug at which its toxicity turns exponential.

10.0
dose_an Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The dose of the antiangiogenic drug, in mg per kg.

15.0
dose_im Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The dose of the immunotherapeutic drug, in mg per kg.

20.0
period float

The time between the starts of doses.

21.0
width float

The duration of an infusion.

1 / 24
doses int

The number of doses.

6

Examples:

>>> from skcomplex.models.biology.oncology import AngiogenesisImmunotherapyTumourElement
>>> AngiogenesisImmunotherapyTumourElement('tumour').Vb
625.0
Source code in src/skcomplex/models/biology/oncology/_angiogenesis_immunotherapy_tumour.py
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    A: Annotated[float, StateSpec(domain=RealSet.open(0, oo))] = 5000.0,
    Vb: Annotated[float, StateSpec(domain=RealSet.open(0, oo))] = 625.0,
    E: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.1,
    c_an: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    q_an: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    R_an: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    c_im: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    q_im: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    R_im: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    v1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.025,
    v2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.2,
    a1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.1,
    xi_s: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 8.7,
    xi_i: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.00873,
    a2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.35,
    r1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 3e-05,
    c1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0005,
    d1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.37451,
    s_e: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.15,
    a3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.1,
    alpha_an: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.4811,
    beta_an: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.0348,
    k12_an: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.223,
    k21_an: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.215,
    u50_an: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 11.4274,
    alpha_im: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.5827,
    beta_im: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.0271,
    k12_im: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.3,
    k21_im: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.2455,
    u50_im: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 7.1903,
    g: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1.0,
    delta_r: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.01,
    u_theta: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 5.0,
    tox_an: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 10.0,
    tox_im: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 10.0,
    dose_an: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 15.0,
    dose_im: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 20.0,
    period: float = 21.0,
    width: float = 1 / 24,
    doses: int = 6,
) -> None:
    super().__init__(label, visual=visual)
    self.A = A
    self.Vb = Vb
    self.E = E
    self.c_an = c_an
    self.q_an = q_an
    self.R_an = R_an
    self.c_im = c_im
    self.q_im = q_im
    self.R_im = R_im
    self.v1 = v1
    self.v2 = v2
    self.a1 = a1
    self.xi_s = xi_s
    self.xi_i = xi_i
    self.a2 = a2
    self.r1 = r1
    self.c1 = c1
    self.d1 = d1
    self.s_e = s_e
    self.a3 = a3
    self.alpha_an = alpha_an
    self.beta_an = beta_an
    self.k12_an = k12_an
    self.k21_an = k21_an
    self.u50_an = u50_an
    self.alpha_im = alpha_im
    self.beta_im = beta_im
    self.k12_im = k12_im
    self.k21_im = k21_im
    self.u50_im = u50_im
    self.g = g
    self.delta_r = delta_r
    self.u_theta = u_theta
    self.tox_an = tox_an
    self.tox_im = tox_im
    self.dose_an = dose_an
    self.dose_im = dose_im
    self.period = period
    self.width = width
    self.doses = doses

AngiogenicTumourElement(label, visual=None, *, A=17347.0, Vb=17347.0, U=0.0, lambda1=0.192, lambda2=0.0, xi_s=5.85, xi_i=0.00873, a=0.66, du=1.3, dose=20.0, period=1.0, width=1.0, start=0.0)

Bases: Element

Tumour volume, the vascular volume that sets its carrying capacity, and an angiogenesis inhibitor.

The tumour follows dA/dt = -lambda1 A log(A / Vb), the vasculature dVb/dt = -lambda2 Vb + xi_s A - xi_i Vb A^(2/3) - a Vb U, and the inhibitor dU/dt = -du U + u(t), where the infusion u is dose for width time units every period, from start on. A width equal to the period is a continuous infusion.

The element holds the states and parameters and has no laws of its own: the interactions of hahnfeldt read its parameters.

Parameters:

Name Type Description Default
label str

The label of the tumour.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
A Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial tumour volume.

17347.0
Vb Annotated[float, StateSpec(domain=open(0, oo))]

The initial vascular volume.

17347.0
U Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial concentration of the inhibitor.

0.0
lambda1 Annotated[float, ParameterSpec(domain=open(0, oo))]

The rate at which the tumour approaches its capacity.

0.192
lambda2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The spontaneous loss rate of the vasculature.

0.0
xi_s Annotated[float, ParameterSpec(domain=open(0, oo))]

The angiogenic stimulation by the tumour.

5.85
xi_i Annotated[float, ParameterSpec(domain=open(0, oo))]

The angiogenic inhibition by the tumour.

0.00873
a Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The vascular loss per unit of inhibitor.

0.66
du Annotated[float, ParameterSpec(domain=open(0, oo))]

The clearance rate of the inhibitor.

1.3
dose Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The infusion rate during a dose.

20.0
period float

The time between the starts of doses.

1.0
width float

The duration of a dose.

1.0
start float

The time of the first dose.

0.0

Examples:

>>> from skcomplex.models.biology.oncology import AngiogenicTumourElement
>>> AngiogenicTumourElement('tumour').xi_s
5.85
Source code in src/skcomplex/models/biology/oncology/_angiogenic_tumour.py
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    A: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 17347.0,
    Vb: Annotated[float, StateSpec(domain=RealSet.open(0, oo))] = 17347.0,
    U: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    lambda1: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.192,
    lambda2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    xi_s: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 5.85,
    xi_i: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.00873,
    a: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.66,
    du: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1.3,
    dose: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 20.0,
    period: float = 1.0,
    width: float = 1.0,
    start: float = 0.0,
) -> None:
    super().__init__(label, visual=visual)
    self.A = A
    self.Vb = Vb
    self.U = U
    self.lambda1 = lambda1
    self.lambda2 = lambda2
    self.xi_s = xi_s
    self.xi_i = xi_i
    self.a = a
    self.du = du
    self.dose = dose
    self.period = period
    self.width = width
    self.start = start

BoneMarrowBloodElement(label, visual=None, *, NBM=10000000000000.0, NPB=3500000000.0, ABM=400000000000.0, APB=5000000000.0, AS=100000.0, r1=0.149, b1=58000000000000.0, b2=10000000000000.0, theta1=10000000000.0, m1=0.0013, m2=27000.0, theta2=10000000000.0, r2=1e-12, m3=1e-07, c1=1e-14, alpha1=0.02, tau1=96.0, c2=1e-14, d1=0.0083, r3=0.00396, b3=368800000000000.0, theta3=10000000000.0, m4=0.0065, m5=0.05, alpha2=0.002, tau2=576.0, r4=1e-12, d2=0.2, r5=0.05, b4=1e-06)

Bases: Element

Normal and malignant cells in the bone marrow and the peripheral blood, and cancer stem cells.

Normal marrow cells renew as r1 NBM log((b1 + b2) / (theta1 + NBM)), mutate into blasts at the rate m1 and into cancer stem cells at the rate m3, and move to the blood, where they arrive after the maturation time tau1 with the survival exp(-alpha1 tau1 - r2 APB(t - tau1)). Blasts grow as r3 ABM log(b3 / (theta3 + ABM)) and move to the blood at the rate m4. Cancer stem cells renew logistically and convert into blasts after the time tau2. Malignant cells inhibit normal ones in both places.

The element holds the states and parameters and has no laws of its own: the interactions of bone_marrow_blood_leukaemia read its parameters.

Parameters:

Name Type Description Default
label str

The label of the patient.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
NBM Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial normal marrow cells.

10000000000000.0
NPB Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial normal blood cells.

3500000000.0
ABM Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial marrow blasts.

400000000000.0
APB Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial blood blasts.

5000000000.0
AS Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial cancer stem cells.

100000.0
r1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of normal marrow cells.

0.149
b1 Annotated[float, ParameterSpec(domain=open(0, oo))]

The carrying capacity of normal marrow cells.

58000000000000.0
b2 Annotated[float, ParameterSpec(domain=open(0, oo))]

The carrying capacity of normal blood cells.

10000000000000.0
theta1 Annotated[float, ParameterSpec(domain=open(0, oo))]

The threshold of the renewal of normal marrow cells.

10000000000.0
m1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The mutation rate of normal marrow cells into blasts.

0.0013
m2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The largest release rate of normal marrow cells into the blood.

27000.0
theta2 Annotated[float, ParameterSpec(domain=open(0, oo))]

The number of normal blood cells that halves the release.

10000000000.0
r2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The inhibition of the release by blood blasts.

1e-12
m3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The mutation rate of normal marrow cells into cancer stem cells.

1e-07
c1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The inhibition of normal marrow cells by marrow blasts.

1e-14
alpha1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The loss rate of normal cells during maturation.

0.02
tau1 Annotated[float, ParameterSpec(domain=open(0, oo))]

The maturation time of normal cells.

96.0
c2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The inhibition of normal blood cells by blood blasts.

1e-14
d1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of normal blood cells.

0.0083
r3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of marrow blasts.

0.00396
b3 Annotated[float, ParameterSpec(domain=open(0, oo))]

The carrying capacity of marrow blasts.

368800000000000.0
theta3 Annotated[float, ParameterSpec(domain=open(0, oo))]

The threshold of the growth of marrow blasts.

10000000000.0
m4 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which marrow blasts move to the blood.

0.0065
m5 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The conversion rate of cancer stem cells into blasts.

0.05
alpha2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The loss rate of converting stem cells.

0.002
tau2 Annotated[float, ParameterSpec(domain=open(0, oo))]

The conversion time of cancer stem cells into blasts.

576.0
r4 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The inhibition of the conversion by blood blasts.

1e-12
d2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The loss rate of blood blasts.

0.2
r5 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The renewal rate of cancer stem cells.

0.05
b4 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The reciprocal carrying capacity of cancer stem cells.

1e-06

Examples:

>>> from skcomplex.models.biology.oncology import BoneMarrowBloodElement
>>> BoneMarrowBloodElement('patient').tau1
96.0
Source code in src/skcomplex/models/biology/oncology/_bone_marrow_blood.py
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    NBM: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 10000000000000.0,
    NPB: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 3500000000.0,
    ABM: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 400000000000.0,
    APB: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 5000000000.0,
    AS: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 100000.0,
    r1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.149,
    b1: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 58000000000000.0,
    b2: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 10000000000000.0,
    theta1: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 10000000000.0,
    m1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0013,
    m2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 27000.0,
    theta2: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 10000000000.0,
    r2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1e-12,
    m3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1e-07,
    c1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1e-14,
    alpha1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.02,
    tau1: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 96.0,
    c2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1e-14,
    d1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0083,
    r3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.00396,
    b3: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 368800000000000.0,
    theta3: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 10000000000.0,
    m4: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0065,
    m5: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.05,
    alpha2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.002,
    tau2: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 576.0,
    r4: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1e-12,
    d2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.2,
    r5: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.05,
    b4: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1e-06,
) -> None:
    super().__init__(label, visual=visual)
    self.NBM = NBM
    self.NPB = NPB
    self.ABM = ABM
    self.APB = APB
    self.AS = AS
    self.r1 = r1
    self.b1 = b1
    self.b2 = b2
    self.theta1 = theta1
    self.m1 = m1
    self.m2 = m2
    self.theta2 = theta2
    self.r2 = r2
    self.m3 = m3
    self.c1 = c1
    self.alpha1 = alpha1
    self.tau1 = tau1
    self.c2 = c2
    self.d1 = d1
    self.r3 = r3
    self.b3 = b3
    self.theta3 = theta3
    self.m4 = m4
    self.m5 = m5
    self.alpha2 = alpha2
    self.tau2 = tau2
    self.r4 = r4
    self.d2 = d2
    self.r5 = r5
    self.b4 = b4

CellCycleElement(label, visual=None, *, A1=15.0, A2=3.8, A3=0.8, l1=0.197, l2=0.395, l3=0.107, u1=0.0, u2=0.0)

Bases: Element

Tumour cells in three phases of the cell cycle under a killing and a blocking agent.

The compartments hold the cells in G0 and G1 A1, in S A2, and in G2 and M A3, and follow dA1/dt = -l1 A1 + 2 (1 - u1) l3 A3, dA2/dt = l1 A1 - (1 - u2) l2 A2, and dA3/dt = (1 - u2) l2 A2 - l3 A3. The killing agent kills the fraction u1 of the cells that divide, and the blocking agent slows the transit through S by the fraction u2.

The element holds the states and parameters and has no laws of its own: the interactions of cell_cycle_chemotherapy read its parameters.

Parameters:

Name Type Description Default
label str

The label of the tumour.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
A1 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial cells in G0 and G1.

15.0
A2 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial cells in S.

3.8
A3 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial cells in G2 and M.

0.8
l1 Annotated[float, ParameterSpec(domain=open(0, oo))]

The rate of exit from G0 and G1.

0.197
l2 Annotated[float, ParameterSpec(domain=open(0, oo))]

The rate of exit from S.

0.395
l3 Annotated[float, ParameterSpec(domain=open(0, oo))]

The rate of exit from G2 and M.

0.107
u1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The fraction of dividing cells the killing agent kills.

0.0
u2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The fraction by which the blocking agent slows the transit through S.

0.0

Examples:

>>> from skcomplex.models.biology.oncology import CellCycleElement
>>> CellCycleElement('tumour').l2
0.395
Source code in src/skcomplex/models/biology/oncology/_cell_cycle.py
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    A1: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 15.0,
    A2: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 3.8,
    A3: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.8,
    l1: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.197,
    l2: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.395,
    l3: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.107,
    u1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    u2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
) -> None:
    super().__init__(label, visual=visual)
    self.A1 = A1
    self.A2 = A2
    self.A3 = A3
    self.l1 = l1
    self.l2 = l2
    self.l3 = l3
    self.u1 = u1
    self.u2 = u2

CellQuotaProstateElement(label, visual=None, *, AD=15.0, AI=0.0, Q1=0.5, Q2=0.5, P=3.4, U=15.0, rm=0.025, q1=0.3, q2=0.15, d1=0.015, d2=0.015, d3=0.09, qm=5.0, vm=0.275, v50=4.0, mx1=0.00015, mx2=0.0001, m501=0.08, m502=1.7, n=3.0, r0=0.01, r1=0.15, r2=0.15, rho1=1.3, rho2=1.1, theta=3.0, du=0.08, U0=15.0, Umin=0.5, du1=0.08, period=500.0, width=250.0)

Bases: Element

Prostate cancer cells whose growth and mutation follow their androgen cell quota, with the PSA they release.

The cells grow at the Droop rate rm (1 - q_i / Q_i), die at d_i, and switch from dependent to independent at mx1 m501^n / (Q1^n + m501^n) and back at mx2 Q2^n / (Q2^n + m502^n). The quotas follow dQ_i/dt = vm (qm - Q_i) / (qm - q_i) U / (U + v50) - rm (Q_i - q_i) - d3 Q_i, and the serum PSA dP/dt = r0 (AD + AI) + r1 AD Q1^theta / (Q1^theta + rho1^theta) + r2 AI Q2^theta / (Q2^theta + rho2^theta) - du P. The serum androgen relaxes at the rate du1 to Umin during the width days of therapy that open every period days and to U0 otherwise.

The element holds the states and parameters and has no laws of its own: the interactions of prostate_cell_quota read its parameters.

Parameters:

Name Type Description Default
label str

The label of the tumour.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
AD Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of androgen-dependent cells.

15.0
AI Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of androgen-independent cells.

0.0
Q1 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial cell quota of the dependent cells.

0.5
Q2 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial cell quota of the independent cells.

0.5
P Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial serum PSA.

3.4
U Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial serum androgen.

15.0
rm Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The maximum proliferation rate.

0.025
q1 Annotated[float, ParameterSpec(domain=open(0, oo))]

The minimum quota of the dependent cells.

0.3
q2 Annotated[float, ParameterSpec(domain=open(0, oo))]

The minimum quota of the independent cells.

0.15
d1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of the dependent cells.

0.015
d2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of the independent cells.

0.015
d3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The degradation rate of the quota.

0.09
qm Annotated[float, ParameterSpec(domain=open(0, oo))]

The maximum quota.

5.0
vm Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The maximum uptake rate of androgen.

0.275
v50 Annotated[float, ParameterSpec(domain=open(0, oo))]

The serum androgen at which the uptake is half way.

4.0
mx1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The maximum mutation rate from dependent to independent.

0.00015
mx2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The maximum mutation rate from independent to dependent.

0.0001
m501 Annotated[float, ParameterSpec(domain=open(0, oo))]

The quota at which the mutation to independence is half way.

0.08
m502 Annotated[float, ParameterSpec(domain=open(0, oo))]

The quota at which the mutation back to dependence is half way.

1.7
n Annotated[float, ParameterSpec(domain=open(0, oo))]

The steepness of the mutation rates.

3.0
r0 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The baseline PSA production per cell.

0.01
r1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The androgen-driven PSA production per dependent cell.

0.15
r2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The androgen-driven PSA production per independent cell.

0.15
rho1 Annotated[float, ParameterSpec(domain=open(0, oo))]

The quota at which the PSA production of the dependent cells is half way.

1.3
rho2 Annotated[float, ParameterSpec(domain=open(0, oo))]

The quota at which the PSA production of the independent cells is half way.

1.1
theta Annotated[float, ParameterSpec(domain=open(0, oo))]

The steepness of the PSA production.

3.0
du Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The clearance rate of the PSA.

0.08
U0 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The normal serum androgen.

15.0
Umin Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The serum androgen under therapy.

0.5
du1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which the serum androgen relaxes.

0.08
period float

The time between the starts of therapy periods.

500.0
width float

The duration of a therapy period.

250.0

Examples:

>>> from skcomplex.models.biology.oncology import CellQuotaProstateElement
>>> CellQuotaProstateElement('tumour').qm
5.0
Source code in src/skcomplex/models/biology/oncology/_cell_quota_prostate.py
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    AD: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 15.0,
    AI: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    Q1: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.5,
    Q2: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.5,
    P: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 3.4,
    U: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 15.0,
    rm: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.025,
    q1: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.3,
    q2: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.15,
    d1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.015,
    d2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.015,
    d3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.09,
    qm: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 5.0,
    vm: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.275,
    v50: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 4.0,
    mx1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.00015,
    mx2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0001,
    m501: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.08,
    m502: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1.7,
    n: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 3.0,
    r0: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.01,
    r1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.15,
    r2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.15,
    rho1: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1.3,
    rho2: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1.1,
    theta: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 3.0,
    du: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.08,
    U0: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 15.0,
    Umin: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.5,
    du1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.08,
    period: float = 500.0,
    width: float = 250.0,
) -> None:
    super().__init__(label, visual=visual)
    self.AD = AD
    self.AI = AI
    self.Q1 = Q1
    self.Q2 = Q2
    self.P = P
    self.U = U
    self.rm = rm
    self.q1 = q1
    self.q2 = q2
    self.d1 = d1
    self.d2 = d2
    self.d3 = d3
    self.qm = qm
    self.vm = vm
    self.v50 = v50
    self.mx1 = mx1
    self.mx2 = mx2
    self.m501 = m501
    self.m502 = m502
    self.n = n
    self.r0 = r0
    self.r1 = r1
    self.r2 = r2
    self.rho1 = rho1
    self.rho2 = rho2
    self.theta = theta
    self.du = du
    self.U0 = U0
    self.Umin = Umin
    self.du1 = du1
    self.period = period
    self.width = width

CheckpointTumourElement(label, visual=None, *, E=0.006, A=0.3968, UAP=0.0, ENC=0.0001, r1=8.81, r2=0.5, C1_50=1.5e-10, C2_50=2.37e-11, C1_ss=1.5e-10, C2_ss=2.37e-11, psi_pp=1.365e-18, d1=0.05, r3=0.18, b=1 / 0.8, a_rho=57.5, a_rl=4908500.0, rho_r=3.19e-07, du1=10.0, du2=0.033, sigma_l=3.56e-07, c_l=1.0, sigma=5.0, u_ap=1e-10)

Bases: Element

Activated T cells, tumour cells, and an anti-PD-1 drug that frees T cells from PD-1-PD-L1 inhibition.

The T cells follow dE/dt = (r1 ENC C1 / (C1_50 + C1) + r2 E C2 / (C2_50 + C2)) / (1 + UPP / psi_pp) - d1 E, with the cytokines at their steady states C1 = C1_ss and C2 = C2_ss, the tumour dA/dt = r3 A (1 - b A) - a_rho A E, and the drug dUAP/dt = u_ap - a_rl UFP1 UAP - du2 UAP. Free PD-1 is UFP1 = max(rho_r - du1 UAP, 0) E, free PD-L1 UFL1 = sigma_l (E + c_l A), and the complex UPP = sigma UFP1 UFL1.

The element holds the states and parameters and has no laws of its own: the interactions of anti_pd1_checkpoint read its parameters.

Parameters:

Name Type Description Default
label str

The label of the tumour site.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
E Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial activated T cells.

0.006
A Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial tumour cells.

0.3968
UAP Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial drug concentration.

0.0
ENC Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The naive T cells.

0.0001
r1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The activation rate of naive T cells by IL-12.

8.81
r2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The proliferation rate of T cells by IL-2.

0.5
C1_50 Annotated[float, ParameterSpec(domain=open(0, oo))]

The IL-12 at half activation.

1.5e-10
C2_50 Annotated[float, ParameterSpec(domain=open(0, oo))]

The IL-2 at half proliferation.

2.37e-11
C1_ss Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The steady IL-12 concentration.

1.5e-10
C2_ss Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The steady IL-2 concentration.

2.37e-11
psi_pp Annotated[float, ParameterSpec(domain=open(0, oo))]

The PD-1-PD-L1 complex at half inhibition.

1.365e-18
d1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of T cells.

0.05
r3 Annotated[float, ParameterSpec(domain=open(0, oo))]

The growth rate of the tumour.

0.18
b Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The inverse carrying capacity of the tumour.

1 / 0.8
a_rho Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The kill rate of tumour cells by T cells.

57.5
a_rl Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The blocking rate of PD-1 by the drug.

4908500.0
rho_r Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The expression of PD-1 on T cells.

3.19e-07
du1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The depletion of PD-1 per unit of drug.

10.0
du2 Annotated[float, ParameterSpec(domain=open(0, oo))]

The degradation rate of the drug.

0.033
sigma_l Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The expression of PD-L1 on T cells.

3.56e-07
c_l Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The expression of PD-L1 on tumour cells relative to T cells.

1.0
sigma Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The ratio of association to dissociation of PD-1 and PD-L1.

5.0
u_ap Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The infusion rate of the drug.

1e-10

Examples:

>>> from skcomplex.models.biology.oncology import CheckpointTumourElement
>>> CheckpointTumourElement('site').a_rho
57.5
Source code in src/skcomplex/models/biology/oncology/_checkpoint_tumour.py
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    E: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.006,
    A: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.3968,
    UAP: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    ENC: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0001,
    r1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 8.81,
    r2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.5,
    C1_50: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1.5e-10,
    C2_50: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 2.37e-11,
    C1_ss: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.5e-10,
    C2_ss: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 2.37e-11,
    psi_pp: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1.365e-18,
    d1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.05,
    r3: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.18,
    b: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1 / 0.8,
    a_rho: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 57.5,
    a_rl: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 4908500.0,
    rho_r: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 3.19e-07,
    du1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 10.0,
    du2: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.033,
    sigma_l: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 3.56e-07,
    c_l: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    sigma: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 5.0,
    u_ap: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1e-10,
) -> None:
    super().__init__(label, visual=visual)
    self.E = E
    self.A = A
    self.UAP = UAP
    self.ENC = ENC
    self.r1 = r1
    self.r2 = r2
    self.C1_50 = C1_50
    self.C2_50 = C2_50
    self.C1_ss = C1_ss
    self.C2_ss = C2_ss
    self.psi_pp = psi_pp
    self.d1 = d1
    self.r3 = r3
    self.b = b
    self.a_rho = a_rho
    self.a_rl = a_rl
    self.rho_r = rho_r
    self.du1 = du1
    self.du2 = du2
    self.sigma_l = sigma_l
    self.c_l = c_l
    self.sigma = sigma
    self.u_ap = u_ap

ChemoimmunotherapyTumourElement(label, visual=None, *, A=1000000.0, N=50000.0, E=100.0, C=11000000.0, I=0.0, M=0.0, r1=0.431, b1=2.17e-08, c1=7.13e-10, a1=8.17, g1=0.618, l=0.657, a2=0.9, m1=0.00129, d1=0.0412, r2=0.4198, g2=20200000.0, psi1=1e-07, a3=0.6, r3=0.996, g3=303000.0, d2=0.02, psi2=3.42e-10, psi3=1.8e-08, r4=1.1e-07, r5=3e-11, a4=0.6, r6=0.125, g4=20000000.0, s1=121000.0, d3=0.012, a5=0.6, d_u1=10.0, d_u2=0.9, u_til=10000000.0, u_il2=10000000.0, u_chemo=2.0, start=7.0, period=7.0, width=1.0, doses=3)

Bases: Element

Tumour with NK cells, CD8 T cells, and circulating lymphocytes under chemotherapy, IL-2, and TIL injection.

The tumour A grows logistically and NK cells N and CD8 T cells E kill it. CD8 T cells kill at the rate D = a1 (E / A)^l / (g1 + (E / A)^l). The circulating lymphocytes C feed the NK cells. The chemotherapy M kills a fraction 1 - exp(-M) of every population at its own rate, IL-2 I stimulates the CD8 T cells, and a TIL injection adds CD8 T cells. All three drugs follow the same schedule of doses at the rates u_til, u_il2, and u_chemo. Cells are counted, and time is in days.

The element holds the states and parameters and has no laws of its own: the interactions of chemoimmunotherapy read its parameters.

Parameters:

Name Type Description Default
label str

The label of the tumour.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
A Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of tumour cells.

1000000.0
N Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of NK cells.

50000.0
E Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of CD8 T cells.

100.0
C Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of circulating lymphocytes.

11000000.0
I Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial amount of IL-2.

0.0
M Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial amount of chemotherapeutic drug.

0.0
r1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of the tumour.

0.431
b1 Annotated[float, ParameterSpec(domain=open(0, oo))]

The reciprocal carrying capacity of the tumour.

2.17e-08
c1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which NK cells kill tumour cells.

7.13e-10
a1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The highest rate at which CD8 T cells kill tumour cells.

8.17
g1 Annotated[float, ParameterSpec(domain=open(0, oo))]

The half-saturation of the CD8 T cell kill.

0.618
l Annotated[float, ParameterSpec(domain=open(0, oo))]

The exponent of the CD8 T cell kill.

0.657
a2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The chemotherapy kill rate of tumour cells.

0.9
m1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which circulating lymphocytes become NK cells.

0.00129
d1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of NK cells.

0.0412
r2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The highest recruitment rate of NK cells by the tumour.

0.4198
g2 Annotated[float, ParameterSpec(domain=open(0, oo))]

The half-saturation of the NK cell recruitment, in cells².

20200000.0
psi1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which the tumour inactivates NK cells.

1e-07
a3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The chemotherapy kill rate of NK cells.

0.6
r3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The highest recruitment rate of CD8 T cells by the tumour kill.

0.996
g3 Annotated[float, ParameterSpec(domain=open(0, oo))]

The half-saturation of the CD8 T cell recruitment, in cells².

303000.0
d2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of CD8 T cells.

0.02
psi2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which the tumour inactivates CD8 T cells.

3.42e-10
psi3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which NK cells regulate CD8 T cells.

1.8e-08
r4 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which the NK cell kill of tumour cells activates CD8 T cells.

1.1e-07
r5 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which circulating lymphocytes meeting tumour cells activate CD8 T cells.

3e-11
a4 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The chemotherapy kill rate of CD8 T cells.

0.6
r6 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The highest rate at which IL-2 stimulates CD8 T cells.

0.125
g4 Annotated[float, ParameterSpec(domain=open(0, oo))]

The half-saturation of the IL-2 stimulation.

20000000.0
s1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The influx of circulating lymphocytes.

121000.0
d3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of circulating lymphocytes.

0.012
a5 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The chemotherapy kill rate of circulating lymphocytes.

0.6
d_u1 Annotated[float, ParameterSpec(domain=open(0, oo))]

The decay rate of IL-2.

10.0
d_u2 Annotated[float, ParameterSpec(domain=open(0, oo))]

The decay rate of the chemotherapeutic drug.

0.9
u_til Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate of TIL injection during a dose, in cells per day.

10000000.0
u_il2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate of IL-2 injection during a dose.

10000000.0
u_chemo Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate of chemotherapy infusion during a dose.

2.0
start float

The time of the first dose.

7.0
period float

The time between the starts of doses.

7.0
width float

The duration of a dose.

1.0
doses int

The number of doses.

3

Examples:

>>> from skcomplex.models.biology.oncology import ChemoimmunotherapyTumourElement
>>> ChemoimmunotherapyTumourElement('tumour').r1
0.431
Source code in src/skcomplex/models/biology/oncology/_chemoimmunotherapy_tumour.py
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    A: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 1000000.0,
    N: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 50000.0,
    E: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 100.0,
    C: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 11000000.0,
    I: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    M: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    r1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.431,
    b1: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 2.17e-08,
    c1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 7.13e-10,
    a1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 8.17,
    g1: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.618,
    l: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.657,
    a2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.9,
    m1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.00129,
    d1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0412,
    r2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.4198,
    g2: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 20200000.0,
    psi1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1e-07,
    a3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.6,
    r3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.996,
    g3: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 303000.0,
    d2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.02,
    psi2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 3.42e-10,
    psi3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.8e-08,
    r4: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.1e-07,
    r5: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 3e-11,
    a4: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.6,
    r6: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.125,
    g4: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 20000000.0,
    s1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 121000.0,
    d3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.012,
    a5: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.6,
    d_u1: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 10.0,
    d_u2: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.9,
    u_til: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 10000000.0,
    u_il2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 10000000.0,
    u_chemo: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 2.0,
    start: float = 7.0,
    period: float = 7.0,
    width: float = 1.0,
    doses: int = 3,
) -> None:
    super().__init__(label, visual=visual)
    self.A = A
    self.N = N
    self.E = E
    self.C = C
    self.I = I
    self.M = M
    self.r1 = r1
    self.b1 = b1
    self.c1 = c1
    self.a1 = a1
    self.g1 = g1
    self.l = l
    self.a2 = a2
    self.m1 = m1
    self.d1 = d1
    self.r2 = r2
    self.g2 = g2
    self.psi1 = psi1
    self.a3 = a3
    self.r3 = r3
    self.g3 = g3
    self.d2 = d2
    self.psi2 = psi2
    self.psi3 = psi3
    self.r4 = r4
    self.r5 = r5
    self.a4 = a4
    self.r6 = r6
    self.g4 = g4
    self.s1 = s1
    self.d3 = d3
    self.a5 = a5
    self.d_u1 = d_u1
    self.d_u2 = d_u2
    self.u_til = u_til
    self.u_il2 = u_il2
    self.u_chemo = u_chemo
    self.start = start
    self.period = period
    self.width = width
    self.doses = doses

ChemovirotherapyTumourElement(label, visual=None, *, AU=1.0, AV=0.0, V=0.1, U=0.1, r1=0.206, b=1e-06, alpha=0.001, a1=0.005, a2=0.5115, a3=0.006, beta_v=10.0, d1=0.001, d_u=4.16, u1=10.0, infusion='constant')

Bases: Element

Uninfected and infected tumour cells, an oncolytic virus, and a chemotherapeutic drug.

The uninfected cells AU grow logistically, the virus V infects them, and infected cells AV burst at the rate a2, releasing beta_v virions each. The drug U kills both kinds of cells and is infused at the rate u1, constantly, as u1 exp(-d_u t), or as u1 sin(d_u t)^2. One unit of cells is a million cells, and one unit of time is two days.

The element holds the states and parameters and has no laws of its own: the interactions of chemovirotherapy read its parameters.

Parameters:

Name Type Description Default
label str

The label of the tumour.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
AU Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of uninfected cells.

1.0
AV Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of infected cells.

0.0
V Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of virions.

0.1
U Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial amount of drug.

0.1
r1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of uninfected cells.

0.206
b Annotated[float, ParameterSpec(domain=open(0, oo))]

The reciprocal carrying capacity.

1e-06
alpha Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The infection rate.

0.001
a1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The drug kill rate of uninfected cells.

0.005
a2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which the virus kills infected cells.

0.5115
a3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The drug kill rate of infected cells.

0.006
beta_v Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The burst size.

10.0
d1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The decay rate of the virus.

0.001
d_u Annotated[float, ParameterSpec(domain=open(0, oo))]

The decay rate of the drug.

4.16
u1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The infusion rate of the drug.

10.0
infusion str

The form of the infusion, 'constant', 'exponential', or 'periodic'.

'constant'

Raises:

Type Description
ParameterError

The infusion is not one of the known forms.

Examples:

>>> from skcomplex.models.biology.oncology import ChemovirotherapyTumourElement
>>> ChemovirotherapyTumourElement('tumour', infusion='periodic').infusion
'periodic'
Source code in src/skcomplex/models/biology/oncology/_chemovirotherapy_tumour.py
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    AU: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    AV: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    V: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.1,
    U: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.1,
    r1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.206,
    b: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1e-06,
    alpha: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.001,
    a1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.005,
    a2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.5115,
    a3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.006,
    beta_v: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 10.0,
    d1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.001,
    d_u: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 4.16,
    u1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 10.0,
    infusion: str = 'constant',
) -> None:
    super().__init__(label, visual=visual)
    self.AU = AU
    self.AV = AV
    self.V = V
    self.U = U
    self.r1 = r1
    self.b = b
    self.alpha = alpha
    self.a1 = a1
    self.a2 = a2
    self.a3 = a3
    self.beta_v = beta_v
    self.d1 = d1
    self.d_u = d_u
    self.u1 = u1
    self.infusion = infusion

ClonalTumourElement(label, visual=None, *, A1=90000.0, A2=40000.0, E=500.0, r1=0.15, r2=0.11, b1=2e-08, b2=2e-08, c1=0.1, c2=5.5, c3=0.1, c4=5.5, r3=0.8, theta=300000.0, s1=0.0018, s2=0.0018, u_chemo1=0.2, u_chemo2=0.02, u_vaccine=20.0)

Bases: Element

Two competing tumour clones and an immune response under chemotherapy and a dendritic-cell vaccine.

Each clone grows logistically, competes with the other clone and with the immune cells E, and dies at the chemotherapy rate u_chemo1 or u_chemo2 and at the rate b UIm E of the vaccine-recruited immune cells. The immune cells grow logistically to theta and are recruited by both clones. Cells are counted, and time is in days.

The element holds the states and parameters and has no laws of its own: the interactions of clonal_chemoimmunotherapy read its parameters.

Parameters:

Name Type Description Default
label str

The label of the tumour.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
A1 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of cells of the first clone.

90000.0
A2 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of cells of the second clone.

40000.0
E Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of immune cells.

500.0
r1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of the first clone.

0.15
r2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of the second clone.

0.11
b1 Annotated[float, ParameterSpec(domain=open(0, oo))]

The reciprocal carrying capacity of the first clone.

2e-08
b2 Annotated[float, ParameterSpec(domain=open(0, oo))]

The reciprocal carrying capacity of the second clone.

2e-08
c1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The competition of the second clone on the first.

0.1
c2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The competition of the immune cells on the first clone.

5.5
c3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The competition of the first clone on the second.

0.1
c4 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The competition of the immune cells on the second clone.

5.5
r3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of the immune cells.

0.8
theta Annotated[float, ParameterSpec(domain=open(0, oo))]

The immune threshold.

300000.0
s1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which the first clone recruits immune cells.

0.0018
s2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which the second clone recruits immune cells.

0.0018
u_chemo1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The chemotherapy kill rate of the first clone.

0.2
u_chemo2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The chemotherapy kill rate of the second clone.

0.02
u_vaccine Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The level of the immunotherapeutic agent.

20.0

Examples:

>>> from skcomplex.models.biology.oncology import ClonalTumourElement
>>> ClonalTumourElement('tumour').theta
300000.0
Source code in src/skcomplex/models/biology/oncology/_clonal_tumour.py
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    A1: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 90000.0,
    A2: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 40000.0,
    E: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 500.0,
    r1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.15,
    r2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.11,
    b1: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 2e-08,
    b2: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 2e-08,
    c1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.1,
    c2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 5.5,
    c3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.1,
    c4: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 5.5,
    r3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.8,
    theta: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 300000.0,
    s1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0018,
    s2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0018,
    u_chemo1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.2,
    u_chemo2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.02,
    u_vaccine: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 20.0,
) -> None:
    super().__init__(label, visual=visual)
    self.A1 = A1
    self.A2 = A2
    self.E = E
    self.r1 = r1
    self.r2 = r2
    self.b1 = b1
    self.b2 = b2
    self.c1 = c1
    self.c2 = c2
    self.c3 = c3
    self.c4 = c4
    self.r3 = r3
    self.theta = theta
    self.s1 = s1
    self.s2 = s2
    self.u_chemo1 = u_chemo1
    self.u_chemo2 = u_chemo2
    self.u_vaccine = u_vaccine

DelayedVaccinatedTumourElement(label, visual=None, *, A=500000.0, ENK=44000.0, ENC=120000.0, E=10.0, ED=10.0, C=48.0, ER=1100000.0, ENH=126000.0, E1H=10.0, r1=0.16, b=5000000000.0, a1=6.9, g1=3.5, a2=7.13e-10, s1=13200.0, d1=0.0412, rho1=0.0668, g2=25000.0, psi1=1e-07, s2=500000.0, d2=0.03, rho2=1.2, g3=10 ** 5.4, d3=0.4, rho3=8.98e-07, m1=0.38, rho4=0.19, g4=6250000.0, psi2=4.3e-07, d4=0.237, kappa1=24380.0, g5=100000.0, s3=280.5, d5=5.5, rho5=1.1, g6=100000000000.0, rho6=4.99, g7=100000.0, s4=321200.0, d6=0.3, rho7=0.26, g8=4.5e+17, rho8=0.399, g9=10 ** 4.4, s5=550000.0, d7=0.03, rho9=1.05, d8=0.44, m2=0.45, psi3=8e-07, rho10=1.4, tau1=1.26, tau2=0.45, tau3=0.47, dose=1000000.0, period=7.0, width=1.0, start=0.0, doses=4)

Bases: Element

Tumour, natural killer cells, naive and mature CD8+ cells, dendritic cells, IL-2, regulatory, and helper cells.

The equations are those of Padmanabhan et al. (4.13) to (4.21), with the delays tau1, tau2, and tau3 of one division of natural killer, CD8+, and helper cells. Naive CD8+ cells mature after 7 tau2 and naive helper cells after 2 tau3. The tumour is killed by mature CD8+ cells through a1 x^5 / (g1 + x^5) with x = log(E) / log(A). The vaccine u is dose for width time units every period from start, doses times.

The element holds the states and parameters and has no laws of its own: the interactions of delayed_dc_vaccine read its parameters.

Parameters:

Name Type Description Default
label str

The label of the tumour site.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
A Annotated[float, StateSpec(domain=open(0, oo))]

The initial tumour cells.

500000.0
ENK Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial natural killer cells.

44000.0
ENC Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial naive CD8+ cells.

120000.0
E Annotated[float, StateSpec(domain=open(0, oo))]

The initial mature CD8+ cells.

10.0
ED Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial dendritic cells.

10.0
C Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial IL-2 concentration.

48.0
ER Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial regulatory T cells.

1100000.0
ENH Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial naive helper T cells.

126000.0
E1H Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial type 1 helper T cells.

10.0
r1 Annotated[float, ParameterSpec(domain=open(0, oo))]

The growth rate of the tumour.

0.16
b Annotated[float, ParameterSpec(domain=open(0, oo))]

The carrying capacity of the tumour.

5000000000.0
a1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The maximal kill rate by mature CD8+ cells.

6.9
g1 Annotated[float, ParameterSpec(domain=open(0, oo))]

The steepness of the kill by mature CD8+ cells.

3.5
a2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The kill rate by natural killer cells.

7.13e-10
s1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The influx of natural killer cells.

13200.0
d1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of natural killer cells.

0.0412
rho1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The production rate of natural killer cells by IL-2.

0.0668
g2 Annotated[float, ParameterSpec(domain=open(0, oo))]

The IL-2 at half production of natural killer cells.

25000.0
psi1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The inactivation rate of natural killer cells by regulatory cells.

1e-07
s2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The influx of naive CD8+ cells.

500000.0
d2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of naive CD8+ cells.

0.03
rho2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The activation rate of naive CD8+ cells by dendritic cells.

1.2
g3 Annotated[float, ParameterSpec(domain=open(0, oo))]

The dendritic cells at half activation.

10 ** 5.4
d3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of mature CD8+ cells.

0.4
rho3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The production rate of mature CD8+ cells by dendritic cells.

8.98e-07
m1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The proliferation rate of mature CD8+ cells with dendritic cells.

0.38
rho4 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The proliferation rate of mature CD8+ cells by IL-2.

0.19
g4 Annotated[float, ParameterSpec(domain=open(0, oo))]

The squared IL-2 at half proliferation.

6250000.0
psi2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The inactivation rate of mature CD8+ cells by regulatory cells.

4.3e-07
d4 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of dendritic cells.

0.237
kappa1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The production of dendritic cells from tumour antigen.

24380.0
g5 Annotated[float, ParameterSpec(domain=open(0, oo))]

The tumour at half production of dendritic cells.

100000.0
s3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The influx of IL-2.

280.5
d5 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The decay rate of IL-2.

5.5
rho5 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The secretion rate of IL-2 by mature CD8+ cells.

1.1
g6 Annotated[float, ParameterSpec(domain=open(0, oo))]

The squared mature CD8+ cells at half secretion.

100000000000.0
rho6 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The secretion rate of IL-2 by type 1 helper cells.

4.99
g7 Annotated[float, ParameterSpec(domain=open(0, oo))]

The type 1 helper cells at half secretion.

100000.0
s4 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The influx of regulatory cells.

321200.0
d6 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of regulatory cells.

0.3
rho7 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The production rate of regulatory cells by the tumour.

0.26
g8 Annotated[float, ParameterSpec(domain=open(0, oo))]

The squared tumour at half production of regulatory cells.

4.5e+17
rho8 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The production rate of regulatory cells by IL-2.

0.399
g9 Annotated[float, ParameterSpec(domain=open(0, oo))]

The IL-2 at half production of regulatory cells.

10 ** 4.4
s5 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The influx of naive helper cells.

550000.0
d7 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of naive helper cells.

0.03
rho9 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The activation rate of naive helper cells by dendritic cells.

1.05
d8 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of type 1 helper cells.

0.44
m2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The maturation rate of naive helper cells.

0.45
psi3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The inactivation rate of type 1 helper cells by regulatory cells.

8e-07
rho10 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The proliferation rate of type 1 helper cells with dendritic cells.

1.4
tau1 Annotated[float, ParameterSpec(domain=open(0, oo))]

The division time of natural killer cells.

1.26
tau2 Annotated[float, ParameterSpec(domain=open(0, oo))]

The division time of CD8+ cells.

0.45
tau3 Annotated[float, ParameterSpec(domain=open(0, oo))]

The division time of helper cells.

0.47
dose Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The injection rate of dendritic cells during a dose.

1000000.0
period float

The time between the starts of doses.

7.0
width float

The duration of a dose.

1.0
start float

The time of the first dose.

0.0
doses int

The number of doses.

4

Examples:

>>> from skcomplex.models.biology.oncology import DelayedVaccinatedTumourElement
>>> DelayedVaccinatedTumourElement('site').tau1
1.26
Source code in src/skcomplex/models/biology/oncology/_delayed_vaccinated_tumour.py
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    A: Annotated[float, StateSpec(domain=RealSet.open(0, oo))] = 500000.0,
    ENK: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 44000.0,
    ENC: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 120000.0,
    E: Annotated[float, StateSpec(domain=RealSet.open(0, oo))] = 10.0,
    ED: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 10.0,
    C: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 48.0,
    ER: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 1100000.0,
    ENH: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 126000.0,
    E1H: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 10.0,
    r1: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.16,
    b: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 5000000000.0,
    a1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 6.9,
    g1: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 3.5,
    a2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 7.13e-10,
    s1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 13200.0,
    d1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0412,
    rho1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0668,
    g2: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 25000.0,
    psi1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1e-07,
    s2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 500000.0,
    d2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.03,
    rho2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.2,
    g3: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 10**5.4,
    d3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.4,
    rho3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 8.98e-07,
    m1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.38,
    rho4: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.19,
    g4: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 6250000.0,
    psi2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 4.3e-07,
    d4: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.237,
    kappa1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 24380.0,
    g5: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 100000.0,
    s3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 280.5,
    d5: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 5.5,
    rho5: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.1,
    g6: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 100000000000.0,
    rho6: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 4.99,
    g7: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 100000.0,
    s4: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 321200.0,
    d6: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.3,
    rho7: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.26,
    g8: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 4.5e17,
    rho8: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.399,
    g9: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 10**4.4,
    s5: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 550000.0,
    d7: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.03,
    rho9: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.05,
    d8: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.44,
    m2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.45,
    psi3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 8e-07,
    rho10: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.4,
    tau1: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1.26,
    tau2: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.45,
    tau3: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.47,
    dose: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1000000.0,
    period: float = 7.0,
    width: float = 1.0,
    start: float = 0.0,
    doses: int = 4,
) -> None:
    super().__init__(label, visual=visual)
    self.A = A
    self.ENK = ENK
    self.ENC = ENC
    self.E = E
    self.ED = ED
    self.C = C
    self.ER = ER
    self.ENH = ENH
    self.E1H = E1H
    self.r1 = r1
    self.b = b
    self.a1 = a1
    self.g1 = g1
    self.a2 = a2
    self.s1 = s1
    self.d1 = d1
    self.rho1 = rho1
    self.g2 = g2
    self.psi1 = psi1
    self.s2 = s2
    self.d2 = d2
    self.rho2 = rho2
    self.g3 = g3
    self.d3 = d3
    self.rho3 = rho3
    self.m1 = m1
    self.rho4 = rho4
    self.g4 = g4
    self.psi2 = psi2
    self.d4 = d4
    self.kappa1 = kappa1
    self.g5 = g5
    self.s3 = s3
    self.d5 = d5
    self.rho5 = rho5
    self.g6 = g6
    self.rho6 = rho6
    self.g7 = g7
    self.s4 = s4
    self.d6 = d6
    self.rho7 = rho7
    self.g8 = g8
    self.rho8 = rho8
    self.g9 = g9
    self.s5 = s5
    self.d7 = d7
    self.rho9 = rho9
    self.d8 = d8
    self.m2 = m2
    self.psi3 = psi3
    self.rho10 = rho10
    self.tau1 = tau1
    self.tau2 = tau2
    self.tau3 = tau3
    self.dose = dose
    self.period = period
    self.width = width
    self.start = start
    self.doses = doses

DormantCellCycleElement(label, visual=None, *, A0=6.5, A1=0.2, A2=0.1, l0=0.05, l1=0.5, l2=1.0, b0=0.9, b1=0.1, u=0.0, v=0.0)

Bases: Element

Tumour cells in a dormant phase and two cycling phases under a killing and a recruiting agent.

The compartments hold the dormant cells in G0 A0, the cells in G1 and S A1, and the cells in G2 and M A2. A fraction b0 of the daughters enters G0 and b1 enters G1, so dA0/dt = -l0 (1 + v) A0 + 2 b0 (1 - u) l2 A2, dA1/dt = l0 (1 + v) A0 - l1 A1 + 2 b1 (1 - u) l2 A2, and dA2/dt = l1 A1 - l2 A2. The killing agent kills the fraction u of the cells that divide, and the recruiting agent speeds the exit from G0 by the factor 1 + v.

The element holds the states and parameters and has no laws of its own: the interactions of cell_cycle_chemotherapy read its parameters.

Parameters:

Name Type Description Default
label str

The label of the tumour.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
A0 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial dormant cells.

6.5
A1 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial cells in G1 and S.

0.2
A2 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial cells in G2 and M.

0.1
l0 Annotated[float, ParameterSpec(domain=open(0, oo))]

The rate of exit from G0.

0.05
l1 Annotated[float, ParameterSpec(domain=open(0, oo))]

The rate of exit from G1 and S.

0.5
l2 Annotated[float, ParameterSpec(domain=open(0, oo))]

The rate of exit from G2 and M.

1.0
b0 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The fraction of daughters that enters G0.

0.9
b1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The fraction of daughters that enters G1.

0.1
u Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The fraction of dividing cells the killing agent kills.

0.0
v Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The relative increase of the exit from G0 the recruiting agent causes.

0.0

Examples:

>>> from skcomplex.models.biology.oncology import DormantCellCycleElement
>>> DormantCellCycleElement('tumour').b0
0.9
Source code in src/skcomplex/models/biology/oncology/_dormant_cell_cycle.py
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    A0: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 6.5,
    A1: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.2,
    A2: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.1,
    l0: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.05,
    l1: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.5,
    l2: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1.0,
    b0: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.9,
    b1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.1,
    u: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    v: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
) -> None:
    super().__init__(label, visual=visual)
    self.A0 = A0
    self.A1 = A1
    self.A2 = A2
    self.l0 = l0
    self.l1 = l1
    self.l2 = l2
    self.b0 = b0
    self.b1 = b1
    self.u = u
    self.v = v

ErythropoiesisElement(label, visual=None, *, L=3.84, Q=19.6, P=2.16, MCV=85.0, r1=0.00139, d1=0.0071, a0=0.00022, tau_h=0.68, MCV_h=85.0, MCV0=85.0, g1=0.0317, m0=1.01, Q50=0.027, n=1.0, lifespan=120.0, U=0.0)

Bases: Element

Quiescent, proliferating, and mature red cells and their mean volume under a constant 6-mercaptopurine level.

The drug sets the death rate of proliferating cells a1 = a0 U and the cell-cycle time tau = (g1 U + MCV0) tau_h / MCV_h. Quiescent cells enter the cycle at the rate m(Q) = m0 Q50^n / (Q50^n + Q^n), of which the fraction exp(-a1 tau) survives to give two daughters, and leave to mature at the rate r1, so dQ/dt = -r1 Q + (2 exp(-a1 tau) - 1) m(Q) Q. The proliferating cells follow dP/dt = -a1 P + (1 - exp(-a1 tau)) m(Q) Q, the mature cells, which live lifespan days, dL/dt = r1 Q - d1 L(t - lifespan), and their mean corpuscular volume dMCV/dt = ((g1 U + MCV0) r1 Q - 0.85 MCV(t - lifespan) d1 L(t - lifespan) - 0.15 MCV d1 L) / L. Before the start the mature cells and their volume keep their initial values.

The element holds the states and parameters and has no laws of its own: the interactions of erythropoiesis_mercaptopurine read its parameters.

Parameters:

Name Type Description Default
label str

The label of the patient.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
L Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial mature red cells.

3.84
Q Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial quiescent cells.

19.6
P Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial proliferating cells.

2.16
MCV Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial mean corpuscular volume.

85.0
r1 Annotated[float, ParameterSpec(domain=open(0, oo))]

The rate of differentiation of quiescent cells.

0.00139
d1 Annotated[float, ParameterSpec(domain=open(0, oo))]

The death rate of mature cells.

0.0071
a0 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of proliferating cells per unit of drug.

0.00022
tau_h Annotated[float, ParameterSpec(domain=open(0, oo))]

The cell-cycle time of healthy cells.

0.68
MCV_h Annotated[float, ParameterSpec(domain=open(0, oo))]

The healthy mean corpuscular volume.

85.0
MCV0 Annotated[float, ParameterSpec(domain=open(0, oo))]

The volume of new cells without the drug.

85.0
g1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The increase of the volume of new cells per unit of drug.

0.0317
m0 Annotated[float, ParameterSpec(domain=open(0, oo))]

The maximum rate at which quiescent cells enter the cycle.

1.01
Q50 Annotated[float, ParameterSpec(domain=open(0, oo))]

The quiescent cells at which the rate of entry is half its maximum.

0.027
n Annotated[float, ParameterSpec(domain=open(0, oo))]

The sensitivity of the rate of entry to the quiescent cells.

1.0
lifespan Annotated[float, ParameterSpec(domain=open(0, oo))]

The life span of mature cells.

120.0
U Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The concentration of the drug.

0.0

Examples:

>>> from skcomplex.models.biology.oncology import ErythropoiesisElement
>>> ErythropoiesisElement('patient').lifespan
120.0
Source code in src/skcomplex/models/biology/oncology/_erythropoiesis.py
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    L: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 3.84,
    Q: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 19.6,
    P: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 2.16,
    MCV: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 85.0,
    r1: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.00139,
    d1: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.0071,
    a0: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.00022,
    tau_h: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.68,
    MCV_h: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 85.0,
    MCV0: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 85.0,
    g1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0317,
    m0: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1.01,
    Q50: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.027,
    n: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1.0,
    lifespan: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 120.0,
    U: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
) -> None:
    super().__init__(label, visual=visual)
    self.L = L
    self.Q = Q
    self.P = P
    self.MCV = MCV
    self.r1 = r1
    self.d1 = d1
    self.a0 = a0
    self.tau_h = tau_h
    self.MCV_h = MCV_h
    self.MCV0 = MCV0
    self.g1 = g1
    self.m0 = m0
    self.Q50 = Q50
    self.n = n
    self.lifespan = lifespan
    self.U = U

ExponentialLinearGrowthInteraction(label, *, target, r0=0.31, r=67.8)

Bases: RateInteraction

Growth that is exponential, dn/dt = r0 n, until it reaches the linear rate r, and linear after.

The switch happens at tau = log(r / (r0 n0)) / r0, where the two rates meet, so the solution is continuously differentiable.

Parameters:

Name Type Description Default
label str

The label of the interaction.

required
target Annotated[str, RoleSpec()]

The path of the tumour.

required
r0 Annotated[float, ParameterSpec(domain=open(0, oo))]

The exponential growth rate.

0.31
r Annotated[float, ParameterSpec(domain=open(0, oo))]

The linear growth rate.

67.8

Examples:

>>> from skcomplex.models.biology.oncology import ExponentialLinearGrowthInteraction
>>> ExponentialLinearGrowthInteraction('growth', target='tumour', r=67.8).r
67.8
Source code in src/skcomplex/models/biology/oncology/_exponential_linear_growth.py
42
43
44
45
46
47
48
49
50
51
52
def __init__(
    self,
    label: str,
    *,
    target: Annotated[str, RoleSpec()],
    r0: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.31,
    r: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 67.8,
) -> None:
    super().__init__(label, target=target, state='n')
    self.r0 = r0
    self.r = r

GliomaBrainElement(label, visual=None, *, G=5940000000000.0, N=5940000000000.0, AU=60000000000.0, AV=0.0, V=1000000000.0, U=0.0, r1=0.0068, r2=0.012, b=1.67e-13, c1=3.0769e-15, c2=3.0769e-16, a1=280800.0, a2=280800.0, a3=280800000.0, g1=6000000000000.0, g2=6000000000000.0, g3=6000000000000.0, psi=3.418e-13, alpha=1.2e-10, a4=0.5, beta_v=1000.0, d_u1=24.0, d_u2=0.2, u1=400.0)

Bases: Element

Glia, neurons, and a glioma under temozolomide and an oncolytic virus.

Normal glia G and the glioma compete. Neurons N die in proportion to the loss of glia, psi dG/dt H(-dG/dt) N. The drug U kills glia, neurons, and glioma with saturating kills. The virus V infects only glioma cells, and the infected cells AV burst. Cells and virions are counted, the drug is in mg per m², and time is in days.

The element holds the states and parameters and has no laws of its own: the interactions of glioma_chemovirotherapy read its parameters.

Parameters:

Name Type Description Default
label str

The label of the brain.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
G Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of glial cells.

5940000000000.0
N Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of neurons.

5940000000000.0
AU Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of uninfected glioma cells.

60000000000.0
AV Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of infected glioma cells.

0.0
V Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of virions.

1000000000.0
U Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial amount of drug.

0.0
r1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of glia.

0.0068
r2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of the glioma.

0.012
b Annotated[float, ParameterSpec(domain=open(0, oo))]

The reciprocal carrying capacity of glia and glioma.

1.67e-13
c1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The competition of the glioma on glia.

3.0769e-15
c2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The competition of glia on the glioma.

3.0769e-16
a1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The drug kill rate of glia.

280800.0
a2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The drug kill rate of neurons.

280800.0
a3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The drug kill rate of the glioma.

280800000.0
g1 Annotated[float, ParameterSpec(domain=open(0, oo))]

The half-saturation of the drug kill of glia.

6000000000000.0
g2 Annotated[float, ParameterSpec(domain=open(0, oo))]

The half-saturation of the drug kill of neurons.

6000000000000.0
g3 Annotated[float, ParameterSpec(domain=open(0, oo))]

The half-saturation of the drug kill of the glioma.

6000000000000.0
psi Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The loss of neurons per glial cell lost.

3.418e-13
alpha Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The infection rate.

1.2e-10
a4 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which the virus kills infected cells.

0.5
beta_v Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The burst size.

1000.0
d_u1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The decay rate of the virus.

24.0
d_u2 Annotated[float, ParameterSpec(domain=open(0, oo))]

The clearance rate of the drug.

0.2
u1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The infusion rate of the drug, in mg per m² per day.

400.0

Examples:

>>> from skcomplex.models.biology.oncology import GliomaBrainElement
>>> GliomaBrainElement('brain').u1
400.0
Source code in src/skcomplex/models/biology/oncology/_glioma_brain.py
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    G: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 5940000000000.0,
    N: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 5940000000000.0,
    AU: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 60000000000.0,
    AV: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    V: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 1000000000.0,
    U: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    r1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0068,
    r2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.012,
    b: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1.67e-13,
    c1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 3.0769e-15,
    c2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 3.0769e-16,
    a1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 280800.0,
    a2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 280800.0,
    a3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 280800000.0,
    g1: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 6000000000000.0,
    g2: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 6000000000000.0,
    g3: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 6000000000000.0,
    psi: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 3.418e-13,
    alpha: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.2e-10,
    a4: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.5,
    beta_v: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1000.0,
    d_u1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 24.0,
    d_u2: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.2,
    u1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 400.0,
) -> None:
    super().__init__(label, visual=visual)
    self.G = G
    self.N = N
    self.AU = AU
    self.AV = AV
    self.V = V
    self.U = U
    self.r1 = r1
    self.r2 = r2
    self.b = b
    self.c1 = c1
    self.c2 = c2
    self.a1 = a1
    self.a2 = a2
    self.a3 = a3
    self.g1 = g1
    self.g2 = g2
    self.g3 = g3
    self.psi = psi
    self.alpha = alpha
    self.a4 = a4
    self.beta_v = beta_v
    self.d_u1 = d_u1
    self.d_u2 = d_u2
    self.u1 = u1

Her2TumourElement(label, visual=None, *, A=0.035, Ab=0.0, Pin=0.0, r=0.83, kc=0.67, a1=2.51, a2=23.0, gamma_p=6.35, sigma=1.0, theta_ab=8.78, theta_r=1940000.0, alpha_p=0.68, antibody=0.2, paclitaxel=2.0, t_antibody=1.0, t_a=2.0, t_p=1.0)

Bases: Element

HER2+ breast cancer cells under trastuzumab and paclitaxel, with antibody binding and drug uptake.

The tumour grows logistically, dA/dt = r (1 - DIm) (1 - A / (kc - DCh)) A. The bound antibody Ab lowers the proliferation by DIm = a1 Ab from the time t_a on, and the internalized paclitaxel Pin lowers the carrying capacity by DCh = sigma a2 exp(-gamma_p (t - t_p)) Pin from the dose time t_p on. The free antibody and the free paclitaxel are drivers, held at the levels antibody and paclitaxel from their dose times on. The antibody binds the receptors, dAb/dt = theta_ab (Af - Ab) (theta_r A - Ab), and the paclitaxel enters the cells, dPin/dt = alpha_p (Pf - Pin) A, while the free drugs are present. Cells are counted in millions, so the carrying capacity is 0.67, the antibody is in millions of molecules, and time is in days.

Parameters:

Name Type Description Default
label str

The label of the tumour.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
A Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of cells.

0.035
Ab Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial bound antibody.

0.0
Pin Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial internalized paclitaxel.

0.0
r Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate.

0.83
kc Annotated[float, ParameterSpec(domain=open(0, oo))]

The carrying capacity.

0.67
a1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The inhibition of proliferation per unit of bound antibody.

2.51
a2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The reduction of the carrying capacity per unit of internalized paclitaxel.

23.0
gamma_p Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The decay rate of the cytotoxicity of paclitaxel.

6.35
sigma Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The synergy of the two drugs, 1 for none.

1.0
theta_ab Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The binding rate of the antibody.

8.78
theta_r Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The number of receptors per cell.

1940000.0
alpha_p Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The uptake rate of paclitaxel.

0.68
antibody Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The level of free antibody from its dose on.

0.2
paclitaxel Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The level of free paclitaxel from its dose on, in pmol.

2.0
t_antibody float

The time of the antibody dose.

1.0
t_a float

The time from which the bound antibody inhibits proliferation.

2.0
t_p float

The time of the paclitaxel dose.

1.0

Examples:

>>> from skcomplex.models.biology.oncology import Her2TumourElement
>>> Her2TumourElement('tumour').kc
0.67
Source code in src/skcomplex/models/biology/oncology/_her2_tumour.py
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    A: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.035,
    Ab: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    Pin: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    r: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.83,
    kc: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.67,
    a1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 2.51,
    a2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 23.0,
    gamma_p: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 6.35,
    sigma: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    theta_ab: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 8.78,
    theta_r: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1940000.0,
    alpha_p: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.68,
    antibody: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.2,
    paclitaxel: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 2.0,
    t_antibody: float = 1.0,
    t_a: float = 2.0,
    t_p: float = 1.0,
) -> None:
    super().__init__(label, visual=visual)
    self.A = A
    self.Ab = Ab
    self.Pin = Pin
    self.r = r
    self.kc = kc
    self.a1 = a1
    self.a2 = a2
    self.gamma_p = gamma_p
    self.sigma = sigma
    self.theta_ab = theta_ab
    self.theta_r = theta_r
    self.alpha_p = alpha_p
    self.antibody = antibody
    self.paclitaxel = paclitaxel
    self.t_antibody = t_antibody
    self.t_a = t_a
    self.t_p = t_p

IntermittentSuppressionElement(label, visual=None, *, AD=5.0, AI=0.0, U=30.0, u=0.0, r1=0.0204, r2=0.0242, d1=0.0076, d2=0.0168, m1=5e-05, k1=0.0, k2=2.0, k3=8.0, k4=0.5, U0=30.0, du=0.08, x1=1.0, x2=1.0)

Bases: Element

Prostate cancer cells under androgen suppression that PSA thresholds switch on and off.

The dependent cells follow dAD/dt = r1 (k1 + (1 - k1) U / (U + k2)) AD - d1 (k3 + (1 - k3) U / (U + k4)) AD - m1 (1 - U / U0) AD, the independent cells dAI/dt = m1 (1 - U / U0) AD + r2 (1 - U / U0) AI - d2 AI, and the serum androgen du/dt = -du (U - U0) - U0 du u. The therapy u turns 1 when the PSA x1 AD + x2 AI rises through h1 and 0 when it falls through h0.

The element holds the states and parameters and has no laws of its own: the interactions of ideta_intermittent_androgen read its parameters.

Parameters:

Name Type Description Default
label str

The label of the tumour.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
AD Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of androgen-dependent cells.

5.0
AI Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of androgen-independent cells.

0.0
U Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial serum androgen concentration.

30.0
u Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial therapy, 1 on and 0 off.

0.0
r1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of the dependent cells.

0.0204
r2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of the independent cells.

0.0242
d1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of the dependent cells.

0.0076
d2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of the independent cells.

0.0168
m1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The maximum rate at which dependent cells turn independent.

5e-05
k1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth of the dependent cells without androgen, relative to r1.

0.0
k2 Annotated[float, ParameterSpec(domain=open(0, oo))]

The androgen at which the growth of the dependent cells is half way.

2.0
k3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death of the dependent cells without androgen, relative to d1.

8.0
k4 Annotated[float, ParameterSpec(domain=open(0, oo))]

The androgen at which the death of the dependent cells is half way.

0.5
U0 Annotated[float, ParameterSpec(domain=open(0, oo))]

The normal androgen concentration.

30.0
du Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The elimination rate of the androgen.

0.08
x1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The PSA per dependent cell.

1.0
x2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The PSA per independent cell.

1.0

Examples:

>>> from skcomplex.models.biology.oncology import IntermittentSuppressionElement
>>> IntermittentSuppressionElement('tumour').U0
30.0
Source code in src/skcomplex/models/biology/oncology/_intermittent_suppression.py
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    AD: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 5.0,
    AI: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    U: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 30.0,
    u: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    r1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0204,
    r2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0242,
    d1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0076,
    d2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0168,
    m1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 5e-05,
    k1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    k2: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 2.0,
    k3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 8.0,
    k4: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.5,
    U0: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 30.0,
    du: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.08,
    x1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    x2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
) -> None:
    super().__init__(label, visual=visual)
    self.AD = AD
    self.AI = AI
    self.U = U
    self.u = u
    self.r1 = r1
    self.r2 = r2
    self.d1 = d1
    self.d2 = d2
    self.m1 = m1
    self.k1 = k1
    self.k2 = k2
    self.k3 = k3
    self.k4 = k4
    self.U0 = U0
    self.du = du
    self.x1 = x1
    self.x2 = x2

IrradiatedTumourElement(label, visual=None, *, A1=27.0, A2=0.0, A3=0.0, A4=0.0, A5=0.0, A6=0.0, Us=0.0, u_tot=0.0, r=0.04, m1=0.26, a_gamma=0.004, du=5.544)

Bases: Element

Tumour in six compartments under linear-quadratic radiation fractions and a radiosensitizer.

The proliferating cells follow dA1/dt = r A1 exp(-a_gamma u_tot), where u_tot is the dose that the fractions of an irradiation accumulate. The lethally irradiated cells of A5 divide once into A6, dA5/dt = -(r + m1) A5 and dA6/dt = 2 r A5 - m1 A6, and both feed the dying chain A2 -> A3 -> A4, which leaves the tumour at the rate m1. The radiosensitizer is eliminated as dUs/dt = -du Us.

The element holds the states and parameters and has no laws of its own: the interactions of lq_radiosensitizer read its parameters.

Parameters:

Name Type Description Default
label str

The label of the tumour.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
A1 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial volume of proliferating cells.

27.0
A2 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial volume of the first dying compartment.

0.0
A3 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial volume of the second dying compartment.

0.0
A4 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial volume of the third dying compartment.

0.0
A5 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial volume of lethally irradiated cells that divide once more.

0.0
A6 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial volume of lethally irradiated cells that no longer divide.

0.0
Us Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial plasma concentration of the radiosensitizer.

0.0
u_tot Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial accumulated dose.

0.0
r Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate.

0.04
m1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The transit rate of the damaged cells.

0.26
a_gamma Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The inhibition of proliferation per unit of accumulated dose.

0.004
du Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The elimination rate of the radiosensitizer.

5.544

Examples:

>>> from skcomplex.models.biology.oncology import IrradiatedTumourElement
>>> IrradiatedTumourElement('tumour', A1=10.0).A1
10.0
Source code in src/skcomplex/models/biology/oncology/_irradiated_tumour.py
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    A1: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 27.0,
    A2: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    A3: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    A4: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    A5: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    A6: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    Us: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    u_tot: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    r: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.04,
    m1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.26,
    a_gamma: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.004,
    du: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 5.544,
) -> None:
    super().__init__(label, visual=visual)
    self.A1 = A1
    self.A2 = A2
    self.A3 = A3
    self.A4 = A4
    self.A5 = A5
    self.A6 = A6
    self.Us = Us
    self.u_tot = u_tot
    self.r = r
    self.m1 = m1
    self.a_gamma = a_gamma
    self.du = du

IrradiationInteraction(label, *, target, alpha=0.054, beta=0.0054, ap=0.42, au=0.15, dose=2.0, period=1.0, start=0.125, fractions=10)

Bases: ImpulseInteraction

Radiation fractions of a dose d, which move the lethally irradiated part of the proliferating cells.

A fraction at the time start + i period moves the part M = 1 - exp(-(1 + ap Us)(alpha d + beta d^2)) of the proliferating cells A1 to the lethally irradiated cells A5 and raises the accumulated dose u_tot by (1 + au Us) d, where Us is the radiosensitizer. Every fraction is an event labelled by the interaction.

Parameters:

Name Type Description Default
label str

The label of the interaction and of its events.

required
target Annotated[str, RoleSpec()]

The path of the tumour, with the states A1, A5, Us, and u_tot.

required
alpha Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The linear coefficient of the linear-quadratic model.

0.054
beta Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The quadratic coefficient of the linear-quadratic model.

0.0054
ap Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The potency of the radiosensitizer in raising the cell kill.

0.42
au Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The potency of the radiosensitizer in raising the accumulated dose.

0.15
dose Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The dose of a fraction.

2.0
period float

The time between fractions.

1.0
start float

The time of the first fraction.

0.125
fractions int

The number of fractions.

10

Raises:

Type Description
ValidationError

The times, the period, or the count of the fractions cannot be taken.

Examples:

>>> from skcomplex.models.biology.oncology import IrradiationInteraction
>>> IrradiationInteraction('fraction', target='tumour', fractions=5).check().count
5
Source code in src/skcomplex/models/biology/oncology/_irradiation.py
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
def __init__(
    self,
    label: str,
    *,
    target: Annotated[str, RoleSpec()],
    alpha: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.054,
    beta: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0054,
    ap: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.42,
    au: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.15,
    dose: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 2.0,
    period: float = 1.0,
    start: float = 0.125,
    fractions: int = 10,
) -> None:
    super().__init__(label, target=target, reset=self._get_resets(), period=period, start=start, count=fractions)
    self.alpha = alpha
    self.beta = beta
    self.ap = ap
    self.au = au
    self.dose = dose
    self.fractions = fractions

KirschnerPanettaTumourElement(label, visual=None, *, E=1.0, A=1.0, C=1.0, alpha_a=0.02, d1=0.03, rho1=0.1245, alpha1=20000000.0, r1=0.18, b=1e-09, c1=1.0, alpha2=100000.0, rho2=5.0, alpha3=1000.0, du=10.0, a1=500.0, a2=70000000.0, u1=0.0, u2=0.0)

Bases: Element

Effector cells, tumour cells, and IL-2 under adoptive cellular therapy and IL-2 injection.

The effector cells follow dE/dt = alpha_a A - d1 E + a1 u1 + rho1 E C / (alpha1 + C), the tumour dA/dt = r1 A (1 - b A) - c1 E A / (alpha2 + A), and the IL-2 dC/dt = a2 u2 + rho2 E A / (alpha3 + A) - du C, with constant inputs u1 and u2. The element holds the states and parameters and has no laws of its own: the rate and reaction interactions of kirschner_panetta read its parameters.

Parameters:

Name Type Description Default
label str

The label of the tumour site.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
E Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial effector cells.

1.0
A Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial tumour cells.

1.0
C Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial IL-2 concentration.

1.0
alpha_a Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The antigenicity of the tumour.

0.02
d1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of effector cells.

0.03
rho1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The proliferation rate of effector cells stimulated by IL-2.

0.1245
alpha1 Annotated[float, ParameterSpec(domain=open(0, oo))]

The IL-2 at half the proliferation.

20000000.0
r1 Annotated[float, ParameterSpec(domain=open(0, oo))]

The growth rate of the tumour.

0.18
b Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The inverse carrying capacity of the tumour.

1e-09
c1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The kill rate of tumour cells by effector cells.

1.0
alpha2 Annotated[float, ParameterSpec(domain=open(0, oo))]

The tumour at half the kill.

100000.0
rho2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The IL-2 production rate by effector-tumour encounters.

5.0
alpha3 Annotated[float, ParameterSpec(domain=open(0, oo))]

The tumour at half the IL-2 production.

1000.0
du Annotated[float, ParameterSpec(domain=open(0, oo))]

The loss rate of IL-2.

10.0
a1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The effector cells per unit of adoptive therapy.

500.0
a2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The IL-2 per unit of IL-2 injection.

70000000.0
u1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The adoptive therapy input.

0.0
u2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The IL-2 injection input.

0.0

Examples:

>>> from skcomplex.models.biology.oncology import KirschnerPanettaTumourElement
>>> KirschnerPanettaTumourElement('site').rho1
0.1245
Source code in src/skcomplex/models/biology/oncology/_kirschner_panetta_tumour.py
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    E: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    A: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    C: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    alpha_a: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.02,
    d1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.03,
    rho1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.1245,
    alpha1: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 20000000.0,
    r1: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.18,
    b: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1e-09,
    c1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    alpha2: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 100000.0,
    rho2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 5.0,
    alpha3: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1000.0,
    du: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 10.0,
    a1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 500.0,
    a2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 70000000.0,
    u1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    u2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
) -> None:
    super().__init__(label, visual=visual)
    self.E = E
    self.A = A
    self.C = C
    self.alpha_a = alpha_a
    self.d1 = d1
    self.rho1 = rho1
    self.alpha1 = alpha1
    self.r1 = r1
    self.b = b
    self.c1 = c1
    self.alpha2 = alpha2
    self.rho2 = rho2
    self.alpha3 = alpha3
    self.du = du
    self.a1 = a1
    self.a2 = a2
    self.u1 = u1
    self.u2 = u2

LeukaemiaStemCellsElement(label, visual=None, *, NS=100.0, NPr=0.0, ND=0.0, AS=1.0, AD=0.0, r1=0.6, m1=0.2, d1=0.1, r2=0.3, r3=0.1, d2=0.4, m2=0.5, d3=0.2, r4=0.7, m3=0.2, d4=0.1, r5=0.3, d5=0.2, beta1=0.01, beta2=0.01, beta3=0.01)

Bases: Element

Normal and leukaemic stem cells that share a niche, with the progeny that feeds back on them.

Stem cells renew symmetrically at the rate r e^-psi1 and differentiate symmetrically at the rate m e^-psi1 e^-psi3, where psi1 = beta1 (NS + AS) counts the stem cells in the niche and psi2 = beta2 (NPr + ND + AD) and psi3 = beta3 (NPr + ND + AD) count their progeny. Asymmetric division at the rate r e^-psi1 e^-psi2 and symmetric differentiation feed the progenitors and the leukaemic cells.

The element holds the states and parameters and has no laws of its own: the interactions of leukaemia_stem_cells read its parameters.

Parameters:

Name Type Description Default
label str

The label of the niche.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
NS Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial normal stem cells.

100.0
NPr Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial normal progenitors.

0.0
ND Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial normal differentiated cells.

0.0
AS Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial leukaemic stem cells.

1.0
AD Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial differentiated leukaemic cells.

0.0
r1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The symmetric renewal rate of normal stem cells.

0.6
m1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The symmetric differentiation rate of normal stem cells.

0.2
d1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of normal stem cells.

0.1
r2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The asymmetric division rate of normal stem cells.

0.3
r3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The proliferation rate of progenitors.

0.1
d2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which progenitors leave their compartment.

0.4
m2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The fraction of leaving progenitors that become differentiated cells.

0.5
d3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of differentiated cells.

0.2
r4 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The symmetric renewal rate of leukaemic stem cells.

0.7
m3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The symmetric differentiation rate of leukaemic stem cells.

0.2
d4 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of leukaemic stem cells.

0.1
r5 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The asymmetric division rate of leukaemic stem cells.

0.3
d5 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of differentiated leukaemic cells.

0.2
beta1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The feedback gain of the stem cells.

0.01
beta2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The feedback gain of the progeny on asymmetric division.

0.01
beta3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The feedback gain of the progeny on differentiation.

0.01

Examples:

>>> from skcomplex.models.biology.oncology import LeukaemiaStemCellsElement
>>> LeukaemiaStemCellsElement('niche').beta1
0.01
Source code in src/skcomplex/models/biology/oncology/_leukaemia_stem_cells.py
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    NS: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 100.0,
    NPr: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    ND: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    AS: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    AD: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    r1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.6,
    m1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.2,
    d1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.1,
    r2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.3,
    r3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.1,
    d2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.4,
    m2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.5,
    d3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.2,
    r4: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.7,
    m3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.2,
    d4: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.1,
    r5: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.3,
    d5: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.2,
    beta1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.01,
    beta2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.01,
    beta3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.01,
) -> None:
    super().__init__(label, visual=visual)
    self.NS = NS
    self.NPr = NPr
    self.ND = ND
    self.AS = AS
    self.AD = AD
    self.r1 = r1
    self.m1 = m1
    self.d1 = d1
    self.r2 = r2
    self.r3 = r3
    self.d2 = d2
    self.m2 = m2
    self.d3 = d3
    self.r4 = r4
    self.m3 = m3
    self.d4 = d4
    self.r5 = r5
    self.d5 = d5
    self.beta1 = beta1
    self.beta2 = beta2
    self.beta3 = beta3

LinearQuadraticSurvivalElement(label, *, survival=1.0, protraction=1.0, effective_dose=0.0, alpha=0.3, beta=0.03, dose=2.0, fractions=1.0, repair_rate=0.46, delivery_time=0.001)

Bases: Element

Surviving fraction of cells, Lea-Catcheside factor, and biologically effective dose of a total dose.

The survival is S = exp(-alpha D - beta G D^2), where D is the total dose. The Lea-Catcheside factor of n fractions, each delivered at a constant rate in a time T with repair at the rate mu, far enough apart to repair between them, is G = 2 (mu T - 1 + exp(-mu T)) / (n (mu T)^2), which tends to 1 / n as T tends to 0. The biologically effective dose is BED = D (1 + G D beta / alpha).

Parameters:

Name Type Description Default
label str

The label of the cells.

required
survival Annotated[float, StateSpec()]

The initial guess of the surviving fraction, which the equations replace.

1.0
protraction Annotated[float, StateSpec()]

The initial guess of the Lea-Catcheside factor, which the equations replace.

1.0
effective_dose Annotated[float, StateSpec()]

The initial guess of the biologically effective dose, which the equations replace.

0.0
alpha Annotated[float, ParameterSpec(domain=open(0, oo))]

The linear coefficient, per Gy.

0.3
beta Annotated[float, ParameterSpec(domain=open(0, oo))]

The quadratic coefficient, per Gy squared.

0.03
dose Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The total dose, in Gy.

2.0
fractions Annotated[float, ParameterSpec(domain=closed_open(1, oo))]

The number of fractions.

1.0
repair_rate Annotated[float, ParameterSpec(domain=open(0, oo))]

The rate of repair of sublethal damage, per hour.

0.46
delivery_time Annotated[float, ParameterSpec(domain=open(0, oo))]

The time to deliver one fraction, in hours.

0.001

Examples:

>>> from skcomplex.models.biology.oncology import LinearQuadraticSurvivalElement
>>> LinearQuadraticSurvivalElement('cells', dose=60.0, fractions=30.0).fractions
30.0
Source code in src/skcomplex/models/biology/oncology/_linear_quadratic_survival.py
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
def __init__(
    self,
    label: str,
    *,
    survival: Annotated[float, StateSpec()] = 1.0,
    protraction: Annotated[float, StateSpec()] = 1.0,
    effective_dose: Annotated[float, StateSpec()] = 0.0,
    alpha: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.3,
    beta: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.03,
    dose: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 2.0,
    fractions: Annotated[float, ParameterSpec(domain=RealSet.closed_open(1, oo))] = 1.0,
    repair_rate: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.46,
    delivery_time: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1e-3,
) -> None:
    super().__init__(label)
    self.survival = survival
    self.protraction = protraction
    self.effective_dose = effective_dose
    self.alpha = alpha
    self.beta = beta
    self.dose = dose
    self.fractions = fractions
    self.repair_rate = repair_rate
    self.delivery_time = delivery_time

LogKillInteraction(label, *, target, a=0.5, dose=1.0, period=7.0, width=1.0, start=0.0)

Bases: RateInteraction

Cell kill proportional to the tumour and to a drug exposure given in a train of rectangular doses.

The kill is dn/dt = -a n U(t), where the exposure U is dose for width time units every period, from start on. Without growth, every dose lowers log n by a dose width.

Parameters:

Name Type Description Default
label str

The label of the interaction.

required
target Annotated[str, RoleSpec()]

The path of the tumour.

required
a Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The kill rate per unit of exposure.

0.5
dose Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The exposure during a dose.

1.0
period float

The time between the starts of doses.

7.0
width float

The duration of a dose.

1.0
start float

The time of the first dose.

0.0

Examples:

>>> from skcomplex.models.biology.oncology import LogKillInteraction
>>> LogKillInteraction('kill', target='tumour', period=21.0).period
21.0
Source code in src/skcomplex/models/biology/oncology/_log_kill.py
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
def __init__(
    self,
    label: str,
    *,
    target: Annotated[str, RoleSpec()],
    a: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.5,
    dose: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    period: float = 7.0,
    width: float = 1.0,
    start: float = 0.0,
) -> None:
    super().__init__(label, target=target, state='n')
    self.a = a
    self.dose = dose
    self.period = period
    self.width = width
    self.start = start

MetastasisChemotherapyElement(label, visual=None, *, Np=1460.0, Ap=165.0, Up=0.0, Ns=1750.0, As=0.0, Us=0.0, r1=1.5, r2=10.0, r3=2.0, r4=12.0, b1=0.00068, b2=0.00047, b3=0.00057, b4=0.00043, c1=0.0075, c2=0.005, c3=0.002, c4=0.001, a1=0.0008, a2=0.08, a3=0.0006, a4=0.1, g1=0.0024, g2=0.24, g3=0.0018, g4=0.3, bc=1.0, k=20.0, delta=0.1, epsilon=0.0001, tau=1.0, up=0.0, us=0.0)

Bases: Element

Normal and tumour cells at a primary and a secondary site, each with its drug, and a delayed migration.

At each site the normal and tumour cells grow logistically, compete, and a drug kills them with a saturating response, a N U / (bc + N). The drug at a site follows dU/dt = u - (k + g1 N / (bc + N) + g2 A / (bc + A)) U. Tumour cells leave the primary site at the rate delta, and a fraction epsilon of them reaches the secondary site after the delay tau, dAs/dt = ... + epsilon delta Ap(t - tau). Before the start the primary tumour keeps its initial value.

The element holds the states and parameters and has no laws of its own: the interactions of delayed_metastasis read its parameters.

Parameters:

Name Type Description Default
label str

The label of the patient.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
Np Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial normal cells at the primary site.

1460.0
Ap Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial tumour cells at the primary site.

165.0
Up Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial drug concentration at the primary site.

0.0
Ns Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial normal cells at the secondary site.

1750.0
As Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial tumour cells at the secondary site.

0.0
Us Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial drug concentration at the secondary site.

0.0
r1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of normal cells at the primary site.

1.5
r2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of tumour cells at the primary site.

10.0
r3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of normal cells at the secondary site.

2.0
r4 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of tumour cells at the secondary site.

12.0
b1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The reciprocal carrying capacity of normal cells at the primary site.

0.00068
b2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The reciprocal carrying capacity of tumour cells at the primary site.

0.00047
b3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The reciprocal carrying capacity of normal cells at the secondary site.

0.00057
b4 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The reciprocal carrying capacity of tumour cells at the secondary site.

0.00043
c1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which the tumour competes with normal cells at the primary site.

0.0075
c2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which normal cells compete with the tumour at the primary site.

0.005
c3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which the tumour competes with normal cells at the secondary site.

0.002
c4 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which normal cells compete with the tumour at the secondary site.

0.001
a1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The kill rate of the drug on normal cells at the primary site.

0.0008
a2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The kill rate of the drug on tumour cells at the primary site.

0.08
a3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The kill rate of the drug on normal cells at the secondary site.

0.0006
a4 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The kill rate of the drug on tumour cells at the secondary site.

0.1
g1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which the drug combines with normal cells at the primary site.

0.0024
g2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which the drug combines with tumour cells at the primary site.

0.24
g3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which the drug combines with normal cells at the secondary site.

0.0018
g4 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which the drug combines with tumour cells at the secondary site.

0.3
bc Annotated[float, ParameterSpec(domain=open(0, oo))]

The half saturation of the kill and of the binding.

1.0
k Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The elimination rate of the drug at both sites, dU1 and dU2 in the book.

20.0
delta Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which tumour cells leave the primary site.

0.1
epsilon Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The fraction of leaving cells that reaches the secondary site.

0.0001
tau Annotated[float, ParameterSpec(domain=open(0, oo))]

The delay of the migration.

1.0
up Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The infusion rate of the drug at the primary site.

0.0
us Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The infusion rate of the drug at the secondary site.

0.0

Examples:

>>> from skcomplex.models.biology.oncology import MetastasisChemotherapyElement
>>> MetastasisChemotherapyElement('patient').epsilon
0.0001
Source code in src/skcomplex/models/biology/oncology/_metastasis_chemotherapy.py
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    Np: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 1460.0,
    Ap: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 165.0,
    Up: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    Ns: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 1750.0,
    As: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    Us: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    r1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.5,
    r2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 10.0,
    r3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 2.0,
    r4: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 12.0,
    b1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.00068,
    b2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.00047,
    b3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.00057,
    b4: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.00043,
    c1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0075,
    c2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.005,
    c3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.002,
    c4: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.001,
    a1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0008,
    a2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.08,
    a3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0006,
    a4: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.1,
    g1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0024,
    g2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.24,
    g3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0018,
    g4: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.3,
    bc: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1.0,
    k: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 20.0,
    delta: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.1,
    epsilon: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0001,
    tau: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1.0,
    up: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    us: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
) -> None:
    super().__init__(label, visual=visual)
    self.Np = Np
    self.Ap = Ap
    self.Up = Up
    self.Ns = Ns
    self.As = As
    self.Us = Us
    self.r1 = r1
    self.r2 = r2
    self.r3 = r3
    self.r4 = r4
    self.b1 = b1
    self.b2 = b2
    self.b3 = b3
    self.b4 = b4
    self.c1 = c1
    self.c2 = c2
    self.c3 = c3
    self.c4 = c4
    self.a1 = a1
    self.a2 = a2
    self.a3 = a3
    self.a4 = a4
    self.g1 = g1
    self.g2 = g2
    self.g3 = g3
    self.g4 = g4
    self.bc = bc
    self.k = k
    self.delta = delta
    self.epsilon = epsilon
    self.tau = tau
    self.up = up
    self.us = us

MultidrugResistanceElement(label, visual=None, *, S=460500000000.0, R1=0.0, R2=0.0, R3=0.0, R12=0.0, R13=0.0, R23=0.0, R123=0.0, U1=0.0, U2=0.0, U3=0.0, TX1=0.0, TX2=0.0, TX3=0.0, r=0.0099, m1=0.008, m2=0.01, m3=0.014, a1=0.0084, a2=0.0074, a3=0.0092, Uth=10.0, k1=0.32, k2=0.27, k3=0.25, eta1=0.4, eta2=0.5, eta3=0.45, u1=0.0, u2=0.0, u3=0.0)

Bases: Element

Tumour cells split by their resistance to three drugs, each given by a constant infusion with its toxicity.

The sensitive cells S, the cells resistant to one drug R1, R2, R3, to two drugs R12, R13, R23, and to all three R123 grow at the same rate r. A fraction m_i of the offspring of a population gains resistance to drug i, so dS/dt = r (1 - m1 - m2 - m3) S - K S, dRi/dt = r ((1 - mj - mk) Ri + mi S) - K Ri, and so on, where K sums the kill a_i (U_i - Uth) F(U_i - Uth) of every drug the population is sensitive to. The drugs follow dU_i/dt = u_i - k_i U_i and their toxicities dTX_i/dt = U_i - eta_i TX_i.

The element holds the states and parameters and has no laws of its own: the interactions of multidrug_resistance read its parameters.

Parameters:

Name Type Description Default
label str

The label of the tumour.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
S Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial sensitive cells.

460500000000.0
R1 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial cells resistant to drug 1.

0.0
R2 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial cells resistant to drug 2.

0.0
R3 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial cells resistant to drug 3.

0.0
R12 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial cells resistant to drugs 1 and 2.

0.0
R13 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial cells resistant to drugs 1 and 3.

0.0
R23 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial cells resistant to drugs 2 and 3.

0.0
R123 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial cells resistant to all drugs.

0.0
U1 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial concentration of drug 1.

0.0
U2 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial concentration of drug 2.

0.0
U3 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial concentration of drug 3.

0.0
TX1 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial toxicity of drug 1.

0.0
TX2 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial toxicity of drug 2.

0.0
TX3 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial toxicity of drug 3.

0.0
r Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of every population.

0.0099
m1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate of mutation to resistance against drug 1.

0.008
m2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate of mutation to resistance against drug 2.

0.01
m3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate of mutation to resistance against drug 3.

0.014
a1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The kill rate of drug 1 per unit of concentration above the threshold.

0.0084
a2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The kill rate of drug 2 per unit of concentration above the threshold.

0.0074
a3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The kill rate of drug 3 per unit of concentration above the threshold.

0.0092
Uth Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The concentration above which a drug kills.

10.0
k1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The decay rate of drug 1, dU1 in the book.

0.32
k2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The decay rate of drug 2, dU2 in the book.

0.27
k3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The decay rate of drug 3, dU3 in the book.

0.25
eta1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The metabolic rate that lowers the toxicity of drug 1.

0.4
eta2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The metabolic rate that lowers the toxicity of drug 2.

0.5
eta3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The metabolic rate that lowers the toxicity of drug 3.

0.45
u1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The infusion rate of drug 1.

0.0
u2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The infusion rate of drug 2.

0.0
u3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The infusion rate of drug 3.

0.0

Examples:

>>> from skcomplex.models.biology.oncology import MultidrugResistanceElement
>>> MultidrugResistanceElement('tumour').Uth
10.0
Source code in src/skcomplex/models/biology/oncology/_multidrug_resistance.py
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    S: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 460500000000.0,
    R1: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    R2: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    R3: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    R12: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    R13: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    R23: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    R123: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    U1: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    U2: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    U3: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    TX1: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    TX2: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    TX3: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    r: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0099,
    m1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.008,
    m2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.01,
    m3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.014,
    a1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0084,
    a2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0074,
    a3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0092,
    Uth: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 10.0,
    k1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.32,
    k2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.27,
    k3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.25,
    eta1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.4,
    eta2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.5,
    eta3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.45,
    u1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    u2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    u3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
) -> None:
    super().__init__(label, visual=visual)
    self.S = S
    self.R1 = R1
    self.R2 = R2
    self.R3 = R3
    self.R12 = R12
    self.R13 = R13
    self.R23 = R23
    self.R123 = R123
    self.U1 = U1
    self.U2 = U2
    self.U3 = U3
    self.TX1 = TX1
    self.TX2 = TX2
    self.TX3 = TX3
    self.r = r
    self.m1 = m1
    self.m2 = m2
    self.m3 = m3
    self.a1 = a1
    self.a2 = a2
    self.a3 = a3
    self.Uth = Uth
    self.k1 = k1
    self.k2 = k2
    self.k3 = k3
    self.eta1 = eta1
    self.eta2 = eta2
    self.eta3 = eta3
    self.u1 = u1
    self.u2 = u2
    self.u3 = u3

OncolyticVirusDendriticElement(label, visual=None, *, AU=60.0, AV=0.0, V=0.0, E=0.0, EN=0.0, D=0.0, r1=0.3198, alpha=0.00100854, a0=0.0, a1=5.954e-07, a2=1.0, r2=3500.0, du1=2.3, a3=1.6984, m=0.0, a4=4.6754, d1=0.35, a5=0.22, d2=0.35, du2=0.35, uv=2500000000.0, ud=1000000.0)

Bases: Element

Tumour cells, an oncolytic adenovirus, activated and naive T cells, and injected dendritic cells.

The uninfected cells grow at the rate r1 and the virus infects them at the rate alpha AU V / Atot, where Atot = AU + AV + E + EN. Activated T cells kill both kinds of tumour cells at the rate (a0 + a1 AV) E / Atot. Infected cells lyse at the rate a2 and release r2 virions each. The infected cells, the naive T cells, and the dendritic cells activate T cells.

The element holds the states and parameters and has no laws of its own: the interactions of oncolytic_virus_dendritic read its parameters.

Parameters:

Name Type Description Default
label str

The label of the tumour site.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
AU Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial uninfected tumour volume.

60.0
AV Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial infected tumour volume.

0.0
V Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of virions.

0.0
E Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of activated T cells.

0.0
EN Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of naive T cells.

0.0
D Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of dendritic cells.

0.0
r1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of uninfected cells.

0.3198
alpha Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The infection rate.

0.00100854
a0 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The kill rate of T cells that does not depend on the virus.

0.0
a1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The kill rate of T cells per infected cell.

5.954e-07
a2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The lysis rate of infected cells.

1.0
r2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The number of virions released per lysed cell.

3500.0
du1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The decay rate of virions.

2.3
a3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The activation rate of T cells by infected cells.

1.6984
m Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The activation rate of naive T cells.

0.0
a4 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The activation rate of T cells by dendritic cells.

4.6754
d1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of activated T cells.

0.35
a5 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The recruitment rate of naive T cells by infected cells.

0.22
d2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of naive T cells.

0.35
du2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The decay rate of dendritic cells.

0.35
uv Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The infusion rate of virions.

2500000000.0
ud Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The injection rate of dendritic cells.

1000000.0

Examples:

>>> from skcomplex.models.biology.oncology import OncolyticVirusDendriticElement
>>> OncolyticVirusDendriticElement('site').r2
3500.0
Source code in src/skcomplex/models/biology/oncology/_oncolytic_virus_dendritic.py
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    AU: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 60.0,
    AV: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    V: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    E: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    EN: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    D: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    r1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.3198,
    alpha: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.00100854,
    a0: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    a1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 5.954e-07,
    a2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    r2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 3500.0,
    du1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 2.3,
    a3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.6984,
    m: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    a4: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 4.6754,
    d1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.35,
    a5: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.22,
    d2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.35,
    du2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.35,
    uv: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 2500000000.0,
    ud: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1000000.0,
) -> None:
    super().__init__(label, visual=visual)
    self.AU = AU
    self.AV = AV
    self.V = V
    self.E = E
    self.EN = EN
    self.D = D
    self.r1 = r1
    self.alpha = alpha
    self.a0 = a0
    self.a1 = a1
    self.a2 = a2
    self.r2 = r2
    self.du1 = du1
    self.a3 = a3
    self.m = m
    self.a4 = a4
    self.d1 = d1
    self.a5 = a5
    self.d2 = d2
    self.du2 = du2
    self.uv = uv
    self.ud = ud

OncolyticVirusElement(label, visual=None, *, AU=0.1, AV=0.0001, alpha=1.0, r=0.5, d=0.5)

Bases: Element

Uninfected and infected tumour cells that share a carrying capacity, with infection by mass action.

In units of the carrying capacity and of the growth time of uninfected cells, the uninfected cells follow dAU/dt = AU (1 - AU - AV) - alpha AU AV and the infected cells dAV/dt = r AV (1 - AU - AV) + alpha AU AV - d AV.

The element holds the states and parameters and has no laws of its own: the interactions of oncolytic_virus read its parameters.

Parameters:

Name Type Description Default
label str

The label of the tumour.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
AU Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial uninfected tumour cells.

0.1
AV Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial infected tumour cells.

0.0001
alpha Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The infection rate.

1.0
r Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of infected cells.

0.5
d Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of infected cells.

0.5

Examples:

>>> from skcomplex.models.biology.oncology import OncolyticVirusElement
>>> OncolyticVirusElement('tumour').alpha
1.0
Source code in src/skcomplex/models/biology/oncology/_oncolytic_virus.py
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    AU: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.1,
    AV: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0001,
    alpha: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    r: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.5,
    d: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.5,
) -> None:
    super().__init__(label, visual=visual)
    self.AU = AU
    self.AV = AV
    self.alpha = alpha
    self.r = r
    self.d = d

OptimalChemotherapyElement(label, visual=None, *, E=0.15, A=0.25, N=1.0, U=0.0, s=0.33, rho=0.01, alpha=0.3, c1=1.0, c2=0.5, c3=1.0, c4=1.0, d1=0.2, r1=1.5, r2=1.0, b1=1.0, b2=1.0, a1=0.2, a2=0.3, a3=0.1, k=1.0, u=0.0, w=0.1)

Bases: TumourImmuneChemotherapyElement

Immune, tumour, and normal cells under a chemotherapy whose infusion rate is a bounded control input.

The cells and the drug follow the model of de Pillis and Radunskaya, TumourImmuneChemotherapyElement, with the infusion rate u between 0 and its largest dose. The oncologist minimises the tumour burden and the toxicity of the drug, ∫ (A + w u^2 / 2) dt + A(T), where the terminal term weighs the tumour left at the end of the treatment.

Parameters:

Name Type Description Default
label str

The label of the patient.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
E float

The initial immune cells.

0.15
A float

The initial tumour cells.

0.25
N float

The initial normal cells.

1.0
U float

The initial drug concentration.

0.0
s float

The influx of immune cells.

0.33
rho float

The immune response rate.

0.01
alpha float

The immune threshold.

0.3
c1 float

The rate at which the tumour inactivates immune cells.

1.0
c2 float

The rate at which immune cells kill the tumour.

0.5
c3 float

The rate at which normal cells compete with the tumour.

1.0
c4 float

The rate at which the tumour competes with normal cells.

1.0
d1 float

The death rate of immune cells.

0.2
r1 float

The growth rate of the tumour.

1.5
r2 float

The growth rate of normal cells.

1.0
b1 float

The reciprocal carrying capacity of the tumour.

1.0
b2 float

The reciprocal carrying capacity of normal cells.

1.0
a1 float

The fraction of immune cells the drug kills.

0.2
a2 float

The fraction of tumour cells the drug kills.

0.3
a3 float

The fraction of normal cells the drug kills.

0.1
k float

The decay rate of the drug, dU in the book.

1.0
u Annotated[float, ParameterSpec(adaptive=True, bounds=(0.0, MAX_DOSE))]

The infusion rate of the drug, the control input.

0.0
w Annotated[float, ParameterSpec(domain=open(0, oo))]

The weight of the squared infusion rate in the cost.

0.1

Examples:

>>> from skcomplex.models.biology.oncology import OptimalChemotherapyElement
>>> OptimalChemotherapyElement('patient', w=0.5).w
0.5
Source code in src/skcomplex/models/biology/oncology/_optimal_chemotherapy.py
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    E: float = 0.15,
    A: float = 0.25,
    N: float = 1.0,
    U: float = 0.0,
    s: float = 0.33,
    rho: float = 0.01,
    alpha: float = 0.3,
    c1: float = 1.0,
    c2: float = 0.5,
    c3: float = 1.0,
    c4: float = 1.0,
    d1: float = 0.2,
    r1: float = 1.5,
    r2: float = 1.0,
    b1: float = 1.0,
    b2: float = 1.0,
    a1: float = 0.2,
    a2: float = 0.3,
    a3: float = 0.1,
    k: float = 1.0,
    u: Annotated[float, ParameterSpec(adaptive=True, bounds=(0.0, MAX_DOSE))] = 0.0,
    w: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.1,
) -> None:
    super().__init__(
        label,
        visual=visual,
        E=E,
        A=A,
        N=N,
        U=U,
        s=s,
        rho=rho,
        alpha=alpha,
        c1=c1,
        c2=c2,
        c3=c3,
        c4=c4,
        d1=d1,
        r1=r1,
        r2=r2,
        b1=b1,
        b2=b2,
        a1=a1,
        a2=a2,
        a3=a3,
        k=k,
        u=u,
    )
    self.w = w

OptimalImmunotherapyElement(label, visual=None, *, x=0.1, y=1.0, z=0.0, u1=0.0, u2=0.0, alpha_a=0.005, d1=0.03, rho1=0.1245, r1=0.18, b=0.0001, c1=1.0, rho2=0.025, alpha3=0.01, du=10.0, a1=0.05, a2=3.5, w1=1.0, w2=1.0)

Bases: Element

Effector cells, tumour cells, and IL-2 under adoptive therapy and IL-2 injection at bounded rates.

The Kirschner-Panetta model in scaled units, with the effector and tumour cells in units of 10^5 and IL-2 in units of 2 10^7, follows x' = alpha_a y - d1 x + a1 u1 + rho1 x z / (1 + z) for the effector cells, y' = r1 y (1 - b y) - c1 x y / (1 + y) for the tumour, and z' = a2 u2 + rho2 x y / (alpha3 + y) - du z for IL-2. The adoptive therapy u1 and the IL-2 injection u2 are control inputs between 0 and 1, and the oncologist minimises ∫ (y + w1 u1^2 / 2 + w2 u2^2 / 2) dt + y(T).

The element holds the states and parameters and has no laws of its own: the interactions of optimal_immunotherapy read its parameters.

Parameters:

Name Type Description Default
label str

The label of the tumour site.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
x Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial effector cells.

0.1
y Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial tumour cells.

1.0
z Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial IL-2 concentration.

0.0
u1 Annotated[float, ParameterSpec(adaptive=True, bounds=(0.0, MAX_DOSE))]

The adoptive therapy rate, a control input.

0.0
u2 Annotated[float, ParameterSpec(adaptive=True, bounds=(0.0, MAX_DOSE))]

The IL-2 injection rate, a control input.

0.0
alpha_a Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The antigenicity of the tumour.

0.005
d1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of effector cells.

0.03
rho1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The proliferation rate of effector cells stimulated by IL-2.

0.1245
r1 Annotated[float, ParameterSpec(domain=open(0, oo))]

The growth rate of the tumour.

0.18
b Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The inverse carrying capacity of the tumour.

0.0001
c1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The kill rate of tumour cells by effector cells.

1.0
rho2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The IL-2 production rate by effector-tumour encounters.

0.025
alpha3 Annotated[float, ParameterSpec(domain=open(0, oo))]

The tumour at half the IL-2 production.

0.01
du Annotated[float, ParameterSpec(domain=open(0, oo))]

The loss rate of IL-2.

10.0
a1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The effector cells per unit of adoptive therapy.

0.05
a2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The IL-2 per unit of IL-2 injection.

3.5
w1 Annotated[float, ParameterSpec(domain=open(0, oo))]

The weight of the squared adoptive therapy rate in the cost.

1.0
w2 Annotated[float, ParameterSpec(domain=open(0, oo))]

The weight of the squared IL-2 injection rate in the cost.

1.0

Examples:

>>> from skcomplex.models.biology.oncology import OptimalImmunotherapyElement
>>> OptimalImmunotherapyElement('site').rho1
0.1245
Source code in src/skcomplex/models/biology/oncology/_optimal_immunotherapy.py
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    x: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.1,
    y: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    z: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    u1: Annotated[float, ParameterSpec(adaptive=True, bounds=(0.0, MAX_DOSE))] = 0.0,
    u2: Annotated[float, ParameterSpec(adaptive=True, bounds=(0.0, MAX_DOSE))] = 0.0,
    alpha_a: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.005,
    d1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.03,
    rho1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.1245,
    r1: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.18,
    b: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0001,
    c1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    rho2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.025,
    alpha3: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.01,
    du: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 10.0,
    a1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.05,
    a2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 3.5,
    w1: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1.0,
    w2: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1.0,
) -> None:
    super().__init__(label, visual=visual)
    self.x = x
    self.y = y
    self.z = z
    self.u1 = u1
    self.u2 = u2
    self.alpha_a = alpha_a
    self.d1 = d1
    self.rho1 = rho1
    self.r1 = r1
    self.b = b
    self.c1 = c1
    self.rho2 = rho2
    self.alpha3 = alpha3
    self.du = du
    self.a1 = a1
    self.a2 = a2
    self.w1 = w1
    self.w2 = w2

PiecewiseLinearProstateElement(label, visual=None, *, AD=17.84, AIR=0.778, AII=0.382, u=1.0, w11_on=-0.043844, w21_on=0.00130716, w22_on=-0.004282, w31_on=0.0, w32_on=0.0, w33_on=0.00181, w11_off=0.00223, w12_off=0.1, w22_off=0.00392, w33_off=-0.2, x1=1.0, x2=1.0, x3=1.0)

Bases: Element

Androgen-dependent, reversibly and irreversibly independent prostate cancer cells under intermittent therapy.

During therapy, u = 1, the cells follow dAD/dt = w11_on AD, dAIR/dt = w21_on AD + w22_on AIR, and dAII/dt = w31_on AD + w32_on AIR + w33_on AII. Off therapy they follow dAD/dt = w11_off AD + w12_off AIR, dAIR/dt = w22_off AIR, and dAII/dt = w33_off AII. Switches on the PSA x1 AD + x2 AIR + x3 AII set the therapy u.

Parameters:

Name Type Description Default
label str

The label of the tumour.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
AD Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial androgen-dependent cells.

17.84
AIR Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial reversibly independent cells.

0.778
AII Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial irreversibly independent cells.

0.382
u Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial therapy, 1 on and 0 off.

1.0
w11_on Annotated[float, ParameterSpec()]

The net growth rate of the dependent cells during therapy.

-0.043844
w21_on Annotated[float, ParameterSpec()]

The rate at which dependent cells adapt during therapy.

0.00130716
w22_on Annotated[float, ParameterSpec()]

The net growth rate of the adapted cells during therapy.

-0.004282
w31_on Annotated[float, ParameterSpec()]

The rate at which dependent cells mutate during therapy.

0.0
w32_on Annotated[float, ParameterSpec()]

The rate at which adapted cells mutate during therapy.

0.0
w33_on Annotated[float, ParameterSpec()]

The net growth rate of the mutated cells during therapy.

0.00181
w11_off Annotated[float, ParameterSpec()]

The net growth rate of the dependent cells off therapy.

0.00223
w12_off Annotated[float, ParameterSpec()]

The rate at which adapted cells return to dependence off therapy.

0.1
w22_off Annotated[float, ParameterSpec()]

The net growth rate of the adapted cells off therapy.

0.00392
w33_off Annotated[float, ParameterSpec()]

The net growth rate of the mutated cells off therapy.

-0.2
x1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The PSA per dependent cell.

1.0
x2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The PSA per adapted cell.

1.0
x3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The PSA per mutated cell.

1.0

Examples:

>>> from skcomplex.models.biology.oncology import PiecewiseLinearProstateElement
>>> PiecewiseLinearProstateElement('tumour').u
1.0
Source code in src/skcomplex/models/biology/oncology/_piecewise_linear_prostate.py
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    AD: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 17.84,
    AIR: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.778,
    AII: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.382,
    u: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    w11_on: Annotated[float, ParameterSpec()] = -0.043844,
    w21_on: Annotated[float, ParameterSpec()] = 0.00130716,
    w22_on: Annotated[float, ParameterSpec()] = -0.004282,
    w31_on: Annotated[float, ParameterSpec()] = 0.0,
    w32_on: Annotated[float, ParameterSpec()] = 0.0,
    w33_on: Annotated[float, ParameterSpec()] = 0.00181,
    w11_off: Annotated[float, ParameterSpec()] = 0.00223,
    w12_off: Annotated[float, ParameterSpec()] = 0.1,
    w22_off: Annotated[float, ParameterSpec()] = 0.00392,
    w33_off: Annotated[float, ParameterSpec()] = -0.2,
    x1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    x2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    x3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
) -> None:
    super().__init__(label, visual=visual)
    self.AD = AD
    self.AIR = AIR
    self.AII = AII
    self.u = u
    self.w11_on = w11_on
    self.w21_on = w21_on
    self.w22_on = w22_on
    self.w31_on = w31_on
    self.w32_on = w32_on
    self.w33_on = w33_on
    self.w11_off = w11_off
    self.w12_off = w12_off
    self.w22_off = w22_off
    self.w33_off = w33_off
    self.x1 = x1
    self.x2 = x2
    self.x3 = x3

RadiationCompetitionElement(label, visual=None, *, N=0.5, A=0.8, r1=0.008, r2=0.4, b1=1.0, b2=1.0, c1=0.01, c2=0.15, a2=0.2, epsilon=0.001, period=7.0, width=5.0)

Bases: Element

Normal and tumour cells in Lotka-Volterra competition under periodic irradiation.

The normal cells follow dN/dt = r1 N (1 - b1 N) - c1 N A - epsilon N and the tumour cells dA/dt = r2 A (1 - b2 A) - c2 N A - a2 D(t) A, where the irradiation D is 1 for width time units every period and 0 otherwise, and epsilon N is the radiation that spills over to the normal tissue.

The element holds the states and parameters and has no laws of its own: the interactions of radiotherapy_competition read its parameters.

Parameters:

Name Type Description Default
label str

The label of the tissue.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
N Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial concentration of normal cells.

0.5
A Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial concentration of tumour cells.

0.8
r1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of the normal cells.

0.008
r2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of the tumour cells.

0.4
b1 Annotated[float, ParameterSpec(domain=open(0, oo))]

The reciprocal carrying capacity of the normal cells.

1.0
b2 Annotated[float, ParameterSpec(domain=open(0, oo))]

The reciprocal carrying capacity of the tumour cells.

1.0
c1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which the tumour cells suppress the normal cells.

0.01
c2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which the normal cells suppress the tumour cells.

0.15
a2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The per capita rate at which the radiation kills tumour cells during an irradiation.

0.2
epsilon Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The per capita rate at which the spilled radiation kills normal cells.

0.001
period float

The time between the starts of irradiations.

7.0
width float

The duration of an irradiation.

5.0

Examples:

>>> from skcomplex.models.biology.oncology import RadiationCompetitionElement
>>> RadiationCompetitionElement('tissue', N=0.5, A=0.8).A
0.8
Source code in src/skcomplex/models/biology/oncology/_radiation_competition.py
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    N: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.5,
    A: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.8,
    r1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.008,
    r2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.4,
    b1: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1.0,
    b2: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1.0,
    c1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.01,
    c2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.15,
    a2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.2,
    epsilon: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.001,
    period: float = 7.0,
    width: float = 5.0,
) -> None:
    super().__init__(label, visual=visual)
    self.N = N
    self.A = A
    self.r1 = r1
    self.r2 = r2
    self.b1 = b1
    self.b2 = b2
    self.c1 = c1
    self.c2 = c2
    self.a2 = a2
    self.epsilon = epsilon
    self.period = period
    self.width = width

ResistanceSwitchingElement(label, visual=None, *, S=0.01, Rm=0.0, Rp=0.0, r1=1.0, r2=0.2, r3=0.2, b=1.0, m1=1e-06, m2=0.0, alpha_m=0.01, alpha_p=0.0, m5=0.0, a=1.0, am=0.0, ap=0.0, u=1.0)

Bases: Element

Sensitive cells and cells resistant by mutation or by a reversible phenotype switch, under a constant dose.

With the total V = S + Rm + Rp, the sensitive cells follow dS/dt = r1 (1 - b V) S - (m1 + m2) S - (alpha_m + alpha_p) u S - a u S + m5 Rp, the mutated cells dRm/dt = r2 (1 - b V) Rm + m1 S + alpha_m u S - am u Rm, and the switched cells dRp/dt = r3 (1 - b V) Rp + m2 S + alpha_p u S - m5 Rp - ap u Rp. The rates m1 and m2 are the spontaneous (acquired) resistance, alpha_m and alpha_p the resistance the drug induces, and m5 the resensitization of switched cells.

Parameters:

Name Type Description Default
label str

The label of the tumour.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
S Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial sensitive cells.

0.01
Rm Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial cells resistant by mutation.

0.0
Rp Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial cells resistant by phenotype switching.

0.0
r1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of sensitive cells.

1.0
r2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of mutated cells.

0.2
r3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of switched cells.

0.2
b Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The reciprocal carrying capacity of the tumour.

1.0
m1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate of spontaneous resistance by mutation.

1e-06
m2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate of spontaneous resistance by phenotype switching.

0.0
alpha_m Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate per unit of dose of resistance induced by mutation.

0.01
alpha_p Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate per unit of dose of resistance induced by phenotype switching.

0.0
m5 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which switched cells become sensitive again.

0.0
a Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The kill rate of sensitive cells per unit of dose.

1.0
am Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The kill rate of mutated cells per unit of dose.

0.0
ap Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The kill rate of switched cells per unit of dose.

0.0
u Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The effective dose.

1.0

Examples:

>>> from skcomplex.models.biology.oncology import ResistanceSwitchingElement
>>> ResistanceSwitchingElement('tumour').alpha_m
0.01
Source code in src/skcomplex/models/biology/oncology/_resistance_switching.py
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    S: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.01,
    Rm: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    Rp: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    r1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    r2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.2,
    r3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.2,
    b: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    m1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1e-06,
    m2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    alpha_m: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.01,
    alpha_p: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    m5: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    a: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    am: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    ap: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    u: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
) -> None:
    super().__init__(label, visual=visual)
    self.S = S
    self.Rm = Rm
    self.Rp = Rp
    self.r1 = r1
    self.r2 = r2
    self.r3 = r3
    self.b = b
    self.m1 = m1
    self.m2 = m2
    self.alpha_m = alpha_m
    self.alpha_p = alpha_p
    self.m5 = m5
    self.a = a
    self.am = am
    self.ap = ap
    self.u = u

RestingHuntingChemotherapyElement(label, visual=None, *, E=0.01, Q=0.48, A=0.18, U=0.0, m1=0.093, d1=0.0412, c1=0.005133, c2=1.6515, r1=0.0245, b1=1.5, r2=0.18, b2=3.0, a=0.001, bd=0.0001, g=0.1, k=0.2, tau=45.6, u=0.0)

Bases: Element

Hunting immune cells recruited from resting cells after a delay, a tumour, and a drug that kills all three.

The hunting cells follow dE/dt = m1 E Q(t - tau) - d1 E - c1 A E - a E / (bd + E) U, the resting cells dQ/dt = r1 Q (1 - b1 Q) - m1 E Q(t - tau) - a Q / (bd + Q) U, the tumour dA/dt = r2 A (1 - b2 A) - c2 A E - a A / (bd + A) U, and the drug dU/dt = u - (k + g (E / (bd + E) + Q / (bd + Q) + A / (bd + A))) U, which binds to the cells it kills. Before the start the resting cells keep their initial value.

The element holds the states and parameters and has no laws of its own: the interactions of delayed_resting_hunting_chemotherapy read its parameters.

Parameters:

Name Type Description Default
label str

The label of the patient.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
E Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial hunting cells.

0.01
Q Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial resting cells.

0.48
A Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial tumour cells.

0.18
U Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial drug concentration.

0.0
m1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which resting cells become hunting cells.

0.093
d1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of hunting cells.

0.0412
c1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which the tumour inactivates hunting cells.

0.005133
c2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which hunting cells kill the tumour.

1.6515
r1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of resting cells.

0.0245
b1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The reciprocal carrying capacity of resting cells.

1.5
r2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of the tumour.

0.18
b2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The reciprocal carrying capacity of the tumour.

3.0
a Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The kill rate of the drug on every population.

0.001
bd Annotated[float, ParameterSpec(domain=open(0, oo))]

The half saturation of the kill.

0.0001
g Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which the drug combines with every population.

0.1
k Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The elimination rate of the drug, dU in the book.

0.2
tau Annotated[float, ParameterSpec(domain=open(0, oo))]

The delay of the conversion of resting cells to hunting cells.

45.6
u Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The constant infusion rate of the drug.

0.0

Examples:

>>> from skcomplex.models.biology.oncology import RestingHuntingChemotherapyElement
>>> RestingHuntingChemotherapyElement('patient').tau
45.6
Source code in src/skcomplex/models/biology/oncology/_resting_hunting_chemotherapy.py
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    E: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.01,
    Q: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.48,
    A: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.18,
    U: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    m1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.093,
    d1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0412,
    c1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.005133,
    c2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.6515,
    r1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0245,
    b1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.5,
    r2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.18,
    b2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 3.0,
    a: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.001,
    bd: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.0001,
    g: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.1,
    k: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.2,
    tau: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 45.6,
    u: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
) -> None:
    super().__init__(label, visual=visual)
    self.E = E
    self.Q = Q
    self.A = A
    self.U = U
    self.m1 = m1
    self.d1 = d1
    self.c1 = c1
    self.c2 = c2
    self.r1 = r1
    self.b1 = b1
    self.r2 = r2
    self.b2 = b2
    self.a = a
    self.bd = bd
    self.g = g
    self.k = k
    self.tau = tau
    self.u = u

SirnaTgfBetaElement(label, visual=None, *, E=1000.0, A=1000.0, C1=0.0, C2=0.0, G=0.0, alpha=0.035, gamma1=10.0, d1=0.03, g1=20000000.0, rho1=0.1245, rmax=0.1121, g2=2000000.0, r1=0.18, b=1e-09, a1=1.0, g3=100000.0, rho2=0.27, g4=20000000.0, rho3=5.0, g5=1000.0, gamma2=0.001, d2=10.0, rho4=300000000.0, mu=1000000.0, psi=1.0, gamma3=1.0, d3=10.0, u=0.0, du=0.66)

Bases: Element

Effector cells, tumour cells, IL-2, TGF-beta, and the siRNA that silences the production of TGF-beta.

The model extends Kirschner and Panetta. TGF-beta lowers the recruitment and the IL-2 driven proliferation of effector cells and the production of IL-2, and raises the growth of the tumour. The siRNA, infused at the rate u, divides the production of TGF-beta by 1 + psi G^gamma3.

The element holds the states and parameters and has no laws of its own: the interactions of sirna_tgf_beta read its parameters.

Parameters:

Name Type Description Default
label str

The label of the tumour site.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
E Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of effector cells.

1000.0
A Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of tumour cells.

1000.0
C1 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial concentration of IL-2.

0.0
C2 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial concentration of TGF-beta.

0.0
G Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial amount of siRNA.

0.0
alpha Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The antigenicity of the tumour.

0.035
gamma1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The inhibition of the recruitment of effector cells by TGF-beta.

10.0
d1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of effector cells.

0.03
g1 Annotated[float, ParameterSpec(domain=open(0, oo))]

The half-saturation constant of the proliferation of effector cells by IL-2.

20000000.0
rho1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The proliferation rate of effector cells without TGF-beta.

0.1245
rmax Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The largest inhibition of that proliferation by TGF-beta.

0.1121
g2 Annotated[float, ParameterSpec(domain=open(0, oo))]

The half-saturation constant of that inhibition.

2000000.0
r1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of tumour cells.

0.18
b Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The reciprocal carrying capacity of tumour cells.

1e-09
a1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The kill rate of tumour cells by effector cells.

1.0
g3 Annotated[float, ParameterSpec(domain=open(0, oo))]

The half-saturation constant of the kill.

100000.0
rho2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The largest growth of tumour cells that TGF-beta adds.

0.27
g4 Annotated[float, ParameterSpec(domain=open(0, oo))]

The half-saturation constant of that growth.

20000000.0
rho3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The production rate of IL-2.

5.0
g5 Annotated[float, ParameterSpec(domain=open(0, oo))]

The half-saturation constant of the production of IL-2.

1000.0
gamma2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The inhibition of the production of IL-2 by TGF-beta.

0.001
d2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The decay rate of IL-2.

10.0
rho4 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The largest production rate of TGF-beta.

300000000.0
mu Annotated[float, ParameterSpec(domain=open(0, oo))]

The number of tumour cells at which the production of TGF-beta rises.

1000000.0
psi Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The fraction of the siRNA bound to the mRNA.

1.0
gamma3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The exponent of the suppression of the mRNA by the siRNA.

1.0
d3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The decay rate of TGF-beta.

10.0
u Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The infusion rate of siRNA.

0.0
du Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The decay rate of siRNA.

0.66

Examples:

>>> from skcomplex.models.biology.oncology import SirnaTgfBetaElement
>>> SirnaTgfBetaElement('site').rho4
300000000.0
Source code in src/skcomplex/models/biology/oncology/_sirna_tgf_beta.py
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    E: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 1000.0,
    A: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 1000.0,
    C1: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    C2: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    G: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    alpha: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.035,
    gamma1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 10.0,
    d1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.03,
    g1: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 20000000.0,
    rho1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.1245,
    rmax: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.1121,
    g2: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 2000000.0,
    r1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.18,
    b: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1e-09,
    a1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    g3: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 100000.0,
    rho2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.27,
    g4: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 20000000.0,
    rho3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 5.0,
    g5: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1000.0,
    gamma2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.001,
    d2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 10.0,
    rho4: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 300000000.0,
    mu: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1000000.0,
    psi: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    gamma3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    d3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 10.0,
    u: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    du: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.66,
) -> None:
    super().__init__(label, visual=visual)
    self.E = E
    self.A = A
    self.C1 = C1
    self.C2 = C2
    self.G = G
    self.alpha = alpha
    self.gamma1 = gamma1
    self.d1 = d1
    self.g1 = g1
    self.rho1 = rho1
    self.rmax = rmax
    self.g2 = g2
    self.r1 = r1
    self.b = b
    self.a1 = a1
    self.g3 = g3
    self.rho2 = rho2
    self.g4 = g4
    self.rho3 = rho3
    self.g5 = g5
    self.gamma2 = gamma2
    self.d2 = d2
    self.rho4 = rho4
    self.mu = mu
    self.psi = psi
    self.gamma3 = gamma3
    self.d3 = d3
    self.u = u
    self.du = du

SproutElement(label, visual=None, *, chemotaxis=30.0, branching=0.02, activation=0.01)

Bases: Element

Endothelial tip cell that climbs the VEGF gradient and leaves a new vessel segment behind it.

Every step the tip moves to a neighbouring cell with a probability that grows with exp(chemotaxis * VEGF / VEGF_here), so it senses the relative gradient, and it leaves a vessel segment where there was none. With probability branching the tip splits in two, the new tip standing where the tip was. Below the VEGF level activation the tip stays put. The model adds the vessel segment, the branching, and the step as member interactions.

Parameters:

Name Type Description Default
label str

The label of the agent or group.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
chemotaxis Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

How strongly VEGF draws the tip.

30.0
branching Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The probability per step of a new tip.

0.02
activation Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The VEGF above which the tip moves.

0.01

Examples:

>>> from skcomplex.core.elements import GroupElement
>>> from skcomplex.models.biology.oncology import SproutElement
>>> GroupElement('sprouts', element=SproutElement, size=2, location=(0, 5)).size
2
Source code in src/skcomplex/models/biology/oncology/_sprout.py
48
49
50
51
52
53
54
55
56
57
58
59
60
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    chemotaxis: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 30.0,
    branching: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.02,
    activation: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.01,
) -> None:
    super().__init__(label, visual=visual)
    self.chemotaxis = chemotaxis
    self.branching = branching
    self.activation = activation

StemCellDifferentiationElement(label, visual=None, *, NSq=100.0, NPr=1000.0, NBs=2000.0, ND=2000.0, ASq=5.0, APr=0.0, ABs=0.0, AD=0.0, d1=0.0001, d2=0.001, d3=0.01, d4=0.001, d5=0.001, d6=0.01, d7=0.01, d8=0.01, k12=0.5, k21=0.05, k23=0.5, k34=0.06, k56=0.1, k65=0.9, k67=0.3, k78=0.05, r1=0.1, r2=0.001, r3=0.001, r4=0.001, m1=0.005, NPinf=100.0, APinf=100.0, NPmax=10000.0, APmax=50000.0, Nbmax=10000.0, Abmax=5000.0, beta0=5.0, kappa0=2000.0, delta=1.0, up=30.0, uc=10.0, therapy='continuous', start=100.0, duration=100.0)

Bases: Element

Normal and malignant lineages of quiescent stem cells, progenitors, basal cells, and differentiated cells.

In each lineage the quiescent stem cells become progenitors at the rate k12 and progenitors return at the rate k21 (1 - NPr / (NPr + NPinf)). Progenitors renew logistically, become basal cells, and basal cells differentiate. The renewal of normal progenitors gets the feedback beta0 (1 - ND / (ND + kappa0)) of the differentiated cells. Normal progenitors mutate into malignant ones at the rate m1. A therapy multiplies the death rates of the progenitors and the basal cells by its dose, and that of the normal progenitors also by 1 + delta times their renewal rate. A pulsed therapy multiplies them by 4 more from start for duration.

The element holds the states and parameters and has no laws of its own: the interactions of stem_cell_differentiation read its parameters.

Parameters:

Name Type Description Default
label str

The label of the tissue.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
NSq Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial normal quiescent stem cells.

100.0
NPr Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial normal progenitors.

1000.0
NBs Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial normal basal cells.

2000.0
ND Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial normal differentiated cells.

2000.0
ASq Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial malignant quiescent stem cells.

5.0
APr Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial malignant progenitors.

0.0
ABs Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial malignant basal cells.

0.0
AD Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial malignant differentiated cells.

0.0
d1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of normal quiescent stem cells.

0.0001
d2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of normal progenitors.

0.001
d3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of normal basal cells.

0.01
d4 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of normal differentiated cells.

0.001
d5 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of malignant quiescent stem cells.

0.001
d6 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of malignant progenitors.

0.01
d7 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of malignant basal cells.

0.01
d8 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of malignant differentiated cells.

0.01
k12 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which normal quiescent stem cells become progenitors.

0.5
k21 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The largest rate at which normal progenitors return to quiescence.

0.05
k23 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which normal progenitors become basal cells.

0.5
k34 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which normal basal cells differentiate.

0.06
k56 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which malignant quiescent stem cells become progenitors.

0.1
k65 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The largest rate at which malignant progenitors return to quiescence.

0.9
k67 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which malignant progenitors become basal cells.

0.3
k78 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which malignant basal cells differentiate.

0.05
r1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The renewal rate of normal progenitors.

0.1
r2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The renewal rate of normal basal cells.

0.001
r3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The renewal rate of malignant progenitors.

0.001
r4 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The renewal rate of malignant basal cells.

0.001
m1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The mutation rate of normal progenitors.

0.005
NPinf Annotated[float, ParameterSpec(domain=open(0, oo))]

The saturation constant of the return of normal progenitors.

100.0
APinf Annotated[float, ParameterSpec(domain=open(0, oo))]

The saturation constant of the return of malignant progenitors.

100.0
NPmax Annotated[float, ParameterSpec(domain=open(0, oo))]

The largest number of normal progenitors.

10000.0
APmax Annotated[float, ParameterSpec(domain=open(0, oo))]

The largest number of malignant progenitors.

50000.0
Nbmax Annotated[float, ParameterSpec(domain=open(0, oo))]

The largest number of normal basal cells.

10000.0
Abmax Annotated[float, ParameterSpec(domain=open(0, oo))]

The largest number of malignant basal cells.

5000.0
beta0 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The feedback constant.

5.0
kappa0 Annotated[float, ParameterSpec(domain=open(0, oo))]

The number of differentiated cells that halves the feedback.

2000.0
delta Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The weight of the renewal in the death the therapy causes to normal progenitors.

1.0
up Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The dose of the pulsed therapy.

30.0
uc Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The dose of the continuous therapy.

10.0
therapy str

The mode of therapy, 'none', 'pulsed', or 'continuous'.

'continuous'
start float

The time the pulse of a pulsed therapy starts.

100.0
duration float

The duration of the pulse of a pulsed therapy.

100.0

Examples:

>>> from skcomplex.models.biology.oncology import StemCellDifferentiationElement
>>> StemCellDifferentiationElement('tissue', therapy='pulsed').therapy
'pulsed'
Source code in src/skcomplex/models/biology/oncology/_stem_cell_differentiation.py
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    NSq: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 100.0,
    NPr: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 1000.0,
    NBs: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 2000.0,
    ND: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 2000.0,
    ASq: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 5.0,
    APr: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    ABs: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    AD: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    d1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0001,
    d2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.001,
    d3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.01,
    d4: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.001,
    d5: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.001,
    d6: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.01,
    d7: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.01,
    d8: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.01,
    k12: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.5,
    k21: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.05,
    k23: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.5,
    k34: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.06,
    k56: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.1,
    k65: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.9,
    k67: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.3,
    k78: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.05,
    r1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.1,
    r2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.001,
    r3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.001,
    r4: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.001,
    m1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.005,
    NPinf: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 100.0,
    APinf: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 100.0,
    NPmax: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 10000.0,
    APmax: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 50000.0,
    Nbmax: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 10000.0,
    Abmax: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 5000.0,
    beta0: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 5.0,
    kappa0: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 2000.0,
    delta: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    up: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 30.0,
    uc: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 10.0,
    therapy: str = 'continuous',
    start: float = 100.0,
    duration: float = 100.0,
) -> None:
    super().__init__(label, visual=visual)
    self.NSq = NSq
    self.NPr = NPr
    self.NBs = NBs
    self.ND = ND
    self.ASq = ASq
    self.APr = APr
    self.ABs = ABs
    self.AD = AD
    self.d1 = d1
    self.d2 = d2
    self.d3 = d3
    self.d4 = d4
    self.d5 = d5
    self.d6 = d6
    self.d7 = d7
    self.d8 = d8
    self.k12 = k12
    self.k21 = k21
    self.k23 = k23
    self.k34 = k34
    self.k56 = k56
    self.k65 = k65
    self.k67 = k67
    self.k78 = k78
    self.r1 = r1
    self.r2 = r2
    self.r3 = r3
    self.r4 = r4
    self.m1 = m1
    self.NPinf = NPinf
    self.APinf = APinf
    self.NPmax = NPmax
    self.APmax = APmax
    self.Nbmax = Nbmax
    self.Abmax = Abmax
    self.beta0 = beta0
    self.kappa0 = kappa0
    self.delta = delta
    self.up = up
    self.uc = uc
    self.therapy = therapy
    self.start = start
    self.duration = duration

SuppressedTumourElement(label, visual=None, *, A=1.0, EUD=1e-05, ED=1e-05, EPC=1e-05, E=1e-05, EPH=1e-05, EH=1e-05, EPR=1e-05, ER=1e-05, C1=0.0, C2=0.0, C3=0.0, r1=0.333, r2=333.0, n=0.5, p=3.0, q=2 / 3, a1=0.9, g1=1.2, g2=11.0, g3=100.0, C3_50=3.5, alpha_a=1.0, C2_50=0.4, ER_50=20000000.0, lambda_a=0.5, d1=0.14, d2=0.5, a2=23.0, g4=0.33, d3=0.2, a3=16.0, EC1_50=0.3, EC3_50=2.9, d4=1.0, a4=9.9, d5=0.2, a5=1.9, a6=0.022, g5=1.7, d6=0.1, a7=5.1, d7=0.2, a8=2.1, d8=0.1, a9=1.7e-05, CC2_50=0.75, CC3_50=0.9, tau1=0.08, r3=1.4e-08, r4=1.3e-10, tau2=0.05, r5=1.8e-08, r6=1.1e-07, tau3=0.07, EMC=10000.0, EMH=10000.0, EMR=10000.0)

Bases: Element

Tumour, dendritic cells, proliferating and active T cells, IL-2, IL-10, and TGF-beta.

The equations are those of Padmanabhan et al. (4.22) to (4.33). The tumour grows by the smooth minimum A / ((1 / r1)^p + (A^(1 - n) / r2)^p)^(1/p) of exponential and power growth and is killed through its fraction A* = A / (1 + (A^(1 - q) / g3)^p)^(1/p) accessible to the cytotoxic T cells E, at the rate a1 A* E / (E + A* / g1 + ER / g2) / (1 + C3 / C3_50). Antigen matures unlicensed dendritic cells, which helper memory cells license, and dendritic cells recruit the memory pools EMC, EMH, and EMR into proliferating cytotoxic, helper, and regulatory cells, which IL-2 matures. IL-10 and TGF-beta, from regulatory and tumour cells, suppress maturation, IL-2 production, and killing, and TGF-beta converts helper into regulatory cells.

The element holds the states and parameters and has no laws of its own: the interactions of tumour_immune_suppression read its parameters.

Parameters:

Name Type Description Default
label str

The label of the tumour site.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
A Annotated[float, StateSpec(domain=open(0, oo))]

The initial tumour cells.

1.0
EUD Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial unlicensed dendritic cells.

1e-05
ED Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial licensed dendritic cells.

1e-05
EPC Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial proliferating cytotoxic T cells.

1e-05
E Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial active cytotoxic T cells.

1e-05
EPH Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial proliferating helper T cells.

1e-05
EH Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial active helper T cells.

1e-05
EPR Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial proliferating regulatory T cells.

1e-05
ER Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial active regulatory T cells.

1e-05
C1 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial IL-2 concentration.

0.0
C2 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial IL-10 concentration.

0.0
C3 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial TGF-beta concentration.

0.0
r1 Annotated[float, ParameterSpec(domain=open(0, oo))]

The exponential growth rate of the tumour.

0.333
r2 Annotated[float, ParameterSpec(domain=open(0, oo))]

The power growth coefficient of the tumour.

333.0
n Annotated[float, ParameterSpec(domain=open(0, oo))]

The exponent of the power growth.

0.5
p Annotated[float, ParameterSpec(domain=open(0, oo))]

The smoothness of the transitions.

3.0
q Annotated[float, ParameterSpec(domain=open(0, oo))]

The exponent of the accessible fraction of a large tumour.

2 / 3
a1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The maximal kill rate of tumour cells.

0.9
g1 Annotated[float, ParameterSpec(domain=open(0, oo))]

The ratio of tumour to cytotoxic cells at half kill.

1.2
g2 Annotated[float, ParameterSpec(domain=open(0, oo))]

The ratio of regulatory to cytotoxic cells at half kill.

11.0
g3 Annotated[float, ParameterSpec(domain=open(0, oo))]

The size scale of the accessible fraction.

100.0
C3_50 Annotated[float, ParameterSpec(domain=open(0, oo))]

The TGF-beta at half kill.

3.5
alpha_a Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The antigenicity of the tumour.

1.0
C2_50 Annotated[float, ParameterSpec(domain=open(0, oo))]

The IL-10 at half dendritic maturation.

0.4
ER_50 Annotated[float, ParameterSpec(domain=open(0, oo))]

The regulatory cells at half dendritic maturation.

20000000.0
lambda_a Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The licensing rate of dendritic cells.

0.5
d1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of unlicensed dendritic cells.

0.14
d2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of licensed dendritic cells.

0.5
a2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The recruitment rate of proliferating cytotoxic cells.

23.0
g4 Annotated[float, ParameterSpec(domain=open(0, oo))]

The steepness of the recruitment by dendritic cells.

0.33
d3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of proliferating cytotoxic cells.

0.2
a3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The maturation rate of cytotoxic cells.

16.0
EC1_50 Annotated[float, ParameterSpec(domain=open(0, oo))]

The IL-2 at half maturation.

0.3
EC3_50 Annotated[float, ParameterSpec(domain=open(0, oo))]

The TGF-beta at half maturation.

2.9
d4 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of active cytotoxic cells.

1.0
a4 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The recruitment rate of proliferating helper cells.

9.9
d5 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of proliferating helper cells.

0.2
a5 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The maturation rate of helper cells.

1.9
a6 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The conversion rate of helper into regulatory cells.

0.022
g5 Annotated[float, ParameterSpec(domain=open(0, oo))]

The TGF-beta at half conversion.

1.7
d6 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of active helper cells.

0.1
a7 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The recruitment rate of proliferating regulatory cells.

5.1
d7 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of proliferating regulatory cells.

0.2
a8 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The maturation rate of regulatory cells.

2.1
d8 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of active regulatory cells.

0.1
a9 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The IL-2 production by helper cells.

1.7e-05
CC2_50 Annotated[float, ParameterSpec(domain=open(0, oo))]

The IL-10 at half suppression of IL-2.

0.75
CC3_50 Annotated[float, ParameterSpec(domain=open(0, oo))]

The TGF-beta at half suppression of IL-2.

0.9
tau1 Annotated[float, ParameterSpec(domain=open(0, oo))]

The lifetime of IL-2.

0.08
r3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The IL-10 production by regulatory cells.

1.4e-08
r4 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The IL-10 production by tumour cells.

1.3e-10
tau2 Annotated[float, ParameterSpec(domain=open(0, oo))]

The lifetime of IL-10.

0.05
r5 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The TGF-beta production by regulatory cells.

1.8e-08
r6 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The TGF-beta production by tumour cells.

1.1e-07
tau3 Annotated[float, ParameterSpec(domain=open(0, oo))]

The lifetime of TGF-beta.

0.07
EMC Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The memory cytotoxic T cells.

10000.0
EMH Annotated[float, ParameterSpec(domain=open(0, oo))]

The memory helper T cells.

10000.0
EMR Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The memory regulatory T cells.

10000.0

Examples:

>>> from skcomplex.models.biology.oncology import SuppressedTumourElement
>>> SuppressedTumourElement('site').lambda_a
0.5
Source code in src/skcomplex/models/biology/oncology/_suppressed_tumour.py
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    A: Annotated[float, StateSpec(domain=RealSet.open(0, oo))] = 1.0,
    EUD: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 1e-05,
    ED: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 1e-05,
    EPC: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 1e-05,
    E: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 1e-05,
    EPH: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 1e-05,
    EH: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 1e-05,
    EPR: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 1e-05,
    ER: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 1e-05,
    C1: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    C2: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    C3: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    r1: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.333,
    r2: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 333.0,
    n: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.5,
    p: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 3.0,
    q: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 2 / 3,
    a1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.9,
    g1: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1.2,
    g2: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 11.0,
    g3: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 100.0,
    C3_50: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 3.5,
    alpha_a: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    C2_50: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.4,
    ER_50: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 20000000.0,
    lambda_a: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.5,
    d1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.14,
    d2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.5,
    a2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 23.0,
    g4: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.33,
    d3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.2,
    a3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 16.0,
    EC1_50: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.3,
    EC3_50: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 2.9,
    d4: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    a4: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 9.9,
    d5: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.2,
    a5: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.9,
    a6: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.022,
    g5: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1.7,
    d6: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.1,
    a7: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 5.1,
    d7: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.2,
    a8: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 2.1,
    d8: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.1,
    a9: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.7e-05,
    CC2_50: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.75,
    CC3_50: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.9,
    tau1: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.08,
    r3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.4e-08,
    r4: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.3e-10,
    tau2: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.05,
    r5: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.8e-08,
    r6: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.1e-07,
    tau3: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.07,
    EMC: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 10000.0,
    EMH: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 10000.0,
    EMR: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 10000.0,
) -> None:
    super().__init__(label, visual=visual)
    self.A = A
    self.EUD = EUD
    self.ED = ED
    self.EPC = EPC
    self.E = E
    self.EPH = EPH
    self.EH = EH
    self.EPR = EPR
    self.ER = ER
    self.C1 = C1
    self.C2 = C2
    self.C3 = C3
    self.r1 = r1
    self.r2 = r2
    self.n = n
    self.p = p
    self.q = q
    self.a1 = a1
    self.g1 = g1
    self.g2 = g2
    self.g3 = g3
    self.C3_50 = C3_50
    self.alpha_a = alpha_a
    self.C2_50 = C2_50
    self.ER_50 = ER_50
    self.lambda_a = lambda_a
    self.d1 = d1
    self.d2 = d2
    self.a2 = a2
    self.g4 = g4
    self.d3 = d3
    self.a3 = a3
    self.EC1_50 = EC1_50
    self.EC3_50 = EC3_50
    self.d4 = d4
    self.a4 = a4
    self.d5 = d5
    self.a5 = a5
    self.a6 = a6
    self.g5 = g5
    self.d6 = d6
    self.a7 = a7
    self.d7 = d7
    self.a8 = a8
    self.d8 = d8
    self.a9 = a9
    self.CC2_50 = CC2_50
    self.CC3_50 = CC3_50
    self.tau1 = tau1
    self.r3 = r3
    self.r4 = r4
    self.tau2 = tau2
    self.r5 = r5
    self.r6 = r6
    self.tau3 = tau3
    self.EMC = EMC
    self.EMH = EMH
    self.EMR = EMR

TamoxifenTumourElement(label, visual=None, *, Ag=900.0, As=50.0, Am=50.0, X0=0.0, X1=0.0, X2=0.0, X3=0.0, E=10.0, mg=0.0013, ms=0.039, mm=0.0169, Asat=10000.0, a1=0.0062, a2=0.01, delta1=25.0, delta2=25.0, k01=0.048, k12=0.993, k23=35.932, du1=1.145, du2=39.525, V=8.592, s=0.121, d1=0.012, u=12.5)

Bases: Element

Breast tumour in three Gompertzian cell-cycle phases under tamoxifen, its metabolite, and the lymphocytes.

The phases follow dAg/dt = -mg Ag L + 2 mm Am L - a1 Ag (UX + delta1 UH), dAs/dt = -ms As + mg Ag L, and dAm/dt = -mm Am L + ms As, with L = log(Asat / (Ag + As + Am)). Tamoxifen passes from the gut X0 through X1 to the plasma X2, dX0/dt = -k01 X0 + u(t), dX1/dt = k01 X0 - k12 X1, dX2/dt = k12 X1 - (du1 + k23) X2, and the plasma turns it into 4-hydroxytamoxifen, dX3/dt = k23 X2 - du2 X3, with the concentrations UX = X2 / V and UH = X3 / V. The lymphocytes follow dE/dt = s - d1 E - a2 E (UX + delta2 UH), and tamoxifen enters the gut at the constant rate u.

The element holds the states and parameters and has no laws of its own: the interactions of tamoxifen_cell_cycle read its parameters.

Parameters:

Name Type Description Default
label str

The label of the tumour.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
Ag Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial volume of cells in the growth phase.

900.0
As Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial volume of cells in the synthesis phase.

50.0
Am Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial volume of cells in mitosis.

50.0
X0 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial tamoxifen in the gut.

0.0
X1 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial tamoxifen in the second compartment.

0.0
X2 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial tamoxifen in the plasma.

0.0
X3 Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial 4-hydroxytamoxifen.

0.0
E Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial circulating lymphocytes, in millions.

10.0
mg Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The transit rate out of the growth phase.

0.0013
ms Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The transit rate out of the synthesis phase.

0.039
mm Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The transit rate out of mitosis.

0.0169
Asat Annotated[float, ParameterSpec(domain=open(0, oo))]

The volume at which growth saturates.

10000.0
a1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The kill rate of the tumour per unit of drug.

0.0062
a2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The kill rate of the lymphocytes per unit of drug.

0.01
delta1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The tumour kill of the metabolite relative to tamoxifen.

25.0
delta2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The lymphocyte kill of the metabolite relative to tamoxifen.

25.0
k01 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The transfer rate from the gut.

0.048
k12 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The transfer rate to the plasma.

0.993
k23 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which the plasma metabolizes tamoxifen.

35.932
du1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The elimination rate of tamoxifen.

1.145
du2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The elimination rate of the metabolite.

39.525
V Annotated[float, ParameterSpec(domain=open(0, oo))]

The volume of distribution.

8.592
s Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The influx of lymphocytes, in millions per unit of time.

0.121
d1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of lymphocytes.

0.012
u Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The infusion rate of tamoxifen.

12.5

Examples:

>>> from skcomplex.models.biology.oncology import TamoxifenTumourElement
>>> TamoxifenTumourElement('tumour').Asat
10000.0
Source code in src/skcomplex/models/biology/oncology/_tamoxifen_tumour.py
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    Ag: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 900.0,
    As: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 50.0,
    Am: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 50.0,
    X0: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    X1: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    X2: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    X3: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    E: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 10.0,
    mg: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0013,
    ms: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.039,
    mm: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0169,
    Asat: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 10000.0,
    a1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0062,
    a2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.01,
    delta1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 25.0,
    delta2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 25.0,
    k01: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.048,
    k12: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.993,
    k23: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 35.932,
    du1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.145,
    du2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 39.525,
    V: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 8.592,
    s: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.121,
    d1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.012,
    u: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 12.5,
) -> None:
    super().__init__(label, visual=visual)
    self.Ag = Ag
    self.As = As
    self.Am = Am
    self.X0 = X0
    self.X1 = X1
    self.X2 = X2
    self.X3 = X3
    self.E = E
    self.mg = mg
    self.ms = ms
    self.mm = mm
    self.Asat = Asat
    self.a1 = a1
    self.a2 = a2
    self.delta1 = delta1
    self.delta2 = delta2
    self.k01 = k01
    self.k12 = k12
    self.k23 = k23
    self.du1 = du1
    self.du2 = du2
    self.V = V
    self.s = s
    self.d1 = d1
    self.u = u

TcrGeneTherapyElement(label, visual=None, *, E=1000.0, A=1000.0, s=1.0, alpha=0.05, d1=0.03, r1=0.1245, g1=0.001, r2=0.18, b=1e-09, a=1.0, g2=100000.0)

Bases: Element

Effector cells and tumour cells under a gene therapy that makes the T cells express a tumour receptor.

The effector cells follow dE/dt = s + alpha A - d1 E + r1 E / (E + g1) and the tumour cells dA/dt = r2 A (1 - b A) - a E A / (A + g2), a predator-prey model of the immune attack.

The element holds the states and parameters and has no laws of its own: the interactions of tcr_gene_therapy read its parameters.

Parameters:

Name Type Description Default
label str

The label of the tumour site.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
E Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of effector cells.

1000.0
A Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of tumour cells.

1000.0
s Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The influx rate of effector cells.

1.0
alpha Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The antigenicity of the tumour.

0.05
d1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of effector cells.

0.03
r1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The proliferation rate of effector cells.

0.1245
g1 Annotated[float, ParameterSpec(domain=open(0, oo))]

The half-saturation constant of the proliferation of effector cells.

0.001
r2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of tumour cells.

0.18
b Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The reciprocal carrying capacity of tumour cells.

1e-09
a Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The kill rate that the therapy gives the effector cells.

1.0
g2 Annotated[float, ParameterSpec(domain=open(0, oo))]

The half-saturation constant of the kill.

100000.0

Examples:

>>> from skcomplex.models.biology.oncology import TcrGeneTherapyElement
>>> TcrGeneTherapyElement('site').r2
0.18
Source code in src/skcomplex/models/biology/oncology/_tcr_gene_therapy.py
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    E: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 1000.0,
    A: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 1000.0,
    s: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    alpha: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.05,
    d1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.03,
    r1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.1245,
    g1: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.001,
    r2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.18,
    b: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1e-09,
    a: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    g2: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 100000.0,
) -> None:
    super().__init__(label, visual=visual)
    self.E = E
    self.A = A
    self.s = s
    self.alpha = alpha
    self.d1 = d1
    self.r1 = r1
    self.g1 = g1
    self.r2 = r2
    self.b = b
    self.a = a
    self.g2 = g2

TherapySwitchInteraction(label, *, target, signal, threshold=0.0, value=1.0, state='u', direction=1)

Bases: CrossingInteraction

Switch that sets the therapy state of a tumour to a value when a signal crosses a threshold in a direction.

A pair of switches, one that sets the therapy to 1 when the signal rises through a high threshold and one that sets it to 0 when the signal falls through a low one, is the relay with hysteresis of intermittent therapy. Every switch is an event labelled by the interaction.

Parameters:

Name Type Description Default
label str

The label of the interaction and of its events.

required
target Annotated[str, RoleSpec()]

The path of the tumour.

required
signal Callable[[SimpleNamespace], object]

A function of the namespace that returns the signal, such as the PSA of the tumour.

required
threshold Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The value of the signal at the switch.

0.0
value float

The value of the therapy state after the switch.

1.0
state str

The name of the therapy state.

'u'
direction int

The direction of the crossing, 1 for a rising and -1 for a falling signal.

1

Raises:

Type Description
ValidationError

The direction is not -1, 0, or 1, or the signal is not a function.

Examples:

>>> from skcomplex.models.biology.oncology import TherapySwitchInteraction
>>> switch = TherapySwitchInteraction('on', target='tumour', signal=lambda s: s.target.AD, threshold=15.0)
>>> switch.check().threshold
15.0
Source code in src/skcomplex/models/biology/oncology/_therapy_switch.py
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
def __init__(
    self,
    label: str,
    *,
    target: Annotated[str, RoleSpec()],
    signal: Callable[[SimpleNamespace], object],
    threshold: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    value: float = 1.0,
    state: str = 'u',
    direction: int = 1,
) -> None:
    super().__init__(
        label,
        target=target,
        guard=self._get_guard,
        reset={state: self._get_value},
        direction=direction,
    )
    self.signal = signal
    self.threshold = threshold
    self.value = value
    self.state = state

TissueElement(label, visual=None, *, oxygen=0.0, vegf=0.0, D_oxygen=1.0, decay_oxygen=0.05, D_vegf=1.0, decay_vegf=0.005)

Bases: Element

Tissue in which oxygen and the vascular endothelial growth factor VEGF diffuse and decay.

Both follow u' = D Δu - lambda u, and cells add or remove amounts at their sites: vessels supply oxygen, tumour cells consume it, and hypoxic tumour cells secrete VEGF. The model adds the diffusion and the decay as interactions.

Parameters:

Name Type Description Default
label str

The label of the tissue or the lattice field.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
oxygen Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial oxygen.

0.0
vegf Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial VEGF.

0.0
D_oxygen Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The diffusion of oxygen.

1.0
decay_oxygen Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The decay rate of oxygen.

0.05
D_vegf Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The diffusion of VEGF.

1.0
decay_vegf Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The decay rate of VEGF.

0.005

Examples:

>>> from skcomplex.models.biology.oncology import TissueElement
>>> TissueElement('tissue').D_vegf
1.0
Source code in src/skcomplex/models/biology/oncology/_tissue.py
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    oxygen: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    vegf: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    D_oxygen: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    decay_oxygen: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.05,
    D_vegf: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    decay_vegf: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.005,
) -> None:
    super().__init__(label, visual=visual)
    self.oxygen = oxygen
    self.vegf = vegf
    self.D_oxygen = D_oxygen
    self.decay_oxygen = decay_oxygen
    self.D_vegf = D_vegf
    self.decay_vegf = decay_vegf

TumourCellElement(label, visual=VisualSpec('agents', {'color_by': 'hypoxic', 'color_range': (0.0, 1.0)}), *, hypoxic=0.0, consumption=0.1, proliferation=1.0, division=0.2, hypoxia=0.5, secretion=1.0, necrosis=0.0)

Bases: Element

Tumour cell that consumes oxygen, divides when supplied, secretes VEGF when hypoxic, and dies without oxygen.

Every step the cell takes up consumption oxygen at its site, or what is left. Above proliferation it divides with probability division into a free neighbouring cell. Below hypoxia it secretes secretion VEGF, and below necrosis it dies. The model adds the uptake, the hypoxia, the secretion, and the life cycle as member interactions.

Parameters:

Name Type Description Default
label str

The label of the agent or group.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

VisualSpec('agents', {'color_by': 'hypoxic', 'color_range': (0.0, 1.0)})
hypoxic Annotated[float, StateSpec(domain=FiniteEnumeratedSet([0, 1]))]

Whether the cell is hypoxic, 1, or not, 0.

0.0
consumption Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The oxygen a cell takes up per step.

0.1
proliferation Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The oxygen above which a cell divides.

1.0
division Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The probability per step of a division.

0.2
hypoxia Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The oxygen below which a cell secretes VEGF.

0.5
secretion Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The VEGF a hypoxic cell secretes per step.

1.0
necrosis Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The oxygen below which a cell dies.

0.0

Examples:

>>> from skcomplex.core.elements import GroupElement
>>> from skcomplex.models.biology.oncology import TumourCellElement
>>> GroupElement('tumour', element=TumourCellElement, size=3, location=(5, 5)).size
3
Source code in src/skcomplex/models/biology/oncology/_tumour_cell.py
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = VisualSpec('agents', {'color_by': 'hypoxic', 'color_range': (0.0, 1.0)}),
    *,
    hypoxic: Annotated[float, StateSpec(domain=FiniteEnumeratedSet([0, 1]))] = 0.0,
    consumption: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.1,
    proliferation: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    division: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.2,
    hypoxia: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.5,
    secretion: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    necrosis: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
) -> None:
    super().__init__(label, visual=visual)
    self.hypoxic = hypoxic
    self.consumption = consumption
    self.proliferation = proliferation
    self.division = division
    self.hypoxia = hypoxia
    self.secretion = secretion
    self.necrosis = necrosis

TumourImmuneChemotherapyElement(label, visual=None, *, E=0.15, A=0.25, N=1.0, U=0.0, s=0.33, rho=0.01, alpha=0.3, c1=1.0, c2=0.5, c3=1.0, c4=1.0, d1=0.2, r1=1.5, r2=1.0, b1=1.0, b2=1.0, a1=0.2, a2=0.3, a3=0.1, k=1.0, u=0.0)

Bases: Element

Immune, tumour, and normal cells that compete and that a drug kills, after de Pillis and Radunskaya.

The immune cells follow dE/dt = s + rho E A / (alpha + A) - d1 E - c1 E A - a1 (1 - exp(-U)) E, the tumour dA/dt = r1 A (1 - b1 A) - c2 E A - c3 N A - a2 (1 - exp(-U)) A, the normal cells dN/dt = r2 N (1 - b2 N) - c4 N A - a3 (1 - exp(-U)) N, and the drug dU/dt = u - k U under a constant infusion u.

Parameters:

Name Type Description Default
label str

The label of the patient.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
E Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial immune cells.

0.15
A Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial tumour cells.

0.25
N Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial normal cells.

1.0
U Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial drug concentration.

0.0
s Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The influx of immune cells.

0.33
rho Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The immune response rate.

0.01
alpha Annotated[float, ParameterSpec(domain=open(0, oo))]

The immune threshold.

0.3
c1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which the tumour inactivates immune cells.

1.0
c2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which immune cells kill the tumour.

0.5
c3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which normal cells compete with the tumour.

1.0
c4 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which the tumour competes with normal cells.

1.0
d1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of immune cells.

0.2
r1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of the tumour.

1.5
r2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of normal cells.

1.0
b1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The reciprocal carrying capacity of the tumour.

1.0
b2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The reciprocal carrying capacity of normal cells.

1.0
a1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The fraction of immune cells the drug kills.

0.2
a2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The fraction of tumour cells the drug kills.

0.3
a3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The fraction of normal cells the drug kills.

0.1
k Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The decay rate of the drug, dU in the book.

1.0
u Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The constant infusion rate of the drug.

0.0

Examples:

>>> from skcomplex.models.biology.oncology import TumourImmuneChemotherapyElement
>>> TumourImmuneChemotherapyElement('patient', u=1.0).u
1.0
Source code in src/skcomplex/models/biology/oncology/_tumour_immune_chemotherapy.py
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    E: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.15,
    A: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.25,
    N: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    U: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    s: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.33,
    rho: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.01,
    alpha: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.3,
    c1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    c2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.5,
    c3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    c4: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    d1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.2,
    r1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.5,
    r2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    b1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    b2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    a1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.2,
    a2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.3,
    a3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.1,
    k: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    u: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
) -> None:
    super().__init__(label, visual=visual)
    self.E = E
    self.A = A
    self.N = N
    self.U = U
    self.s = s
    self.rho = rho
    self.alpha = alpha
    self.c1 = c1
    self.c2 = c2
    self.c3 = c3
    self.c4 = c4
    self.d1 = d1
    self.r1 = r1
    self.r2 = r2
    self.b1 = b1
    self.b2 = b2
    self.a1 = a1
    self.a2 = a2
    self.a3 = a3
    self.k = k
    self.u = u

VaccinatedTumourElement(label, visual=None, *, EH=0.02, E=0.02, A=0.1, ED=0.0, C=0.0, s1=0.0001, s2=0.0001, rho1=10.0, rho2=10.0, r1=0.01, r2=0.01, r3=0.02, r4=0.01, b1=1.0, b2=1.0, b3=1.0, d1=0.005, d2=0.005, d3=0.01, c1=0.1, c2=0.1, c3=1e-07, dose=0.5, period=168.0, width=1.0, start=0.0, doses=8)

Bases: Element

Helper T cells, cytotoxic T cells, tumour cells, dendritic cells, and IL-2 under dendritic-cell vaccination.

The helper cells follow dEH/dt = s1 + rho1 ED r1 EH (1 - b1 EH) - d1 EH, the cytotoxic cells dE/dt = s2 + rho2 C (A + ED) r2 E (1 - b2 E) - d2 E, the tumour dA/dt = r3 A (1 - b3 A) - c1 A E, the dendritic cells dED/dt = -c2 E ED + u(t), and the IL-2 dC/dt = r4 EH ED - c3 E C - d3 C. The vaccine u is dose for width time units every period from start, doses times.

The element holds the states and parameters and has no laws of its own: the interactions of dendritic_cell_vaccine read its parameters.

Parameters:

Name Type Description Default
label str

The label of the tumour site.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
EH Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial helper T cells.

0.02
E Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial cytotoxic T cells.

0.02
A Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial tumour cells.

0.1
ED Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial dendritic cells.

0.0
C Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial IL-2 concentration.

0.0
s1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The influx of helper T cells.

0.0001
s2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The influx of cytotoxic T cells.

0.0001
rho1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The proliferation constant of helper T cells.

10.0
rho2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The proliferation constant of cytotoxic T cells.

10.0
r1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of helper T cells.

0.01
r2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The growth rate of cytotoxic T cells.

0.01
r3 Annotated[float, ParameterSpec(domain=open(0, oo))]

The growth rate of the tumour.

0.02
r4 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The IL-2 secretion rate.

0.01
b1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The inverse capacity of helper T cells.

1.0
b2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The inverse capacity of cytotoxic T cells.

1.0
b3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The inverse capacity of the tumour.

1.0
d1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of helper T cells.

0.005
d2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The death rate of cytotoxic T cells.

0.005
d3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The degradation rate of IL-2.

0.01
c1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The kill rate of tumour cells by cytotoxic T cells.

0.1
c2 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The kill rate of dendritic cells by cytotoxic T cells.

0.1
c3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The consumption rate of IL-2 by cytotoxic T cells.

1e-07
dose Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The injection rate of dendritic cells during a dose.

0.5
period float

The time between the starts of doses.

168.0
width float

The duration of a dose.

1.0
start float

The time of the first dose.

0.0
doses int

The number of doses.

8

Examples:

>>> from skcomplex.models.biology.oncology import VaccinatedTumourElement
>>> VaccinatedTumourElement('site').r3
0.02
Source code in src/skcomplex/models/biology/oncology/_vaccinated_tumour.py
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    EH: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.02,
    E: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.02,
    A: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.1,
    ED: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    C: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    s1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0001,
    s2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.0001,
    rho1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 10.0,
    rho2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 10.0,
    r1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.01,
    r2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.01,
    r3: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.02,
    r4: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.01,
    b1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    b2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    b3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    d1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.005,
    d2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.005,
    d3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.01,
    c1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.1,
    c2: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.1,
    c3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1e-07,
    dose: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.5,
    period: float = 168.0,
    width: float = 1.0,
    start: float = 0.0,
    doses: int = 8,
) -> None:
    super().__init__(label, visual=visual)
    self.EH = EH
    self.E = E
    self.A = A
    self.ED = ED
    self.C = C
    self.s1 = s1
    self.s2 = s2
    self.rho1 = rho1
    self.rho2 = rho2
    self.r1 = r1
    self.r2 = r2
    self.r3 = r3
    self.r4 = r4
    self.b1 = b1
    self.b2 = b2
    self.b3 = b3
    self.d1 = d1
    self.d2 = d2
    self.d3 = d3
    self.c1 = c1
    self.c2 = c2
    self.c3 = c3
    self.dose = dose
    self.period = period
    self.width = width
    self.start = start
    self.doses = doses

VascularSupportInteraction(label, *, tumour, vasculature, r=2.63, d=0.829)

Bases: Interaction

Gompertz growth under a carrying capacity that the vessels on the tumour surface raise.

The tumour follows dn/dt = r n log(K / n) and the capacity dK/dt = d n^(2/3).

Parameters:

Name Type Description Default
label str

The label of the interaction.

required
tumour Annotated[str, RoleSpec()]

The path of the tumour.

required
vasculature Annotated[str, RoleSpec()]

The path of the vasculature.

required
r Annotated[float, ParameterSpec(domain=open(0, oo))]

The rate at which the growth slows.

2.63
d Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which the surface of the tumour raises the capacity.

0.829

Examples:

>>> from skcomplex.models.biology.oncology import VascularSupportInteraction
>>> VascularSupportInteraction('support', tumour='tumour', vasculature='vessels').d
0.829
Source code in src/skcomplex/models/biology/oncology/_vascular_support.py
44
45
46
47
48
49
50
51
52
53
54
55
56
57
def __init__(
    self,
    label: str,
    *,
    tumour: Annotated[str, RoleSpec()],
    vasculature: Annotated[str, RoleSpec()],
    r: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 2.63,
    d: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.829,
) -> None:
    super().__init__(label)
    self.tumour = tumour
    self.vasculature = vasculature
    self.r = r
    self.d = d

VascularizedSpheroidElement(label, visual=None, *, Ar=13.0, Ac=3.0, Ap=495.0, An=0.0, Vbc=0.0, Vbp=0.0, U=0.0, r1=1.2, r2=12.0, r3=0.06, m=1.0, a1=1.0, p1=1.0, p2=400000.0, p3=0.2, p4=0.45, p_g=400000.0, kappa1=0.17, kappa2=-45000.0, kappa3=-0.04, kappa4=-0.06, kappa_g=55000.0, theta1=0.3, theta2=0.3, beta=1.2, xi_e=0.8, rv_ref=0.005, Vx=0.005, du=INHIBITOR_CLEARANCE, dose=5.0, period=7.0, width=1.0, start=0.0)

Bases: Element

Tumour spheroid with a live core, a live periphery, a necrotic core, and the vasculature of core and periphery.

The radius grows as dAr/dt = r1 g(Ap / Vp), with g a sigmoid of the peripheral cell density. The core volume Vc = 4/3 pi (dc Ar)^3 and the periphery Vp = 4/3 pi Ar^3 - Vc follow from the radius and the core-periphery ratio dc(Ar). The increments of the radius, the core volume, and the tumour volume are read as rates, so dAr = dAr/dt, dVc = 4/3 pi (dc (Ar + dAr))^3 - Vc and dVt = 4/3 pi ((Ar + dAr)^3 - Ar^3) are per unit time. Peripheral cells pass to the core at the rate dVc / Vp, proliferate with the nutrient Vbp / (Vp rv_ref) and the density, and core cells die by necrosis when the core nutrient Vbc / (Vc rv_ref) is low. The vasculature grows by tumour angiogenic factor, which the inhibitor U lowers by exp(-xi_e U), the periphery takes in external vasculature of density Vx as the tumour grows, and peripheral vessels pass to the core.

Parameters:

Name Type Description Default
label str

The label of the tumour.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
Ar Annotated[float, StateSpec(domain=open(0, oo))]

The initial radius.

13.0
Ac Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of live core cells.

3.0
Ap Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of live peripheral cells.

495.0
An Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial number of necrotic cells.

0.0
Vbc Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial vascular volume of the core.

0.0
Vbp Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial vascular volume of the periphery.

0.0
U Annotated[float, StateSpec(domain=closed_open(0, oo))]

The initial concentration of the inhibitor.

0.0
r1 Annotated[float, ParameterSpec(domain=open(0, oo))]

The growth rate of the radius.

1.2
r2 Annotated[float, ParameterSpec(domain=open(0, oo))]

The proliferation rate of the peripheral cells.

12.0
r3 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The rate at which peripheral vessels pass to the core.

0.06
m Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The necrosis rate of the core cells.

1.0
a1 Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The angiogenesis rate.

1.0
p1 Annotated[float, ParameterSpec()]

The peripheral nutrient at half proliferation.

1.0
p2 Annotated[float, ParameterSpec()]

The peripheral density at half proliferation.

400000.0
p3 Annotated[float, ParameterSpec()]

The core nutrient at half necrosis.

0.2
p4 Annotated[float, ParameterSpec()]

The core nutrient at half angiogenic factor production.

0.45
p_g Annotated[float, ParameterSpec()]

The peripheral density at half the radial growth.

400000.0
kappa1 Annotated[float, ParameterSpec()]

The width of the nutrient switch of proliferation.

0.17
kappa2 Annotated[float, ParameterSpec()]

The width of the density switch of proliferation, negative so that crowding stops it.

-45000.0
kappa3 Annotated[float, ParameterSpec()]

The width of the necrosis switch, negative so that starvation causes it.

-0.04
kappa4 Annotated[float, ParameterSpec()]

The width of the angiogenic factor switch, negative so that starvation causes it.

-0.06
kappa_g Annotated[float, ParameterSpec()]

The width of the density switch of the radial growth.

55000.0
theta1 Annotated[float, ParameterSpec(domain=open(0, oo))]

The exponent of the necrosis switch.

0.3
theta2 Annotated[float, ParameterSpec(domain=open(0, oo))]

The exponent of the angiogenic factor switch.

0.3
beta Annotated[float, ParameterSpec(domain=open(0, oo))]

The exponent of the radius in the passage of vessels to the core.

1.2
xi_e Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The efficiency of the inhibitor.

0.8
rv_ref Annotated[float, ParameterSpec(domain=open(0, oo))]

The reference vascular fraction that supports tumour cells.

0.005
Vx Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The vascular density of the surrounding tissue.

0.005
du Annotated[float, ParameterSpec(domain=open(0, oo))]

The clearance rate of the inhibitor.

INHIBITOR_CLEARANCE
dose Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The infusion rate during a dose.

5.0
period float

The time between the starts of doses.

7.0
width float

The duration of a dose.

1.0
start float

The time of the first dose.

0.0

Examples:

>>> from skcomplex.models.biology.oncology import VascularizedSpheroidElement
>>> VascularizedSpheroidElement('tumour').Ap
495.0
Source code in src/skcomplex/models/biology/oncology/_vascularized_spheroid.py
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    Ar: Annotated[float, StateSpec(domain=RealSet.open(0, oo))] = 13.0,
    Ac: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 3.0,
    Ap: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 495.0,
    An: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    Vbc: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    Vbp: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    U: Annotated[float, StateSpec(domain=RealSet.closed_open(0, oo))] = 0.0,
    r1: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1.2,
    r2: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 12.0,
    r3: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.06,
    m: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    a1: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
    p1: Annotated[float, ParameterSpec()] = 1.0,
    p2: Annotated[float, ParameterSpec()] = 400000.0,
    p3: Annotated[float, ParameterSpec()] = 0.2,
    p4: Annotated[float, ParameterSpec()] = 0.45,
    p_g: Annotated[float, ParameterSpec()] = 400000.0,
    kappa1: Annotated[float, ParameterSpec()] = 0.17,
    kappa2: Annotated[float, ParameterSpec()] = -45000.0,
    kappa3: Annotated[float, ParameterSpec()] = -0.04,
    kappa4: Annotated[float, ParameterSpec()] = -0.06,
    kappa_g: Annotated[float, ParameterSpec()] = 55000.0,
    theta1: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.3,
    theta2: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.3,
    beta: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1.2,
    xi_e: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.8,
    rv_ref: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.005,
    Vx: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.005,
    du: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = INHIBITOR_CLEARANCE,
    dose: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 5.0,
    period: float = 7.0,
    width: float = 1.0,
    start: float = 0.0,
) -> None:
    super().__init__(label, visual=visual)
    self.Ar = Ar
    self.Ac = Ac
    self.Ap = Ap
    self.An = An
    self.Vbc = Vbc
    self.Vbp = Vbp
    self.U = U
    self.r1 = r1
    self.r2 = r2
    self.r3 = r3
    self.m = m
    self.a1 = a1
    self.p1 = p1
    self.p2 = p2
    self.p3 = p3
    self.p4 = p4
    self.p_g = p_g
    self.kappa1 = kappa1
    self.kappa2 = kappa2
    self.kappa3 = kappa3
    self.kappa4 = kappa4
    self.kappa_g = kappa_g
    self.theta1 = theta1
    self.theta2 = theta2
    self.beta = beta
    self.xi_e = xi_e
    self.rv_ref = rv_ref
    self.Vx = Vx
    self.du = du
    self.dose = dose
    self.period = period
    self.width = width
    self.start = start

VasculatureElement(label, visual=None, *, K=1.0)

Bases: Element

Vasculature of a tumour, which sets its carrying capacity.

Parameters:

Name Type Description Default
label str

The label of the vasculature.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
K Annotated[float, StateSpec(domain=open(0, oo))]

The initial carrying capacity.

1.0

Examples:

>>> from skcomplex.models.biology.oncology import VasculatureElement
>>> VasculatureElement('vessels', K=12.7).K
12.7
Source code in src/skcomplex/models/biology/oncology/_vasculature.py
34
35
36
37
38
39
40
41
42
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    K: Annotated[float, StateSpec(domain=RealSet.open(0, oo))] = 1.0,
) -> None:
    super().__init__(label, visual=visual)
    self.K = K

VesselElement(label, visual=None, *, supply=1.0)

Bases: Element

Segment of a blood vessel, which supplies oxygen to its site every step, a member transfer of the model.

Parameters:

Name Type Description Default
label str

The label of the agent or group.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
supply Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The oxygen supplied per step.

1.0

Examples:

>>> from skcomplex.core.elements import GroupElement
>>> from skcomplex.models.biology.oncology import VesselElement
>>> GroupElement('vessels', element=VesselElement, size=2, location=[(0, 0), (0, 1)]).size
2
Source code in src/skcomplex/models/biology/oncology/_vessel.py
36
37
38
39
40
41
42
43
44
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    supply: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.0,
) -> None:
    super().__init__(label, visual=visual)
    self.supply = supply

activity_grid(classes)

Return the activity of every class, evenly spaced from 0 to 1.

Parameters:

Name Type Description Default
classes int

The number of activity classes.

required

Returns:

Name Type Description
activities NDArray[float64]

The activity of every class.

Examples:

>>> from skcomplex.models.biology.oncology import activity_grid
>>> activity_grid(5).tolist()
[0.0, 0.25, 0.5, 0.75, 1.0]
Source code in src/skcomplex/models/biology/oncology/_immune_competition.py
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
def activity_grid(classes: int) -> npt.NDArray[np.float64]:
    """Return the activity of every class, evenly spaced from 0 to 1.

    Args:
        classes:
            The number of activity classes.

    Returns:
        activities:
            The activity of every class.

    Examples:
        >>> from skcomplex.models.biology.oncology import activity_grid
        >>> activity_grid(5).tolist()
        [0.0, 0.25, 0.5, 0.75, 1.0]
    """
    return np.linspace(0.0, 1.0, classes)

angiogenesis_immunotherapy(A=5000.0, Vb=625.0, E=0.1, *, dose_an=15.0, dose_im=20.0, a2=1.35, a3=0.1, period=21.0, doses=6)

Return the Hahnfeldt tumour with effector cells under bevacizumab and atezolizumab every three weeks.

Each drug alone holds the tumour or slows it, and together they shrink it. The drug amounts follow the two-compartment model whose bolus solution is the book's closed form, with the elimination rate k10 = alpha beta / k21. The effector cells grow as r1 (A - c1 A^2) E, so 1 / c1 is the volume above which the tumour suppresses them. The drug effects in the vasculature and effector balances are the saturating effects of the book's pharmacodynamics. The resistance capacity delta_r = 0.01 and its threshold u_theta = 5 mg per kg are a choice, since the book gives none. The toxicity of each drug is exp(c / tox) - 1, linear for a low amount and exponential for a high one, and the observable toxicity is the mean of both. Volumes are in mm³, drug amounts in mg per kg, and time is in days.

Parameters:

Name Type Description Default
A float

The initial tumour volume.

5000.0
Vb float

The initial vascular capacity.

625.0
E float

The initial effector cells, dimensionless.

0.1
dose_an float

The dose of bevacizumab, in mg per kg, 0 for immunotherapy alone.

15.0
dose_im float

The dose of atezolizumab, in mg per kg, 0 for antiangiogenic therapy alone.

20.0
a2 float

The highest destruction rate of the vasculature by bevacizumab, in the book's range of 1.35 to 11.25.

1.35
a3 float

The highest boost of effector cells by atezolizumab, in the book's range of 0.1 to 0.5.

0.1
period float

The time between doses.

21.0
doses int

The number of doses.

6

Returns:

Name Type Description
system System

The model, with the tumour tumour.A, the capacity tumour.Vb, the effector cells tumour.E, the drug amounts tumour.c_an and tumour.c_im, and the observable toxicity.

Examples:

>>> from skcomplex.models.biology.oncology import angiogenesis_immunotherapy
>>> angiogenesis_immunotherapy(dose_an=0.0).elements[0].dose_an
0.0
Source code in src/skcomplex/models/biology/oncology/_combination_therapy.py
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
@register_model(
    field='biology/oncology',
    tags=('antiangiogenic therapy', 'immunotherapy', 'combination therapy', 'pharmacokinetics', 'resistance', 'ode'),
    references=(BOOK, 'Teles and Lemos 2019', 'Hahnfeldt et al. 1999'),
    defaults={'until': 150.0, 'dt': 0.25},
    observables=lambda system: [ObservableSpec('toxicity', _total_toxicity)],
)
def angiogenesis_immunotherapy(
    A: float = 5000.0,
    Vb: float = 625.0,
    E: float = 0.1,
    *,
    dose_an: float = 15.0,
    dose_im: float = 20.0,
    a2: float = 1.35,
    a3: float = 0.1,
    period: float = 21.0,
    doses: int = 6,
) -> System:
    """Return the Hahnfeldt tumour with effector cells under bevacizumab and atezolizumab every three weeks.

    Each drug alone holds the tumour or slows it, and together they shrink it. The drug amounts follow the
    two-compartment model whose bolus solution is the book's closed form, with the elimination rate
    `k10 = alpha beta / k21`. The effector cells grow as `r1 (A - c1 A^2) E`, so `1 / c1` is the volume above which the
    tumour suppresses them. The drug effects in the vasculature and effector balances are the saturating effects of
    the book's pharmacodynamics. The resistance capacity `delta_r = 0.01` and its threshold `u_theta = 5` mg per kg
    are a choice, since the book gives none. The toxicity of each drug is `exp(c / tox) - 1`, linear for a low amount
    and exponential for a high one, and the observable `toxicity` is the mean of both. Volumes are in mm³, drug amounts
    in mg per kg, and time is in days.

    Args:
        A:
            The initial tumour volume.

        Vb:
            The initial vascular capacity.

        E:
            The initial effector cells, dimensionless.

        dose_an:
            The dose of bevacizumab, in mg per kg, 0 for immunotherapy alone.

        dose_im:
            The dose of atezolizumab, in mg per kg, 0 for antiangiogenic therapy alone.

        a2:
            The highest destruction rate of the vasculature by bevacizumab, in the book's range of 1.35 to 11.25.

        a3:
            The highest boost of effector cells by atezolizumab, in the book's range of 0.1 to 0.5.

        period:
            The time between doses.

        doses:
            The number of doses.

    Returns:
        system:
            The model, with the tumour `tumour.A`, the capacity `tumour.Vb`, the effector cells `tumour.E`, the drug
            amounts `tumour.c_an` and `tumour.c_im`, and the observable `toxicity`.

    Examples:
        >>> from skcomplex.models.biology.oncology import angiogenesis_immunotherapy
        >>> angiogenesis_immunotherapy(dose_an=0.0).elements[0].dose_an
        0.0
    """
    tumour = AngiogenesisImmunotherapyTumourElement(
        'tumour',
        A=A,
        Vb=Vb,
        E=E,
        dose_an=dose_an,
        dose_im=dose_im,
        a2=a2,
        a3=a3,
        period=period,
        doses=doses,
    )
    interactions = [
        RateInteraction(
            'tumour_growth',
            target='tumour',
            state='A',
            rate=lambda s: -s.target.v1 * s.target.A * log(s.target.A / s.target.Vb),
        ),
        ReactionInteraction(
            'immune_kill',
            target='tumour',
            reactants={'A': 1},
            modifiers={'E': 1},
            propensity=lambda s: s.target.a1 * s.target.A * s.target.E,
        ),
        ReactionInteraction(
            'vessel_loss',
            target='tumour',
            reactants={'Vb': 1},
            propensity=lambda s: s.target.v2 * s.target.Vb,
        ),
        RateInteraction('stimulation', target='tumour', state='Vb', rate=lambda s: s.target.xi_s * s.target.A),
        ReactionInteraction(
            'inhibition',
            target='tumour',
            reactants={'Vb': 1},
            propensity=lambda s: s.target.xi_i * s.target.Vb * s.target.A ** (2 / 3),
        ),
        ReactionInteraction(
            'pruning',
            target='tumour',
            reactants={'Vb': 1},
            propensity=lambda s: s.target.a2 * s.target.Vb * _drug_effect(s.target, 'an'),
        ),
        RateInteraction(
            'immune_growth',
            target='tumour',
            state='E',
            rate=lambda s: s.target.r1 * (s.target.A - s.target.c1 * s.target.A**2) * s.target.E,
        ),
        ReactionInteraction(
            'immune_death',
            target='tumour',
            reactants={'E': 1},
            propensity=lambda s: s.target.d1 * s.target.E,
        ),
        RateInteraction('immune_source', target='tumour', state='E', rate=lambda s: s.target.s_e),
        RateInteraction(
            'immune_boost',
            target='tumour',
            state='E',
            rate=lambda s: s.target.a3 * s.target.E * _drug_effect(s.target, 'im'),
        ),
        DosingInteraction(
            'dosing_an',
            target='tumour',
            state='c_an',
            dose=lambda s: s.target.dose_an / tumour.width,
            period=tumour.period,
            width=tumour.width,
            count=tumour.doses,
        ),
        ReactionInteraction(
            'elimination_an',
            target='tumour',
            reactants={'c_an': 1},
            propensity=lambda s: _elimination(s.target, 'an') * s.target.c_an,
        ),
        ReactionInteraction(
            'distribution_an',
            target='tumour',
            reactants={'c_an': 1},
            products={'q_an': 1},
            propensity=lambda s: s.target.k12_an * s.target.c_an,
        ),
        ReactionInteraction(
            'redistribution_an',
            target='tumour',
            reactants={'q_an': 1},
            products={'c_an': 1},
            propensity=lambda s: s.target.k21_an * s.target.q_an,
        ),
        RateInteraction(
            'resistance_an',
            target='tumour',
            state='R_an',
            rate=lambda s: where(s.target.c_an < s.target.u_theta, s.target.u_theta - s.target.c_an, 0),
        ),
        DosingInteraction(
            'dosing_im',
            target='tumour',
            state='c_im',
            dose=lambda s: s.target.dose_im / tumour.width,
            period=tumour.period,
            width=tumour.width,
            count=tumour.doses,
        ),
        ReactionInteraction(
            'elimination_im',
            target='tumour',
            reactants={'c_im': 1},
            propensity=lambda s: _elimination(s.target, 'im') * s.target.c_im,
        ),
        ReactionInteraction(
            'distribution_im',
            target='tumour',
            reactants={'c_im': 1},
            products={'q_im': 1},
            propensity=lambda s: s.target.k12_im * s.target.c_im,
        ),
        ReactionInteraction(
            'redistribution_im',
            target='tumour',
            reactants={'q_im': 1},
            products={'c_im': 1},
            propensity=lambda s: s.target.k21_im * s.target.q_im,
        ),
        RateInteraction(
            'resistance_im',
            target='tumour',
            state='R_im',
            rate=lambda s: where(s.target.c_im < s.target.u_theta, s.target.u_theta - s.target.c_im, 0),
        ),
    ]
    return System(elements=[tumour], interactions=interactions)

anti_pd1_checkpoint(E=0.006, A=0.3968, *, u_ap=1e-10, sigma=5.0, ENC=0.0001, r3=0.18, b=1 / 0.8, c_l=1.0)

Return activated T cells, a tumour, and an anti-PD-1 drug that frees the T cells from checkpoint inhibition.

The PD-1-PD-L1 complex inhibits the activation and proliferation of T cells, and the drug lowers the free PD-1 on T cells. The cytokines are at their steady states, as in the book. The book gives neither the naive T cells ENC nor the association ratio sigma, which are set so that the T cells settle below the level that controls the tumour. The ranged parameters take the low ends of the book's ranges, and the drug is the book's continuous infusion of 10^-10 per day. A larger infusion frees more T cells and lowers the tumour. The book's free PD-1 (rho_r - du1 UAP) E turns negative once the drug exceeds rho_r / du1, and it is held at 0 there. With all PD-1 blocked nothing limits the T cells, which grow without bound and clear the tumour. Cells and the drug are in g/cm³ and time in days.

Parameters:

Name Type Description Default
E float

The initial activated T cells.

0.006
A float

The initial tumour cells.

0.3968
u_ap float

The infusion rate of the drug, 0 for no treatment.

1e-10
sigma float

The ratio of association to dissociation of PD-1 and PD-L1.

5.0
ENC float

The naive T cells.

0.0001
r3 float

The growth rate of the tumour.

0.18
b float

The inverse carrying capacity of the tumour.

1 / 0.8
c_l float

The expression of PD-L1 on tumour cells relative to T cells.

1.0

Returns:

Name Type Description
system System

The model, with the T cells site.E, the tumour site.A, and the drug site.UAP.

Examples:

>>> from skcomplex.models.biology.oncology import anti_pd1_checkpoint
>>> anti_pd1_checkpoint(u_ap=0.0).elements[0].u_ap
0.0
Source code in src/skcomplex/models/biology/oncology/_immunotherapy.py
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
@register_model(
    field='biology/oncology',
    tags=('immunotherapy', 'ode', 'checkpoint inhibitor', 'PD-1', 'dosing'),
    references=(BOOK_REFERENCE, 'Nikolopoulou et al. 2018'),
    defaults={'until': 150.0, 'dt': 0.5, 'solver': STIFF_SOLVER},
)
def anti_pd1_checkpoint(
    E: float = 6e-3,
    A: float = 0.3968,
    *,
    u_ap: float = 1e-10,
    sigma: float = 5.0,
    ENC: float = 1e-4,
    r3: float = 0.18,
    b: float = 1 / 0.8,
    c_l: float = 1.0,
) -> System:
    """Return activated T cells, a tumour, and an anti-PD-1 drug that frees the T cells from checkpoint inhibition.

    The PD-1-PD-L1 complex inhibits the activation and proliferation of T cells, and the drug lowers the free PD-1 on
    T cells. The cytokines are at their steady states, as in the book. The book gives neither the naive T cells `ENC`
    nor the association ratio `sigma`, which are set so that the T cells settle below the level that controls the
    tumour. The ranged parameters take the low ends of the book's ranges, and the drug is the book's continuous
    infusion of `10^-10` per day. A larger infusion frees more T cells and lowers the tumour. The book's free PD-1
    `(rho_r - du1 UAP) E` turns negative once the drug exceeds `rho_r / du1`, and it is held at 0 there. With all PD-1
    blocked nothing limits the T cells, which grow without bound and clear the tumour. Cells and the drug are in g/cm³
    and time in days.

    Args:
        E:
            The initial activated T cells.

        A:
            The initial tumour cells.

        u_ap:
            The infusion rate of the drug, 0 for no treatment.

        sigma:
            The ratio of association to dissociation of PD-1 and PD-L1.

        ENC:
            The naive T cells.

        r3:
            The growth rate of the tumour.

        b:
            The inverse carrying capacity of the tumour.

        c_l:
            The expression of PD-L1 on tumour cells relative to T cells.

    Returns:
        system:
            The model, with the T cells `site.E`, the tumour `site.A`, and the drug `site.UAP`.

    Examples:
        >>> from skcomplex.models.biology.oncology import anti_pd1_checkpoint
        >>> anti_pd1_checkpoint(u_ap=0.0).elements[0].u_ap
        0.0
    """
    site = CheckpointTumourElement('site', E=E, A=A, u_ap=u_ap, sigma=sigma, ENC=ENC, r3=r3, b=b, c_l=c_l)

    def free_receptor(s: SimpleNamespace) -> Expression:
        """Return the free PD-1 on the T cells, which the drug lowers."""
        expression = s.target.rho_r - s.target.du1 * s.target.UAP
        receptor: Expression = where(expression > 0, expression, 0) * s.target.E
        return receptor

    interactions = [
        RateInteraction(
            'activation',
            target='site',
            state='E',
            rate=lambda s: (
                s.target.r1 * s.target.ENC * hill(s.target.C1_ss, s.target.C1_50)
                + s.target.r2 * s.target.E * hill(s.target.C2_ss, s.target.C2_50)
            )
            / (
                1
                + s.target.sigma
                * free_receptor(s)
                * s.target.sigma_l
                * (s.target.E + s.target.c_l * s.target.A)
                / s.target.psi_pp
            ),
        ),
        ReactionInteraction(
            'effector_death',
            target='site',
            reactants={'E': 1},
            propensity=lambda s: s.target.d1 * s.target.E,
        ),
        RateInteraction(
            'tumour_growth',
            target='site',
            state='A',
            rate=lambda s: s.target.r3 * s.target.A * (1 - s.target.b * s.target.A),
        ),
        ReactionInteraction(
            'kill',
            target='site',
            reactants={'A': 1},
            modifiers={'E': 1},
            propensity=lambda s: s.target.a_rho * s.target.A * s.target.E,
        ),
        DosingInteraction('infusion', target='site', state='UAP', dose=lambda s: s.target.u_ap),
        ReactionInteraction(
            'binding',
            target='site',
            reactants={'UAP': 1},
            modifiers={'E': 1},
            propensity=lambda s: s.target.a_rl * free_receptor(s) * s.target.UAP,
        ),
        ReactionInteraction(
            'clearance',
            target='site',
            reactants={'UAP': 1},
            propensity=lambda s: s.target.du2 * s.target.UAP,
        ),
    ]
    return System(elements=[site], interactions=interactions)

bone_marrow_blood_leukaemia(*, m1=0.0013, m3=1e-07, tau1=96.0, tau2=576.0)

Return the bone marrow and blood model of leukaemia, in which blasts crowd out the normal cells.

Normal marrow cells renew, mutate into blasts and cancer stem cells, and mature into blood cells after the delay tau1. Blasts grow in the marrow, move to the blood, and inhibit the normal cells, and cancer stem cells convert into blasts after the delay tau2. Cells are counts, time is in hours, and the history before the start is the initial state. The book's table gives ranges, and the defaults are values in them: the largest growth rate of normal marrow cells and carrying capacity of blasts, the smallest delays, and the release rate m2 that keeps the normal blood cells near their initial number. The book prints the arrival of marrow cells in the blood with a minus sign, and the model uses the plus sign of the release it balances. The blasts take over the marrow and the normal blood cells fall by orders of magnitude.

Parameters:

Name Type Description Default
m1 float

The mutation rate of normal marrow cells into blasts, per hour.

0.0013
m3 float

The mutation rate of normal marrow cells into cancer stem cells, per hour.

1e-07
tau1 float

The maturation time of normal cells, in hours.

96.0
tau2 float

The conversion time of cancer stem cells into blasts, in hours.

576.0

Returns:

Name Type Description
system System

The model, with the normal marrow and blood cells patient.NBM and patient.NPB, the blasts patient.ABM and patient.APB, and the cancer stem cells patient.AS.

Examples:

>>> from skcomplex.models.biology.oncology import bone_marrow_blood_leukaemia
>>> bone_marrow_blood_leukaemia(tau1=144.0).elements[0].tau1
144.0
Source code in src/skcomplex/models/biology/oncology/_stem_cells.py
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
@register_model(
    field='biology/oncology',
    tags=('leukaemia', 'stem cells', 'delay', 'bone marrow'),
    references=(BOOK, 'Afenya, Ouifki, and Mundle 2019'),
    defaults={'until': 3000.0, 'dt': 10.0, 'solver': ScipyODESolver(method='BDF')},
)
def bone_marrow_blood_leukaemia(
    *,
    m1: float = 0.0013,
    m3: float = 1e-7,
    tau1: float = 96.0,
    tau2: float = 576.0,
) -> System:
    """Return the bone marrow and blood model of leukaemia, in which blasts crowd out the normal cells.

    Normal marrow cells renew, mutate into blasts and cancer stem cells, and mature into blood cells after the delay
    `tau1`. Blasts grow in the marrow, move to the blood, and inhibit the normal cells, and cancer stem cells convert
    into blasts after the delay `tau2`. Cells are counts, time is in hours, and the history before the start is the
    initial state. The book's table gives ranges, and the defaults are values in them: the largest growth rate of
    normal marrow cells and carrying capacity of blasts, the smallest delays, and the release rate `m2` that keeps
    the normal blood cells near their initial number. The book prints the arrival of marrow cells in the blood with
    a minus sign, and the model uses the plus sign of the release it balances. The blasts take over the marrow and
    the normal blood cells fall by orders of magnitude.

    Args:
        m1:
            The mutation rate of normal marrow cells into blasts, per hour.

        m3:
            The mutation rate of normal marrow cells into cancer stem cells, per hour.

        tau1:
            The maturation time of normal cells, in hours.

        tau2:
            The conversion time of cancer stem cells into blasts, in hours.

    Returns:
        system:
            The model, with the normal marrow and blood cells `patient.NBM` and `patient.NPB`, the blasts
            `patient.ABM` and `patient.APB`, and the cancer stem cells `patient.AS`.

    Examples:
        >>> from skcomplex.models.biology.oncology import bone_marrow_blood_leukaemia
        >>> bone_marrow_blood_leukaemia(tau1=144.0).elements[0].tau1
        144.0
    """
    patient = BoneMarrowBloodElement('patient', m1=m1, m3=m3, tau1=tau1, tau2=tau2)
    interactions = [
        RateInteraction(
            'marrow_growth',
            target='patient',
            state='NBM',
            rate=lambda s: s.target.r1
            * s.target.NBM
            * log((s.target.b1 + s.target.b2) / (s.target.theta1 + s.target.NBM)),
        ),
        ReactionInteraction(
            'mutation',
            target='patient',
            reactants={'NBM': 1},
            products={'ABM': 1},
            propensity=lambda s: s.target.m1 * s.target.NBM,
        ),
        ReactionInteraction(
            'stem_mutation',
            target='patient',
            reactants={'NBM': 1},
            products={'AS': 1},
            propensity=lambda s: s.target.m3 * s.target.NBM,
        ),
        RateInteraction(
            'release',
            target='patient',
            state='NBM',
            rate=lambda s: -s.target.m2
            * s.target.NBM
            * exp(-s.target.r2 * s.target.APB)
            / (s.target.theta2 + s.target.NPB),
        ),
        RateInteraction(
            'arrival',
            target='patient',
            state='NPB',
            rate=lambda s: s.target.m2
            * delayed(s.target.NBM, s.target.tau1)
            * exp(-s.target.alpha1 * s.target.tau1 - s.target.r2 * delayed(s.target.APB, s.target.tau1))
            / (s.target.theta2 + delayed(s.target.NPB, s.target.tau1)),
        ),
        ReactionInteraction(
            'marrow_competition',
            target='patient',
            reactants={'NBM': 1},
            modifiers={'ABM': 1},
            propensity=lambda s: s.target.c1 * s.target.NBM * s.target.ABM,
        ),
        ReactionInteraction(
            'blood_competition',
            target='patient',
            reactants={'NPB': 1},
            modifiers={'APB': 1},
            propensity=lambda s: s.target.c2 * s.target.NPB * s.target.APB,
        ),
        ReactionInteraction(
            'blood_death',
            target='patient',
            reactants={'NPB': 1},
            propensity=lambda s: s.target.d1 * s.target.NPB,
        ),
        RateInteraction(
            'leukaemic_growth',
            target='patient',
            state='ABM',
            rate=lambda s: s.target.r3 * s.target.ABM * log(s.target.b3 / (s.target.theta3 + s.target.ABM)),
        ),
        ReactionInteraction(
            'leukaemic_release',
            target='patient',
            reactants={'ABM': 1},
            products={'APB': 1},
            propensity=lambda s: s.target.m4 * s.target.ABM,
        ),
        RateInteraction(
            'conversion_arrival',
            target='patient',
            state='ABM',
            rate=lambda s: s.target.m5
            * exp(-s.target.alpha2 * s.target.tau2 - s.target.r4 * delayed(s.target.APB, s.target.tau2))
            * delayed(s.target.AS, s.target.tau2),
        ),
        ReactionInteraction(
            'leukaemic_death',
            target='patient',
            reactants={'APB': 1},
            propensity=lambda s: s.target.d2 * s.target.APB,
        ),
        RateInteraction(
            'stem_growth',
            target='patient',
            state='AS',
            rate=lambda s: s.target.r5 * s.target.AS * (1 - s.target.b4 * s.target.AS),
        ),
        RateInteraction(
            'conversion',
            target='patient',
            state='AS',
            rate=lambda s: -s.target.m5 * exp(-s.target.r4 * s.target.APB) * s.target.AS,
        ),
    ]
    return System(elements=[patient], interactions=interactions)

cell_cycle_chemotherapy(*, dormant=False, u1=0.0, u2=0.0, v=0.0)

Return tumour cells in cell-cycle compartments under killing, blocking, and recruiting agents.

Without a dormant phase the cells cycle through G0 and G1, S, and G2 and M, a killing agent kills a fraction u1 of the dividing cells, and a blocking agent slows the transit through S by u2. With a dormant phase the cells rest in G0, cycle through G1 and S and through G2 and M, the killing agent kills u1 of the dividing cells, and a recruiting agent speeds the exit from G0 by the factor 1 + v. Each division gives 2 (1 - u1) cells, so the tumour grows for u1 < 1/2 and shrinks for u1 > 1/2, whatever the blocking and the recruitment. The parameters and initial cells are those of Tables 3.8 and 3.9 of Padmanabhan et al., in cell counts and per unit time. The book prints the agents as additive terms 2 l3 u1 and garbles the indices of the dormant model, so the model takes the form of Świerniak et al., where the agents act on the cells of the compartment they leave. Constant agents are given, untreated by default.

Parameters:

Name Type Description Default
dormant bool

Whether the cells have a dormant phase, the model of Table 3.9, or not, the model of Table 3.8.

False
u1 float

The fraction of dividing cells the killing agent kills.

0.0
u2 float

The fraction by which the blocking agent slows the transit through S, without a dormant phase.

0.0
v float

The relative increase of the exit from G0 the recruiting agent causes, with a dormant phase.

0.0

Returns:

Name Type Description
system System

The model, with the cells tumour.A1 to tumour.A3, or tumour.A0 to tumour.A2 with a dormant phase.

Examples:

>>> from skcomplex.models.biology.oncology import cell_cycle_chemotherapy
>>> type(cell_cycle_chemotherapy(dormant=True).elements[0]).__name__
'DormantCellCycleElement'
Source code in src/skcomplex/models/biology/oncology/_cell_kinetics.py
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
@register_model(
    field='biology/oncology',
    tags=('chemotherapy', 'ode', 'cell cycle', 'compartments'),
    references=(BOOK, 'Świerniak, Ledzewicz, and Schättler 2003'),
    defaults={'until': 100.0, 'dt': 0.5},
)
def cell_cycle_chemotherapy(
    *,
    dormant: bool = False,
    u1: float = 0.0,
    u2: float = 0.0,
    v: float = 0.0,
) -> System:
    """Return tumour cells in cell-cycle compartments under killing, blocking, and recruiting agents.

    Without a dormant phase the cells cycle through G0 and G1, S, and G2 and M, a killing agent kills a fraction `u1` of
    the dividing cells, and a blocking agent slows the transit through S by `u2`. With a dormant phase the cells rest
    in G0, cycle through G1 and S and through G2 and M, the killing agent kills `u1` of the dividing cells, and a
    recruiting agent speeds the exit from G0 by the factor `1 + v`. Each division gives `2 (1 - u1)` cells, so the
    tumour grows for `u1 < 1/2` and shrinks for `u1 > 1/2`, whatever the blocking and the recruitment. The parameters
    and initial cells are those of Tables 3.8 and 3.9 of Padmanabhan et al., in cell counts and per unit time. The
    book prints the agents as additive terms `2 l3 u1` and garbles the indices of the dormant model, so the model
    takes the form of Świerniak et al., where the agents act on the cells of the compartment they leave. Constant
    agents are given, untreated by default.

    Args:
        dormant:
            Whether the cells have a dormant phase, the model of Table 3.9, or not, the model of Table 3.8.

        u1:
            The fraction of dividing cells the killing agent kills.

        u2:
            The fraction by which the blocking agent slows the transit through S, without a dormant phase.

        v:
            The relative increase of the exit from G0 the recruiting agent causes, with a dormant phase.

    Returns:
        system:
            The model, with the cells `tumour.A1` to `tumour.A3`, or `tumour.A0` to `tumour.A2` with a dormant phase.

    Examples:
        >>> from skcomplex.models.biology.oncology import cell_cycle_chemotherapy
        >>> type(cell_cycle_chemotherapy(dormant=True).elements[0]).__name__
        'DormantCellCycleElement'
    """
    if dormant:
        dormant_interactions = [
            ReactionInteraction(
                'recruitment',
                target='tumour',
                reactants={'A0': 1},
                products={'A1': 1},
                propensity=lambda s: s.target.l0 * (1 + s.target.v) * s.target.A0,
            ),
            ReactionInteraction(
                'transit',
                target='tumour',
                reactants={'A1': 1},
                products={'A2': 1},
                propensity=lambda s: s.target.l1 * s.target.A1,
            ),
            ReactionInteraction(
                'mitosis',
                target='tumour',
                reactants={'A2': 1},
                propensity=lambda s: s.target.l2 * s.target.A2,
            ),
            RateInteraction(
                'dormant_daughters',
                target='tumour',
                state='A0',
                rate=lambda s: s.target.b0 * 2 * (1 - s.target.u) * s.target.l2 * s.target.A2,
            ),
            RateInteraction(
                'cycling_daughters',
                target='tumour',
                state='A1',
                rate=lambda s: s.target.b1 * 2 * (1 - s.target.u) * s.target.l2 * s.target.A2,
            ),
        ]
        return System(elements=[DormantCellCycleElement('tumour', u=u1, v=v)], interactions=dormant_interactions)
    interactions = [
        ReactionInteraction(
            'g1_exit',
            target='tumour',
            reactants={'A1': 1},
            products={'A2': 1},
            propensity=lambda s: s.target.l1 * s.target.A1,
        ),
        ReactionInteraction(
            's_exit',
            target='tumour',
            reactants={'A2': 1},
            products={'A3': 1},
            propensity=lambda s: (1 - s.target.u2) * s.target.l2 * s.target.A2,
        ),
        ReactionInteraction(
            'division',
            target='tumour',
            reactants={'A3': 1},
            products={'A1': 2},
            propensity=lambda s: (1 - s.target.u1) * s.target.l3 * s.target.A3,
        ),
        ReactionInteraction(
            'kill',
            target='tumour',
            reactants={'A3': 1},
            propensity=lambda s: s.target.u1 * s.target.l3 * s.target.A3,
        ),
    ]
    return System(elements=[CellCycleElement('tumour', u1=u1, u2=u2)], interactions=interactions)

cell_density(s, activities)

Return the density of a population of cells, the order-0 moment of its distribution.

Parameters:

Name Type Description Default
s SimpleNamespace

The namespace of one member of the distribution.

required
activities NDArray[float64]

The activity of every class.

required

Returns:

Name Type Description
density Expression

The order-0 moment.

Source code in src/skcomplex/models/biology/oncology/_immune_competition.py
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
def cell_density(s: SimpleNamespace, activities: npt.NDArray[np.float64]) -> Expression:
    """Return the density of a population of cells, the order-0 moment of its distribution.

    Args:
        s:
            The namespace of one member of the distribution.

        activities:
            The activity of every class.

    Returns:
        density:
            The order-0 moment.
    """
    return moment(s.f, 0, activities)

chemoimmunotherapy(A=1000000.0, N=50000.0, E=100.0, C=11000000.0, *, u_til=10000000.0, u_il2=10000000.0, u_chemo=2.0, start=7.0, period=7.0, width=1.0, doses=3)

Return a tumour with NK cells, CD8 T cells, and lymphocytes under chemotherapy, IL-2, and TIL injection.

The tumour, implanted in a mouse, grows toward a high equilibrium that the immune cells cannot hold back. The doses of chemotherapy shrink it, and the injected tumour-infiltrating lymphocytes clear what the drug leaves. The parameters are the table of the book, except the decay rates of the drugs, which the book's table swaps. The chemotherapeutic drug decays at 0.9 per day and IL-2 at 10 per day, as in de Pillis et al. 2006. The schedule of three weekly one-day doses from day 7 is a choice, since the book gives none. Cells are counted, and time is in days.

Parameters:

Name Type Description Default
A float

The initial number of tumour cells.

1000000.0
N float

The initial number of NK cells.

50000.0
E float

The initial number of CD8 T cells.

100.0
C float

The initial number of circulating lymphocytes.

11000000.0
u_til float

The rate of TIL injection during a dose, in cells per day.

10000000.0
u_il2 float

The rate of IL-2 injection during a dose.

10000000.0
u_chemo float

The rate of chemotherapy infusion during a dose.

2.0
start float

The time of the first dose.

7.0
period float

The time between the starts of doses.

7.0
width float

The duration of a dose.

1.0
doses int

The number of doses.

3

Returns:

Name Type Description
system System

The model, with the states tumour.A, tumour.N, tumour.E, tumour.C, tumour.I, and tumour.M.

Examples:

>>> from skcomplex.models.biology.oncology import chemoimmunotherapy
>>> chemoimmunotherapy(u_til=0.0).elements[0].u_til
0.0
Source code in src/skcomplex/models/biology/oncology/_combination_therapy.py
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
@register_model(
    field='biology/oncology',
    tags=('chemotherapy', 'immunotherapy', 'combination therapy', 'ode', 'dosing'),
    references=(BOOK, 'de Pillis, Gu, and Radunskaya 2006'),
    defaults={'until': 60.0, 'dt': 0.2, 'solver': ScipyODESolver(method='LSODA', rtol=1e-6, atol=1e-6)},
)
def chemoimmunotherapy(
    A: float = 1e6,
    N: float = 5e4,
    E: float = 100.0,
    C: float = 1.1e7,
    *,
    u_til: float = 1e7,
    u_il2: float = 1e7,
    u_chemo: float = 2.0,
    start: float = 7.0,
    period: float = 7.0,
    width: float = 1.0,
    doses: int = 3,
) -> System:
    """Return a tumour with NK cells, CD8 T cells, and lymphocytes under chemotherapy, IL-2, and TIL injection.

    The tumour, implanted in a mouse, grows toward a high equilibrium that the immune cells cannot hold back. The
    doses of chemotherapy shrink it, and the injected tumour-infiltrating lymphocytes clear what the drug leaves. The
    parameters are the table of the book, except the decay rates of the drugs, which the book's table swaps. The
    chemotherapeutic drug decays at 0.9 per day and IL-2 at 10 per day, as in de Pillis et al. 2006. The schedule of
    three weekly one-day doses from day 7 is a choice, since the book gives none. Cells are counted, and time is in
    days.

    Args:
        A:
            The initial number of tumour cells.

        N:
            The initial number of NK cells.

        E:
            The initial number of CD8 T cells.

        C:
            The initial number of circulating lymphocytes.

        u_til:
            The rate of TIL injection during a dose, in cells per day.

        u_il2:
            The rate of IL-2 injection during a dose.

        u_chemo:
            The rate of chemotherapy infusion during a dose.

        start:
            The time of the first dose.

        period:
            The time between the starts of doses.

        width:
            The duration of a dose.

        doses:
            The number of doses.

    Returns:
        system:
            The model, with the states `tumour.A`, `tumour.N`, `tumour.E`, `tumour.C`, `tumour.I`, and `tumour.M`.

    Examples:
        >>> from skcomplex.models.biology.oncology import chemoimmunotherapy
        >>> chemoimmunotherapy(u_til=0.0).elements[0].u_til
        0.0
    """
    tumour = ChemoimmunotherapyTumourElement(
        'tumour',
        A=A,
        N=N,
        E=E,
        C=C,
        u_til=u_til,
        u_il2=u_il2,
        u_chemo=u_chemo,
        start=start,
        period=period,
        width=width,
        doses=doses,
    )
    interactions = [
        RateInteraction(
            'tumour_growth',
            target='tumour',
            state='A',
            rate=lambda s: s.target.r1 * s.target.A * (1 - s.target.b1 * s.target.A),
        ),
        ReactionInteraction(
            'nk_kill',
            target='tumour',
            reactants={'A': 1},
            modifiers={'N': 1},
            propensity=lambda s: s.target.c1 * s.target.N * s.target.A,
        ),
        ReactionInteraction(
            'effector_kill',
            target='tumour',
            reactants={'A': 1},
            propensity=lambda s: _effector_kill(s.target) * s.target.A,
        ),
        ReactionInteraction(
            'chemo_tumour_kill',
            target='tumour',
            reactants={'A': 1},
            propensity=lambda s: s.target.a2 * (1 - exp(-s.target.M)) * s.target.A,
        ),
        RateInteraction('nk_production', target='tumour', state='N', rate=lambda s: s.target.m1 * s.target.C),
        ReactionInteraction(
            'nk_death',
            target='tumour',
            reactants={'N': 1},
            propensity=lambda s: s.target.d1 * s.target.N,
        ),
        RateInteraction(
            'nk_recruitment',
            target='tumour',
            state='N',
            rate=lambda s: s.target.r2 * s.target.A**2 / (s.target.g2 + s.target.A**2) * s.target.N,
        ),
        ReactionInteraction(
            'nk_inactivation',
            target='tumour',
            reactants={'N': 1},
            modifiers={'A': 1},
            propensity=lambda s: s.target.psi1 * s.target.N * s.target.A,
        ),
        ReactionInteraction(
            'chemo_nk_kill',
            target='tumour',
            reactants={'N': 1},
            propensity=lambda s: s.target.a3 * (1 - exp(-s.target.M)) * s.target.N,
        ),
        RateInteraction(
            'effector_recruitment',
            target='tumour',
            state='E',
            rate=lambda s: s.target.r3
            * (_effector_kill(s.target) * s.target.A) ** 2
            / (s.target.g3 + (_effector_kill(s.target) * s.target.A) ** 2)
            * s.target.E,
        ),
        ReactionInteraction(
            'effector_death',
            target='tumour',
            reactants={'E': 1},
            propensity=lambda s: s.target.d2 * s.target.E,
        ),
        ReactionInteraction(
            'effector_inactivation',
            target='tumour',
            reactants={'E': 1},
            modifiers={'A': 1},
            propensity=lambda s: s.target.psi2 * s.target.E * s.target.A,
        ),
        ReactionInteraction(
            'nk_regulation',
            target='tumour',
            reactants={'E': 1},
            propensity=lambda s: s.target.psi3 * s.target.N * s.target.E**2,
        ),
        ReactionInteraction(
            'chemo_effector_kill',
            target='tumour',
            reactants={'E': 1},
            propensity=lambda s: s.target.a4 * (1 - exp(-s.target.M)) * s.target.E,
        ),
        RateInteraction(
            'effector_activation',
            target='tumour',
            state='E',
            rate=lambda s: (s.target.r4 * s.target.N + s.target.r5 * s.target.C) * s.target.A,
        ),
        MichaelisMentenInteraction(
            'il2_proliferation',
            target='tumour',
            products={'E': 1},
            substrate='I',
            vmax=lambda s: s.target.r6,
            km=lambda s: s.target.g4,
            modifiers={'E': 1},
        ),
        DosingInteraction(
            'til_infusion',
            target='tumour',
            state='E',
            dose=lambda s: s.target.u_til,
            period=tumour.period,
            width=tumour.width,
            start=tumour.start,
            count=tumour.doses,
        ),
        RateInteraction('lymphocyte_production', target='tumour', state='C', rate=lambda s: s.target.s1),
        ReactionInteraction(
            'lymphocyte_death',
            target='tumour',
            reactants={'C': 1},
            propensity=lambda s: s.target.d3 * s.target.C,
        ),
        ReactionInteraction(
            'chemo_lymphocyte_kill',
            target='tumour',
            reactants={'C': 1},
            propensity=lambda s: s.target.a5 * (1 - exp(-s.target.M)) * s.target.C,
        ),
        ReactionInteraction(
            'il2_clearance',
            target='tumour',
            reactants={'I': 1},
            propensity=lambda s: s.target.d_u1 * s.target.I,
        ),
        DosingInteraction(
            'il2_infusion',
            target='tumour',
            state='I',
            dose=lambda s: s.target.u_il2,
            period=tumour.period,
            width=tumour.width,
            start=tumour.start,
            count=tumour.doses,
        ),
        ReactionInteraction(
            'chemo_clearance',
            target='tumour',
            reactants={'M': 1},
            propensity=lambda s: s.target.d_u2 * s.target.M,
        ),
        DosingInteraction(
            'chemo_infusion',
            target='tumour',
            state='M',
            dose=lambda s: s.target.u_chemo,
            period=tumour.period,
            width=tumour.width,
            start=tumour.start,
            count=tumour.doses,
        ),
    ]
    return System(elements=[tumour], interactions=interactions)

chemovirotherapy(AU=1.0, V=0.1, U=0.1, *, u1=10.0, infusion='constant')

Return uninfected and infected tumour cells, an oncolytic virus, and a chemotherapeutic drug.

The virus infects the growing tumour, and the drug kills both uninfected and infected cells. Over the default run of 64 days, before the virus bursts through the tumour, the combination leaves the smallest tumour. Later the virus alone clears the tumour slightly faster, because the drug also kills the infected cells that make the virus. The infusion rate is a choice, since the book gives none. One unit of cells is a million cells, and one unit of time is two days.

Parameters:

Name Type Description Default
AU float

The initial number of uninfected cells.

1.0
V float

The initial number of virions, 0 for chemotherapy alone.

0.1
U float

The initial amount of drug.

0.1
u1 float

The infusion rate of the drug, 0 for virotherapy alone.

10.0
infusion str

The form of the infusion, 'constant', 'exponential', or 'periodic'.

'constant'

Returns:

Name Type Description
system System

The model, with the cells tumour.AU and tumour.AV, the virus tumour.V, and the drug tumour.U.

Examples:

>>> from skcomplex.models.biology.oncology import chemovirotherapy
>>> chemovirotherapy(infusion='exponential').elements[0].infusion
'exponential'
Source code in src/skcomplex/models/biology/oncology/_combination_therapy.py
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
@register_model(
    field='biology/oncology',
    tags=('chemotherapy', 'virotherapy', 'combination therapy', 'oncolytic virus', 'ode'),
    references=(BOOK, 'Malinzi 2019'),
    defaults={'until': 32.0, 'dt': 0.1},
)
def chemovirotherapy(
    AU: float = 1.0,
    V: float = 0.1,
    U: float = 0.1,
    *,
    u1: float = 10.0,
    infusion: str = 'constant',
) -> System:
    """Return uninfected and infected tumour cells, an oncolytic virus, and a chemotherapeutic drug.

    The virus infects the growing tumour, and the drug kills both uninfected and infected cells. Over the default run
    of 64 days, before the virus bursts through the tumour, the combination leaves the smallest tumour. Later the virus
    alone clears the tumour slightly faster, because the drug also kills the infected cells that make the virus. The
    infusion rate is a choice, since the book gives none. One unit of cells is a million cells, and one unit of time is
    two days.

    Args:
        AU:
            The initial number of uninfected cells.

        V:
            The initial number of virions, 0 for chemotherapy alone.

        U:
            The initial amount of drug.

        u1:
            The infusion rate of the drug, 0 for virotherapy alone.

        infusion:
            The form of the infusion, `'constant'`, `'exponential'`, or `'periodic'`.

    Returns:
        system:
            The model, with the cells `tumour.AU` and `tumour.AV`, the virus `tumour.V`, and the drug `tumour.U`.

    Examples:
        >>> from skcomplex.models.biology.oncology import chemovirotherapy
        >>> chemovirotherapy(infusion='exponential').elements[0].infusion
        'exponential'
    """
    tumour = ChemovirotherapyTumourElement('tumour', AU=AU, V=V, U=U, u1=u1, infusion=infusion)
    interactions = [
        RateInteraction(
            'tumour_growth',
            target='tumour',
            state='AU',
            rate=lambda s: s.target.r1 * s.target.AU * (1 - s.target.b * (s.target.AU + s.target.AV)),
        ),
        ReactionInteraction(
            'infection',
            target='tumour',
            reactants={'AU': 1, 'V': 1},
            products={'AV': 1},
            propensity=lambda s: s.target.alpha * s.target.AU * s.target.V,
        ),
        ReactionInteraction(
            'drug_kill',
            target='tumour',
            reactants={'AU': 1},
            modifiers={'U': 1},
            propensity=lambda s: s.target.a1 * s.target.AU * s.target.U,
        ),
        ReactionInteraction(
            'lysis',
            target='tumour',
            reactants={'AV': 1},
            propensity=lambda s: s.target.a2 * s.target.AV,
        ),
        ReactionInteraction(
            'infected_drug_kill',
            target='tumour',
            reactants={'AV': 1},
            modifiers={'U': 1},
            propensity=lambda s: s.target.a3 * s.target.AV * s.target.U,
        ),
        RateInteraction(
            'burst',
            target='tumour',
            state='V',
            rate=lambda s: s.target.beta_v * s.target.a2 * s.target.AV,
        ),
        ReactionInteraction(
            'virus_clearance',
            target='tumour',
            reactants={'V': 1},
            propensity=lambda s: s.target.d1 * s.target.V,
        ),
        ReactionInteraction(
            'drug_clearance',
            target='tumour',
            reactants={'U': 1},
            propensity=lambda s: s.target.d_u * s.target.U,
        ),
        RateInteraction(
            'infusion',
            target='tumour',
            state='U',
            rate=lambda s: s.target.u1 * _infusion_shape(s, infusion),
        ),
    ]
    return System(elements=[tumour], interactions=interactions)

clonal_chemoimmunotherapy(A1=90000.0, A2=40000.0, E=500.0, *, c1=0.1, c3=0.1, u_chemo1=0.2, u_chemo2=0.02, u_vaccine=20.0)

Return two competing tumour clones, sensitive and resistant to chemotherapy, under a drug and a vaccine.

The chemotherapy kills the sensitive first clone ten times faster than the resistant second clone. Alone, it removes the sensitive clone and frees the resistant clone from competition, so the tumour relapses resistant. With the dendritic-cell vaccine, the recruited immune cells clear both clones. The book does not model the drugs, so their effects are constant rates, and their values are a choice. The competition rates take a value in the book's range of 0.01 to 1. Cells are counted, and time is in days.

Parameters:

Name Type Description Default
A1 float

The initial number of cells of the sensitive clone.

90000.0
A2 float

The initial number of cells of the resistant clone.

40000.0
E float

The initial number of immune cells.

500.0
c1 float

The competition of the second clone on the first.

0.1
c3 float

The competition of the first clone on the second.

0.1
u_chemo1 float

The chemotherapy kill rate of the first clone.

0.2
u_chemo2 float

The chemotherapy kill rate of the second clone.

0.02
u_vaccine float

The level of the immunotherapeutic agent.

20.0

Returns:

Name Type Description
system System

The model, with the clones tumour.A1 and tumour.A2 and the immune cells tumour.E.

Examples:

>>> from skcomplex.models.biology.oncology import clonal_chemoimmunotherapy
>>> clonal_chemoimmunotherapy(u_vaccine=0.0).elements[0].u_vaccine
0.0
Source code in src/skcomplex/models/biology/oncology/_combination_therapy.py
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
@register_model(
    field='biology/oncology',
    tags=('chemotherapy', 'immunotherapy', 'combination therapy', 'heterogeneity', 'resistance', 'ode'),
    references=(BOOK, 'Piretto, Delitala, and Ferraro 2018'),
    defaults={'until': 300.0, 'dt': 1.0},
)
def clonal_chemoimmunotherapy(
    A1: float = 9e4,
    A2: float = 4e4,
    E: float = 500.0,
    *,
    c1: float = 0.1,
    c3: float = 0.1,
    u_chemo1: float = 0.2,
    u_chemo2: float = 0.02,
    u_vaccine: float = 20.0,
) -> System:
    """Return two competing tumour clones, sensitive and resistant to chemotherapy, under a drug and a vaccine.

    The chemotherapy kills the sensitive first clone ten times faster than the resistant second clone. Alone, it
    removes the sensitive clone and frees the resistant clone from competition, so the tumour relapses resistant. With
    the dendritic-cell vaccine, the recruited immune cells clear both clones. The book does not model the drugs, so
    their effects are constant rates, and their values are a choice. The competition rates take a value in the book's
    range of 0.01 to 1. Cells are counted, and time is in days.

    Args:
        A1:
            The initial number of cells of the sensitive clone.

        A2:
            The initial number of cells of the resistant clone.

        E:
            The initial number of immune cells.

        c1:
            The competition of the second clone on the first.

        c3:
            The competition of the first clone on the second.

        u_chemo1:
            The chemotherapy kill rate of the first clone.

        u_chemo2:
            The chemotherapy kill rate of the second clone.

        u_vaccine:
            The level of the immunotherapeutic agent.

    Returns:
        system:
            The model, with the clones `tumour.A1` and `tumour.A2` and the immune cells `tumour.E`.

    Examples:
        >>> from skcomplex.models.biology.oncology import clonal_chemoimmunotherapy
        >>> clonal_chemoimmunotherapy(u_vaccine=0.0).elements[0].u_vaccine
        0.0
    """
    tumour = ClonalTumourElement(
        'tumour',
        A1=A1,
        A2=A2,
        E=E,
        c1=c1,
        c3=c3,
        u_chemo1=u_chemo1,
        u_chemo2=u_chemo2,
        u_vaccine=u_vaccine,
    )
    interactions = [
        RateInteraction(
            'first_growth',
            target='tumour',
            state='A1',
            rate=lambda s: s.target.r1 * s.target.A1 * (1 - s.target.b1 * s.target.A1),
        ),
        ReactionInteraction(
            'first_competition',
            target='tumour',
            reactants={'A1': 1},
            modifiers={'A2': 1},
            propensity=lambda s: s.target.c1 * s.target.A2 * s.target.b1 * s.target.A1,
        ),
        ReactionInteraction(
            'first_immune_kill',
            target='tumour',
            reactants={'A1': 1},
            modifiers={'E': 1},
            propensity=lambda s: s.target.c2 * s.target.E * s.target.b1 * s.target.A1,
        ),
        ReactionInteraction(
            'first_chemotherapy',
            target='tumour',
            reactants={'A1': 1},
            propensity=lambda s: s.target.u_chemo1 * s.target.A1,
        ),
        ReactionInteraction(
            'first_vaccine_kill',
            target='tumour',
            reactants={'A1': 1},
            modifiers={'E': 1},
            propensity=lambda s: s.target.b1 * s.target.u_vaccine * s.target.A1 * s.target.E,
        ),
        RateInteraction(
            'second_growth',
            target='tumour',
            state='A2',
            rate=lambda s: s.target.r2 * s.target.A2 * (1 - s.target.b2 * s.target.A2),
        ),
        ReactionInteraction(
            'second_competition',
            target='tumour',
            reactants={'A2': 1},
            modifiers={'A1': 1},
            propensity=lambda s: s.target.c3 * s.target.A1 * s.target.b2 * s.target.A2,
        ),
        ReactionInteraction(
            'second_immune_kill',
            target='tumour',
            reactants={'A2': 1},
            modifiers={'E': 1},
            propensity=lambda s: s.target.c4 * s.target.E * s.target.b2 * s.target.A2,
        ),
        ReactionInteraction(
            'second_chemotherapy',
            target='tumour',
            reactants={'A2': 1},
            propensity=lambda s: s.target.u_chemo2 * s.target.A2,
        ),
        ReactionInteraction(
            'second_vaccine_kill',
            target='tumour',
            reactants={'A2': 1},
            modifiers={'E': 1},
            propensity=lambda s: s.target.b2 * s.target.u_vaccine * s.target.A2 * s.target.E,
        ),
        RateInteraction(
            'immune_growth',
            target='tumour',
            state='E',
            rate=lambda s: s.target.r3 * s.target.E * (1 - s.target.E / s.target.theta),
        ),
        RateInteraction(
            'immune_stimulation',
            target='tumour',
            state='E',
            rate=lambda s: (s.target.s1 * s.target.A1 + s.target.s2 * s.target.A2) * s.target.E / s.target.theta,
        ),
    ]
    return System(elements=[tumour], interactions=interactions)

continuous_androgen_suppression(AD=10.0, AI=0.14, U=20.0, *, r1=0.025, r2=0.006, b=9.1e-11, c1=0.9, c2=0.8, d1=0.064, m1=5e-05, U0=20.0, du=0.08, a=0.9)

Return prostate cancer under continuous androgen suppression, which androgen-independent cells survive.

The suppression lowers the serum androgen from U0 to U0 (1 - a) at the rate du. The androgen-dependent cells grow in proportion to the androgen and die and turn independent in proportion to the deprivation 1 - U / U0, so they decline once the suppression is deep enough, while the independent cells grow regardless and cause the relapse. Cells are counted, androgen is in ng/mL, and time is in days. The book's efficacy lies between 0.6 and 0.9, and only the upper end makes the dependent cells decline.

Parameters:

Name Type Description Default
AD float

The initial androgen-dependent cells.

10.0
AI float

The initial androgen-independent cells.

0.14
U float

The initial serum androgen.

20.0
r1 float

The growth rate of the dependent cells per unit of androgen.

0.025
r2 float

The growth rate of the independent cells.

0.006
b float

The reciprocal carrying capacity.

9.1e-11
c1 float

The competition of the independent cells on the dependent ones.

0.9
c2 float

The competition of the dependent cells on the independent ones.

0.8
d1 float

The death rate of the dependent cells under androgen deprivation.

0.064
m1 float

The rate at which androgen deprivation turns dependent cells independent.

5e-05
U0 float

The normal androgen concentration.

20.0
du float

The elimination rate of the androgen.

0.08
a float

The efficacy of the suppression.

0.9

Returns:

Name Type Description
system System

The model, with the cells tumour.AD and tumour.AI and the androgen tumour.U.

Examples:

>>> from skcomplex.models.biology.oncology import continuous_androgen_suppression
>>> continuous_androgen_suppression(a=0.6).elements[0].a
0.6
Source code in src/skcomplex/models/biology/oncology/_hormone_therapy.py
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
@register_model(
    field='biology/oncology',
    tags=('hormone therapy', 'ode', 'prostate cancer', 'androgen'),
    references=(BOOK, 'Zazoua and Wang 2019'),
    defaults={'until': 1500.0, 'dt': 5.0},
)
def continuous_androgen_suppression(
    AD: float = 10.0,
    AI: float = 0.14,
    U: float = 20.0,
    *,
    r1: float = 0.025,
    r2: float = 0.006,
    b: float = 0.091e-9,
    c1: float = 0.9,
    c2: float = 0.8,
    d1: float = 0.064,
    m1: float = 5e-5,
    U0: float = 20.0,
    du: float = 0.08,
    a: float = 0.9,
) -> System:
    """Return prostate cancer under continuous androgen suppression, which androgen-independent cells survive.

    The suppression lowers the serum androgen from `U0` to `U0 (1 - a)` at the rate `du`. The androgen-dependent cells
    grow in proportion to the androgen and die and turn independent in proportion to the deprivation `1 - U / U0`, so
    they decline once the suppression is deep enough, while the independent cells grow regardless and cause the
    relapse. Cells are counted, androgen is in ng/mL, and time is in days. The book's efficacy lies between 0.6 and
    0.9, and only the upper end makes the dependent cells decline.

    Args:
        AD:
            The initial androgen-dependent cells.

        AI:
            The initial androgen-independent cells.

        U:
            The initial serum androgen.

        r1:
            The growth rate of the dependent cells per unit of androgen.

        r2:
            The growth rate of the independent cells.

        b:
            The reciprocal carrying capacity.

        c1:
            The competition of the independent cells on the dependent ones.

        c2:
            The competition of the dependent cells on the independent ones.

        d1:
            The death rate of the dependent cells under androgen deprivation.

        m1:
            The rate at which androgen deprivation turns dependent cells independent.

        U0:
            The normal androgen concentration.

        du:
            The elimination rate of the androgen.

        a:
            The efficacy of the suppression.

    Returns:
        system:
            The model, with the cells `tumour.AD` and `tumour.AI` and the androgen `tumour.U`.

    Examples:
        >>> from skcomplex.models.biology.oncology import continuous_androgen_suppression
        >>> continuous_androgen_suppression(a=0.6).elements[0].a
        0.6
    """
    tumour = AndrogenSuppressionElement(
        'tumour',
        AD=AD,
        AI=AI,
        U=U,
        r1=r1,
        r2=r2,
        b=b,
        c1=c1,
        c2=c2,
        d1=d1,
        m1=m1,
        U0=U0,
        du=du,
        a=a,
    )
    interactions = [
        RateInteraction(
            'dependent_growth',
            target='tumour',
            state='AD',
            rate=lambda s: s.target.r1
            * s.target.U
            * (1 - s.target.b * (s.target.AD + s.target.c1 * s.target.AI))
            * s.target.AD,
        ),
        ReactionInteraction(
            'deprivation_death',
            target='tumour',
            reactants={'AD': 1},
            propensity=lambda s: s.target.d1 * (1 - s.target.U / s.target.U0) * s.target.AD,
        ),
        ReactionInteraction(
            'mutation',
            target='tumour',
            reactants={'AD': 1},
            products={'AI': 1},
            propensity=lambda s: s.target.m1 * (1 - s.target.U / s.target.U0) * s.target.AD,
        ),
        RateInteraction(
            'independent_growth',
            target='tumour',
            state='AI',
            rate=lambda s: s.target.r2 * (1 - s.target.b * (s.target.AI + s.target.c2 * s.target.AD)) * s.target.AI,
        ),
        RateInteraction(
            'androgen_production',
            target='tumour',
            state='U',
            rate=lambda s: -s.target.du * (s.target.U - s.target.U0),
        ),
        RateInteraction(
            'suppression',
            target='tumour',
            state='U',
            rate=lambda s: -s.target.U0 * s.target.du * s.target.a,
        ),
    ]
    return System(elements=[tumour], interactions=interactions)

de_pillis_radunskaya(E=0.15, A=0.25, N=1.0, *, u=0.0, s=0.33, r1=1.5, a2=0.3)

Return the de Pillis-Radunskaya model of immune, tumour, and normal cells under a constant drug infusion.

The cells are normalised so that the carrying capacity of normal cells is 1, and time is in days. Untreated, a tumour that starts at 0.25 escapes the immune cells and settles at the high equilibrium where it outnumbers the normal cells. A constant infusion u = 1 clears it, while the normal cells stay above 0.7. The parameters are those of Table 3.3 of Padmanabhan et al. The book's initial tumour of 1e-5 lies in the basin of the tumour-free equilibrium, which is stable since r1 < c2 s / d1 + c3, so the defaults are the initial conditions of de Pillis and Radunskaya 2003, E = 0.15, A = 0.25, N = 1. The book prints no infusion schedule, so the infusion is a constant rate u per day, untreated by default.

Parameters:

Name Type Description Default
E float

The initial immune cells.

0.15
A float

The initial tumour cells.

0.25
N float

The initial normal cells.

1.0
u float

The constant infusion rate of the drug.

0.0
s float

The influx of immune cells.

0.33
r1 float

The growth rate of the tumour.

1.5
a2 float

The fraction of tumour cells the drug kills.

0.3

Returns:

Name Type Description
system System

The model, with the cells patient.E, patient.A, patient.N and the drug patient.U.

Examples:

>>> from skcomplex.models.biology.oncology import de_pillis_radunskaya
>>> de_pillis_radunskaya(u=1.0).elements[0].u
1.0
Source code in src/skcomplex/models/biology/oncology/_chemotherapy.py
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
@register_model(
    field='biology/oncology',
    tags=('chemotherapy', 'ode', 'tumour-immune', 'competition'),
    references=(BOOK, 'de Pillis and Radunskaya 2003'),
    defaults={'until': 150.0, 'dt': 0.5},
)
def de_pillis_radunskaya(
    E: float = 0.15,
    A: float = 0.25,
    N: float = 1.0,
    *,
    u: float = 0.0,
    s: float = 0.33,
    r1: float = 1.5,
    a2: float = 0.3,
) -> System:
    """Return the de Pillis-Radunskaya model of immune, tumour, and normal cells under a constant drug infusion.

    The cells are normalised so that the carrying capacity of normal cells is 1, and time is in days. Untreated, a
    tumour that starts at 0.25 escapes the immune cells and settles at the high equilibrium where it outnumbers the
    normal cells. A constant infusion `u = 1` clears it, while the normal cells stay above 0.7. The parameters are those
    of Table 3.3 of Padmanabhan et al. The book's initial tumour of `1e-5` lies in the basin of the tumour-free
    equilibrium, which is stable since `r1 < c2 s / d1 + c3`, so the defaults are the initial conditions of de Pillis
    and Radunskaya 2003, `E = 0.15`, `A = 0.25`, `N = 1`. The book prints no infusion schedule, so the infusion is a
    constant rate `u` per day, untreated by default.

    Args:
        E:
            The initial immune cells.

        A:
            The initial tumour cells.

        N:
            The initial normal cells.

        u:
            The constant infusion rate of the drug.

        s:
            The influx of immune cells.

        r1:
            The growth rate of the tumour.

        a2:
            The fraction of tumour cells the drug kills.

    Returns:
        system:
            The model, with the cells `patient.E`, `patient.A`, `patient.N` and the drug `patient.U`.

    Examples:
        >>> from skcomplex.models.biology.oncology import de_pillis_radunskaya
        >>> de_pillis_radunskaya(u=1.0).elements[0].u
        1.0
    """
    return System(elements=[TumourImmuneChemotherapyElement('patient', E=E, A=A, N=N, u=u, s=s, r1=r1, a2=a2)])

delayed_dc_vaccine(*, dose=1000000.0, period=7.0, width=1.0, start=0.0, doses=4, tau1=1.26, tau2=0.45, tau3=0.47)

Return a tumour and eight innate and adaptive immune populations, with division delays, under a vaccine.

Natural killer cells divide in tau1, CD8+ cells mature after seven divisions 7 tau2, and naive helper cells become type 1 helper cells after two divisions 2 tau3. Regulatory T cells, driven by the tumour and IL-2, inhibit natural killer, CD8+, and helper cells. The book's growth term m1 ED E of mature CD8+ cells has no saturation and makes them diverge within a day, so it saturates in the dendritic cells as m1 ED E / (g3 + ED), like every other term the dendritic cells drive. The book gives no schedule, and the vaccine is a one-day injection of dose dendritic cells per day every week, 4 times. The parameters and initial state are the book's, and with them the regulatory T cells hold the adaptive response down, so the tumour grows toward its capacity b. Cells are counts, IL-2 is in IU/L, and time in days.

Parameters:

Name Type Description Default
dose float

The injection rate of dendritic cells during a dose, 0 for no vaccine.

1000000.0
period float

The time between the starts of doses.

7.0
width float

The duration of a dose.

1.0
start float

The time of the first dose.

0.0
doses int

The number of doses.

4
tau1 float

The division time of natural killer cells.

1.26
tau2 float

The division time of CD8+ cells.

0.45
tau3 float

The division time of helper cells.

0.47

Returns:

Name Type Description
system System

The model, with the tumour site.A, the natural killer cells site.ENK, the naive and mature CD8+ cells site.ENC and site.E, the dendritic cells site.ED, the IL-2 site.C, the regulatory cells site.ER, and the naive and type 1 helper cells site.ENH and site.E1H.

Examples:

>>> from skcomplex.models.biology.oncology import delayed_dc_vaccine
>>> delayed_dc_vaccine(tau2=0.5).elements[0].tau2
0.5
Source code in src/skcomplex/models/biology/oncology/_immunotherapy.py
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
@register_model(
    field='biology/oncology',
    tags=('immunotherapy', 'delay', 'vaccine', 'dendritic cells', 'regulatory T cells'),
    references=(BOOK_REFERENCE, 'Qomlaqi et al. 2017'),
    defaults={'until': 30.0, 'dt': 0.1, 'solver': STIFF_SOLVER},
)
def delayed_dc_vaccine(
    *,
    dose: float = 1e6,
    period: float = 7.0,
    width: float = 1.0,
    start: float = 0.0,
    doses: int = 4,
    tau1: float = 1.26,
    tau2: float = 0.45,
    tau3: float = 0.47,
) -> System:
    """Return a tumour and eight innate and adaptive immune populations, with division delays, under a vaccine.

    Natural killer cells divide in `tau1`, CD8+ cells mature after seven divisions `7 tau2`, and naive helper cells
    become type 1 helper cells after two divisions `2 tau3`. Regulatory T cells, driven by the tumour and IL-2, inhibit
    natural killer, CD8+, and helper cells. The book's growth term `m1 ED E` of mature CD8+ cells has no saturation and
    makes them diverge within a day, so it saturates in the dendritic cells as `m1 ED E / (g3 + ED)`, like every other
    term the dendritic cells drive. The book gives no schedule, and the vaccine is a one-day injection of `dose`
    dendritic cells per day every week, 4 times. The parameters and initial state are the book's, and with them the
    regulatory T cells hold the adaptive response down, so the tumour grows toward its capacity `b`. Cells are counts,
    IL-2 is in IU/L, and time in days.

    Args:
        dose:
            The injection rate of dendritic cells during a dose, 0 for no vaccine.

        period:
            The time between the starts of doses.

        width:
            The duration of a dose.

        start:
            The time of the first dose.

        doses:
            The number of doses.

        tau1:
            The division time of natural killer cells.

        tau2:
            The division time of CD8+ cells.

        tau3:
            The division time of helper cells.

    Returns:
        system:
            The model, with the tumour `site.A`, the natural killer cells `site.ENK`, the naive and mature CD8+ cells
            `site.ENC` and `site.E`, the dendritic cells `site.ED`, the IL-2 `site.C`, the regulatory cells `site.ER`,
            and the naive and type 1 helper cells `site.ENH` and `site.E1H`.

    Examples:
        >>> from skcomplex.models.biology.oncology import delayed_dc_vaccine
        >>> delayed_dc_vaccine(tau2=0.5).elements[0].tau2
        0.5
    """
    site = DelayedVaccinatedTumourElement(
        'site',
        dose=dose,
        period=period,
        width=width,
        start=start,
        doses=doses,
        tau1=tau1,
        tau2=tau2,
        tau3=tau3,
    )
    interactions = [
        RateInteraction(
            'tumour_growth',
            target='site',
            state='A',
            rate=lambda s: s.target.r1 * s.target.A * log(s.target.b / s.target.A),
        ),
        ReactionInteraction(
            'cytotoxic_kill',
            target='site',
            reactants={'A': 1},
            modifiers={'E': 1},
            propensity=lambda s: s.target.a1
            * (log(s.target.E) / log(s.target.A)) ** 5
            / ((log(s.target.E) / log(s.target.A)) ** 5 + s.target.g1)
            * s.target.A,
        ),
        ReactionInteraction(
            'nk_kill',
            target='site',
            reactants={'A': 1},
            modifiers={'ENK': 1},
            propensity=lambda s: s.target.a2 * s.target.ENK * s.target.A,
        ),
        DosingInteraction('nk_influx', target='site', state='ENK', dose=lambda s: s.target.s1),
        ReactionInteraction(
            'nk_death',
            target='site',
            reactants={'ENK': 1},
            propensity=lambda s: s.target.d1 * s.target.ENK,
        ),
        RateInteraction(
            'nk_proliferation',
            target='site',
            state='ENK',
            rate=lambda s: s.target.rho1
            * delayed(s.target.ENK, s.target.tau1)
            * delayed(s.target.C, s.target.tau1)
            / (s.target.g2 + delayed(s.target.C, s.target.tau1)),
        ),
        ReactionInteraction(
            'nk_suppression',
            target='site',
            reactants={'ENK': 1},
            modifiers={'ER': 1},
            propensity=lambda s: s.target.psi1 * s.target.ENK * s.target.ER,
        ),
        DosingInteraction('naive_cytotoxic_influx', target='site', state='ENC', dose=lambda s: s.target.s2),
        ReactionInteraction(
            'naive_cytotoxic_death',
            target='site',
            reactants={'ENC': 1},
            propensity=lambda s: s.target.d2 * s.target.ENC,
        ),
        MichaelisMentenInteraction(
            'cytotoxic_priming',
            target='site',
            reactants={'ENC': 1},
            modifiers={'ENC': 1},
            substrate='ED',
            vmax=lambda s: s.target.rho2,
            km=lambda s: s.target.g3,
        ),
        ReactionInteraction(
            'cytotoxic_death',
            target='site',
            reactants={'E': 1},
            propensity=lambda s: s.target.d3 * s.target.E,
        ),
        RateInteraction(
            'primed_expansion',
            target='site',
            state='E',
            rate=lambda s: s.target.rho3
            * delayed(s.target.ENC, 7 * s.target.tau2, 7 * tau2)
            * delayed(s.target.ED, 7 * s.target.tau2, 7 * tau2)
            / (s.target.g3 + delayed(s.target.ED, 7 * s.target.tau2, 7 * tau2)),
        ),
        RateInteraction(
            'dendritic_expansion',
            target='site',
            state='E',
            rate=lambda s: s.target.m1
            * delayed(s.target.ED, s.target.tau2)
            * delayed(s.target.E, s.target.tau2)
            / (s.target.g3 + delayed(s.target.ED, s.target.tau2)),
        ),
        RateInteraction(
            'il2_expansion',
            target='site',
            state='E',
            rate=lambda s: s.target.rho4
            * delayed(s.target.E, s.target.tau2)
            * delayed(s.target.C, s.target.tau2) ** 2
            / (s.target.g4 + delayed(s.target.C, s.target.tau2) ** 2),
        ),
        ReactionInteraction(
            'cytotoxic_suppression',
            target='site',
            reactants={'E': 1},
            modifiers={'ER': 1},
            propensity=lambda s: s.target.psi2 * s.target.E * s.target.ER,
        ),
        ReactionInteraction(
            'dendritic_death',
            target='site',
            reactants={'ED': 1},
            propensity=lambda s: s.target.d4 * s.target.ED,
        ),
        MichaelisMentenInteraction(
            'antigen_presentation',
            target='site',
            products={'ED': 1},
            substrate='A',
            vmax=lambda s: s.target.kappa1,
            km=lambda s: s.target.g5,
        ),
        DosingInteraction(
            'vaccine',
            target='site',
            state='ED',
            dose=lambda s: s.target.dose,
            period=period,
            width=width,
            start=start,
            count=doses,
        ),
        DosingInteraction('il2_influx', target='site', state='C', dose=lambda s: s.target.s3),
        ReactionInteraction(
            'il2_loss',
            target='site',
            reactants={'C': 1},
            propensity=lambda s: s.target.d5 * s.target.C,
        ),
        RateInteraction(
            'cytotoxic_secretion',
            target='site',
            state='C',
            rate=lambda s: s.target.rho5 * s.target.E**2 * s.target.C / (s.target.g6 + s.target.E**2),
        ),
        MichaelisMentenInteraction(
            'helper_secretion',
            target='site',
            products={'C': 1},
            modifiers={'C': 1},
            substrate='E1H',
            vmax=lambda s: s.target.rho6,
            km=lambda s: s.target.g7,
        ),
        DosingInteraction('regulatory_influx', target='site', state='ER', dose=lambda s: s.target.s4),
        ReactionInteraction(
            'regulatory_death',
            target='site',
            reactants={'ER': 1},
            propensity=lambda s: s.target.d6 * s.target.ER,
        ),
        RateInteraction(
            'antigen_expansion',
            target='site',
            state='ER',
            rate=lambda s: s.target.rho7
            * delayed(s.target.ER, s.target.tau3)
            * delayed(s.target.A, s.target.tau3) ** 2
            / (s.target.g8 + delayed(s.target.A, s.target.tau3) ** 2),
        ),
        RateInteraction(
            'il2_regulatory_expansion',
            target='site',
            state='ER',
            rate=lambda s: s.target.rho8
            * delayed(s.target.ER, s.target.tau3)
            * delayed(s.target.C, s.target.tau3)
            / (s.target.g9 + delayed(s.target.C, s.target.tau3)),
        ),
        DosingInteraction('naive_helper_influx', target='site', state='ENH', dose=lambda s: s.target.s5),
        ReactionInteraction(
            'naive_helper_death',
            target='site',
            reactants={'ENH': 1},
            propensity=lambda s: s.target.d7 * s.target.ENH,
        ),
        MichaelisMentenInteraction(
            'helper_priming',
            target='site',
            reactants={'ENH': 1},
            modifiers={'ENH': 1},
            substrate='ED',
            vmax=lambda s: s.target.rho9,
            km=lambda s: s.target.g3,
        ),
        ReactionInteraction(
            'helper_death',
            target='site',
            reactants={'E1H': 1},
            propensity=lambda s: s.target.d8 * s.target.E1H,
        ),
        RateInteraction(
            'primed_helper_expansion',
            target='site',
            state='E1H',
            rate=lambda s: s.target.m2
            * delayed(s.target.ED, 2 * s.target.tau3, 2 * tau3)
            * delayed(s.target.ENH, 2 * s.target.tau3, 2 * tau3)
            / (s.target.g3 + delayed(s.target.ED, 2 * s.target.tau3, 2 * tau3)),
        ),
        ReactionInteraction(
            'helper_suppression',
            target='site',
            reactants={'E1H': 1},
            modifiers={'ER': 1},
            propensity=lambda s: s.target.psi3 * s.target.ER * s.target.E1H,
        ),
        RateInteraction(
            'helper_expansion',
            target='site',
            state='E1H',
            rate=lambda s: s.target.rho10
            * delayed(s.target.ED, s.target.tau3)
            * delayed(s.target.E, s.target.tau3)
            / (s.target.g3 + delayed(s.target.ED, s.target.tau3)),
        ),
    ]
    return System(elements=[site], interactions=interactions)

delayed_metastasis(Np=1460.0, Ap=165.0, Ns=1750.0, As=0.0, *, up=0.0, us=0.0, tau=1.0)

Return normal and tumour cells at a primary and a secondary site, with a delayed migration of tumour cells.

Untreated, the faster tumour cells outcompete the normal cells at the primary site, and the cells that migrate seed a tumour that does the same at the secondary site. The parameters are those of Table 3.7 of Padmanabhan et al., with time in days, and the initial cells are at the upper ends of the book's ranges with the secondary site free of tumour. The book prints the kill at the secondary site with the infusion us in place of the concentration Us, so the model uses Us as at the primary site. The infusions are constant rates, untreated by default, within the book's range of 0 to 650.

Parameters:

Name Type Description Default
Np float

The initial normal cells at the primary site.

1460.0
Ap float

The initial tumour cells at the primary site, also their history.

165.0
Ns float

The initial normal cells at the secondary site.

1750.0
As float

The initial tumour cells at the secondary site.

0.0
up float

The infusion rate of the drug at the primary site.

0.0
us float

The infusion rate of the drug at the secondary site.

0.0
tau float

The delay of the migration.

1.0

Returns:

Name Type Description
system System

The model, with the cells patient.Np, patient.Ap, patient.Ns, patient.As and the drugs patient.Up and patient.Us.

Examples:

>>> from skcomplex.models.biology.oncology import delayed_metastasis
>>> delayed_metastasis(up=650.0).elements[0].up
650.0
Source code in src/skcomplex/models/biology/oncology/_chemotherapy.py
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
@register_model(
    field='biology/oncology',
    tags=('chemotherapy', 'dde', 'delay', 'metastasis'),
    references=(BOOK, 'Pinho, Freedman, and Nani 2002'),
    defaults={'until': 10.0, 'dt': 0.05},
)
def delayed_metastasis(
    Np: float = 1460.0,
    Ap: float = 165.0,
    Ns: float = 1750.0,
    As: float = 0.0,
    *,
    up: float = 0.0,
    us: float = 0.0,
    tau: float = 1.0,
) -> System:
    """Return normal and tumour cells at a primary and a secondary site, with a delayed migration of tumour cells.

    Untreated, the faster tumour cells outcompete the normal cells at the primary site, and the cells that migrate seed
    a tumour that does the same at the secondary site. The parameters are those of Table 3.7 of Padmanabhan et al.,
    with time in days, and the initial cells are at the upper ends of the book's ranges with the secondary site free
    of tumour. The book prints the kill at the secondary site with the infusion `us` in place of the concentration
    `Us`, so the model uses `Us` as at the primary site. The infusions are constant rates, untreated by default, within
    the book's range of 0 to 650.

    Args:
        Np:
            The initial normal cells at the primary site.

        Ap:
            The initial tumour cells at the primary site, also their history.

        Ns:
            The initial normal cells at the secondary site.

        As:
            The initial tumour cells at the secondary site.

        up:
            The infusion rate of the drug at the primary site.

        us:
            The infusion rate of the drug at the secondary site.

        tau:
            The delay of the migration.

    Returns:
        system:
            The model, with the cells `patient.Np`, `patient.Ap`, `patient.Ns`, `patient.As` and the drugs
            `patient.Up` and `patient.Us`.

    Examples:
        >>> from skcomplex.models.biology.oncology import delayed_metastasis
        >>> delayed_metastasis(up=650.0).elements[0].up
        650.0
    """
    patient = MetastasisChemotherapyElement('patient', Np=Np, Ap=Ap, Ns=Ns, As=As, up=up, us=us, tau=tau)

    def population(cells: str, other: str, drug: str, index: int, uptake: str) -> list[BaseInteraction]:
        """Return the growth, the competition, the drug kill, and the drug uptake of the cells of a site."""
        return [
            RateInteraction(
                f'growth_{cells}',
                target='patient',
                state=cells,
                rate=lambda s: getattr(s.target, f'r{index}')
                * getattr(s.target, cells)
                * (1 - getattr(s.target, f'b{index}') * getattr(s.target, cells)),
            ),
            ReactionInteraction(
                f'competition_{cells}',
                target='patient',
                reactants={cells: 1},
                modifiers={other: 1},
                propensity=lambda s: getattr(s.target, f'c{index}')
                * getattr(s.target, cells)
                * getattr(s.target, other),
            ),
            MichaelisMentenInteraction(
                f'drug_kill_{cells}',
                target='patient',
                reactants={cells: 1},
                substrate=cells,
                vmax=lambda s: getattr(s.target, f'a{index}'),
                km=lambda s: s.target.bc,
                modifiers={drug: 1},
            ),
            MichaelisMentenInteraction(
                f'drug_uptake_{cells}',
                target='patient',
                reactants={drug: 1},
                substrate=cells,
                vmax=lambda s: getattr(s.target, uptake),
                km=lambda s: s.target.bc,
                modifiers={drug: 1},
            ),
        ]

    def drug(name: str, dose: str) -> list[BaseInteraction]:
        """Return the infusion and the clearance of the drug at a site."""
        return [
            DosingInteraction(f'infusion_{name}', target='patient', state=name, dose=lambda s: getattr(s.target, dose)),
            ReactionInteraction(
                f'clearance_{name}',
                target='patient',
                reactants={name: 1},
                propensity=lambda s: s.target.k * getattr(s.target, name),
            ),
        ]

    interactions = [
        *population('Np', 'Ap', 'Up', 1, 'g1'),
        *population('Ap', 'Np', 'Up', 2, 'g2'),
        *population('Ns', 'As', 'Us', 3, 'g3'),
        *population('As', 'Ns', 'Us', 4, 'g4'),
        *drug('Up', 'up'),
        *drug('Us', 'us'),
    ]
    interactions += [
        ReactionInteraction(
            'emigration',
            target='patient',
            reactants={'Ap': 1},
            propensity=lambda s: s.target.delta * s.target.Ap,
        ),
        RateInteraction(
            'arrival',
            target='patient',
            state='As',
            rate=lambda s: s.target.epsilon * s.target.delta * delayed(s.target.Ap, s.target.tau),
        ),
    ]
    return System(elements=[patient], interactions=interactions)

delayed_resting_hunting_chemotherapy(E=0.01, Q=0.48, A=0.18, *, u=0.0, tau=45.6, a=0.001)

Return the tumour-immune model of resting and hunting cells with a conversion delay, under a drug infusion.

Resting immune cells become hunting cells after the delay tau, and hunting cells kill the tumour. Time and the cells are dimensionless. The parameters and initial conditions are those of Table 3.6 of Padmanabhan et al., and the infusion is a constant rate u, untreated by default, within the book's range of 0 to 0.03.

Parameters:

Name Type Description Default
E float

The initial hunting cells.

0.01
Q float

The initial resting cells, also their history.

0.48
A float

The initial tumour cells.

0.18
u float

The constant infusion rate of the drug.

0.0
tau float

The delay of the conversion of resting cells to hunting cells.

45.6
a float

The kill rate of the drug on every population.

0.001

Returns:

Name Type Description
system System

The model, with the cells patient.E, patient.Q, patient.A and the drug patient.U.

Examples:

>>> from skcomplex.models.biology.oncology import delayed_resting_hunting_chemotherapy
>>> delayed_resting_hunting_chemotherapy(tau=10.0).elements[0].tau
10.0
Source code in src/skcomplex/models/biology/oncology/_chemotherapy.py
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
@register_model(
    field='biology/oncology',
    tags=('chemotherapy', 'dde', 'delay', 'tumour-immune'),
    references=(BOOK, 'Banerjee and Sarkar 2008', 'Borges et al. 2014'),
    defaults={'until': 1500.0, 'dt': 5.0},
)
def delayed_resting_hunting_chemotherapy(
    E: float = 0.01,
    Q: float = 0.48,
    A: float = 0.18,
    *,
    u: float = 0.0,
    tau: float = 45.6,
    a: float = 0.001,
) -> System:
    """Return the tumour-immune model of resting and hunting cells with a conversion delay, under a drug infusion.

    Resting immune cells become hunting cells after the delay `tau`, and hunting cells kill the tumour. Time and the
    cells are dimensionless. The parameters and initial conditions are those of Table 3.6 of Padmanabhan et al., and
    the infusion is a constant rate `u`, untreated by default, within the book's range of 0 to 0.03.

    Args:
        E:
            The initial hunting cells.

        Q:
            The initial resting cells, also their history.

        A:
            The initial tumour cells.

        u:
            The constant infusion rate of the drug.

        tau:
            The delay of the conversion of resting cells to hunting cells.

        a:
            The kill rate of the drug on every population.

    Returns:
        system:
            The model, with the cells `patient.E`, `patient.Q`, `patient.A` and the drug `patient.U`.

    Examples:
        >>> from skcomplex.models.biology.oncology import delayed_resting_hunting_chemotherapy
        >>> delayed_resting_hunting_chemotherapy(tau=10.0).elements[0].tau
        10.0
    """
    patient = RestingHuntingChemotherapyElement('patient', E=E, Q=Q, A=A, u=u, tau=tau, a=a)
    drug_effects = [
        interaction
        for name in ('E', 'Q', 'A')
        for interaction in (
            MichaelisMentenInteraction(
                f'drug_kill_{name}',
                target='patient',
                reactants={name: 1},
                substrate=name,
                vmax=lambda s: s.target.a,
                km=lambda s: s.target.bd,
                modifiers={'U': 1},
            ),
            MichaelisMentenInteraction(
                f'drug_uptake_{name}',
                target='patient',
                reactants={'U': 1},
                substrate=name,
                vmax=lambda s: s.target.g,
                km=lambda s: s.target.bd,
                modifiers={'U': 1},
            ),
        )
    ]
    interactions = [
        ReactionInteraction(
            'recruitment',
            target='patient',
            reactants={'Q': 1},
            products={'E': 1},
            modifiers={'E': 1},
            propensity=lambda s: s.target.m1 * s.target.E * delayed(s.target.Q, s.target.tau),
        ),
        ReactionInteraction(
            'effector_death',
            target='patient',
            reactants={'E': 1},
            propensity=lambda s: s.target.d1 * s.target.E,
        ),
        ReactionInteraction(
            'effector_inactivation',
            target='patient',
            reactants={'E': 1},
            modifiers={'A': 1},
            propensity=lambda s: s.target.c1 * s.target.A * s.target.E,
        ),
        RateInteraction(
            'resting_growth',
            target='patient',
            state='Q',
            rate=lambda s: s.target.r1 * s.target.Q * (1 - s.target.b1 * s.target.Q),
        ),
        RateInteraction(
            'tumour_growth',
            target='patient',
            state='A',
            rate=lambda s: s.target.r2 * s.target.A * (1 - s.target.b2 * s.target.A),
        ),
        ReactionInteraction(
            'tumour_kill',
            target='patient',
            reactants={'A': 1},
            modifiers={'E': 1},
            propensity=lambda s: s.target.c2 * s.target.A * s.target.E,
        ),
        DosingInteraction('infusion', target='patient', state='U', dose=lambda s: s.target.u),
        ReactionInteraction(
            'clearance',
            target='patient',
            reactants={'U': 1},
            propensity=lambda s: s.target.k * s.target.U,
        ),
        *drug_effects,
    ]
    return System(elements=[patient], interactions=interactions)

dendritic_cell_vaccine(A=0.1, *, rho2=10.0, r4=0.01, dose=0.5, period=168.0, width=1.0, start=0.0, doses=8)

Return helper and cytotoxic T cells, a tumour, dendritic cells, and IL-2 under a dendritic-cell vaccine.

Vaccinated dendritic cells drive the proliferation of helper cells, which secrete IL-2, and IL-2 with the antigen drives the proliferation of cytotoxic cells, which kill the tumour. The book gives no initial state or schedule. The T cells start at their resting level s / d = 0.02, the dendritic cells and IL-2 at 0, and the vaccine is a one-hour injection of dose per hour every week, 8 times. Without vaccine the tumour settles at 1 - c1 s2 / (d2 r3) = 0.9. The populations are in cells per mm³ scaled by the carrying capacity, IL-2 in pg/mm³, and time in hours.

Parameters:

Name Type Description Default
A float

The initial tumour cells.

0.1
rho2 float

The proliferation constant of cytotoxic T cells.

10.0
r4 float

The IL-2 secretion rate.

0.01
dose float

The injection rate of dendritic cells during a dose, 0 for no vaccine.

0.5
period float

The time between the starts of doses.

168.0
width float

The duration of a dose.

1.0
start float

The time of the first dose.

0.0
doses int

The number of doses.

8

Returns:

Name Type Description
system System

The model, with the helper cells site.EH, the cytotoxic cells site.E, the tumour site.A, the dendritic cells site.ED, and the IL-2 site.C.

Examples:

>>> from skcomplex.models.biology.oncology import dendritic_cell_vaccine
>>> dendritic_cell_vaccine(dose=0.0).elements[0].dose
0.0
Source code in src/skcomplex/models/biology/oncology/_immunotherapy.py
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
@register_model(
    field='biology/oncology',
    tags=('immunotherapy', 'ode', 'vaccine', 'dendritic cells', 'dosing'),
    references=(BOOK_REFERENCE, 'Castiglione and Piccoli 2006'),
    defaults={'until': 2880.0, 'dt': 2.0, 'solver': STIFF_SOLVER},
)
def dendritic_cell_vaccine(
    A: float = 0.1,
    *,
    rho2: float = 10.0,
    r4: float = 1e-2,
    dose: float = 0.5,
    period: float = 168.0,
    width: float = 1.0,
    start: float = 0.0,
    doses: int = 8,
) -> System:
    """Return helper and cytotoxic T cells, a tumour, dendritic cells, and IL-2 under a dendritic-cell vaccine.

    Vaccinated dendritic cells drive the proliferation of helper cells, which secrete IL-2, and IL-2 with the antigen
    drives the proliferation of cytotoxic cells, which kill the tumour. The book gives no initial state or schedule.
    The T cells start at their resting level `s / d = 0.02`, the dendritic cells and IL-2 at 0, and the vaccine is a
    one-hour injection of `dose` per hour every week, 8 times. Without vaccine the tumour settles at
    `1 - c1 s2 / (d2 r3) = 0.9`. The populations are in cells per mm³ scaled by the carrying capacity, IL-2 in
    pg/mm³, and time in hours.

    Args:
        A:
            The initial tumour cells.

        rho2:
            The proliferation constant of cytotoxic T cells.

        r4:
            The IL-2 secretion rate.

        dose:
            The injection rate of dendritic cells during a dose, 0 for no vaccine.

        period:
            The time between the starts of doses.

        width:
            The duration of a dose.

        start:
            The time of the first dose.

        doses:
            The number of doses.

    Returns:
        system:
            The model, with the helper cells `site.EH`, the cytotoxic cells `site.E`, the tumour `site.A`, the
            dendritic cells `site.ED`, and the IL-2 `site.C`.

    Examples:
        >>> from skcomplex.models.biology.oncology import dendritic_cell_vaccine
        >>> dendritic_cell_vaccine(dose=0.0).elements[0].dose
        0.0
    """
    site = VaccinatedTumourElement(
        'site',
        A=A,
        rho2=rho2,
        r4=r4,
        dose=dose,
        period=period,
        width=width,
        start=start,
        doses=doses,
    )
    interactions = [
        DosingInteraction('helper_influx', target='site', state='EH', dose=lambda s: s.target.s1),
        RateInteraction(
            'helper_proliferation',
            target='site',
            state='EH',
            rate=lambda s: s.target.rho1 * s.target.ED * s.target.r1 * s.target.EH * (1 - s.target.b1 * s.target.EH),
        ),
        ReactionInteraction(
            'helper_death',
            target='site',
            reactants={'EH': 1},
            propensity=lambda s: s.target.d1 * s.target.EH,
        ),
        DosingInteraction('cytotoxic_influx', target='site', state='E', dose=lambda s: s.target.s2),
        RateInteraction(
            'cytotoxic_proliferation',
            target='site',
            state='E',
            rate=lambda s: s.target.rho2
            * s.target.C
            * (s.target.A + s.target.ED)
            * s.target.r2
            * s.target.E
            * (1 - s.target.b2 * s.target.E),
        ),
        ReactionInteraction(
            'cytotoxic_death',
            target='site',
            reactants={'E': 1},
            propensity=lambda s: s.target.d2 * s.target.E,
        ),
        RateInteraction(
            'tumour_growth',
            target='site',
            state='A',
            rate=lambda s: s.target.r3 * s.target.A * (1 - s.target.b3 * s.target.A),
        ),
        ReactionInteraction(
            'kill',
            target='site',
            reactants={'A': 1},
            modifiers={'E': 1},
            propensity=lambda s: s.target.c1 * s.target.A * s.target.E,
        ),
        DosingInteraction(
            'vaccine',
            target='site',
            state='ED',
            dose=lambda s: s.target.dose,
            period=period,
            width=width,
            start=start,
            count=doses,
        ),
        ReactionInteraction(
            'dendritic_kill',
            target='site',
            reactants={'ED': 1},
            modifiers={'E': 1},
            propensity=lambda s: s.target.c2 * s.target.E * s.target.ED,
        ),
        RateInteraction(
            'il2_production',
            target='site',
            state='C',
            rate=lambda s: s.target.r4 * s.target.EH * s.target.ED,
        ),
        ReactionInteraction(
            'il2_consumption',
            target='site',
            reactants={'C': 1},
            modifiers={'E': 1},
            propensity=lambda s: s.target.c3 * s.target.E * s.target.C,
        ),
        ReactionInteraction(
            'il2_loss',
            target='site',
            reactants={'C': 1},
            propensity=lambda s: s.target.d3 * s.target.C,
        ),
    ]
    return System(elements=[site], interactions=interactions)

drug_resistance_switching(S=0.01, *, u=1.0, m1=1e-06, m2=0.0, alpha_m=0.01, alpha_p=0.0, m5=0.0, r2=0.2, r3=0.2)

Return sensitive cells and cells resistant by mutation or by a reversible phenotype switch under a dose.

The drug kills the sensitive cells, so the resistant cells, which grow slower, take the tumour over. Resistance is acquired spontaneously at the rates m1 and m2 and induced by the drug at the rates alpha_m and alpha_p per unit of dose, and switched cells return to sensitivity at the rate m5. Time and the cells are dimensionless, the carrying capacity being 1. The book gives values only for the two-population model of Greene, Sanchez-Tapia, and Sontag, its Table 3.5, which is this model without switched cells. The defaults are that model, with the induced rate alpha_m = 0.01 of the table and an effective dose of 1, so switching is off until m2, alpha_p, or m5 is set.

Parameters:

Name Type Description Default
S float

The initial sensitive cells, the resistant cells starting at 0.

0.01
u float

The effective dose.

1.0
m1 float

The rate of spontaneous resistance by mutation.

1e-06
m2 float

The rate of spontaneous resistance by phenotype switching.

0.0
alpha_m float

The rate per unit of dose of resistance induced by mutation.

0.01
alpha_p float

The rate per unit of dose of resistance induced by phenotype switching.

0.0
m5 float

The rate at which switched cells become sensitive again.

0.0
r2 float

The growth rate of mutated cells relative to sensitive cells.

0.2
r3 float

The growth rate of switched cells relative to sensitive cells.

0.2

Returns:

Name Type Description
system System

The model, with the cells tumour.S, tumour.Rm, and tumour.Rp.

Examples:

>>> from skcomplex.models.biology.oncology import drug_resistance_switching
>>> drug_resistance_switching(alpha_m=0.0).elements[0].alpha_m
0.0
Source code in src/skcomplex/models/biology/oncology/_chemotherapy.py
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
@register_model(
    field='biology/oncology',
    tags=('chemotherapy', 'ode', 'drug resistance', 'phenotype switching'),
    references=(BOOK, 'Greene, Sanchez-Tapia, and Sontag 2018', 'Greene, Gevertz, and Sontag 2019'),
    defaults={'until': 400.0, 'dt': 1.0},
)
def drug_resistance_switching(
    S: float = 0.01,
    *,
    u: float = 1.0,
    m1: float = 1e-6,
    m2: float = 0.0,
    alpha_m: float = 0.01,
    alpha_p: float = 0.0,
    m5: float = 0.0,
    r2: float = 0.2,
    r3: float = 0.2,
) -> System:
    """Return sensitive cells and cells resistant by mutation or by a reversible phenotype switch under a dose.

    The drug kills the sensitive cells, so the resistant cells, which grow slower, take the tumour over. Resistance is
    acquired spontaneously at the rates `m1` and `m2` and induced by the drug at the rates `alpha_m` and `alpha_p` per
    unit of dose, and switched cells return to sensitivity at the rate `m5`. Time and the cells are dimensionless, the
    carrying capacity being 1. The book gives values only for the two-population model of Greene, Sanchez-Tapia, and
    Sontag, its Table 3.5, which is this model without switched cells. The defaults are that model, with the
    induced rate `alpha_m = 0.01` of the table and an effective dose of 1, so switching is off until `m2`, `alpha_p`,
    or `m5` is set.

    Args:
        S:
            The initial sensitive cells, the resistant cells starting at 0.

        u:
            The effective dose.

        m1:
            The rate of spontaneous resistance by mutation.

        m2:
            The rate of spontaneous resistance by phenotype switching.

        alpha_m:
            The rate per unit of dose of resistance induced by mutation.

        alpha_p:
            The rate per unit of dose of resistance induced by phenotype switching.

        m5:
            The rate at which switched cells become sensitive again.

        r2:
            The growth rate of mutated cells relative to sensitive cells.

        r3:
            The growth rate of switched cells relative to sensitive cells.

    Returns:
        system:
            The model, with the cells `tumour.S`, `tumour.Rm`, and `tumour.Rp`.

    Examples:
        >>> from skcomplex.models.biology.oncology import drug_resistance_switching
        >>> drug_resistance_switching(alpha_m=0.0).elements[0].alpha_m
        0.0
    """
    tumour = ResistanceSwitchingElement(
        'tumour',
        S=S,
        u=u,
        m1=m1,
        m2=m2,
        alpha_m=alpha_m,
        alpha_p=alpha_p,
        m5=m5,
        r2=r2,
        r3=r3,
    )
    return System(elements=[tumour])

dynamic_carrying_capacity(n=1.0, K=12.7, *, r=2.63, d=0.829)

Return Gompertz growth under a carrying capacity that the vessels on the tumour surface keep raising.

The tumour follows dn/dt = r n log(K / n) and the capacity dK/dt = d n^(2/3), so the tumour first fills its initial capacity and then grows as fast as its vasculature, roughly as t^3. The defaults are the fit to breast cancer volumes in mm³ and days.

Parameters:

Name Type Description Default
n float

The initial volume.

1.0
K float

The initial carrying capacity.

12.7
r float

The rate at which the growth slows.

2.63
d float

The rate at which the surface of the tumour raises the capacity.

0.829

Returns:

Name Type Description
system System

The model, with the volume tumour.n and the capacity vessels.K.

Examples:

>>> from skcomplex.models.biology.oncology import dynamic_carrying_capacity
>>> dynamic_carrying_capacity().elements[1].K
12.7
Source code in src/skcomplex/models/biology/oncology/_growth.py
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
@register_model(
    field='biology/oncology',
    tags=('tumour growth', 'ode', 'angiogenesis', 'sigmoid'),
    references=(*GROWTH_REFERENCES, 'Hahnfeldt et al. 1999'),
    defaults={'until': 20.0, 'dt': 0.05},
)
def dynamic_carrying_capacity(n: float = 1.0, K: float = 12.7, *, r: float = 2.63, d: float = 0.829) -> System:
    """Return Gompertz growth under a carrying capacity that the vessels on the tumour surface keep raising.

    The tumour follows `dn/dt = r n log(K / n)` and the capacity `dK/dt = d n^(2/3)`, so the tumour first fills its
    initial capacity and then grows as fast as its vasculature, roughly as `t^3`. The defaults are the fit to breast
    cancer volumes in mm³ and days.

    Args:
        n:
            The initial volume.

        K:
            The initial carrying capacity.

        r:
            The rate at which the growth slows.

        d:
            The rate at which the surface of the tumour raises the capacity.

    Returns:
        system:
            The model, with the volume `tumour.n` and the capacity `vessels.K`.

    Examples:
        >>> from skcomplex.models.biology.oncology import dynamic_carrying_capacity
        >>> dynamic_carrying_capacity().elements[1].K
        12.7
    """
    return System(
        elements=[PopulationElement('tumour', n=n), VasculatureElement('vessels', K=K)],
        interactions=[VascularSupportInteraction('support', tumour='tumour', vasculature='vessels', r=r, d=d)],
    )

erythropoiesis_mercaptopurine(*, U=500.0, r1=0.00139, d1=0.0071, m0=1.01, Q50=0.027, n=1.0)

Return the production of red cells under a constant level of 6-mercaptopurine, starting from health.

The drug kills proliferating cells and lengthens their cycle, so fewer quiescent cells survive to mature, the mature red cells fall, and their mean volume rises to MCV0 + g1 U. The cells are in 10^12 per kg, the volume in fL, the drug in pMol per 8 x 10^8 red cells, and time in days. The parameters are those of Table 3.10 of Padmanabhan et al., with its half saturation of 2.7 x 10^10 cells per kg written as Q50 = 0.027. The patient starts at the healthy steady state, Q = Q50 (m0 / r1 - 1)^(1/n), L = r1 Q / d1, the book's ratio of proliferating to quiescent cells 0.71 / 6.43, and MCV = 85. The book garbles equation 3.36 as -r1 AQ (2 exp(a1 tau) - 1) m(AQ) AQ. The model takes the standard form of Mackey 1978 that Noble et al. use, dQ/dt = -r1 Q + (2 exp(-a1 tau) - 1) m(Q) Q, in which cells leave to mature at the rate r1 and the cells that enter the cycle return doubled once they survive the drug. Its healthy steady state gives 3.8 x 10^12 mature cells per kg, within the book's range.

Parameters:

Name Type Description Default
U float

The concentration of the drug, which the book ranges from 158 to 1000.

500.0
r1 float

The rate of differentiation of quiescent cells.

0.00139
d1 float

The death rate of mature cells.

0.0071
m0 float

The maximum rate at which quiescent cells enter the cycle.

1.01
Q50 float

The quiescent cells at which the rate of entry is half its maximum.

0.027
n float

The sensitivity of the rate of entry to the quiescent cells.

1.0

Returns:

Name Type Description
system System

The model, with the cells patient.Q, patient.P, patient.L and the mean volume patient.MCV.

Examples:

>>> from skcomplex.models.biology.oncology import erythropoiesis_mercaptopurine
>>> erythropoiesis_mercaptopurine(U=0.0).elements[0].MCV
85.0
Source code in src/skcomplex/models/biology/oncology/_cell_kinetics.py
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
@register_model(
    field='biology/oncology',
    tags=('chemotherapy', 'dde', 'delay', 'haematopoiesis', 'leukaemia'),
    references=(BOOK, 'Noble et al. 2010', 'Mackey 1978'),
    defaults={'until': 3000.0, 'dt': 10.0},
)
def erythropoiesis_mercaptopurine(
    *,
    U: float = 500.0,
    r1: float = 0.00139,
    d1: float = 0.0071,
    m0: float = 1.01,
    Q50: float = 0.027,
    n: float = 1.0,
) -> System:
    """Return the production of red cells under a constant level of 6-mercaptopurine, starting from health.

    The drug kills proliferating cells and lengthens their cycle, so fewer quiescent cells survive to mature, the mature
    red cells fall, and their mean volume rises to `MCV0 + g1 U`. The cells are in 10^12 per kg, the volume in fL, the
    drug in pMol per 8 x 10^8 red cells, and time in days. The parameters are those of Table 3.10 of Padmanabhan et al.,
    with its half saturation of 2.7 x 10^10 cells per kg written as `Q50 = 0.027`. The patient starts at the healthy
    steady state, `Q = Q50 (m0 / r1 - 1)^(1/n)`, `L = r1 Q / d1`, the book's ratio of proliferating to quiescent cells
    0.71 / 6.43, and `MCV = 85`. The book garbles equation 3.36 as `-r1 AQ (2 exp(a1 tau) - 1) m(AQ) AQ`. The model
    takes the standard form of Mackey 1978 that Noble et al. use, `dQ/dt = -r1 Q + (2 exp(-a1 tau) - 1) m(Q) Q`, in
    which cells leave to mature at the rate `r1` and the cells that enter the cycle return doubled once they survive the
    drug. Its healthy steady state gives 3.8 x 10^12 mature cells per kg, within the book's range.

    Args:
        U:
            The concentration of the drug, which the book ranges from 158 to 1000.

        r1:
            The rate of differentiation of quiescent cells.

        d1:
            The death rate of mature cells.

        m0:
            The maximum rate at which quiescent cells enter the cycle.

        Q50:
            The quiescent cells at which the rate of entry is half its maximum.

        n:
            The sensitivity of the rate of entry to the quiescent cells.

    Returns:
        system:
            The model, with the cells `patient.Q`, `patient.P`, `patient.L` and the mean volume `patient.MCV`.

    Examples:
        >>> from skcomplex.models.biology.oncology import erythropoiesis_mercaptopurine
        >>> erythropoiesis_mercaptopurine(U=0.0).elements[0].MCV
        85.0
    """
    Q = Q50 * (m0 / r1 - 1) ** (1 / n)
    patient = ErythropoiesisElement(
        'patient',
        L=r1 * Q / d1,
        Q=Q,
        P=0.71 / 6.43 * Q,
        r1=r1,
        d1=d1,
        m0=m0,
        Q50=Q50,
        n=n,
        U=U,
    )
    interactions = [
        ReactionInteraction(
            'maturation',
            target='patient',
            reactants={'Q': 1},
            products={'L': 1},
            propensity=lambda s: s.target.r1 * s.target.Q,
        ),
        ReactionInteraction(
            'division',
            target='patient',
            reactants={'Q': 1},
            products={'Q': 2},
            propensity=lambda s: exp(
                -s.target.a0
                * s.target.U
                * (s.target.g1 * s.target.U + s.target.MCV0)
                * s.target.tau_h
                / s.target.MCV_h,
            )
            * s.target.m0
            * s.target.Q50**s.target.n
            / (s.target.Q50**s.target.n + s.target.Q**s.target.n)
            * s.target.Q,
        ),
        ReactionInteraction(
            'damage',
            target='patient',
            reactants={'Q': 1},
            products={'P': 1},
            propensity=lambda s: (
                1
                - exp(
                    -s.target.a0
                    * s.target.U
                    * (s.target.g1 * s.target.U + s.target.MCV0)
                    * s.target.tau_h
                    / s.target.MCV_h,
                )
            )
            * s.target.m0
            * s.target.Q50**s.target.n
            / (s.target.Q50**s.target.n + s.target.Q**s.target.n)
            * s.target.Q,
        ),
        ReactionInteraction(
            'damaged_loss',
            target='patient',
            reactants={'P': 1},
            propensity=lambda s: s.target.a0 * s.target.U * s.target.P,
        ),
        RateInteraction(
            'senescence',
            target='patient',
            state='L',
            rate=lambda s: -s.target.d1 * delayed(s.target.L, s.target.lifespan),
        ),
        RateInteraction(
            'new_volume',
            target='patient',
            state='MCV',
            rate=lambda s: (s.target.g1 * s.target.U + s.target.MCV0) * s.target.r1 * s.target.Q,
            divisor='L',
        ),
        RateInteraction(
            'senescent_volume',
            target='patient',
            state='MCV',
            rate=lambda s: -0.85
            * delayed(s.target.MCV, s.target.lifespan)
            * s.target.d1
            * delayed(s.target.L, s.target.lifespan),
            divisor='L',
        ),
        RateInteraction(
            'random_volume',
            target='patient',
            state='MCV',
            rate=lambda s: -0.15 * s.target.MCV * s.target.d1 * s.target.L,
            divisor='L',
        ),
    ]
    return System(elements=[patient], interactions=interactions)

exponential_linear_growth(n=2.0, *, r0=0.31, r=67.8)

Return a tumour that grows exponentially while small and linearly once its growth reaches a limiting rate.

The defaults are the fit to breast cancer volumes in mm³ and days, which switches near day 15.

Parameters:

Name Type Description Default
n float

The initial volume.

2.0
r0 float

The exponential growth rate.

0.31
r float

The linear growth rate.

67.8

Returns:

Name Type Description
system System

The model, with the volume tumour.n.

Examples:

>>> from skcomplex.models.biology.oncology import exponential_linear_growth
>>> exponential_linear_growth().interactions[0].r0
0.31
Source code in src/skcomplex/models/biology/oncology/_growth.py
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
@register_model(
    field='biology/oncology',
    tags=('tumour growth', 'ode', 'piecewise'),
    references=GROWTH_REFERENCES,
    defaults={'until': 40.0, 'dt': 0.2},
)
def exponential_linear_growth(n: float = 2.0, *, r0: float = 0.31, r: float = 67.8) -> System:
    """Return a tumour that grows exponentially while small and linearly once its growth reaches a limiting rate.

    The defaults are the fit to breast cancer volumes in mm³ and days, which switches near day 15.

    Args:
        n:
            The initial volume.

        r0:
            The exponential growth rate.

        r:
            The linear growth rate.

    Returns:
        system:
            The model, with the volume `tumour.n`.

    Examples:
        >>> from skcomplex.models.biology.oncology import exponential_linear_growth
        >>> exponential_linear_growth().interactions[0].r0
        0.31
    """
    return System(
        elements=[PopulationElement('tumour', n=n)],
        interactions=[ExponentialLinearGrowthInteraction('growth', target='tumour', r0=r0, r=r)],
    )

generalized_logistic(n=10.0, *, r=0.305, K=1221.0, p=1.0)

Return a tumour that saturates at a carrying capacity, dn/dt = r n (1 - (n / K)^p), logistic for p = 1.

The volume follows n0 K / (n0^p + (K^p - n0^p) exp(-r p t))^(1/p). The defaults are the logistic fit to breast cancer volumes in mm³ and days.

Parameters:

Name Type Description Default
n float

The initial volume.

10.0
r float

The growth rate at low density.

0.305
K float

The carrying capacity.

1221.0
p float

The exponent of the saturation.

1.0

Returns:

Name Type Description
system System

The model, with the volume tumour.n.

Examples:

>>> from skcomplex.models.biology.oncology import generalized_logistic
>>> generalized_logistic(p=0.5).interactions[0].p
0.5
Source code in src/skcomplex/models/biology/oncology/_growth.py
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
@register_model(
    field='biology/oncology',
    tags=('tumour growth', 'ode', 'logistic', 'Richards'),
    references=(*GROWTH_REFERENCES, 'Richards 1959'),
    defaults={'until': 40.0, 'dt': 0.2},
)
def generalized_logistic(n: float = 10.0, *, r: float = 0.305, K: float = 1221.0, p: float = 1.0) -> System:
    """Return a tumour that saturates at a carrying capacity, `dn/dt = r n (1 - (n / K)^p)`, logistic for `p = 1`.

    The volume follows `n0 K / (n0^p + (K^p - n0^p) exp(-r p t))^(1/p)`. The defaults are the logistic fit to breast
    cancer volumes in mm³ and days.

    Args:
        n:
            The initial volume.

        r:
            The growth rate at low density.

        K:
            The carrying capacity.

        p:
            The exponent of the saturation.

    Returns:
        system:
            The model, with the volume `tumour.n`.

    Examples:
        >>> from skcomplex.models.biology.oncology import generalized_logistic
        >>> generalized_logistic(p=0.5).interactions[0].p
        0.5
    """
    return System(
        elements=[PopulationElement('tumour', n=n)],
        interactions=[GrowthInteraction('growth', target='tumour', r=r, K=K, p=p, form='logistic')],
    )

glioma_chemovirotherapy(AU=60000000000.0, V=1000000000.0, *, u1=400.0)

Return glia, neurons, and a glioma under a constant temozolomide infusion and an oncolytic virus.

Untreated, the glioma grows and crowds out the glia, and the neurons die with the glia. The virus or the drug clears the glioma, and the neurons survive. The drug also kills some neurons. The book gives no initial virus or drug, so the run starts with no drug and with a billion virions. Cells and virions are counted, the drug is in mg per m², and time is in days.

Parameters:

Name Type Description Default
AU float

The initial number of glioma cells.

60000000000.0
V float

The initial number of virions, 0 for chemotherapy alone.

1000000000.0
u1 float

The infusion rate of temozolomide, in mg per m² per day, 0 for virotherapy alone.

400.0

Returns:

Name Type Description
system System

The model, with the glia brain.G, the neurons brain.N, the glioma brain.AU and brain.AV, the virus brain.V, and the drug brain.U.

Examples:

>>> from skcomplex.models.biology.oncology import glioma_chemovirotherapy
>>> glioma_chemovirotherapy(u1=0.0).elements[0].u1
0.0
Source code in src/skcomplex/models/biology/oncology/_combination_therapy.py
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
@register_model(
    field='biology/oncology',
    tags=('chemotherapy', 'virotherapy', 'combination therapy', 'glioma', 'neurons', 'ode'),
    references=(BOOK, 'Urenda-Cázares, Gallegos, and Macías-Díaz 2020', 'Iarosz et al. 2015'),
    defaults={'until': 300.0, 'dt': 1.0},
)
def glioma_chemovirotherapy(
    AU: float = 6e10,
    V: float = 1e9,
    *,
    u1: float = 400.0,
) -> System:
    """Return glia, neurons, and a glioma under a constant temozolomide infusion and an oncolytic virus.

    Untreated, the glioma grows and crowds out the glia, and the neurons die with the glia. The virus or the drug clears
    the glioma, and the neurons survive. The drug also kills some neurons. The book gives no initial virus or drug, so
    the run starts with no drug and with a billion virions. Cells and virions are counted, the drug is in mg per m², and
    time is in days.

    Args:
        AU:
            The initial number of glioma cells.

        V:
            The initial number of virions, 0 for chemotherapy alone.

        u1:
            The infusion rate of temozolomide, in mg per m² per day, 0 for virotherapy alone.

    Returns:
        system:
            The model, with the glia `brain.G`, the neurons `brain.N`, the glioma `brain.AU` and `brain.AV`, the virus
            `brain.V`, and the drug `brain.U`.

    Examples:
        >>> from skcomplex.models.biology.oncology import glioma_chemovirotherapy
        >>> glioma_chemovirotherapy(u1=0.0).elements[0].u1
        0.0
    """
    brain = GliomaBrainElement('brain', AU=AU, V=V, u1=u1)
    interactions = [
        RateInteraction(
            'glia_growth',
            target='brain',
            state='G',
            rate=lambda s: s.target.r1 * s.target.G * (1 - s.target.b * s.target.G),
        ),
        ReactionInteraction(
            'glia_competition',
            target='brain',
            reactants={'G': 1},
            modifiers={'AU': 1},
            propensity=lambda s: s.target.c1 * s.target.G * s.target.AU,
        ),
        MichaelisMentenInteraction(
            'glia_drug_kill',
            target='brain',
            reactants={'G': 1},
            substrate='G',
            vmax=lambda s: s.target.a1,
            km=lambda s: s.target.g1,
            modifiers={'U': 1},
        ),
        ReactionInteraction(
            'neuron_loss',
            target='brain',
            reactants={'N': 1},
            propensity=lambda s: -s.target.psi * where(_glia_rate(s.target) < 0, _glia_rate(s.target), 0) * s.target.N,
        ),
        MichaelisMentenInteraction(
            'neuron_drug_kill',
            target='brain',
            reactants={'N': 1},
            substrate='N',
            vmax=lambda s: s.target.a2,
            km=lambda s: s.target.g2,
            modifiers={'U': 1},
        ),
        RateInteraction(
            'glioma_growth',
            target='brain',
            state='AU',
            rate=lambda s: s.target.r2 * s.target.AU * (1 - s.target.b * (s.target.AU + s.target.AV)),
        ),
        ReactionInteraction(
            'glioma_competition',
            target='brain',
            reactants={'AU': 1},
            modifiers={'G': 1},
            propensity=lambda s: s.target.c2 * s.target.G * s.target.AU,
        ),
        MichaelisMentenInteraction(
            'glioma_drug_kill',
            target='brain',
            reactants={'AU': 1},
            substrate='AU',
            vmax=lambda s: s.target.a3,
            km=lambda s: s.target.g3,
            modifiers={'U': 1},
        ),
        ReactionInteraction(
            'infection',
            target='brain',
            reactants={'AU': 1, 'V': 1},
            products={'AV': 1},
            propensity=lambda s: s.target.alpha * s.target.AU * s.target.V,
        ),
        ReactionInteraction(
            'lysis',
            target='brain',
            reactants={'AV': 1},
            propensity=lambda s: s.target.a4 * s.target.AV,
        ),
        RateInteraction('burst', target='brain', state='V', rate=lambda s: s.target.beta_v * s.target.a4 * s.target.AV),
        ReactionInteraction(
            'virus_clearance',
            target='brain',
            reactants={'V': 1},
            propensity=lambda s: s.target.d_u1 * s.target.V,
        ),
        ReactionInteraction(
            'drug_clearance',
            target='brain',
            reactants={'U': 1},
            propensity=lambda s: s.target.d_u2 * s.target.U,
        ),
        DosingInteraction('infusion', target='brain', state='U', dose=lambda s: s.target.u1),
    ]
    return System(elements=[brain], interactions=interactions)

gompertz(n=10.0, *, r=0.0719, K=1964.0)

Return a tumour whose growth slows as the logarithm of the room left, dn/dt = r n log(K / n).

The volume follows K exp(log(n0 / K) exp(-r t)) and tends to K. The rate is the fitted decay of the proliferation of breast cancer, per day, and the capacity is in mm³.

Parameters:

Name Type Description Default
n float

The initial volume.

10.0
r float

The rate at which the growth slows.

0.0719
K float

The carrying capacity.

1964.0

Returns:

Name Type Description
system System

The model, with the volume tumour.n.

Examples:

>>> from skcomplex.models.biology.oncology import gompertz
>>> gompertz(K=1000.0).interactions[0].K
1000.0
Source code in src/skcomplex/models/biology/oncology/_growth.py
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
@register_model(
    field='biology/oncology',
    tags=('tumour growth', 'ode', 'sigmoid'),
    references=(*GROWTH_REFERENCES, 'Gompertz 1825'),
    defaults={'until': 100.0, 'dt': 0.5},
)
def gompertz(n: float = 10.0, *, r: float = 0.0719, K: float = 1964.0) -> System:
    """Return a tumour whose growth slows as the logarithm of the room left, `dn/dt = r n log(K / n)`.

    The volume follows `K exp(log(n0 / K) exp(-r t))` and tends to `K`. The rate is the fitted decay of the
    proliferation of breast cancer, per day, and the capacity is in mm³.

    Args:
        n:
            The initial volume.

        r:
            The rate at which the growth slows.

        K:
            The carrying capacity.

    Returns:
        system:
            The model, with the volume `tumour.n`.

    Examples:
        >>> from skcomplex.models.biology.oncology import gompertz
        >>> gompertz(K=1000.0).interactions[0].K
        1000.0
    """
    return System(
        elements=[PopulationElement('tumour', n=n)],
        interactions=[GompertzGrowthInteraction('growth', target='tumour', r=r, K=K)],
    )

hahnfeldt(A=17347.0, Vb=17347.0, *, lambda1=0.192, lambda2=0.0, xi_s=5.85, xi_i=0.00873, a=0.66, du=1.3, dose=20.0, period=1.0, width=1.0, start=0.0)

Return the Hahnfeldt model, a tumour whose carrying capacity is the vasculature it stimulates and inhibits.

The tumour follows dA/dt = -lambda1 A log(A / Vb) and the vasculature dVb/dt = -lambda2 Vb + xi_s A - xi_i Vb A^(2/3) - a Vb U. The inhibitor follows dU/dt = -du U + u(t), the differential form of the book's convolution. Untreated, tumour and vasculature tend to the volume (xi_s / xi_i)^(3/2), about 17347 mm³, which is the initial state. The inhibitor parameters are those of endostatin in Lewis lung carcinoma, and the default schedule is the continuous infusion of 20 mg/kg/day of Hahnfeldt et al., under which the vasculature and then the tumour regress. Volumes are in mm³, time in days, and the inhibitor in mg/kg.

Parameters:

Name Type Description Default
A float

The initial tumour volume.

17347.0
Vb float

The initial vascular volume.

17347.0
lambda1 float

The rate at which the tumour approaches its capacity.

0.192
lambda2 float

The spontaneous loss rate of the vasculature.

0.0
xi_s float

The angiogenic stimulation by the tumour.

5.85
xi_i float

The angiogenic inhibition by the tumour.

0.00873
a float

The vascular loss per unit of inhibitor.

0.66
du float

The clearance rate of the inhibitor.

1.3
dose float

The infusion rate during a dose, 0 for no treatment.

20.0
period float

The time between the starts of doses.

1.0
width float

The duration of a dose, equal to period for a continuous infusion.

1.0
start float

The time of the first dose.

0.0

Returns:

Name Type Description
system System

The model, with the volumes tumour.A and tumour.Vb and the inhibitor tumour.U.

Examples:

>>> from skcomplex.models.biology.oncology import hahnfeldt
>>> hahnfeldt(dose=0.0).elements[0].dose
0.0
Source code in src/skcomplex/models/biology/oncology/_antiangiogenic.py
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
@register_model(
    field='biology/oncology',
    tags=('anti-angiogenic therapy', 'ode', 'angiogenesis', 'Gompertz', 'dosing'),
    references=(BOOK_REFERENCE, 'Hahnfeldt et al. 1999'),
    defaults={'until': 30.0, 'dt': 0.1},
)
def hahnfeldt(
    A: float = 17347.0,
    Vb: float = 17347.0,
    *,
    lambda1: float = 0.192,
    lambda2: float = 0.0,
    xi_s: float = 5.85,
    xi_i: float = 0.00873,
    a: float = 0.66,
    du: float = 1.3,
    dose: float = 20.0,
    period: float = 1.0,
    width: float = 1.0,
    start: float = 0.0,
) -> System:
    """Return the Hahnfeldt model, a tumour whose carrying capacity is the vasculature it stimulates and inhibits.

    The tumour follows `dA/dt = -lambda1 A log(A / Vb)` and the vasculature
    `dVb/dt = -lambda2 Vb + xi_s A - xi_i Vb A^(2/3) - a Vb U`. The inhibitor follows `dU/dt = -du U + u(t)`, the
    differential form of the book's convolution. Untreated, tumour and vasculature tend to the volume
    `(xi_s / xi_i)^(3/2)`, about 17347 mm³, which is the initial state. The inhibitor parameters are those of endostatin
    in Lewis lung carcinoma, and the default schedule is the continuous infusion of 20 mg/kg/day of Hahnfeldt et al.,
    under which the vasculature and then the tumour regress. Volumes are in mm³, time in days, and the inhibitor in
    mg/kg.

    Args:
        A:
            The initial tumour volume.

        Vb:
            The initial vascular volume.

        lambda1:
            The rate at which the tumour approaches its capacity.

        lambda2:
            The spontaneous loss rate of the vasculature.

        xi_s:
            The angiogenic stimulation by the tumour.

        xi_i:
            The angiogenic inhibition by the tumour.

        a:
            The vascular loss per unit of inhibitor.

        du:
            The clearance rate of the inhibitor.

        dose:
            The infusion rate during a dose, 0 for no treatment.

        period:
            The time between the starts of doses.

        width:
            The duration of a dose, equal to `period` for a continuous infusion.

        start:
            The time of the first dose.

    Returns:
        system:
            The model, with the volumes `tumour.A` and `tumour.Vb` and the inhibitor `tumour.U`.

    Examples:
        >>> from skcomplex.models.biology.oncology import hahnfeldt
        >>> hahnfeldt(dose=0.0).elements[0].dose
        0.0
    """
    tumour = AngiogenicTumourElement(
        'tumour',
        A=A,
        Vb=Vb,
        lambda1=lambda1,
        lambda2=lambda2,
        xi_s=xi_s,
        xi_i=xi_i,
        a=a,
        du=du,
        dose=dose,
        period=period,
        width=width,
        start=start,
    )
    interactions = [
        RateInteraction(
            'tumour_growth',
            target='tumour',
            state='A',
            rate=lambda s: -s.target.lambda1 * s.target.A * log(s.target.A / s.target.Vb),
        ),
        ReactionInteraction(
            'vessel_loss',
            target='tumour',
            reactants={'Vb': 1},
            propensity=lambda s: s.target.lambda2 * s.target.Vb,
        ),
        RateInteraction('stimulation', target='tumour', state='Vb', rate=lambda s: s.target.xi_s * s.target.A),
        ReactionInteraction(
            'inhibition',
            target='tumour',
            reactants={'Vb': 1},
            propensity=lambda s: s.target.xi_i * s.target.Vb * s.target.A ** (2 / 3),
        ),
        ReactionInteraction(
            'pruning',
            target='tumour',
            reactants={'Vb': 1},
            propensity=lambda s: s.target.a * s.target.Vb * s.target.U,
        ),
        DosingInteraction(
            'dosing',
            target='tumour',
            state='U',
            dose=lambda s: s.target.dose,
            period=tumour.period,
            width=tumour.width,
            start=tumour.start,
        ),
        ReactionInteraction(
            'clearance',
            target='tumour',
            reactants={'U': 1},
            propensity=lambda s: s.target.du * s.target.U,
        ),
    ]
    return System(elements=[tumour], interactions=interactions)

her2_targeted_therapy(A=0.035, *, antibody=0.2, paclitaxel=2.0, t_antibody=1.0, t_a=2.0, t_p=1.0, sigma=1.0)

Return HER2+ breast cancer cells under trastuzumab and paclitaxel, with antibody binding and drug uptake.

The free antibody and the free paclitaxel are drivers held at their levels from their doses on. The antibody binds the receptors, which are in excess, so the bound antibody rises to the free antibody, and from the time t_a on it lowers the growth rate to r (1 - a1 Ab). The paclitaxel enters the cells and briefly lowers the carrying capacity. The cytotoxicity falls from one at the dose, so t_p is the dose time. The book's units cannot hold 35,000 cells with a capacity of 0.67, so cells are counted in millions and the antibody in millions of molecules. The dose levels and times are a choice. Time is in days.

Parameters:

Name Type Description Default
A float

The initial number of cells, in millions.

0.035
antibody float

The level of free antibody from its dose on.

0.2
paclitaxel float

The level of free paclitaxel from its dose on, in pmol.

2.0
t_antibody float

The time of the antibody dose.

1.0
t_a float

The time from which the bound antibody inhibits proliferation.

2.0
t_p float

The time of the paclitaxel dose.

1.0
sigma float

The synergy of the two drugs, 1 for none.

1.0

Returns:

Name Type Description
system System

The model, with the cells tumour.A, the bound antibody tumour.Ab, and the internalized paclitaxel tumour.Pin.

Examples:

>>> from skcomplex.models.biology.oncology import her2_targeted_therapy
>>> her2_targeted_therapy(sigma=1.5).elements[0].sigma
1.5
Source code in src/skcomplex/models/biology/oncology/_combination_therapy.py
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
@register_model(
    field='biology/oncology',
    tags=('chemotherapy', 'targeted therapy', 'combination therapy', 'HER2', 'antibody', 'ode'),
    references=(BOOK, 'Jarrett et al. 2019'),
    defaults={'until': 10.0, 'dt': 0.02, 'solver': ScipyODESolver(method='LSODA', rtol=1e-8, atol=1e-10)},
)
def her2_targeted_therapy(
    A: float = 0.035,
    *,
    antibody: float = 0.2,
    paclitaxel: float = 2.0,
    t_antibody: float = 1.0,
    t_a: float = 2.0,
    t_p: float = 1.0,
    sigma: float = 1.0,
) -> System:
    """Return HER2+ breast cancer cells under trastuzumab and paclitaxel, with antibody binding and drug uptake.

    The free antibody and the free paclitaxel are drivers held at their levels from their doses on. The antibody binds
    the receptors, which are in excess, so the bound antibody rises to the free antibody, and from the time `t_a` on it
    lowers the growth rate to `r (1 - a1 Ab)`. The paclitaxel enters the cells and briefly lowers the carrying capacity.
    The cytotoxicity falls from one at the dose, so `t_p` is the dose time. The book's units cannot hold 35,000 cells
    with a capacity of 0.67, so cells are counted in millions and the antibody in millions of molecules. The dose levels
    and times are a choice. Time is in days.

    Args:
        A:
            The initial number of cells, in millions.

        antibody:
            The level of free antibody from its dose on.

        paclitaxel:
            The level of free paclitaxel from its dose on, in pmol.

        t_antibody:
            The time of the antibody dose.

        t_a:
            The time from which the bound antibody inhibits proliferation.

        t_p:
            The time of the paclitaxel dose.

        sigma:
            The synergy of the two drugs, 1 for none.

    Returns:
        system:
            The model, with the cells `tumour.A`, the bound antibody `tumour.Ab`, and the internalized paclitaxel
            `tumour.Pin`.

    Examples:
        >>> from skcomplex.models.biology.oncology import her2_targeted_therapy
        >>> her2_targeted_therapy(sigma=1.5).elements[0].sigma
        1.5
    """
    tumour = Her2TumourElement(
        'tumour',
        A=A,
        antibody=antibody,
        paclitaxel=paclitaxel,
        t_antibody=t_antibody,
        t_a=t_a,
        t_p=t_p,
        sigma=sigma,
    )
    return System(elements=[tumour])

ideta_intermittent_androgen(AD=5.0, AI=0.0, *, r1=0.0204, r2=0.0242, d1=0.0076, d2=0.0168, m1=5e-05, k1=0.0, k2=2.0, k3=8.0, k4=0.5, U0=30.0, du=0.08, h0=10.0, h1=15.0)

Return the Ideta model of intermittent androgen suppression, switched on and off by PSA thresholds.

The therapy starts when the serum PSA, the number of cancer cells, rises through h1 and stops when it falls through h0. The androgen follows with the delay 1 / du, so the dependent cells shrink during therapy and regrow after it, and the PSA cycles between the thresholds while the independent cells stay few. Cells are counted, the PSA is in ng/mL, the androgen in nmol/L, starting at its normal level U0 within the book's 8 to 35, and time is in days.

Parameters:

Name Type Description Default
AD float

The initial androgen-dependent cells.

5.0
AI float

The initial androgen-independent cells.

0.0
r1 float

The growth rate of the dependent cells.

0.0204
r2 float

The growth rate of the independent cells.

0.0242
d1 float

The death rate of the dependent cells.

0.0076
d2 float

The death rate of the independent cells.

0.0168
m1 float

The maximum rate at which dependent cells turn independent.

5e-05
k1 float

The growth of the dependent cells without androgen, relative to r1.

0.0
k2 float

The androgen at which the growth of the dependent cells is half way.

2.0
k3 float

The death of the dependent cells without androgen, relative to d1.

8.0
k4 float

The androgen at which the death of the dependent cells is half way.

0.5
U0 float

The normal androgen concentration.

30.0
du float

The elimination rate of the androgen.

0.08
h0 float

The PSA below which the therapy stops.

10.0
h1 float

The PSA above which the therapy starts.

15.0

Returns:

Name Type Description
system System

The model, with the cells tumour.AD and tumour.AI, the androgen tumour.U, the therapy tumour.u, and the switches as on and off events.

Examples:

>>> from skcomplex.models.biology.oncology import ideta_intermittent_androgen
>>> ideta_intermittent_androgen(h1=20.0).interactions[-2].threshold
20.0
Source code in src/skcomplex/models/biology/oncology/_hormone_therapy.py
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
@register_model(
    field='biology/oncology',
    tags=('hormone therapy', 'ode', 'prostate cancer', 'events', 'intermittent'),
    references=(BOOK, 'Ideta et al. 2008'),
    defaults={'until': 600.0, 'dt': 2.0},
)
def ideta_intermittent_androgen(
    AD: float = 5.0,
    AI: float = 0.0,
    *,
    r1: float = 0.0204,
    r2: float = 0.0242,
    d1: float = 0.0076,
    d2: float = 0.0168,
    m1: float = 5e-5,
    k1: float = 0.0,
    k2: float = 2.0,
    k3: float = 8.0,
    k4: float = 0.5,
    U0: float = 30.0,
    du: float = 0.08,
    h0: float = 10.0,
    h1: float = 15.0,
) -> System:
    """Return the Ideta model of intermittent androgen suppression, switched on and off by PSA thresholds.

    The therapy starts when the serum PSA, the number of cancer cells, rises through `h1` and stops when it falls
    through `h0`. The androgen follows with the delay `1 / du`, so the dependent cells shrink during therapy and regrow
    after it, and the PSA cycles between the thresholds while the independent cells stay few. Cells are counted, the
    PSA is in ng/mL, the androgen in nmol/L, starting at its normal level `U0` within the book's 8 to 35, and time is
    in days.

    Args:
        AD:
            The initial androgen-dependent cells.

        AI:
            The initial androgen-independent cells.

        r1:
            The growth rate of the dependent cells.

        r2:
            The growth rate of the independent cells.

        d1:
            The death rate of the dependent cells.

        d2:
            The death rate of the independent cells.

        m1:
            The maximum rate at which dependent cells turn independent.

        k1:
            The growth of the dependent cells without androgen, relative to `r1`.

        k2:
            The androgen at which the growth of the dependent cells is half way.

        k3:
            The death of the dependent cells without androgen, relative to `d1`.

        k4:
            The androgen at which the death of the dependent cells is half way.

        U0:
            The normal androgen concentration.

        du:
            The elimination rate of the androgen.

        h0:
            The PSA below which the therapy stops.

        h1:
            The PSA above which the therapy starts.

    Returns:
        system:
            The model, with the cells `tumour.AD` and `tumour.AI`, the androgen `tumour.U`, the therapy `tumour.u`, and
            the switches as `on` and `off` events.

    Examples:
        >>> from skcomplex.models.biology.oncology import ideta_intermittent_androgen
        >>> ideta_intermittent_androgen(h1=20.0).interactions[-2].threshold
        20.0
    """
    tumour = IntermittentSuppressionElement(
        'tumour',
        AD=AD,
        AI=AI,
        U=U0,
        r1=r1,
        r2=r2,
        d1=d1,
        d2=d2,
        m1=m1,
        k1=k1,
        k2=k2,
        k3=k3,
        k4=k4,
        U0=U0,
        du=du,
    )
    switches = _get_switches(lambda s: s.target.x1 * s.target.AD + s.target.x2 * s.target.AI, h0, h1)
    interactions = [
        RateInteraction(
            'dependent_growth',
            target='tumour',
            state='AD',
            rate=lambda s: s.target.r1
            * (s.target.k1 + (1 - s.target.k1) * s.target.U / (s.target.U + s.target.k2))
            * s.target.AD,
        ),
        ReactionInteraction(
            'dependent_death',
            target='tumour',
            reactants={'AD': 1},
            propensity=lambda s: s.target.d1
            * (s.target.k3 + (1 - s.target.k3) * s.target.U / (s.target.U + s.target.k4))
            * s.target.AD,
        ),
        ReactionInteraction(
            'mutation',
            target='tumour',
            reactants={'AD': 1},
            products={'AI': 1},
            propensity=lambda s: s.target.m1 * (1 - s.target.U / s.target.U0) * s.target.AD,
        ),
        RateInteraction(
            'independent_growth',
            target='tumour',
            state='AI',
            rate=lambda s: s.target.r2 * (1 - s.target.U / s.target.U0) * s.target.AI,
        ),
        ReactionInteraction(
            'independent_death',
            target='tumour',
            reactants={'AI': 1},
            propensity=lambda s: s.target.d2 * s.target.AI,
        ),
        RateInteraction(
            'androgen_production',
            target='tumour',
            state='U',
            rate=lambda s: -s.target.du * (s.target.U - s.target.U0),
        ),
        RateInteraction(
            'suppression',
            target='tumour',
            state='U',
            rate=lambda s: -s.target.U0 * s.target.du * s.target.u,
        ),
        *switches,
    ]
    return System(elements=[tumour], interactions=interactions)

immune_competition(classes=5, *, activation=0.75, tumour=0.05, immune=1.0, growth=0.3, progression=0.05, kill=1.0, inhibition=0.2)

Return the kinetic model of the competition between tumour cells and immune cells.

Tumour cells and immune cells are distributions over activity classes, the progression of tumour cells and the activation of immune cells, held by site groups on a lattice of the classes. Tumour cells proliferate in the host and progress, active immune cells destroy them, and tumour cells inhibit the activation of immune cells. The tumour starts in the lowest progression class and the immune cells in the class nearest activation. While kill activation immune exceeds growth, the immune response wins and the tumour density decays. Below that threshold the tumour grows, inhibits the immune cells further, and escapes.

Parameters:

Name Type Description Default
classes int

The number of activity classes of both distributions.

5
activation float

The initial activation of the immune cells, between 0 and 1.

0.75
tumour float

The initial density of tumour cells.

0.05
immune float

The density of immune cells.

1.0
growth float

The proliferation rate of tumour cells.

0.3
progression float

The rate at which tumour cells progress one class.

0.05
kill float

The rate at which fully active immune cells destroy tumour cells.

1.0
inhibition float

The rate at which the most progressed tumour cells inhibit immune cells.

0.2

Returns:

Name Type Description
system System

The model, with the distributions tumour and immune, the host host, and the interactions growth and competition. Its standard observables are the tumour density, the mean tumour progression, and the mean immune activation.

Examples:

>>> from skcomplex.models.biology.oncology import immune_competition
>>> [item.label for item in immune_competition().elements]
['tumour', 'immune', 'host']
Source code in src/skcomplex/models/biology/oncology/_immune_competition.py
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
@register_model(
    field='biology/oncology',
    tags=('tumour', 'immune', 'kinetic', 'distribution'),
    references=IMMUNE_REFERENCES,
    defaults={'until': 40, 'dt': 0.5},
    observables=lambda system: immune_observables(_classes_of(system)),
)
def immune_competition(
    classes: int = 5,
    *,
    activation: float = 0.75,
    tumour: float = 0.05,
    immune: float = 1.0,
    growth: float = 0.3,
    progression: float = 0.05,
    kill: float = 1.0,
    inhibition: float = 0.2,
) -> System:
    """Return the kinetic model of the competition between tumour cells and immune cells.

    Tumour cells and immune cells are distributions over activity classes, the progression of tumour cells and the
    activation of immune cells, held by site groups on a lattice of the classes. Tumour cells proliferate in the host
    and progress, active immune cells destroy them, and tumour cells inhibit the activation of immune cells. The
    tumour starts in the lowest progression class and the immune cells in the class nearest `activation`. While
    `kill activation immune` exceeds `growth`, the immune response wins and the tumour density decays. Below that
    threshold the tumour grows, inhibits the immune cells further, and escapes.

    Args:
        classes:
            The number of activity classes of both distributions.

        activation:
            The initial activation of the immune cells, between 0 and 1.

        tumour:
            The initial density of tumour cells.

        immune:
            The density of immune cells.

        growth:
            The proliferation rate of tumour cells.

        progression:
            The rate at which tumour cells progress one class.

        kill:
            The rate at which fully active immune cells destroy tumour cells.

        inhibition:
            The rate at which the most progressed tumour cells inhibit immune cells.

    Returns:
        system:
            The model, with the distributions `tumour` and `immune`, the host `host`, and the interactions `growth`
            and `competition`. Its standard observables are the tumour density, the mean tumour progression, and the
            mean immune activation.

    Examples:
        >>> from skcomplex.models.biology.oncology import immune_competition
        >>> [item.label for item in immune_competition().elements]
        ['tumour', 'immune', 'host']
    """
    activities = activity_grid(classes)
    activation_rates = np.tile(activities, (classes, 1))
    tumour_density = np.zeros(classes)
    tumour_density[0] = tumour
    immune_density = np.zeros(classes)
    immune_density[int(np.argmin(np.abs(activities - activation)))] = immune
    return System(
        elements=[
            GroupElement('tumour', element=DensityElement, size=classes, on='sites', values={'f': tumour_density}),
            GroupElement('immune', element=DensityElement, size=classes, on='sites', values={'f': immune_density}),
            GroupElement('host', element=DensityElement, size=1, values={'f': 1.0}),
        ],
        interactions=[
            EncounterInteraction(
                'proliferation',
                candidate='tumour',
                field='host',
                rate=lambda _: growth,
                outcome='proliferative',
            ),
            EncounterInteraction(
                'progression',
                candidate='tumour',
                field='host',
                rate=lambda _: progression,
                kernel=lambda _: step_table(classes, 1),
            ),
            EncounterInteraction(
                'destruction',
                candidate='tumour',
                field='immune',
                rate=lambda _: activation_rates * kill,
                outcome='destructive',
            ),
            EncounterInteraction(
                'inhibition',
                candidate='immune',
                field='tumour',
                rate=lambda _: activation_rates * inhibition,
                kernel=lambda _: step_table(classes, -1, classes),
            ),
        ],
        space=LatticeSpace(classes, boundary='fixed'),
        time=ContinuousTime(),
    )

immune_observables(classes)

Return the tumour density, the mean tumour progression, and the mean immune activation of the model.

Parameters:

Name Type Description Default
classes int

The number of activity classes.

required

Returns:

Name Type Description
observables list[ObservableSpec]

The observables, each reading the moments of a distribution.

Examples:

>>> from skcomplex.models.biology.oncology import immune_observables
>>> [item.label for item in immune_observables(5)]
['tumour_density', 'tumour_progression', 'immune_activation']
Source code in src/skcomplex/models/biology/oncology/_immune_competition.py
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
def immune_observables(classes: int) -> list[ObservableSpec]:
    """Return the tumour density, the mean tumour progression, and the mean immune activation of the model.

    Args:
        classes:
            The number of activity classes.

    Returns:
        observables:
            The observables, each reading the moments of a distribution.

    Examples:
        >>> from skcomplex.models.biology.oncology import immune_observables
        >>> [item.label for item in immune_observables(5)]
        ['tumour_density', 'tumour_progression', 'immune_activation']
    """
    activities = activity_grid(classes)
    return [
        ObservableSpec('tumour_density', partial(cell_density, activities=activities), group='tumour'),
        ObservableSpec('tumour_progression', partial(mean_activity, activities=activities), group='tumour'),
        ObservableSpec('immune_activation', partial(mean_activity, activities=activities), group='immune'),
    ]

kirschner_panetta(E=1.0, A=1.0, C=1.0, *, alpha_a=0.02, r1=0.18, c1=1.0, a1=500.0, a2=70000000.0, u1=0.0, u2=0.0)

Return the Kirschner-Panetta model of effector cells, tumour cells, and IL-2 under adoptive therapy and IL-2.

Untreated, a tumour of antigenicity in the oscillatory range, such as the default 0.02, and the effector cells oscillate in long cycles in which the tumour nearly vanishes and regrows to about 4 10^5. The adoptive therapy adds a1 u1 effector cells per day and the IL-2 injection a2 u2 IL-2 per day. With u1 and u2 above 1, the book's treatment factors a1 = 500 and a2 = 7 10^7 are exceeded and the tumour is cleared. The populations are in volume units, the inputs in volume per day, and time in days, and the initial state is the book's.

Parameters:

Name Type Description Default
E float

The initial effector cells.

1.0
A float

The initial tumour cells.

1.0
C float

The initial IL-2 concentration.

1.0
alpha_a float

The antigenicity of the tumour, in the book's range 0 to 0.05.

0.02
r1 float

The growth rate of the tumour.

0.18
c1 float

The kill rate of tumour cells by effector cells.

1.0
a1 float

The effector cells per unit of adoptive therapy.

500.0
a2 float

The IL-2 per unit of IL-2 injection.

70000000.0
u1 float

The adoptive therapy input.

0.0
u2 float

The IL-2 injection input.

0.0

Returns:

Name Type Description
system System

The model, with the effector cells site.E, the tumour cells site.A, and the IL-2 site.C.

Examples:

>>> from skcomplex.models.biology.oncology import kirschner_panetta
>>> kirschner_panetta(u1=1.0).elements[0].u1
1.0
Source code in src/skcomplex/models/biology/oncology/_immunotherapy.py
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
@register_model(
    field='biology/oncology',
    tags=('immunotherapy', 'ode', 'adoptive therapy', 'IL-2', 'oscillations'),
    references=(BOOK_REFERENCE, 'Kirschner and Panetta 1998'),
    defaults={'until': 1000.0, 'dt': 1.0, 'solver': STIFF_SOLVER},
)
def kirschner_panetta(
    E: float = 1.0,
    A: float = 1.0,
    C: float = 1.0,
    *,
    alpha_a: float = 0.02,
    r1: float = 0.18,
    c1: float = 1.0,
    a1: float = 500.0,
    a2: float = 7e7,
    u1: float = 0.0,
    u2: float = 0.0,
) -> System:
    """Return the Kirschner-Panetta model of effector cells, tumour cells, and IL-2 under adoptive therapy and IL-2.

    Untreated, a tumour of antigenicity in the oscillatory range, such as the default 0.02, and the effector cells
    oscillate in long cycles in which the tumour nearly vanishes and regrows to about `4 10^5`. The adoptive therapy
    adds `a1 u1` effector cells per day and the IL-2 injection `a2 u2` IL-2 per day. With `u1` and `u2` above 1, the
    book's treatment factors `a1 = 500` and `a2 = 7 10^7` are exceeded and the tumour is cleared. The populations are
    in volume units, the inputs in volume per day, and time in days, and the initial state is the book's.

    Args:
        E:
            The initial effector cells.

        A:
            The initial tumour cells.

        C:
            The initial IL-2 concentration.

        alpha_a:
            The antigenicity of the tumour, in the book's range 0 to 0.05.

        r1:
            The growth rate of the tumour.

        c1:
            The kill rate of tumour cells by effector cells.

        a1:
            The effector cells per unit of adoptive therapy.

        a2:
            The IL-2 per unit of IL-2 injection.

        u1:
            The adoptive therapy input.

        u2:
            The IL-2 injection input.

    Returns:
        system:
            The model, with the effector cells `site.E`, the tumour cells `site.A`, and the IL-2 `site.C`.

    Examples:
        >>> from skcomplex.models.biology.oncology import kirschner_panetta
        >>> kirschner_panetta(u1=1.0).elements[0].u1
        1.0
    """
    site = KirschnerPanettaTumourElement(
        'site',
        E=E,
        A=A,
        C=C,
        alpha_a=alpha_a,
        r1=r1,
        c1=c1,
        a1=a1,
        a2=a2,
        u1=u1,
        u2=u2,
    )
    interactions = [
        RateInteraction('stimulation', target='site', state='E', rate=lambda s: s.target.alpha_a * s.target.A),
        ReactionInteraction(
            'effector_death',
            target='site',
            reactants={'E': 1},
            propensity=lambda s: s.target.d1 * s.target.E,
        ),
        DosingInteraction('adoptive_therapy', target='site', state='E', dose=lambda s: s.target.a1 * s.target.u1),
        MichaelisMentenInteraction(
            'effector_proliferation',
            target='site',
            products={'E': 1},
            substrate='C',
            vmax=lambda s: s.target.rho1,
            km=lambda s: s.target.alpha1,
            modifiers={'E': 1},
        ),
        RateInteraction(
            'tumour_growth',
            target='site',
            state='A',
            rate=lambda s: s.target.r1 * s.target.A * (1 - s.target.b * s.target.A),
        ),
        MichaelisMentenInteraction(
            'kill',
            target='site',
            reactants={'A': 1},
            substrate='A',
            vmax=lambda s: s.target.c1,
            km=lambda s: s.target.alpha2,
            modifiers={'E': 1},
        ),
        DosingInteraction('il2_injection', target='site', state='C', dose=lambda s: s.target.a2 * s.target.u2),
        MichaelisMentenInteraction(
            'il2_production',
            target='site',
            products={'C': 1},
            substrate='A',
            vmax=lambda s: s.target.rho2,
            km=lambda s: s.target.alpha3,
            modifiers={'E': 1},
        ),
        ReactionInteraction(
            'il2_loss',
            target='site',
            reactants={'C': 1},
            propensity=lambda s: s.target.du * s.target.C,
        ),
    ]
    return System(elements=[site], interactions=interactions)

leukaemia_stem_cells(NS=100.0, AS=1.0, *, r1=0.6, m1=0.2, d1=0.1, r4=0.7, m3=0.2, d4=0.1)

Return normal and leukaemic stem cells that compete for one niche through the feedback of their progeny.

Both kinds of stem cells renew at the rate r e^-psi1 - m e^-psi1 e^-psi3, where psi1 counts the stem cells in the niche and psi3 their progeny, so the kind with the larger net renewal excludes the other. With the defaults the leukaemic stem cells win and take over, and with r4 = 0.5 the leukaemia is controlled. The book gives ranges for the rates, and the defaults are values in them with the feedback gains 0.01 of the book. The book gives no initial cells, so a niche of 100 normal stem cells receives one leukaemic stem cell.

Parameters:

Name Type Description Default
NS float

The initial normal stem cells.

100.0
AS float

The initial leukaemic stem cells.

1.0
r1 float

The symmetric renewal rate of normal stem cells.

0.6
m1 float

The symmetric differentiation rate of normal stem cells.

0.2
d1 float

The death rate of normal stem cells.

0.1
r4 float

The symmetric renewal rate of leukaemic stem cells.

0.7
m3 float

The symmetric differentiation rate of leukaemic stem cells.

0.2
d4 float

The death rate of leukaemic stem cells.

0.1

Returns:

Name Type Description
system System

The model, with the normal cells niche.NS, niche.NPr, and niche.ND and the leukaemic cells niche.AS and niche.AD.

Examples:

>>> from skcomplex.models.biology.oncology import leukaemia_stem_cells
>>> leukaemia_stem_cells(r4=0.5).elements[0].r4
0.5
Source code in src/skcomplex/models/biology/oncology/_stem_cells.py
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
@register_model(
    field='biology/oncology',
    tags=('leukaemia', 'stem cells', 'ode', 'feedback', 'competition'),
    references=(BOOK, 'MacLean, Lo Celso, and Stumpf 2013'),
    defaults={'until': 500.0, 'dt': 1.0},
)
def leukaemia_stem_cells(
    NS: float = 100.0,
    AS: float = 1.0,
    *,
    r1: float = 0.6,
    m1: float = 0.2,
    d1: float = 0.1,
    r4: float = 0.7,
    m3: float = 0.2,
    d4: float = 0.1,
) -> System:
    """Return normal and leukaemic stem cells that compete for one niche through the feedback of their progeny.

    Both kinds of stem cells renew at the rate `r e^-psi1 - m e^-psi1 e^-psi3`, where `psi1` counts the stem cells
    in the niche and `psi3` their progeny, so the kind with the larger net renewal excludes the other. With the
    defaults the leukaemic stem cells win and take over, and with `r4 = 0.5` the leukaemia is controlled. The book
    gives ranges for the rates, and the defaults are values in them with the feedback gains `0.01` of the book.
    The book gives no initial cells, so a niche of 100 normal stem cells receives one leukaemic stem cell.

    Args:
        NS:
            The initial normal stem cells.

        AS:
            The initial leukaemic stem cells.

        r1:
            The symmetric renewal rate of normal stem cells.

        m1:
            The symmetric differentiation rate of normal stem cells.

        d1:
            The death rate of normal stem cells.

        r4:
            The symmetric renewal rate of leukaemic stem cells.

        m3:
            The symmetric differentiation rate of leukaemic stem cells.

        d4:
            The death rate of leukaemic stem cells.

    Returns:
        system:
            The model, with the normal cells `niche.NS`, `niche.NPr`, and `niche.ND` and the leukaemic cells
            `niche.AS` and `niche.AD`.

    Examples:
        >>> from skcomplex.models.biology.oncology import leukaemia_stem_cells
        >>> leukaemia_stem_cells(r4=0.5).elements[0].r4
        0.5
    """
    niche = LeukaemiaStemCellsElement('niche', NS=NS, AS=AS, r1=r1, m1=m1, d1=d1, r4=r4, m3=m3, d4=d4)
    interactions = [
        RateInteraction(
            'normal_renewal',
            target='niche',
            state='NS',
            rate=lambda s: s.target.r1 * s.target.NS * exp(-s.target.beta1 * (s.target.NS + s.target.AS)),
        ),
        ReactionInteraction(
            'normal_differentiation',
            target='niche',
            reactants={'NS': 1},
            products={'NPr': 2},
            propensity=lambda s: s.target.m1
            * exp(-s.target.beta3 * (s.target.NPr + s.target.ND + s.target.AD))
            * s.target.NS
            * exp(-s.target.beta1 * (s.target.NS + s.target.AS)),
        ),
        ReactionInteraction(
            'normal_death',
            target='niche',
            reactants={'NS': 1},
            propensity=lambda s: s.target.d1 * s.target.NS,
        ),
        RateInteraction(
            'normal_division',
            target='niche',
            state='NPr',
            rate=lambda s: s.target.r2
            * exp(-s.target.beta2 * (s.target.NPr + s.target.ND + s.target.AD))
            * s.target.NS
            * exp(-s.target.beta1 * (s.target.NS + s.target.AS)),
        ),
        RateInteraction('progenitor_growth', target='niche', state='NPr', rate=lambda s: s.target.r3 * s.target.NPr),
        RateInteraction('progenitor_loss', target='niche', state='NPr', rate=lambda s: -s.target.d2 * s.target.NPr),
        RateInteraction(
            'maturation',
            target='niche',
            state='ND',
            rate=lambda s: s.target.m2 * s.target.d2 * s.target.NPr,
        ),
        ReactionInteraction(
            'differentiated_death',
            target='niche',
            reactants={'ND': 1},
            propensity=lambda s: s.target.d3 * s.target.ND,
        ),
        RateInteraction(
            'leukaemic_renewal',
            target='niche',
            state='AS',
            rate=lambda s: s.target.r4 * s.target.AS * exp(-s.target.beta1 * (s.target.NS + s.target.AS)),
        ),
        ReactionInteraction(
            'leukaemic_differentiation',
            target='niche',
            reactants={'AS': 1},
            products={'AD': 2},
            propensity=lambda s: s.target.m3
            * exp(-s.target.beta3 * (s.target.NPr + s.target.ND + s.target.AD))
            * s.target.AS
            * exp(-s.target.beta1 * (s.target.NS + s.target.AS)),
        ),
        ReactionInteraction(
            'leukaemic_death',
            target='niche',
            reactants={'AS': 1},
            propensity=lambda s: s.target.d4 * s.target.AS,
        ),
        RateInteraction(
            'leukaemic_division',
            target='niche',
            state='AD',
            rate=lambda s: s.target.r5
            * exp(-s.target.beta2 * (s.target.NPr + s.target.ND + s.target.AD))
            * s.target.AS
            * exp(-s.target.beta1 * (s.target.NS + s.target.AS)),
        ),
        ReactionInteraction(
            'leukaemic_progeny_death',
            target='niche',
            reactants={'AD': 1},
            propensity=lambda s: s.target.d5 * s.target.AD,
        ),
    ]
    return System(elements=[niche], interactions=interactions)

lq_cell_survival(dose=2.0, *, fractions=1.0, alpha=0.3, beta=0.03, repair_rate=0.46, delivery_time=0.001)

Return the linear-quadratic survival of cells after a total dose, with its biologically effective dose.

The survival is exp(-alpha D - beta G D^2) (Padmanabhan et al. 2021 Eqs. 6.6-6.8), and the Lea-Catcheside factor G holds the repair between and during fractions. A sweep of the dose through Experiment gives the survival curve, and 30 fractions of 2 Gy at alpha / beta = 10 give the biologically effective dose of 72 Gy.

Parameters:

Name Type Description Default
dose float

The total dose, in Gy.

2.0
fractions float

The number of fractions.

1.0
alpha float

The linear coefficient, per Gy.

0.3
beta float

The quadratic coefficient, per Gy squared.

0.03
repair_rate float

The rate of repair of sublethal damage, per hour.

0.46
delivery_time float

The time to deliver one fraction, in hours.

0.001

Returns:

Name Type Description
system System

The model, with the states cells.survival, cells.protraction, and cells.effective_dose.

Examples:

>>> from skcomplex.engine.runtime import Simulation
>>> from skcomplex.models.biology.oncology import lq_cell_survival
>>> system = lq_cell_survival(60.0, fractions=30.0)
>>> trajectory = Simulation(system).check().prepare().run(1.0).trajectory_
>>> round(float(trajectory.values('cells.effective_dose')[0]), 1)
72.0
Source code in src/skcomplex/models/biology/oncology/_cell_survival.py
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
@register_model(
    field='biology/oncology',
    tags=('radiotherapy', 'static', 'dose response'),
    references=('Padmanabhan, Meskin, and Al Moustafa 2021', 'Fowler 1989'),
)
def lq_cell_survival(
    dose: float = 2.0,
    *,
    fractions: float = 1.0,
    alpha: float = 0.3,
    beta: float = 0.03,
    repair_rate: float = 0.46,
    delivery_time: float = 1e-3,
) -> System:
    """Return the linear-quadratic survival of cells after a total dose, with its biologically effective dose.

    The survival is `exp(-alpha D - beta G D^2)` (Padmanabhan et al. 2021 Eqs. 6.6-6.8), and the Lea-Catcheside factor
    `G` holds the repair between and during fractions. A sweep of the dose through `Experiment` gives the survival
    curve, and 30 fractions of 2 Gy at `alpha / beta = 10` give the biologically effective dose of 72 Gy.

    Args:
        dose:
            The total dose, in Gy.

        fractions:
            The number of fractions.

        alpha:
            The linear coefficient, per Gy.

        beta:
            The quadratic coefficient, per Gy squared.

        repair_rate:
            The rate of repair of sublethal damage, per hour.

        delivery_time:
            The time to deliver one fraction, in hours.

    Returns:
        system:
            The model, with the states `cells.survival`, `cells.protraction`, and `cells.effective_dose`.

    Examples:
        >>> from skcomplex.engine.runtime import Simulation
        >>> from skcomplex.models.biology.oncology import lq_cell_survival
        >>> system = lq_cell_survival(60.0, fractions=30.0)
        >>> trajectory = Simulation(system).check().prepare().run(1.0).trajectory_
        >>> round(float(trajectory.values('cells.effective_dose')[0]), 1)
        72.0
    """
    cells = LinearQuadraticSurvivalElement(
        'cells',
        alpha=alpha,
        beta=beta,
        dose=dose,
        fractions=fractions,
        repair_rate=repair_rate,
        delivery_time=delivery_time,
    )
    return System(elements=[cells], time=StaticTime())

lq_radiosensitizer(A1=27.0, Us=2.0, *, r=0.04, m1=0.26, a_gamma=0.004, alpha=0.054, beta=0.0054, ap=0.42, au=0.15, du=5.544, dose=2.0, period=1.0, start=0.125, fractions=10)

Return a xenograft tumour irradiated in fractions that the linear-quadratic model scores, with a radiosensitizer.

Every fraction kills the part 1 - exp(-(1 + ap Us)(alpha d + beta d^2)) of the proliferating cells at once, which divide once more and die through a chain of damaged compartments, and the accumulated dose slows the growth of the survivors as exp(-a_gamma u_tot). The radiosensitizer, given once at time 0, raises both effects while it lasts. Volumes are in mm³, doses in Gy, concentrations in μg/mL, and time in days, so the book's alpha = 54 and a_gamma = 4 per kGy are 0.054 and 0.004 per Gy, beta = alpha / 10 per Gy², and the elimination rate of 0.231 per hour is 5.544 per day. Fractions are instantaneous, so the dose-protraction factor is 1. The book's equations 6.10 and 6.13 also move m1 A1 from the proliferating cells to the dying chain, which would make the untreated tumour shrink at r - m1 < 0, so the chain is fed by the irradiated compartments alone and the tumour starts with no damaged cells. The book derives Us(0) from a dose without its bioavailability and volume, so the initial concentration is given directly.

Parameters:

Name Type Description Default
A1 float

The initial tumour volume, all proliferating.

27.0
Us float

The initial plasma concentration of the radiosensitizer.

2.0
r float

The growth rate.

0.04
m1 float

The transit rate of the damaged cells.

0.26
a_gamma float

The inhibition of proliferation per unit of accumulated dose.

0.004
alpha float

The linear coefficient of the linear-quadratic model.

0.054
beta float

The quadratic coefficient of the linear-quadratic model.

0.0054
ap float

The potency of the radiosensitizer in raising the cell kill.

0.42
au float

The potency of the radiosensitizer in raising the accumulated dose.

0.15
du float

The elimination rate of the radiosensitizer.

5.544
dose float

The dose of a fraction.

2.0
period float

The time between fractions.

1.0
start float

The time of the first fraction.

0.125
fractions int

The number of fractions.

10

Returns:

Name Type Description
system System

The model, with the compartments tumour.A1 to tumour.A6, the radiosensitizer tumour.Us, the accumulated dose tumour.u_tot, and the fractions as fraction events.

Examples:

>>> from skcomplex.models.biology.oncology import lq_radiosensitizer
>>> lq_radiosensitizer(Us=0.0).elements[0].Us
0.0
Source code in src/skcomplex/models/biology/oncology/_radiotherapy.py
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
@register_model(
    field='biology/oncology',
    tags=('radiotherapy', 'ode', 'linear-quadratic', 'events', 'dosing'),
    references=(BOOK, 'Cardilin et al. 2019'),
    defaults={'until': 120.0, 'dt': 0.5},
)
def lq_radiosensitizer(
    A1: float = 27.0,
    Us: float = 2.0,
    *,
    r: float = 0.04,
    m1: float = 0.26,
    a_gamma: float = 0.004,
    alpha: float = 0.054,
    beta: float = 0.0054,
    ap: float = 0.42,
    au: float = 0.15,
    du: float = 5.544,
    dose: float = 2.0,
    period: float = 1.0,
    start: float = 0.125,
    fractions: int = 10,
) -> System:
    """Return a xenograft tumour irradiated in fractions that the linear-quadratic model scores, with a radiosensitizer.

    Every fraction kills the part `1 - exp(-(1 + ap Us)(alpha d + beta d^2))` of the proliferating cells at once,
    which divide once more and die through a chain of damaged compartments, and the accumulated dose slows the growth
    of the survivors as `exp(-a_gamma u_tot)`. The radiosensitizer, given once at time 0, raises both effects while it
    lasts. Volumes are in mm³, doses in Gy, concentrations in μg/mL, and time in days, so the book's `alpha = 54` and
    `a_gamma = 4` per kGy are 0.054 and 0.004 per Gy, `beta = alpha / 10` per Gy², and the elimination rate of 0.231
    per hour is 5.544 per day. Fractions are instantaneous, so the dose-protraction factor is 1. The book's equations
    6.10 and 6.13 also move `m1 A1` from the proliferating cells to the dying chain, which would make the untreated
    tumour shrink at `r - m1 < 0`, so the chain is fed by the irradiated compartments alone and the tumour starts
    with no damaged cells. The book derives `Us(0)` from a dose without its bioavailability and volume, so the
    initial concentration is given directly.

    Args:
        A1:
            The initial tumour volume, all proliferating.

        Us:
            The initial plasma concentration of the radiosensitizer.

        r:
            The growth rate.

        m1:
            The transit rate of the damaged cells.

        a_gamma:
            The inhibition of proliferation per unit of accumulated dose.

        alpha:
            The linear coefficient of the linear-quadratic model.

        beta:
            The quadratic coefficient of the linear-quadratic model.

        ap:
            The potency of the radiosensitizer in raising the cell kill.

        au:
            The potency of the radiosensitizer in raising the accumulated dose.

        du:
            The elimination rate of the radiosensitizer.

        dose:
            The dose of a fraction.

        period:
            The time between fractions.

        start:
            The time of the first fraction.

        fractions:
            The number of fractions.

    Returns:
        system:
            The model, with the compartments `tumour.A1` to `tumour.A6`, the radiosensitizer `tumour.Us`, the
            accumulated dose `tumour.u_tot`, and the fractions as `fraction` events.

    Examples:
        >>> from skcomplex.models.biology.oncology import lq_radiosensitizer
        >>> lq_radiosensitizer(Us=0.0).elements[0].Us
        0.0
    """
    tumour = IrradiatedTumourElement(
        'tumour',
        A1=A1,
        Us=Us,
        r=r,
        m1=m1,
        a_gamma=a_gamma,
        du=du,
    )
    irradiation = IrradiationInteraction(
        'fraction',
        target='tumour',
        alpha=alpha,
        beta=beta,
        ap=ap,
        au=au,
        dose=dose,
        period=period,
        start=start,
        fractions=fractions,
    )
    interactions = [
        RateInteraction(
            'growth',
            target='tumour',
            state='A1',
            rate=lambda s: s.target.r * s.target.A1 * exp(-s.target.a_gamma * s.target.u_tot),
        ),
        ReactionInteraction(
            'damaged_division',
            target='tumour',
            reactants={'A5': 1},
            products={'A6': 2},
            propensity=lambda s: s.target.r * s.target.A5,
        ),
        ReactionInteraction(
            'arrest',
            target='tumour',
            reactants={'A5': 1},
            products={'A2': 1},
            propensity=lambda s: s.target.m1 * s.target.A5,
        ),
        ReactionInteraction(
            'daughter_arrest',
            target='tumour',
            reactants={'A6': 1},
            products={'A2': 1},
            propensity=lambda s: s.target.m1 * s.target.A6,
        ),
        ReactionInteraction(
            'first_dying_transit',
            target='tumour',
            reactants={'A2': 1},
            products={'A3': 1},
            propensity=lambda s: s.target.m1 * s.target.A2,
        ),
        ReactionInteraction(
            'second_dying_transit',
            target='tumour',
            reactants={'A3': 1},
            products={'A4': 1},
            propensity=lambda s: s.target.m1 * s.target.A3,
        ),
        ReactionInteraction(
            'removal',
            target='tumour',
            reactants={'A4': 1},
            propensity=lambda s: s.target.m1 * s.target.A4,
        ),
        ReactionInteraction(
            'sensitizer_elimination',
            target='tumour',
            reactants={'Us': 1},
            propensity=lambda s: s.target.du * s.target.Us,
        ),
        irradiation,
    ]
    return System(elements=[tumour], interactions=interactions)

mean_activity(s, activities)

Return the mean activity of a population of cells.

Parameters:

Name Type Description Default
s SimpleNamespace

The namespace of one member of the distribution.

required
activities NDArray[float64]

The activity of every class.

required

Returns:

Name Type Description
mean Expression

The normalized first moment.

Source code in src/skcomplex/models/biology/oncology/_immune_competition.py
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
def mean_activity(s: SimpleNamespace, activities: npt.NDArray[np.float64]) -> Expression:
    """Return the mean activity of a population of cells.

    Args:
        s:
            The namespace of one member of the distribution.

        activities:
            The activity of every class.

    Returns:
        mean:
            The normalized first moment.
    """
    return moment(s.f, 1, activities, normalized=True)

multidrug_resistance(S=460500000000.0, *, r=0.0099, u1=10.0, u2=10.0, u3=10.0)

Return a tumour of eight populations resistant to subsets of three drugs, given by constant infusions.

Each drug kills the populations sensitive to it once its concentration exceeds a threshold, so the drugs clear the sensitive cells while the cells resistant to all three keep growing. Time is in days, the cells are counted, and the drugs are in dosage units D. The parameters are those of Table 3.4 of Padmanabhan et al. The book prints the triple-resistant population without its own growth, dR123/dt = r (m1 R23 + m2 R13 + m3 R12), against its assumption that all populations grow at the same rate, so the model adds the growth r R123. The book prints no infusion schedule, so the drugs are constant infusions whose concentrations settle within the book's range of 0 to 50.

Parameters:

Name Type Description Default
S float

The initial sensitive cells, all cells resistant to any drug starting at 0.

460500000000.0
r float

The growth rate of every population.

0.0099
u1 float

The infusion rate of drug 1.

10.0
u2 float

The infusion rate of drug 2.

10.0
u3 float

The infusion rate of drug 3.

10.0

Returns:

Name Type Description
system System

The model, with the populations tumour.S, tumour.R1 to tumour.R123, the drugs tumour.U1 to tumour.U3, and their toxicities tumour.TX1 to tumour.TX3.

Examples:

>>> from skcomplex.models.biology.oncology import multidrug_resistance
>>> multidrug_resistance(u2=0.0).elements[0].u2
0.0
Source code in src/skcomplex/models/biology/oncology/_chemotherapy.py
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
@register_model(
    field='biology/oncology',
    tags=('chemotherapy', 'ode', 'drug resistance', 'toxicity'),
    references=(BOOK, 'Tse et al. 2007'),
    defaults={'until': 300.0, 'dt': 1.0},
)
def multidrug_resistance(
    S: float = 4.605e11,
    *,
    r: float = 0.0099,
    u1: float = 10.0,
    u2: float = 10.0,
    u3: float = 10.0,
) -> System:
    """Return a tumour of eight populations resistant to subsets of three drugs, given by constant infusions.

    Each drug kills the populations sensitive to it once its concentration exceeds a threshold, so the drugs clear the
    sensitive cells while the cells resistant to all three keep growing. Time is in days, the cells are counted, and the
    drugs are in dosage units D. The parameters are those of Table 3.4 of Padmanabhan et al. The book prints the
    triple-resistant population without its own growth, `dR123/dt = r (m1 R23 + m2 R13 + m3 R12)`, against its
    assumption that all populations grow at the same rate, so the model adds the growth `r R123`. The book prints no
    infusion schedule, so the drugs are constant infusions whose concentrations settle within the book's range of 0 to
    50.

    Args:
        S:
            The initial sensitive cells, all cells resistant to any drug starting at 0.

        r:
            The growth rate of every population.

        u1:
            The infusion rate of drug 1.

        u2:
            The infusion rate of drug 2.

        u3:
            The infusion rate of drug 3.

    Returns:
        system:
            The model, with the populations `tumour.S`, `tumour.R1` to `tumour.R123`, the drugs `tumour.U1` to
            `tumour.U3`, and their toxicities `tumour.TX1` to `tumour.TX3`.

    Examples:
        >>> from skcomplex.models.biology.oncology import multidrug_resistance
        >>> multidrug_resistance(u2=0.0).elements[0].u2
        0.0
    """
    tumour = MultidrugResistanceElement('tumour', S=S, r=r, u1=u1, u2=u2, u3=u3)

    def growth(name: str) -> RateInteraction:
        """Return the division of the cells of a resistance class."""
        return RateInteraction(
            f'growth_{name}',
            target='tumour',
            state=name,
            rate=lambda s: s.target.r * getattr(s.target, name),
        )

    def mutation(name: str, drug: int, mutant: str) -> ReactionInteraction:
        """Return the offspring of a resistance class that gain the resistance to one more drug."""
        return ReactionInteraction(
            f'mutation_{name}_{drug}',
            target='tumour',
            reactants={name: 1},
            products={mutant: 1},
            propensity=lambda s: s.target.r * getattr(s.target, f'm{drug}') * getattr(s.target, name),
        )

    def kill(name: str, drug: int) -> ReactionInteraction:
        """Return the kill of a resistance class by a drug it is sensitive to, above the threshold."""
        return ReactionInteraction(
            f'kill_{name}_{drug}',
            target='tumour',
            reactants={name: 1},
            modifiers={f'U{drug}': 1},
            propensity=lambda s: getattr(s.target, f'a{drug}')
            * clip(getattr(s.target, f'U{drug}') - s.target.Uth, 0)
            * getattr(s.target, name),
        )

    def pharmacokinetics(drug: int) -> list[BaseInteraction]:
        """Return the infusion and clearance of a drug, and the build-up and recovery of its toxicity."""
        return [
            DosingInteraction(
                f'infusion_{drug}',
                target='tumour',
                state=f'U{drug}',
                dose=lambda s: getattr(s.target, f'u{drug}'),
            ),
            ReactionInteraction(
                f'clearance_{drug}',
                target='tumour',
                reactants={f'U{drug}': 1},
                propensity=lambda s: getattr(s.target, f'k{drug}') * getattr(s.target, f'U{drug}'),
            ),
            RateInteraction(
                f'toxicity_{drug}',
                target='tumour',
                state=f'TX{drug}',
                rate=lambda s: getattr(s.target, f'U{drug}'),
            ),
            ReactionInteraction(
                f'recovery_{drug}',
                target='tumour',
                reactants={f'TX{drug}': 1},
                propensity=lambda s: getattr(s.target, f'eta{drug}') * getattr(s.target, f'TX{drug}'),
            ),
        ]

    growths = [growth(name) for name in RESISTANCE_CLASSES.values()]
    sensitivities = [
        (resistances, name, drug)
        for resistances, name in RESISTANCE_CLASSES.items()
        for drug in DRUGS
        if drug not in resistances
    ]
    mutations = [
        mutation(name, drug, RESISTANCE_CLASSES[tuple(sorted((*resistances, drug)))])
        for resistances, name, drug in sensitivities
    ]
    kills = [kill(name, drug) for _, name, drug in sensitivities]
    drugs = [interaction for drug in DRUGS for interaction in pharmacokinetics(drug)]
    return System(elements=[tumour], interactions=[*growths, *mutations, *kills, *drugs])

norton_simon(n=100.0, *, r=0.0719, K=1964.0, a=1.0, dose=1.0, period=21.0, width=1.0, start=42.0)

Return the Norton-Simon model, a Gompertzian tumour killed in proportion to its size by a dose schedule.

The tumour follows dn/dt = r n log(K / n) - a n U(t). A Gompertzian tumour regrows faster the smaller it is, so a dose that shrinks it is followed by fast regrowth, and the schedule settles on a cycle below the capacity.

Parameters:

Name Type Description Default
n float

The initial volume.

100.0
r float

The rate at which the growth slows.

0.0719
K float

The carrying capacity.

1964.0
a float

The kill rate per unit of exposure.

1.0
dose float

The exposure during a dose.

1.0
period float

The time between the starts of doses.

21.0
width float

The duration of a dose.

1.0
start float

The time of the first dose.

42.0

Returns:

Name Type Description
system System

The model, with the volume tumour.n.

Examples:

>>> from skcomplex.models.biology.oncology import norton_simon
>>> norton_simon().interactions[1].start
42.0
Source code in src/skcomplex/models/biology/oncology/_growth.py
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
@register_model(
    field='biology/oncology',
    tags=('chemotherapy', 'ode', 'log kill', 'Gompertz', 'dosing'),
    references=('Padmanabhan, Meskin, and Al Moustafa 2021', 'Norton and Simon 1977'),
    defaults={'until': 150.0, 'dt': 0.5},
)
def norton_simon(
    n: float = 100.0,
    *,
    r: float = 0.0719,
    K: float = 1964.0,
    a: float = 1.0,
    dose: float = 1.0,
    period: float = 21.0,
    width: float = 1.0,
    start: float = 42.0,
) -> System:
    """Return the Norton-Simon model, a Gompertzian tumour killed in proportion to its size by a dose schedule.

    The tumour follows `dn/dt = r n log(K / n) - a n U(t)`. A Gompertzian tumour regrows faster the smaller it is, so
    a dose that shrinks it is followed by fast regrowth, and the schedule settles on a cycle below the capacity.

    Args:
        n:
            The initial volume.

        r:
            The rate at which the growth slows.

        K:
            The carrying capacity.

        a:
            The kill rate per unit of exposure.

        dose:
            The exposure during a dose.

        period:
            The time between the starts of doses.

        width:
            The duration of a dose.

        start:
            The time of the first dose.

    Returns:
        system:
            The model, with the volume `tumour.n`.

    Examples:
        >>> from skcomplex.models.biology.oncology import norton_simon
        >>> norton_simon().interactions[1].start
        42.0
    """
    return System(
        elements=[PopulationElement('tumour', n=n)],
        interactions=[
            GompertzGrowthInteraction('growth', target='tumour', r=r, K=K),
            LogKillInteraction('kill', target='tumour', a=a, dose=dose, period=period, width=width, start=start),
        ],
    )

oncolytic_virus(AU=0.1, AV=0.0001, *, alpha=1.0, r=0.5, d=0.5)

Return uninfected and infected tumour cells that share a carrying capacity, with infection by mass action.

The uninfected cells follow dAU/dt = AU (1 - AU - AV) - alpha AU AV and the infected cells dAV/dt = r AV (1 - AU - AV) + alpha AU AV - d AV, in units of the carrying capacity and of the growth time of uninfected cells. The defaults lie in the ranges of the book's table. For alpha > d and 1 + alpha > r the cells settle on the coexistence point AV = (1 - d / alpha) / (1 + alpha - r), AU = d / alpha - r AV, so the virus reduces the tumour without eradicating it.

Parameters:

Name Type Description Default
AU float

The initial uninfected cells.

0.1
AV float

The initial infected cells.

0.0001
alpha float

The infection rate.

1.0
r float

The growth rate of infected cells.

0.5
d float

The death rate of infected cells.

0.5

Returns:

Name Type Description
system System

The model, with the uninfected cells tumour.AU and the infected cells tumour.AV.

Examples:

>>> from skcomplex.models.biology.oncology import oncolytic_virus
>>> oncolytic_virus(alpha=1.5).elements[0].alpha
1.5
Source code in src/skcomplex/models/biology/oncology/_gene_viral_therapy.py
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
@register_model(
    field='biology/oncology',
    tags=('virotherapy', 'ode', 'infection', 'competition'),
    references=(BOOK, 'Novozhilov et al. 2006'),
    defaults={'until': 60.0, 'dt': 0.2},
)
def oncolytic_virus(AU: float = 0.1, AV: float = 1e-4, *, alpha: float = 1.0, r: float = 0.5, d: float = 0.5) -> System:
    """Return uninfected and infected tumour cells that share a carrying capacity, with infection by mass action.

    The uninfected cells follow `dAU/dt = AU (1 - AU - AV) - alpha AU AV` and the infected cells
    `dAV/dt = r AV (1 - AU - AV) + alpha AU AV - d AV`, in units of the carrying capacity and of the growth time of
    uninfected cells. The defaults lie in the ranges of the book's table. For `alpha > d` and `1 + alpha > r` the
    cells settle on the coexistence point `AV = (1 - d / alpha) / (1 + alpha - r)`, `AU = d / alpha - r AV`, so the
    virus reduces the tumour without eradicating it.

    Args:
        AU:
            The initial uninfected cells.

        AV:
            The initial infected cells.

        alpha:
            The infection rate.

        r:
            The growth rate of infected cells.

        d:
            The death rate of infected cells.

    Returns:
        system:
            The model, with the uninfected cells `tumour.AU` and the infected cells `tumour.AV`.

    Examples:
        >>> from skcomplex.models.biology.oncology import oncolytic_virus
        >>> oncolytic_virus(alpha=1.5).elements[0].alpha
        1.5
    """
    tumour = OncolyticVirusElement('tumour', AU=AU, AV=AV, alpha=alpha, r=r, d=d)
    interactions = [
        RateInteraction(
            'uninfected_growth',
            target='tumour',
            state='AU',
            rate=lambda s: s.target.AU * (1 - s.target.AU - s.target.AV),
        ),
        RateInteraction(
            'infected_growth',
            target='tumour',
            state='AV',
            rate=lambda s: s.target.r * s.target.AV * (1 - s.target.AU - s.target.AV),
        ),
        ReactionInteraction(
            'infection',
            target='tumour',
            reactants={'AU': 1},
            products={'AV': 1},
            modifiers={'AV': 1},
            propensity=lambda s: s.target.alpha * s.target.AU * s.target.AV,
        ),
        ReactionInteraction(
            'lysis',
            target='tumour',
            reactants={'AV': 1},
            propensity=lambda s: s.target.d * s.target.AV,
        ),
    ]
    return System(elements=[tumour], interactions=interactions)

oncolytic_virus_dendritic(AU=60.0, *, uv=2500000000.0, ud=1000000.0, a0=0.0, m=0.0, a5=0.22)

Return a tumour treated with an oncolytic adenovirus that expresses immune signals and with dendritic cells.

The virus infects the uninfected cells at the rate alpha AU V / Atot, where Atot = AU + AV + E + EN, the infected cells lyse and release virions, and the T cells that the infected and the dendritic cells activate kill both kinds of tumour cells. Volumes are in mm³, virions and cells are counts, and time is in days. The virus and the dendritic cells are given at the constant rates of the book. The book gives no values for the kill rate a0 independent of the virus and the activation rate m of naive T cells, so both default to 0. The virus at the book's rate clears the tumour within days, while the dendritic cells, by raising the number of T cells in Atot, dilute the infection and let the tumour regrow.

Parameters:

Name Type Description Default
AU float

The initial uninfected tumour volume, in mm³.

60.0
uv float

The infusion rate of virions, per day.

2500000000.0
ud float

The injection rate of dendritic cells, per day.

1000000.0
a0 float

The kill rate of T cells that does not depend on the virus, per day.

0.0
m float

The activation rate of naive T cells, per day.

0.0
a5 float

The recruitment rate of naive T cells by infected cells, per day.

0.22

Returns:

Name Type Description
system System

The model, with the tumour volumes site.AU and site.AV, the virions site.V, the activated and naive T cells site.E and site.EN, and the dendritic cells site.D.

Examples:

>>> from skcomplex.models.biology.oncology import oncolytic_virus_dendritic
>>> oncolytic_virus_dendritic(ud=0.0).elements[0].ud
0.0
Source code in src/skcomplex/models/biology/oncology/_gene_viral_therapy.py
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
@register_model(
    field='biology/oncology',
    tags=('virotherapy', 'immunotherapy', 'dendritic cells', 'ode'),
    references=(BOOK, 'Wares et al. 2015'),
    defaults={'until': 30.0, 'dt': 0.1, 'solver': ScipyODESolver(method='LSODA')},
)
def oncolytic_virus_dendritic(
    AU: float = 60.0,
    *,
    uv: float = 2.5e9,
    ud: float = 1e6,
    a0: float = 0.0,
    m: float = 0.0,
    a5: float = 0.22,
) -> System:
    """Return a tumour treated with an oncolytic adenovirus that expresses immune signals and with dendritic cells.

    The virus infects the uninfected cells at the rate `alpha AU V / Atot`, where `Atot = AU + AV + E + EN`, the
    infected cells lyse and release virions, and the T cells that the infected and the dendritic cells activate kill
    both kinds of tumour cells. Volumes are in mm³, virions and cells are counts, and time is in days. The virus and
    the dendritic cells are given at the constant rates of the book. The book gives no values for the kill rate
    `a0` independent of the virus and the activation rate `m` of naive T cells, so both default to 0. The virus at
    the book's rate clears the tumour within days, while the dendritic cells, by raising the number of T cells in
    `Atot`, dilute the infection and let the tumour regrow.

    Args:
        AU:
            The initial uninfected tumour volume, in mm³.

        uv:
            The infusion rate of virions, per day.

        ud:
            The injection rate of dendritic cells, per day.

        a0:
            The kill rate of T cells that does not depend on the virus, per day.

        m:
            The activation rate of naive T cells, per day.

        a5:
            The recruitment rate of naive T cells by infected cells, per day.

    Returns:
        system:
            The model, with the tumour volumes `site.AU` and `site.AV`, the virions `site.V`, the activated and
            naive T cells `site.E` and `site.EN`, and the dendritic cells `site.D`.

    Examples:
        >>> from skcomplex.models.biology.oncology import oncolytic_virus_dendritic
        >>> oncolytic_virus_dendritic(ud=0.0).elements[0].ud
        0.0
    """
    site = OncolyticVirusDendriticElement('site', AU=AU, uv=uv, ud=ud, a0=a0, m=m, a5=a5)
    interactions = [
        RateInteraction('tumour_growth', target='site', state='AU', rate=lambda s: s.target.r1 * s.target.AU),
        ReactionInteraction(
            'infection',
            target='site',
            reactants={'AU': 1},
            products={'AV': 1},
            modifiers={'V': 1},
            propensity=lambda s: s.target.alpha
            * s.target.AU
            * s.target.V
            / (s.target.AU + s.target.AV + s.target.E + s.target.EN),
        ),
        ReactionInteraction(
            'uninfected_kill',
            target='site',
            reactants={'AU': 1},
            modifiers={'E': 1},
            propensity=lambda s: (s.target.a0 + s.target.a1 * s.target.AV)
            * s.target.E
            / (s.target.AU + s.target.AV + s.target.E + s.target.EN)
            * s.target.AU,
        ),
        ReactionInteraction(
            'infected_kill',
            target='site',
            reactants={'AV': 1},
            modifiers={'E': 1},
            propensity=lambda s: (s.target.a0 + s.target.a1 * s.target.AV)
            * s.target.E
            / (s.target.AU + s.target.AV + s.target.E + s.target.EN)
            * s.target.AV,
        ),
        ReactionInteraction(
            'lysis',
            target='site',
            reactants={'AV': 1},
            propensity=lambda s: s.target.a2 * s.target.AV,
        ),
        RateInteraction(
            'virus_release',
            target='site',
            state='V',
            rate=lambda s: s.target.r2 * s.target.a2 * s.target.AV,
        ),
        DosingInteraction('virus_injection', target='site', state='V', dose=lambda s: s.target.uv),
        ReactionInteraction(
            'virus_clearance',
            target='site',
            reactants={'V': 1},
            propensity=lambda s: s.target.du1 * s.target.V,
        ),
        RateInteraction('effector_recruitment', target='site', state='E', rate=lambda s: s.target.a3 * s.target.AV),
        RateInteraction('naive_activation', target='site', state='E', rate=lambda s: s.target.m * s.target.EN),
        RateInteraction('dendritic_activation', target='site', state='E', rate=lambda s: s.target.a4 * s.target.D),
        ReactionInteraction(
            'effector_death',
            target='site',
            reactants={'E': 1},
            propensity=lambda s: s.target.d1 * s.target.E,
        ),
        RateInteraction('naive_recruitment', target='site', state='EN', rate=lambda s: s.target.a5 * s.target.AV),
        ReactionInteraction(
            'naive_death',
            target='site',
            reactants={'EN': 1},
            propensity=lambda s: s.target.d2 * s.target.EN,
        ),
        DosingInteraction('dendritic_injection', target='site', state='D', dose=lambda s: s.target.ud),
        ReactionInteraction(
            'dendritic_clearance',
            target='site',
            reactants={'D': 1},
            propensity=lambda s: s.target.du2 * s.target.D,
        ),
    ]
    return System(elements=[site], interactions=interactions)

optimal_chemotherapy(E=0.15, A=0.25, N=1.0, *, w=0.1)

Return a patient under the chemotherapy that minimises the tumour burden and the toxicity of the drug.

Run with an optimal control solver, the infusion is largest at the start, when the tumour is largest, and falls as the tumour shrinks, so the tumour ends far below its untreated level.

Parameters:

Name Type Description Default
E float

The initial immune cells.

0.15
A float

The initial tumour cells.

0.25
N float

The initial normal cells.

1.0
w float

The weight of the squared infusion rate in the cost.

0.1

Returns:

Name Type Description
system System

The model, with the cells patient.E, patient.A, and patient.N, the drug patient.U, the infusion rate patient.u, and the observable tumour_share.

Examples:

>>> from skcomplex.models.biology.oncology import optimal_chemotherapy
>>> optimal_chemotherapy(w=1.0).elements[0].w
1.0
Source code in src/skcomplex/models/biology/oncology/_optimal_therapy.py
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
@register_model(
    field='biology/oncology',
    tags=('optimal control', 'chemotherapy', 'pontryagin', 'ode'),
    references=(BOOK, 'de Pillis and Radunskaya 2001'),
    defaults={'until': 30.0, 'dt': 0.25, 'solver': PontryaginSolver(objective=_chemotherapy_cost, terminal=_tumour)},
    observables=lambda system: [ObservableSpec('tumour_share', _tumour_share)],
)
def optimal_chemotherapy(
    E: float = 0.15,
    A: float = 0.25,
    N: float = 1.0,
    *,
    w: float = 0.1,
) -> System:
    """Return a patient under the chemotherapy that minimises the tumour burden and the toxicity of the drug.

    Run with an optimal control solver, the infusion is largest at the start, when the tumour is largest, and falls as
    the tumour shrinks, so the tumour ends far below its untreated level.

    Args:
        E:
            The initial immune cells.

        A:
            The initial tumour cells.

        N:
            The initial normal cells.

        w:
            The weight of the squared infusion rate in the cost.

    Returns:
        system:
            The model, with the cells `patient.E`, `patient.A`, and `patient.N`, the drug `patient.U`, the infusion
            rate `patient.u`, and the observable `tumour_share`.

    Examples:
        >>> from skcomplex.models.biology.oncology import optimal_chemotherapy
        >>> optimal_chemotherapy(w=1.0).elements[0].w
        1.0
    """
    return System(elements=[OptimalChemotherapyElement('patient', E=E, A=A, N=N, w=w)])

optimal_immunotherapy(x=0.1, y=1.0, *, alpha_a=0.005, w1=1.0, w2=1.0)

Return a tumour under the adoptive therapy and IL-2 injection that minimise its burden and their cost.

Run with an optimal control solver, the therapies are strongest while the tumour is large, the effector cells expand, and the tumour shrinks.

Parameters:

Name Type Description Default
x float

The initial effector cells, in units of 10^5.

0.1
y float

The initial tumour cells, in units of 10^5.

1.0
alpha_a float

The antigenicity of the tumour.

0.005
w1 float

The weight of the squared adoptive therapy rate in the cost.

1.0
w2 float

The weight of the squared IL-2 injection rate in the cost.

1.0

Returns:

Name Type Description
system System

The model, with the effector cells site.x, the tumour site.y, IL-2 site.z, the therapies site.u1 and site.u2, and the observable immune_ratio.

Examples:

>>> from skcomplex.models.biology.oncology import optimal_immunotherapy
>>> optimal_immunotherapy(w1=0.5).elements[0].w1
0.5
Source code in src/skcomplex/models/biology/oncology/_optimal_therapy.py
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
@register_model(
    field='biology/oncology',
    tags=('optimal control', 'immunotherapy', 'adoptive therapy', 'IL-2', 'pontryagin', 'ode'),
    references=(BOOK, 'Kirschner and Panetta 1998'),
    defaults={
        'until': 50.0,
        'dt': 0.5,
        'solver': PontryaginSolver(objective=_immunotherapy_cost, terminal=_tumour_site, nodes=1001),
    },
    observables=lambda system: [ObservableSpec('immune_ratio', _immune_ratio)],
)
def optimal_immunotherapy(
    x: float = 0.1,
    y: float = 1.0,
    *,
    alpha_a: float = 0.005,
    w1: float = 1.0,
    w2: float = 1.0,
) -> System:
    """Return a tumour under the adoptive therapy and IL-2 injection that minimise its burden and their cost.

    Run with an optimal control solver, the therapies are strongest while the tumour is large, the effector cells
    expand, and the tumour shrinks.

    Args:
        x:
            The initial effector cells, in units of `10^5`.

        y:
            The initial tumour cells, in units of `10^5`.

        alpha_a:
            The antigenicity of the tumour.

        w1:
            The weight of the squared adoptive therapy rate in the cost.

        w2:
            The weight of the squared IL-2 injection rate in the cost.

    Returns:
        system:
            The model, with the effector cells `site.x`, the tumour `site.y`, IL-2 `site.z`, the therapies `site.u1`
            and `site.u2`, and the observable `immune_ratio`.

    Examples:
        >>> from skcomplex.models.biology.oncology import optimal_immunotherapy
        >>> optimal_immunotherapy(w1=0.5).elements[0].w1
        0.5
    """
    site = OptimalImmunotherapyElement('site', x=x, y=y, alpha_a=alpha_a, w1=w1, w2=w2)
    interactions = [
        RateInteraction('stimulation', target='site', state='x', rate=lambda s: s.target.alpha_a * s.target.y),
        ReactionInteraction(
            'effector_death',
            target='site',
            reactants={'x': 1},
            propensity=lambda s: s.target.d1 * s.target.x,
        ),
        DosingInteraction('adoptive_therapy', target='site', state='x', dose=lambda s: s.target.a1 * s.target.u1),
        MichaelisMentenInteraction(
            'effector_proliferation',
            target='site',
            products={'x': 1},
            substrate='z',
            vmax=lambda s: s.target.rho1,
            km=1.0,
            modifiers={'x': 1},
        ),
        RateInteraction(
            'tumour_growth',
            target='site',
            state='y',
            rate=lambda s: s.target.r1 * s.target.y * (1 - s.target.b * s.target.y),
        ),
        MichaelisMentenInteraction(
            'kill',
            target='site',
            reactants={'y': 1},
            substrate='y',
            vmax=lambda s: s.target.c1,
            km=1.0,
            modifiers={'x': 1},
        ),
        DosingInteraction('il2_injection', target='site', state='z', dose=lambda s: s.target.a2 * s.target.u2),
        MichaelisMentenInteraction(
            'il2_production',
            target='site',
            products={'z': 1},
            substrate='y',
            vmax=lambda s: s.target.rho2,
            km=lambda s: s.target.alpha3,
            modifiers={'x': 1},
        ),
        ReactionInteraction(
            'il2_loss',
            target='site',
            reactants={'z': 1},
            propensity=lambda s: s.target.du * s.target.z,
        ),
    ]
    return System(elements=[site], interactions=interactions)

piecewise_linear_ias(patient=1, *, h0=4.0, h1=10.0)

Return the Hirata piecewise-linear model of intermittent androgen suppression for one of three patient types.

The androgen-dependent, adapted, and mutated cells grow and change into each other linearly, with one set of rates during therapy and one off therapy, and the therapy switches on when the PSA, the sum of the cells, rises through h1 and off when it falls through h0. The rates are the book's daily factors, w = omega - 1 on the diagonal and w = omega off it. Patient 1 does not relapse, patient 2 relapses late, and patient 3 relapses, once the mutated cells outgrow the therapy. The book only states that therapy starts above 10 ng/mL, so the therapy stops below 4 ng/mL and is on at the start when the PSA exceeds h1. The cells are in units of the PSA, ng/mL, and time is in days.

Parameters:

Name Type Description Default
patient int

The patient type, 1, 2, or 3, which sets the rates and the initial cells.

1
h0 float

The PSA below which the therapy stops.

4.0
h1 float

The PSA above which the therapy starts.

10.0

Returns:

Name Type Description
system System

The model, with the cells tumour.AD, tumour.AIR, and tumour.AII, the therapy tumour.u, and the switches as on and off events.

Raises:

Type Description
ValidationError

The patient type is not 1, 2, or 3.

Examples:

>>> from skcomplex.models.biology.oncology import piecewise_linear_ias
>>> piecewise_linear_ias(patient=3).elements[0].AD
11.02
Source code in src/skcomplex/models/biology/oncology/_hormone_therapy.py
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
@register_model(
    field='biology/oncology',
    tags=('hormone therapy', 'ode', 'prostate cancer', 'piecewise linear', 'events', 'intermittent'),
    references=(BOOK, 'Hirata, Bruchovsky, and Aihara 2010'),
    defaults={'until': 1500.0, 'dt': 5.0},
)
def piecewise_linear_ias(patient: int = 1, *, h0: float = 4.0, h1: float = 10.0) -> System:
    """Return the Hirata piecewise-linear model of intermittent androgen suppression for one of three patient types.

    The androgen-dependent, adapted, and mutated cells grow and change into each other linearly, with one set of
    rates during therapy and one off therapy, and the therapy switches on when the PSA, the sum of the cells, rises
    through `h1` and off when it falls through `h0`. The rates are the book's daily factors, `w = omega - 1` on the
    diagonal and `w = omega` off it. Patient 1 does not relapse, patient 2 relapses late, and patient 3 relapses,
    once the mutated cells outgrow the therapy. The book only states that therapy starts above 10 ng/mL, so the
    therapy stops below 4 ng/mL and is on at the start when the PSA exceeds `h1`. The cells are in units of the PSA,
    ng/mL, and time is in days.

    Args:
        patient:
            The patient type, 1, 2, or 3, which sets the rates and the initial cells.

        h0:
            The PSA below which the therapy stops.

        h1:
            The PSA above which the therapy starts.

    Returns:
        system:
            The model, with the cells `tumour.AD`, `tumour.AIR`, and `tumour.AII`, the therapy `tumour.u`, and the
            switches as `on` and `off` events.

    Raises:
        ValidationError:
            The patient type is not 1, 2, or 3.

    Examples:
        >>> from skcomplex.models.biology.oncology import piecewise_linear_ias
        >>> piecewise_linear_ias(patient=3).elements[0].AD
        11.02
    """
    if patient not in PATIENT_FACTORS:
        error_msg = f'The patient type must be 1, 2, or 3, got {patient!r}.'
        raise ValidationError(error_msg)
    factors = PATIENT_FACTORS[patient]
    on11, on21, on22, on31, on32, on33 = factors['on']
    off11, off12, off22, off33 = factors['off']
    AD, AIR, AII = factors['cells']
    tumour = PiecewiseLinearProstateElement(
        'tumour',
        AD=AD,
        AIR=AIR,
        AII=AII,
        u=float(h1 < AD + AIR + AII),
        w11_on=on11 - 1,
        w21_on=on21,
        w22_on=on22 - 1,
        w31_on=on31,
        w32_on=on32,
        w33_on=on33 - 1,
        w11_off=off11 - 1,
        w12_off=off12,
        w22_off=off22 - 1,
        w33_off=off33 - 1,
    )
    switches = _get_switches(
        lambda s: s.target.x1 * s.target.AD + s.target.x2 * s.target.AIR + s.target.x3 * s.target.AII,
        h0,
        h1,
    )
    return System(elements=[tumour], interactions=switches)

power_law_growth(n=10.0, *, r=1.32, p=0.58)

Return a tumour whose proliferating part scales as a power of its size, dn/dt = r n^p.

For p < 1 the volume follows (n0^(1-p) + (1-p) r t)^(1/(1-p)), a growth slower than exponential. The defaults are the fit to breast cancer volumes in mm³ and days.

Parameters:

Name Type Description Default
n float

The initial volume.

10.0
r float

The growth rate.

1.32
p float

The exponent.

0.58

Returns:

Name Type Description
system System

The model, with the volume tumour.n.

Examples:

>>> from skcomplex.models.biology.oncology import power_law_growth
>>> power_law_growth(p=2 / 3).interactions[0].p
0.6666666666666666
Source code in src/skcomplex/models/biology/oncology/_growth.py
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
@register_model(
    field='biology/oncology',
    tags=('tumour growth', 'ode', 'power law'),
    references=GROWTH_REFERENCES,
    defaults={'until': 40.0, 'dt': 0.2},
)
def power_law_growth(n: float = 10.0, *, r: float = 1.32, p: float = 0.58) -> System:
    """Return a tumour whose proliferating part scales as a power of its size, `dn/dt = r n^p`.

    For `p < 1` the volume follows `(n0^(1-p) + (1-p) r t)^(1/(1-p))`, a growth slower than exponential. The defaults
    are the fit to breast cancer volumes in mm³ and days.

    Args:
        n:
            The initial volume.

        r:
            The growth rate.

        p:
            The exponent.

    Returns:
        system:
            The model, with the volume `tumour.n`.

    Examples:
        >>> from skcomplex.models.biology.oncology import power_law_growth
        >>> power_law_growth(p=2 / 3).interactions[0].p
        0.6666666666666666
    """
    return System(
        elements=[PopulationElement('tumour', n=n)],
        interactions=[PowerLawGrowthInteraction('growth', target='tumour', r=r, p=p)],
    )

prostate_androgen_receptor(N=1.5, AD=1.0, AI=0.0, *, UT=40.0, UD=40.0, m1=0.0001, age=60.0)

Return the Jain model of prostate epithelium and cancer driven by activated androgen receptors, with PSA.

The growth and death rates of the normal, androgen-dependent, and androgen-independent cells follow the receptors activated by testosterone, UT, and dihydrotestosterone, UD, which are parameters, so androgen ablation is a lower activation. The normal cells fill a capacity that grows with the age-dependent prostate volume, and the PSA the cells produce in the tissue leaks into the serum through the normal epithelium and, faster, through the tumour. Cells are in billions, receptors in nM, PSA in ng/mL, and time in hours, the age in years. The book leaves several parts open, filled as follows. The half saturations psi2, phi2, and psi4 of the cancer cells are those of the normal cells. The death rate is psi3_i / (psi4 + UD + UT). One activation UT, UD holds for all cell types, and so does sigma. The independent cells gain the part m1 of the divisions of the dependent cells. The negligible interaction c1 is 0. The capacity of the normal cells is the prostate volume over the volume of a billion cells, and the PSA leak rate per million cells becomes 0.3125 per billion.

Parameters:

Name Type Description Default
N float

The initial normal epithelial cells.

1.5
AD float

The initial androgen-dependent cells.

1.0
AI float

The initial androgen-independent cells.

0.0
UT float

The concentration of receptors activated by testosterone.

40.0
UD float

The concentration of receptors activated by dihydrotestosterone.

40.0
m1 float

The fraction of the divisions of dependent cells that yields independent cells.

0.0001
age float

The age of the patient at the start.

60.0

Returns:

Name Type Description
system System

The model, with the cells prostate.N, prostate.AD, and prostate.AI, and the PSA prostate.UIP in the tissue and prostate.UP in the serum.

Examples:

>>> from skcomplex.models.biology.oncology import prostate_androgen_receptor
>>> prostate_androgen_receptor(UT=5.0).elements[0].UT
5.0
Source code in src/skcomplex/models/biology/oncology/_hormone_therapy.py
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
@register_model(
    field='biology/oncology',
    tags=('hormone therapy', 'ode', 'prostate cancer', 'androgen receptor', 'PSA'),
    references=(BOOK, 'Jain et al. 2011'),
    defaults={'until': 26280.0, 'dt': 168.0, 'solver': ScipyODESolver(method='LSODA')},
)
def prostate_androgen_receptor(
    N: float = 1.5,
    AD: float = 1.0,
    AI: float = 0.0,
    *,
    UT: float = 40.0,
    UD: float = 40.0,
    m1: float = 1e-4,
    age: float = 60.0,
) -> System:
    """Return the Jain model of prostate epithelium and cancer driven by activated androgen receptors, with PSA.

    The growth and death rates of the normal, androgen-dependent, and androgen-independent cells follow the receptors
    activated by testosterone, `UT`, and dihydrotestosterone, `UD`, which are parameters, so androgen ablation is a
    lower activation. The normal cells fill a capacity that grows with the age-dependent prostate volume, and the PSA
    the cells produce in the tissue leaks into the serum through the normal epithelium and, faster, through the
    tumour. Cells are in billions, receptors in nM, PSA in ng/mL, and time in hours, the age in years. The book
    leaves several parts open, filled as follows. The half saturations `psi2`, `phi2`, and `psi4` of the cancer cells
    are those of the normal cells. The death rate is `psi3_i / (psi4 + UD + UT)`. One activation `UT`, `UD` holds
    for all cell types, and so does `sigma`. The independent cells gain the part `m1` of the divisions of the
    dependent cells. The negligible interaction `c1` is 0. The capacity of the normal cells is the prostate volume
    over the volume of a billion cells, and the PSA leak rate per million cells becomes `0.3125` per billion.

    Args:
        N:
            The initial normal epithelial cells.

        AD:
            The initial androgen-dependent cells.

        AI:
            The initial androgen-independent cells.

        UT:
            The concentration of receptors activated by testosterone.

        UD:
            The concentration of receptors activated by dihydrotestosterone.

        m1:
            The fraction of the divisions of dependent cells that yields independent cells.

        age:
            The age of the patient at the start.

    Returns:
        system:
            The model, with the cells `prostate.N`, `prostate.AD`, and `prostate.AI`, and the PSA `prostate.UIP` in
            the tissue and `prostate.UP` in the serum.

    Examples:
        >>> from skcomplex.models.biology.oncology import prostate_androgen_receptor
        >>> prostate_androgen_receptor(UT=5.0).elements[0].UT
        5.0
    """
    prostate = AndrogenReceptorProstateElement('prostate', N=N, AD=AD, AI=AI, UT=UT, UD=UD, m1=m1, age=age)
    interactions = [
        RateInteraction(
            'normal_growth',
            target='prostate',
            state='N',
            rate=lambda s: _receptor_growth(s.target, s.target.psi1_n, s.target.phi1_n)
            * s.target.N
            * (
                1
                - (s.target.N + s.target.c1 * (s.target.AD + s.target.AI))
                / (_prostate_volume(s.target, s.t) / s.target.Vc)
            ),
        ),
        ReactionInteraction(
            'normal_death',
            target='prostate',
            reactants={'N': 1},
            propensity=lambda s: _receptor_death(s.target, s.target.psi3_n) * s.target.N,
        ),
        RateInteraction(
            'dependent_division',
            target='prostate',
            state='AD',
            rate=lambda s: _dependent_division(s.target),
        ),
        ReactionInteraction(
            'mutation',
            target='prostate',
            reactants={'AD': 1},
            products={'AI': 1},
            propensity=lambda s: s.target.m1 * _dependent_division(s.target),
        ),
        ReactionInteraction(
            'dependent_death',
            target='prostate',
            reactants={'AD': 1},
            propensity=lambda s: _receptor_death(s.target, s.target.psi3_d) * s.target.AD,
        ),
        RateInteraction(
            'independent_growth',
            target='prostate',
            state='AI',
            rate=lambda s: _receptor_growth(s.target, s.target.psi1_i, s.target.phi1_i)
            * s.target.AI
            * (1 - (s.target.c1 * s.target.N + s.target.AD + s.target.AI) / s.target.b3),
        ),
        ReactionInteraction(
            'independent_death',
            target='prostate',
            reactants={'AI': 1},
            propensity=lambda s: _receptor_death(s.target, s.target.psi3_i) * s.target.AI,
        ),
        RateInteraction(
            'psa_production',
            target='prostate',
            state='UIP',
            rate=lambda s: (s.target.UT + s.target.UD + s.target.sigma)
            * (s.target.beta_n * s.target.N + s.target.beta_d * s.target.AD + s.target.beta_i * s.target.AI),
        ),
        ReactionInteraction(
            'normal_leak',
            target='prostate',
            reactants={'UIP': 1},
            products={'UP': 1},
            propensity=lambda s: s.target.du1
            * s.target.UIP
            * s.target.N
            / (_prostate_volume(s.target, s.t) / s.target.Vc),
        ),
        ReactionInteraction(
            'cancer_leak',
            target='prostate',
            reactants={'UIP': 1},
            products={'UP': 1},
            propensity=lambda s: s.target.gamma_p
            * s.target.UIP
            * (s.target.AD + s.target.AI) ** 2
            / (s.target.KP + s.target.AD + s.target.AI),
        ),
        ReactionInteraction(
            'intracellular_clearance',
            target='prostate',
            reactants={'UIP': 1},
            propensity=lambda s: s.target.du2 * s.target.UIP,
        ),
        ReactionInteraction(
            'serum_clearance',
            target='prostate',
            reactants={'UP': 1},
            propensity=lambda s: s.target.du3 * s.target.UP,
        ),
    ]
    return System(elements=[prostate], interactions=interactions)

prostate_cell_quota(AD=15.0, AI=0.0, *, rm=0.025, q1=0.3, q2=0.15, d1=0.015, d2=0.015, r0=0.01, r1=0.15, r2=0.15, n=3.0, theta=3.0, U0=15.0, Umin=0.5, du1=0.08, period=500.0, width=250.0)

Return the Portz cell-quota model of prostate cancer, whose cells grow on their internal androgen.

The androgen-dependent and independent cells grow at the Droop rate rm (1 - q_i / Q_i) of their cell quotas, which take up serum androgen, and the PSA they release follows the quotas. A deprived dependent cell turns independent faster, and an independent cell full of androgen turns back. The serum androgen follows the exponential relaxation of the book's equation 7.18 between the normal level U0 and Umin, with therapy during the first width days of every period. The book gives neither the steepness n of the mutation rates nor theta of the PSA production, nor the serum levels, their relaxation rate, and the schedule, so these defaults are chosen, and the other defaults lie within the book's ranges. Cells are in billions, quotas in nM, PSA in ng/mL, and time in days. The PSA starts near its value for the initial quotas.

Parameters:

Name Type Description Default
AD float

The initial androgen-dependent cells.

15.0
AI float

The initial androgen-independent cells.

0.0
rm float

The maximum proliferation rate.

0.025
q1 float

The minimum quota of the dependent cells.

0.3
q2 float

The minimum quota of the independent cells.

0.15
d1 float

The death rate of the dependent cells.

0.015
d2 float

The death rate of the independent cells.

0.015
r0 float

The baseline PSA production per cell.

0.01
r1 float

The androgen-driven PSA production per dependent cell.

0.15
r2 float

The androgen-driven PSA production per independent cell.

0.15
n float

The steepness of the mutation rates.

3.0
theta float

The steepness of the PSA production.

3.0
U0 float

The normal serum androgen.

15.0
Umin float

The serum androgen under therapy.

0.5
du1 float

The rate at which the serum androgen relaxes.

0.08
period float

The time between the starts of therapy periods.

500.0
width float

The duration of a therapy period.

250.0

Returns:

Name Type Description
system System

The model, with the cells tumour.AD and tumour.AI, the quotas tumour.Q1 and tumour.Q2, the PSA tumour.P, and the androgen tumour.U.

Examples:

>>> from skcomplex.models.biology.oncology import prostate_cell_quota
>>> prostate_cell_quota(q1=0.45).elements[0].q1
0.45
Source code in src/skcomplex/models/biology/oncology/_hormone_therapy.py
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
@register_model(
    field='biology/oncology',
    tags=('hormone therapy', 'ode', 'prostate cancer', 'cell quota', 'intermittent'),
    references=(BOOK, 'Portz, Kuang, and Nagy 2012'),
    defaults={'until': 1500.0, 'dt': 5.0},
)
def prostate_cell_quota(
    AD: float = 15.0,
    AI: float = 0.0,
    *,
    rm: float = 0.025,
    q1: float = 0.3,
    q2: float = 0.15,
    d1: float = 0.015,
    d2: float = 0.015,
    r0: float = 0.01,
    r1: float = 0.15,
    r2: float = 0.15,
    n: float = 3.0,
    theta: float = 3.0,
    U0: float = 15.0,
    Umin: float = 0.5,
    du1: float = 0.08,
    period: float = 500.0,
    width: float = 250.0,
) -> System:
    """Return the Portz cell-quota model of prostate cancer, whose cells grow on their internal androgen.

    The androgen-dependent and independent cells grow at the Droop rate `rm (1 - q_i / Q_i)` of their cell quotas,
    which take up serum androgen, and the PSA they release follows the quotas. A deprived dependent cell turns
    independent faster, and an independent cell full of androgen turns back. The serum androgen follows the
    exponential relaxation of the book's equation 7.18 between the normal level `U0` and `Umin`, with therapy during
    the first `width` days of every `period`. The book gives neither the steepness `n` of the mutation rates nor
    `theta` of the PSA production, nor the serum levels, their relaxation rate, and the schedule, so these defaults
    are chosen, and the other defaults lie within the book's ranges. Cells are in billions, quotas in nM, PSA in
    ng/mL, and time in days. The PSA starts near its value for the initial quotas.

    Args:
        AD:
            The initial androgen-dependent cells.

        AI:
            The initial androgen-independent cells.

        rm:
            The maximum proliferation rate.

        q1:
            The minimum quota of the dependent cells.

        q2:
            The minimum quota of the independent cells.

        d1:
            The death rate of the dependent cells.

        d2:
            The death rate of the independent cells.

        r0:
            The baseline PSA production per cell.

        r1:
            The androgen-driven PSA production per dependent cell.

        r2:
            The androgen-driven PSA production per independent cell.

        n:
            The steepness of the mutation rates.

        theta:
            The steepness of the PSA production.

        U0:
            The normal serum androgen.

        Umin:
            The serum androgen under therapy.

        du1:
            The rate at which the serum androgen relaxes.

        period:
            The time between the starts of therapy periods.

        width:
            The duration of a therapy period.

    Returns:
        system:
            The model, with the cells `tumour.AD` and `tumour.AI`, the quotas `tumour.Q1` and `tumour.Q2`, the PSA
            `tumour.P`, and the androgen `tumour.U`.

    Examples:
        >>> from skcomplex.models.biology.oncology import prostate_cell_quota
        >>> prostate_cell_quota(q1=0.45).elements[0].q1
        0.45
    """
    tumour = CellQuotaProstateElement(
        'tumour',
        AD=AD,
        AI=AI,
        U=U0,
        rm=rm,
        q1=q1,
        q2=q2,
        d1=d1,
        d2=d2,
        r0=r0,
        r1=r1,
        r2=r2,
        n=n,
        theta=theta,
        U0=U0,
        Umin=Umin,
        du1=du1,
        period=period,
        width=width,
    )
    interactions = [
        RateInteraction(
            'dependent_growth',
            target='tumour',
            state='AD',
            rate=lambda s: s.target.rm * (1 - s.target.q1 / s.target.Q1) * s.target.AD,
        ),
        ReactionInteraction(
            'dependent_death',
            target='tumour',
            reactants={'AD': 1},
            propensity=lambda s: s.target.d1 * s.target.AD,
        ),
        ReactionInteraction(
            'to_independent',
            target='tumour',
            reactants={'AD': 1},
            products={'AI': 1},
            propensity=lambda s: s.target.mx1 * (1 - hill(s.target.Q1, s.target.m501, s.target.n)) * s.target.AD,
        ),
        ReactionInteraction(
            'to_dependent',
            target='tumour',
            reactants={'AI': 1},
            products={'AD': 1},
            propensity=lambda s: s.target.mx2 * hill(s.target.Q2, s.target.m502, s.target.n) * s.target.AI,
        ),
        RateInteraction(
            'independent_growth',
            target='tumour',
            state='AI',
            rate=lambda s: s.target.rm * (1 - s.target.q2 / s.target.Q2) * s.target.AI,
        ),
        ReactionInteraction(
            'independent_death',
            target='tumour',
            reactants={'AI': 1},
            propensity=lambda s: s.target.d2 * s.target.AI,
        ),
        RateInteraction(
            'dependent_uptake',
            target='tumour',
            state='Q1',
            rate=lambda s: _quota_uptake(s.target, s.target.Q1, s.target.q1),
        ),
        RateInteraction(
            'dependent_use',
            target='tumour',
            state='Q1',
            rate=lambda s: -s.target.rm * (s.target.Q1 - s.target.q1),
        ),
        ReactionInteraction(
            'dependent_degradation',
            target='tumour',
            reactants={'Q1': 1},
            propensity=lambda s: s.target.d3 * s.target.Q1,
        ),
        RateInteraction(
            'independent_uptake',
            target='tumour',
            state='Q2',
            rate=lambda s: _quota_uptake(s.target, s.target.Q2, s.target.q2),
        ),
        RateInteraction(
            'independent_use',
            target='tumour',
            state='Q2',
            rate=lambda s: -s.target.rm * (s.target.Q2 - s.target.q2),
        ),
        ReactionInteraction(
            'independent_degradation',
            target='tumour',
            reactants={'Q2': 1},
            propensity=lambda s: s.target.d3 * s.target.Q2,
        ),
        RateInteraction(
            'psa_leak',
            target='tumour',
            state='P',
            rate=lambda s: s.target.r0 * (s.target.AD + s.target.AI),
        ),
        RateInteraction(
            'psa_production',
            target='tumour',
            state='P',
            rate=lambda s: s.target.r1 * s.target.AD * hill(s.target.Q1, s.target.rho1, s.target.theta)
            + s.target.r2 * s.target.AI * hill(s.target.Q2, s.target.rho2, s.target.theta),
        ),
        ReactionInteraction(
            'psa_clearance',
            target='tumour',
            reactants={'P': 1},
            propensity=lambda s: s.target.du * s.target.P,
        ),
        RateInteraction(
            'androgen',
            target='tumour',
            state='U',
            rate=lambda s: s.target.du1
            * (
                s.target.U0 - (s.target.U0 - s.target.Umin) * pulse_train(s.t, tumour.period, tumour.width) - s.target.U
            ),
        ),
    ]
    return System(elements=[tumour], interactions=interactions)

radiotherapy_competition(N=0.5, A=0.8, *, r1=0.008, r2=0.4, c1=0.01, c2=0.15, a2=0.2, epsilon=0.001, period=7.0, width=5.0)

Return normal and tumour cells in Lotka-Volterra competition, the tumour irradiated periodically.

The tumour cells outcompete the normal cells without treatment. The irradiation kills tumour cells at the per capita rate a2 for width days every period days, which takes the tumour below the level at which the normal cells can invade, so the two coexist, and the radiation that spills over removes normal cells at the rate epsilon. The book combines a periodic constant dose with the dose proportional to the tumour. A constant dose drives an eradicated tumour negative, so the periodic dose here is proportional to the tumour. The book gives no schedule, so the defaults irradiate five days a week. The concentrations are normalized by the carrying capacities, b1 = b2 = 1, and time is in days.

Parameters:

Name Type Description Default
N float

The initial concentration of normal cells.

0.5
A float

The initial concentration of tumour cells.

0.8
r1 float

The growth rate of the normal cells.

0.008
r2 float

The growth rate of the tumour cells.

0.4
c1 float

The rate at which the tumour cells suppress the normal cells.

0.01
c2 float

The rate at which the normal cells suppress the tumour cells.

0.15
a2 float

The per capita kill rate of the radiation during an irradiation, between 0.01 and 0.2.

0.2
epsilon float

The per capita kill rate of the radiation that spills over to the normal cells.

0.001
period float

The time between the starts of irradiations.

7.0
width float

The duration of an irradiation.

5.0

Returns:

Name Type Description
system System

The model, with the normal cells tissue.N and the tumour cells tissue.A.

Examples:

>>> from skcomplex.models.biology.oncology import radiotherapy_competition
>>> radiotherapy_competition(a2=0.1).elements[0].a2
0.1
Source code in src/skcomplex/models/biology/oncology/_radiotherapy.py
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
@register_model(
    field='biology/oncology',
    tags=('radiotherapy', 'ode', 'competition', 'dosing'),
    references=(BOOK, 'Belostotski and Freedman 2005', 'Liu and Yang 2014'),
    defaults={'until': 1400.0, 'dt': 5.0},
)
def radiotherapy_competition(
    N: float = 0.5,
    A: float = 0.8,
    *,
    r1: float = 0.008,
    r2: float = 0.4,
    c1: float = 0.01,
    c2: float = 0.15,
    a2: float = 0.2,
    epsilon: float = 0.001,
    period: float = 7.0,
    width: float = 5.0,
) -> System:
    """Return normal and tumour cells in Lotka-Volterra competition, the tumour irradiated periodically.

    The tumour cells outcompete the normal cells without treatment. The irradiation kills tumour cells at the per
    capita rate `a2` for `width` days every `period` days, which takes the tumour below the level at which the normal
    cells can invade, so the two coexist, and the radiation that spills over removes normal cells at the rate
    `epsilon`. The book combines a periodic constant dose with the dose proportional to the tumour. A constant dose
    drives an eradicated tumour negative, so the periodic dose here is proportional to the tumour. The book gives no
    schedule, so the defaults irradiate five days a week. The concentrations are normalized by the carrying
    capacities, `b1 = b2 = 1`, and time is in days.

    Args:
        N:
            The initial concentration of normal cells.

        A:
            The initial concentration of tumour cells.

        r1:
            The growth rate of the normal cells.

        r2:
            The growth rate of the tumour cells.

        c1:
            The rate at which the tumour cells suppress the normal cells.

        c2:
            The rate at which the normal cells suppress the tumour cells.

        a2:
            The per capita kill rate of the radiation during an irradiation, between 0.01 and 0.2.

        epsilon:
            The per capita kill rate of the radiation that spills over to the normal cells.

        period:
            The time between the starts of irradiations.

        width:
            The duration of an irradiation.

    Returns:
        system:
            The model, with the normal cells `tissue.N` and the tumour cells `tissue.A`.

    Examples:
        >>> from skcomplex.models.biology.oncology import radiotherapy_competition
        >>> radiotherapy_competition(a2=0.1).elements[0].a2
        0.1
    """
    tissue = RadiationCompetitionElement(
        'tissue',
        N=N,
        A=A,
        r1=r1,
        r2=r2,
        c1=c1,
        c2=c2,
        a2=a2,
        epsilon=epsilon,
        period=period,
        width=width,
    )
    interactions = [
        RateInteraction(
            'normal_growth',
            target='tissue',
            state='N',
            rate=lambda s: s.target.r1 * s.target.N * (1 - s.target.b1 * s.target.N),
        ),
        ReactionInteraction(
            'normal_competition',
            target='tissue',
            reactants={'N': 1},
            modifiers={'A': 1},
            propensity=lambda s: s.target.c1 * s.target.N * s.target.A,
        ),
        ReactionInteraction(
            'spillover',
            target='tissue',
            reactants={'N': 1},
            propensity=lambda s: s.target.epsilon * s.target.N,
        ),
        RateInteraction(
            'tumour_growth',
            target='tissue',
            state='A',
            rate=lambda s: s.target.r2 * s.target.A * (1 - s.target.b2 * s.target.A),
        ),
        ReactionInteraction(
            'tumour_competition',
            target='tissue',
            reactants={'A': 1},
            modifiers={'N': 1},
            propensity=lambda s: s.target.c2 * s.target.N * s.target.A,
        ),
        ReactionInteraction(
            'irradiation',
            target='tissue',
            reactants={'A': 1},
            propensity=lambda s: s.target.a2 * pulse_train(s.t, period, width) * s.target.A,
        ),
    ]
    return System(elements=[tissue], interactions=interactions)

sirna_tgf_beta(E=1000.0, A=1000.0, *, alpha=0.035, rho4=300000000.0, psi=1.0, gamma3=1.0, u=0.0, du=0.66)

Return the Kirschner-Panetta model with TGF-beta, which lets the tumour evade the immune system, and siRNA.

TGF-beta lowers the recruitment of effector cells by 1 + gamma1 C2 and the production of IL-2, and raises the growth of the tumour. Without TGF-beta, rho4 = 0, the effector cells hold the tumour near 1e4 cells. With the book's production of TGF-beta the tumour escapes to its carrying capacity, and a large enough infusion of siRNA clears it. Cells are counts, the cytokines are in pg/ml, and time is in days. The other parameters are those of the book's table. Three decisions fill gaps in the book: the decay of IL-2 is d2 C1, where the book prints d2 E; the production of TGF-beta is rho4 A^2 / (mu^2 + (1 + psi G^gamma3) A^2); and the book gives no values for psi, gamma3, or u, so psi = gamma3 = 1 and G is in units where the infusion u is the dose.

Parameters:

Name Type Description Default
E float

The initial number of effector cells.

1000.0
A float

The initial number of tumour cells.

1000.0
alpha float

The antigenicity of the tumour, per day.

0.035
rho4 float

The largest production rate of TGF-beta, in pg/ml per day.

300000000.0
psi float

The fraction of the siRNA bound to the mRNA.

1.0
gamma3 float

The exponent of the suppression of the mRNA by the siRNA.

1.0
u float

The infusion rate of siRNA, per day.

0.0
du float

The decay rate of siRNA, per day.

0.66

Returns:

Name Type Description
system System

The model, with the effector cells site.E, the tumour cells site.A, IL-2 site.C1, TGF-beta site.C2, and the siRNA site.G.

Examples:

>>> from skcomplex.models.biology.oncology import sirna_tgf_beta
>>> sirna_tgf_beta(u=1e6).elements[0].u
1000000.0
Source code in src/skcomplex/models/biology/oncology/_gene_viral_therapy.py
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
@register_model(
    field='biology/oncology',
    tags=('gene therapy', 'immunotherapy', 'cytokines', 'ode'),
    references=(BOOK, 'Arciero, Jackson, and Kirschner 2004'),
    defaults={'until': 200.0, 'dt': 0.5},
)
def sirna_tgf_beta(
    E: float = 1e3,
    A: float = 1e3,
    *,
    alpha: float = 0.035,
    rho4: float = 3e8,
    psi: float = 1.0,
    gamma3: float = 1.0,
    u: float = 0.0,
    du: float = 0.66,
) -> System:
    """Return the Kirschner-Panetta model with TGF-beta, which lets the tumour evade the immune system, and siRNA.

    TGF-beta lowers the recruitment of effector cells by `1 + gamma1 C2` and the production of IL-2, and raises the
    growth of the tumour. Without TGF-beta, `rho4 = 0`, the effector cells hold the tumour near `1e4` cells. With the
    book's production of TGF-beta the tumour escapes to its carrying capacity, and a large enough infusion of siRNA
    clears it. Cells are counts, the cytokines are in pg/ml, and time is in days. The other parameters are those of
    the book's table. Three decisions fill gaps in the book: the decay of IL-2 is `d2 C1`, where the book prints
    `d2 E`; the production of TGF-beta is `rho4 A^2 / (mu^2 + (1 + psi G^gamma3) A^2)`; and the book gives no values
    for `psi`, `gamma3`, or `u`, so `psi = gamma3 = 1` and `G` is in units where the infusion `u` is the dose.

    Args:
        E:
            The initial number of effector cells.

        A:
            The initial number of tumour cells.

        alpha:
            The antigenicity of the tumour, per day.

        rho4:
            The largest production rate of TGF-beta, in pg/ml per day.

        psi:
            The fraction of the siRNA bound to the mRNA.

        gamma3:
            The exponent of the suppression of the mRNA by the siRNA.

        u:
            The infusion rate of siRNA, per day.

        du:
            The decay rate of siRNA, per day.

    Returns:
        system:
            The model, with the effector cells `site.E`, the tumour cells `site.A`, IL-2 `site.C1`, TGF-beta
            `site.C2`, and the siRNA `site.G`.

    Examples:
        >>> from skcomplex.models.biology.oncology import sirna_tgf_beta
        >>> sirna_tgf_beta(u=1e6).elements[0].u
        1000000.0
    """
    site = SirnaTgfBetaElement('site', E=E, A=A, alpha=alpha, rho4=rho4, psi=psi, gamma3=gamma3, u=u, du=du)
    interactions = [
        RateInteraction(
            'stimulation',
            target='site',
            state='E',
            rate=lambda s: s.target.alpha * s.target.A / (1 + s.target.gamma1 * s.target.C2),
        ),
        ReactionInteraction(
            'effector_death',
            target='site',
            reactants={'E': 1},
            propensity=lambda s: s.target.d1 * s.target.E,
        ),
        RateInteraction(
            'effector_proliferation',
            target='site',
            state='E',
            rate=lambda s: s.target.E
            * s.target.C1
            / (s.target.g1 + s.target.C1)
            * (s.target.rho1 - s.target.rmax * s.target.C2 / (s.target.g2 + s.target.C2)),
        ),
        RateInteraction(
            'tumour_growth',
            target='site',
            state='A',
            rate=lambda s: s.target.r1 * s.target.A * (1 - s.target.b * s.target.A),
        ),
        MichaelisMentenInteraction(
            'kill',
            target='site',
            reactants={'A': 1},
            substrate='A',
            vmax=lambda s: s.target.a1,
            km=lambda s: s.target.g3,
            modifiers={'E': 1},
        ),
        MichaelisMentenInteraction(
            'stimulated_growth',
            target='site',
            products={'A': 1},
            substrate='C2',
            vmax=lambda s: s.target.rho2,
            km=lambda s: s.target.g4,
            modifiers={'A': 1},
        ),
        RateInteraction(
            'il2_production',
            target='site',
            state='C1',
            rate=lambda s: s.target.rho3
            * s.target.E
            * s.target.A
            / ((s.target.g5 + s.target.A) * (1 + s.target.gamma2 * s.target.C2)),
        ),
        ReactionInteraction(
            'il2_loss',
            target='site',
            reactants={'C1': 1},
            propensity=lambda s: s.target.d2 * s.target.C1,
        ),
        RateInteraction(
            'tgf_beta_production',
            target='site',
            state='C2',
            rate=lambda s: s.target.rho4
            * s.target.A**2
            / (s.target.mu**2 + (1 + s.target.psi * s.target.G**s.target.gamma3) * s.target.A**2),
        ),
        ReactionInteraction(
            'tgf_beta_loss',
            target='site',
            reactants={'C2': 1},
            propensity=lambda s: s.target.d3 * s.target.C2,
        ),
        DosingInteraction('sirna_dosing', target='site', state='G', dose=lambda s: s.target.u),
        ReactionInteraction(
            'sirna_loss',
            target='site',
            reactants={'G': 1},
            propensity=lambda s: s.target.du * s.target.G,
        ),
    ]
    return System(elements=[site], interactions=interactions)

skipper_log_kill(n=1000000.0, *, r=0.223, a=2.0, dose=1.0, period=7.0, width=1.0)

Return the log-kill model, an exponentially growing tumour of which every dose kills a fixed fraction.

The tumour follows dn/dt = r n - a n U(t), where the exposure U is dose for width days every period days. Every dose lowers log n by a dose width, whatever the size, and the tumour regrows between doses. The growth rate is the exponential fit to breast cancer, per day.

Parameters:

Name Type Description Default
n float

The initial number of cells.

1000000.0
r float

The growth rate.

0.223
a float

The kill rate per unit of exposure.

2.0
dose float

The exposure during a dose.

1.0
period float

The time between the starts of doses.

7.0
width float

The duration of a dose.

1.0

Returns:

Name Type Description
system System

The model, with the cells tumour.n.

Examples:

>>> from skcomplex.models.biology.oncology import skipper_log_kill
>>> skipper_log_kill(period=21.0).interactions[1].period
21.0
Source code in src/skcomplex/models/biology/oncology/_growth.py
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
@register_model(
    field='biology/oncology',
    tags=('chemotherapy', 'ode', 'log kill', 'dosing'),
    references=('Padmanabhan, Meskin, and Al Moustafa 2021', 'Skipper, Schabel, and Wilcox 1964'),
    defaults={'until': 42.0, 'dt': 0.1},
)
def skipper_log_kill(
    n: float = 1e6,
    *,
    r: float = 0.223,
    a: float = 2.0,
    dose: float = 1.0,
    period: float = 7.0,
    width: float = 1.0,
) -> System:
    """Return the log-kill model, an exponentially growing tumour of which every dose kills a fixed fraction.

    The tumour follows `dn/dt = r n - a n U(t)`, where the exposure `U` is `dose` for `width` days every `period`
    days. Every dose lowers `log n` by `a dose width`, whatever the size, and the tumour regrows between doses. The
    growth rate is the exponential fit to breast cancer, per day.

    Args:
        n:
            The initial number of cells.

        r:
            The growth rate.

        a:
            The kill rate per unit of exposure.

        dose:
            The exposure during a dose.

        period:
            The time between the starts of doses.

        width:
            The duration of a dose.

    Returns:
        system:
            The model, with the cells `tumour.n`.

    Examples:
        >>> from skcomplex.models.biology.oncology import skipper_log_kill
        >>> skipper_log_kill(period=21.0).interactions[1].period
        21.0
    """
    return System(
        elements=[PopulationElement('tumour', n=n)],
        interactions=[
            ExponentialGrowthInteraction('growth', target='tumour', r=r),
            LogKillInteraction('kill', target='tumour', a=a, dose=dose, period=period, width=width),
        ],
    )

stem_cell_differentiation(*, m0=0.005, beta0=5.0, delta=1.0, therapy='continuous', start=100.0, duration=100.0, seed=0)

Return the eight-compartment model of normal and malignant stem-cell lineages with feedback and therapy.

Each lineage runs from quiescent stem cells through progenitors and basal cells to differentiated cells, and normal progenitors mutate into malignant ones. The mutation rate m1 = m0 (1 + w) carries the random factor w, which is drawn once per run from the uniform distribution on [0, 1) with the seed. The parameters and the initial cells are those of the book's table, with beta0 at the top of its range. The book gives no value for delta, so it defaults to 1, and no times for the pulse of a pulsed therapy. The book prints the death rates off the pulse as the death rates times the dose, and the model keeps that. Time is in the units of the source. Under the continuous therapy the lineages settle on a steady state in which the mutation feeds a small malignant population.

Parameters:

Name Type Description Default
m0 float

The mutation rate without the random factor.

0.005
beta0 float

The feedback constant.

5.0
delta float

The weight of the renewal in the death the therapy causes to normal progenitors.

1.0
therapy Literal['none', 'pulsed', 'continuous']

The mode of therapy, 'none', 'pulsed', or 'continuous'.

'continuous'
start float

The time the pulse of a pulsed therapy starts.

100.0
duration float

The duration of the pulse of a pulsed therapy.

100.0
seed int

The seed of the random factor of the mutation rate.

0

Returns:

Name Type Description
system System

The model, with the normal cells tissue.NSq, tissue.NPr, tissue.NBs, and tissue.ND and the malignant cells tissue.ASq, tissue.APr, tissue.ABs, and tissue.AD.

Examples:

>>> from skcomplex.models.biology.oncology import stem_cell_differentiation
>>> 0.005 <= stem_cell_differentiation(seed=1).elements[0].m1 < 0.01
True
Source code in src/skcomplex/models/biology/oncology/_stem_cells.py
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
@register_model(
    field='biology/oncology',
    tags=('stem cells', 'cancer stem cells', 'ode', 'feedback', 'random'),
    references=(BOOK, 'Calmelet et al. 2010'),
    defaults={'until': 2000.0, 'dt': 10.0},
)
def stem_cell_differentiation(
    *,
    m0: float = 0.005,
    beta0: float = 5.0,
    delta: float = 1.0,
    therapy: Literal['none', 'pulsed', 'continuous'] = 'continuous',
    start: float = 100.0,
    duration: float = 100.0,
    seed: int = 0,
) -> System:
    """Return the eight-compartment model of normal and malignant stem-cell lineages with feedback and therapy.

    Each lineage runs from quiescent stem cells through progenitors and basal cells to differentiated cells, and
    normal progenitors mutate into malignant ones. The mutation rate `m1 = m0 (1 + w)` carries the random factor `w`,
    which is drawn once per run from the uniform distribution on `[0, 1)` with the seed. The parameters and the
    initial cells are those of the book's table, with `beta0` at the top of its range. The book gives no value for
    `delta`, so it defaults to 1, and no times for the pulse of a pulsed therapy. The book prints the death rates
    off the pulse as the death rates times the dose, and the model keeps that. Time is in the units of the source.
    Under the continuous therapy the lineages settle on a steady state in which the mutation feeds a small malignant
    population.

    Args:
        m0:
            The mutation rate without the random factor.

        beta0:
            The feedback constant.

        delta:
            The weight of the renewal in the death the therapy causes to normal progenitors.

        therapy:
            The mode of therapy, `'none'`, `'pulsed'`, or `'continuous'`.

        start:
            The time the pulse of a pulsed therapy starts.

        duration:
            The duration of the pulse of a pulsed therapy.

        seed:
            The seed of the random factor of the mutation rate.

    Returns:
        system:
            The model, with the normal cells `tissue.NSq`, `tissue.NPr`, `tissue.NBs`, and `tissue.ND` and the
            malignant cells `tissue.ASq`, `tissue.APr`, `tissue.ABs`, and `tissue.AD`.

    Examples:
        >>> from skcomplex.models.biology.oncology import stem_cell_differentiation
        >>> 0.005 <= stem_cell_differentiation(seed=1).elements[0].m1 < 0.01
        True
    """
    m1 = m0 * (1 + np.random.default_rng(seed).uniform())
    tissue = StemCellDifferentiationElement(
        'tissue',
        m1=m1,
        beta0=beta0,
        delta=delta,
        therapy=therapy,
        start=start,
        duration=duration,
    )
    interactions = [
        ReactionInteraction(
            'normal_quiescent_death',
            target='tissue',
            reactants={'NSq': 1},
            propensity=lambda s: s.target.d1 * s.target.NSq,
        ),
        ReactionInteraction(
            'normal_activation',
            target='tissue',
            reactants={'NSq': 1},
            products={'NPr': 1},
            propensity=lambda s: s.target.k12 * s.target.NSq,
        ),
        ReactionInteraction(
            'normal_return',
            target='tissue',
            reactants={'NPr': 1},
            products={'NSq': 1},
            propensity=lambda s: s.target.k21 * (1 - s.target.NPr / (s.target.NPr + s.target.NPinf)) * s.target.NPr,
        ),
        RateInteraction(
            'normal_renewal',
            target='tissue',
            state='NPr',
            rate=lambda s: _normal_renewal(s.target) * s.target.NPr,
        ),
        RateInteraction(
            'normal_progenitor_death',
            target='tissue',
            state='NPr',
            rate=lambda s: -_therapy_deaths(s, therapy, start, duration)[0] * s.target.NPr,
        ),
        ReactionInteraction(
            'mutation',
            target='tissue',
            reactants={'NPr': 1},
            products={'APr': 1},
            propensity=lambda s: s.target.m1 * s.target.NPr,
        ),
        ReactionInteraction(
            'normal_commitment',
            target='tissue',
            reactants={'NPr': 1},
            products={'NBs': 1},
            propensity=lambda s: s.target.k23 * s.target.NPr,
        ),
        RateInteraction(
            'normal_basal_death',
            target='tissue',
            state='NBs',
            rate=lambda s: -s.target.d3 * _therapy_deaths(s, therapy, start, duration)[1] * s.target.NBs,
        ),
        ReactionInteraction(
            'normal_differentiation',
            target='tissue',
            reactants={'NBs': 1},
            products={'ND': 1},
            propensity=lambda s: s.target.k34 * s.target.NBs,
        ),
        RateInteraction(
            'normal_basal_growth',
            target='tissue',
            state='NBs',
            rate=lambda s: s.target.r2 * (1 - s.target.NBs / s.target.Nbmax) * s.target.NBs,
        ),
        ReactionInteraction(
            'normal_death',
            target='tissue',
            reactants={'ND': 1},
            propensity=lambda s: s.target.d4 * s.target.ND,
        ),
        ReactionInteraction(
            'malignant_quiescent_death',
            target='tissue',
            reactants={'ASq': 1},
            propensity=lambda s: s.target.d5 * s.target.ASq,
        ),
        ReactionInteraction(
            'malignant_activation',
            target='tissue',
            reactants={'ASq': 1},
            products={'APr': 1},
            propensity=lambda s: s.target.k56 * s.target.ASq,
        ),
        ReactionInteraction(
            'malignant_return',
            target='tissue',
            reactants={'APr': 1},
            products={'ASq': 1},
            propensity=lambda s: s.target.k65 * (1 - s.target.APr / (s.target.APr + s.target.APinf)) * s.target.APr,
        ),
        RateInteraction(
            'malignant_renewal',
            target='tissue',
            state='APr',
            rate=lambda s: s.target.r3 * (1 - s.target.APr / s.target.APmax) * s.target.APr,
        ),
        RateInteraction(
            'malignant_progenitor_death',
            target='tissue',
            state='APr',
            rate=lambda s: -s.target.d6 * _therapy_deaths(s, therapy, start, duration)[1] * s.target.APr,
        ),
        ReactionInteraction(
            'malignant_commitment',
            target='tissue',
            reactants={'APr': 1},
            products={'ABs': 1},
            propensity=lambda s: s.target.k67 * s.target.APr,
        ),
        RateInteraction(
            'malignant_basal_death',
            target='tissue',
            state='ABs',
            rate=lambda s: -s.target.d7 * _therapy_deaths(s, therapy, start, duration)[1] * s.target.ABs,
        ),
        ReactionInteraction(
            'malignant_differentiation',
            target='tissue',
            reactants={'ABs': 1},
            products={'AD': 1},
            propensity=lambda s: s.target.k78 * s.target.ABs,
        ),
        RateInteraction(
            'malignant_basal_growth',
            target='tissue',
            state='ABs',
            rate=lambda s: s.target.r4 * (1 - s.target.ABs / s.target.Abmax) * s.target.ABs,
        ),
        ReactionInteraction(
            'malignant_death',
            target='tissue',
            reactants={'AD': 1},
            propensity=lambda s: s.target.d8 * s.target.AD,
        ),
    ]
    return System(elements=[tissue], interactions=interactions)

step_table(classes, step, fields=1)

Return the transition table that moves a candidate one class up or down, staying at the end classes.

Parameters:

Name Type Description Default
classes int

The number of activity classes of the candidate.

required
step int

1 to move up and -1 to move down.

required
fields int

The number of activity classes of the field.

1

Returns:

Name Type Description
table NDArray[float64]

The transition table A[h, k, i].

Examples:

>>> from skcomplex.models.biology.oncology import step_table
>>> step_table(3, -1)[:, 0].tolist()
[[1.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]
Source code in src/skcomplex/models/biology/oncology/_immune_competition.py
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
def step_table(classes: int, step: int, fields: int = 1) -> npt.NDArray[np.float64]:
    """Return the transition table that moves a candidate one class up or down, staying at the end classes.

    Args:
        classes:
            The number of activity classes of the candidate.

        step:
            `1` to move up and `-1` to move down.

        fields:
            The number of activity classes of the field.

    Returns:
        table:
            The transition table `A[h, k, i]`.

    Examples:
        >>> from skcomplex.models.biology.oncology import step_table
        >>> step_table(3, -1)[:, 0].tolist()
        [[1.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]
    """
    table = np.zeros((classes, fields, classes))
    for candidate in range(classes):
        table[candidate, :, min(max(candidate + step, 0), classes - 1)] = 1.0
    return table

tamoxifen_cell_cycle(Ag=900.0, As=50.0, Am=50.0, *, u=12.5, a1=0.0062, a2=0.01)

Return a breast tumour in Gompertzian cell-cycle phases under daily tamoxifen and its active metabolite.

The cells pass from the growth phase through synthesis to mitosis and divide back into the growth phase, at rates that slow as the tumour approaches Asat. Tamoxifen is absorbed from the gut into the plasma, where it is metabolized into 4-hydroxytamoxifen, and both kill cells in the growth phase, the metabolite 25 times more. They also kill circulating lymphocytes, which stay at s / d1 without the drug. The book gives no infusion rate, so the default u is 300 μg a day, given continuously. Volumes are in mm³, drug masses in μg, concentrations in μg/mL, lymphocytes in millions, and time in hours.

Parameters:

Name Type Description Default
Ag float

The initial volume of cells in the growth phase.

900.0
As float

The initial volume of cells in the synthesis phase.

50.0
Am float

The initial volume of cells in mitosis.

50.0
u float

The infusion rate of tamoxifen.

12.5
a1 float

The kill rate of the tumour per unit of drug.

0.0062
a2 float

The kill rate of the lymphocytes per unit of drug.

0.01

Returns:

Name Type Description
system System

The model, with the phases tumour.Ag, tumour.As, and tumour.Am, the drug masses tumour.X0 to tumour.X3, and the lymphocytes tumour.E.

Examples:

>>> from skcomplex.models.biology.oncology import tamoxifen_cell_cycle
>>> tamoxifen_cell_cycle(u=0.0).elements[0].u
0.0
Source code in src/skcomplex/models/biology/oncology/_hormone_therapy.py
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
@register_model(
    field='biology/oncology',
    tags=('hormone therapy', 'ode', 'breast cancer', 'cell cycle', 'pharmacokinetics'),
    references=(BOOK, 'Chen, Kirkby, and Jena 2012'),
    defaults={'until': 2400.0, 'dt': 8.0, 'solver': ScipyODESolver(method='LSODA')},
)
def tamoxifen_cell_cycle(
    Ag: float = 900.0,
    As: float = 50.0,
    Am: float = 50.0,
    *,
    u: float = 12.5,
    a1: float = 0.0062,
    a2: float = 0.010,
) -> System:
    """Return a breast tumour in Gompertzian cell-cycle phases under daily tamoxifen and its active metabolite.

    The cells pass from the growth phase through synthesis to mitosis and divide back into the growth phase, at
    rates that slow as the tumour approaches `Asat`. Tamoxifen is absorbed from the gut into the plasma, where it is
    metabolized into 4-hydroxytamoxifen, and both kill cells in the growth phase, the metabolite 25 times more. They
    also kill circulating lymphocytes, which stay at `s / d1` without the drug. The book gives no infusion rate, so the
    default `u` is 300 μg a day, given continuously. Volumes are in mm³, drug masses in μg, concentrations in
    μg/mL, lymphocytes in millions, and time in hours.

    Args:
        Ag:
            The initial volume of cells in the growth phase.

        As:
            The initial volume of cells in the synthesis phase.

        Am:
            The initial volume of cells in mitosis.

        u:
            The infusion rate of tamoxifen.

        a1:
            The kill rate of the tumour per unit of drug.

        a2:
            The kill rate of the lymphocytes per unit of drug.

    Returns:
        system:
            The model, with the phases `tumour.Ag`, `tumour.As`, and `tumour.Am`, the drug masses `tumour.X0` to
            `tumour.X3`, and the lymphocytes `tumour.E`.

    Examples:
        >>> from skcomplex.models.biology.oncology import tamoxifen_cell_cycle
        >>> tamoxifen_cell_cycle(u=0.0).elements[0].u
        0.0
    """
    tumour = TamoxifenTumourElement('tumour', Ag=Ag, As=As, Am=Am, u=u, a1=a1, a2=a2)
    interactions = [
        ReactionInteraction(
            'g1_exit',
            target='tumour',
            reactants={'Ag': 1},
            products={'As': 1},
            propensity=lambda s: s.target.mg * s.target.Ag * _room(s.target),
        ),
        ReactionInteraction(
            'synthesis',
            target='tumour',
            reactants={'As': 1},
            products={'Am': 1},
            propensity=lambda s: s.target.ms * s.target.As,
        ),
        ReactionInteraction(
            'mitosis',
            target='tumour',
            reactants={'Am': 1},
            products={'Ag': 2},
            propensity=lambda s: s.target.mm * s.target.Am * _room(s.target),
        ),
        ReactionInteraction(
            'drug_kill',
            target='tumour',
            reactants={'Ag': 1},
            propensity=lambda s: s.target.a1
            * s.target.Ag
            * (s.target.X2 / s.target.V + s.target.delta1 * s.target.X3 / s.target.V),
        ),
        DosingInteraction('dosing', target='tumour', state='X0', dose=lambda s: s.target.u),
        ReactionInteraction(
            'absorption',
            target='tumour',
            reactants={'X0': 1},
            products={'X1': 1},
            propensity=lambda s: s.target.k01 * s.target.X0,
        ),
        ReactionInteraction(
            'transport',
            target='tumour',
            reactants={'X1': 1},
            products={'X2': 1},
            propensity=lambda s: s.target.k12 * s.target.X1,
        ),
        ReactionInteraction(
            'metabolism',
            target='tumour',
            reactants={'X2': 1},
            products={'X3': 1},
            propensity=lambda s: s.target.k23 * s.target.X2,
        ),
        ReactionInteraction(
            'tamoxifen_clearance',
            target='tumour',
            reactants={'X2': 1},
            propensity=lambda s: s.target.du1 * s.target.X2,
        ),
        ReactionInteraction(
            'metabolite_clearance',
            target='tumour',
            reactants={'X3': 1},
            propensity=lambda s: s.target.du2 * s.target.X3,
        ),
        RateInteraction('effector_source', target='tumour', state='E', rate=lambda s: s.target.s),
        ReactionInteraction(
            'effector_death',
            target='tumour',
            reactants={'E': 1},
            propensity=lambda s: s.target.d1 * s.target.E,
        ),
        ReactionInteraction(
            'effector_drug_kill',
            target='tumour',
            reactants={'E': 1},
            propensity=lambda s: s.target.a2
            * s.target.E
            * (s.target.X2 / s.target.V + s.target.delta2 * s.target.X3 / s.target.V),
        ),
    ]
    return System(elements=[tumour], interactions=interactions)

tcr_gene_therapy(E=1000.0, A=1000.0, *, s=1.0, alpha=0.05, d1=0.03, r1=0.1245, g1=0.001, r2=0.18, b=1e-09, a=1.0, g2=100000.0)

Return the predator-prey model of a gene therapy that lets the T cells recognise the tumour.

The effector cells follow dE/dt = s + alpha A - d1 E + r1 E / (E + g1) and the tumour cells dA/dt = r2 A (1 - b A) - a E A / (A + g2). The book takes the time-varying influx, antigenicity, growth, and kill as constants. Cells are counts and time is in days. The tumour and the effector cells oscillate in damped cycles and settle on a dormant tumour far below its carrying capacity.

Parameters:

Name Type Description Default
E float

The initial number of effector cells.

1000.0
A float

The initial number of tumour cells.

1000.0
s float

The influx rate of effector cells, per day.

1.0
alpha float

The antigenicity of the tumour, per day.

0.05
d1 float

The death rate of effector cells, per day.

0.03
r1 float

The proliferation rate of effector cells, per day.

0.1245
g1 float

The half-saturation constant of the proliferation of effector cells.

0.001
r2 float

The growth rate of tumour cells, per day.

0.18
b float

The reciprocal carrying capacity of tumour cells, per cell.

1e-09
a float

The kill rate that the therapy gives the effector cells, per day.

1.0
g2 float

The half-saturation constant of the kill, in cells.

100000.0

Returns:

Name Type Description
system System

The model, with the effector cells site.E and the tumour cells site.A.

Examples:

>>> from skcomplex.models.biology.oncology import tcr_gene_therapy
>>> tcr_gene_therapy().elements[0].g2
100000.0
Source code in src/skcomplex/models/biology/oncology/_gene_viral_therapy.py
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
@register_model(
    field='biology/oncology',
    tags=('gene therapy', 'immunotherapy', 'ode', 'predator-prey'),
    references=(BOOK, 'Tsygvintsev, Marino, and Kirschner 2013'),
    defaults={'until': 1500.0, 'dt': 5.0},
)
def tcr_gene_therapy(
    E: float = 1e3,
    A: float = 1e3,
    *,
    s: float = 1.0,
    alpha: float = 0.05,
    d1: float = 0.03,
    r1: float = 0.1245,
    g1: float = 1e-3,
    r2: float = 0.18,
    b: float = 1e-9,
    a: float = 1.0,
    g2: float = 1e5,
) -> System:
    """Return the predator-prey model of a gene therapy that lets the T cells recognise the tumour.

    The effector cells follow `dE/dt = s + alpha A - d1 E + r1 E / (E + g1)` and the tumour cells
    `dA/dt = r2 A (1 - b A) - a E A / (A + g2)`. The book takes the time-varying influx, antigenicity, growth, and
    kill as constants. Cells are counts and time is in days. The tumour and the effector cells oscillate in damped
    cycles and settle on a dormant tumour far below its carrying capacity.

    Args:
        E:
            The initial number of effector cells.

        A:
            The initial number of tumour cells.

        s:
            The influx rate of effector cells, per day.

        alpha:
            The antigenicity of the tumour, per day.

        d1:
            The death rate of effector cells, per day.

        r1:
            The proliferation rate of effector cells, per day.

        g1:
            The half-saturation constant of the proliferation of effector cells.

        r2:
            The growth rate of tumour cells, per day.

        b:
            The reciprocal carrying capacity of tumour cells, per cell.

        a:
            The kill rate that the therapy gives the effector cells, per day.

        g2:
            The half-saturation constant of the kill, in cells.

    Returns:
        system:
            The model, with the effector cells `site.E` and the tumour cells `site.A`.

    Examples:
        >>> from skcomplex.models.biology.oncology import tcr_gene_therapy
        >>> tcr_gene_therapy().elements[0].g2
        100000.0
    """
    site = TcrGeneTherapyElement('site', E=E, A=A, s=s, alpha=alpha, d1=d1, r1=r1, g1=g1, r2=r2, b=b, a=a, g2=g2)
    interactions = [
        DosingInteraction('influx', target='site', state='E', dose=lambda s: s.target.s),
        RateInteraction('stimulation', target='site', state='E', rate=lambda s: s.target.alpha * s.target.A),
        ReactionInteraction(
            'effector_death',
            target='site',
            reactants={'E': 1},
            propensity=lambda s: s.target.d1 * s.target.E,
        ),
        MichaelisMentenInteraction(
            'self_proliferation',
            target='site',
            products={'E': 1},
            substrate='E',
            vmax=lambda s: s.target.r1,
            km=lambda s: s.target.g1,
        ),
        RateInteraction(
            'tumour_growth',
            target='site',
            state='A',
            rate=lambda s: s.target.r2 * s.target.A * (1 - s.target.b * s.target.A),
        ),
        MichaelisMentenInteraction(
            'kill',
            target='site',
            reactants={'A': 1},
            substrate='A',
            vmax=lambda s: s.target.a,
            km=lambda s: s.target.g2,
            modifiers={'E': 1},
        ),
    ]
    return System(elements=[site], interactions=interactions)

tumour_angiogenesis(width=40, height=25, *, n_sprouts=5, radius=2, chemotaxis=30.0, random_state=0)

Return a tumour that outgrows its oxygen supply and recruits new blood vessels from a parent vessel.

The scales are coupled: tumour cells and vessel tips are agents on a grid, and oxygen and VEGF are fields on a lattice of the same shape. The tumour starts far from the parent vessel along the left edge, so its cells become hypoxic and secrete VEGF, which draws tips out of the vessel. The new vessels bring oxygen and the tumour grows.

Parameters:

Name Type Description Default
width int

The number of columns.

40
height int

The number of rows.

25
n_sprouts int

The number of tips on the parent vessel.

5
radius int

The radius of the initial tumour, centred three quarters of the way to the right.

2
chemotaxis float

How strongly VEGF draws the tips.

30.0
random_state int | Generator | None

The seed or generator of the positions of the tips.

0

Returns:

Name Type Description
system System

The model, with the agents cells/tumour, cells/vessels, and cells/sprouts, and the fields tissue/tissue.oxygen and tissue/tissue.vegf.

Examples:

>>> from skcomplex.models.biology.oncology import tumour_angiogenesis
>>> [group.label for group in tumour_angiogenesis().systems[0].elements]
['tumour', 'vessels', 'sprouts']
Source code in src/skcomplex/models/biology/oncology/_angiogenesis.py
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
@register_model(
    field='biology/oncology',
    tags=('agents', 'field', 'multiscale', 'angiogenesis', 'co-simulation'),
    references=('Carmichael and Hadžikadić 2019', 'Anderson and Chaplain 1998'),
    defaults={'until': 120, 'dt': 1},
)
def tumour_angiogenesis(
    width: int = 40,
    height: int = 25,
    *,
    n_sprouts: int = 5,
    radius: int = 2,
    chemotaxis: float = 30.0,
    random_state: int | np.random.Generator | None = 0,
) -> System:
    """Return a tumour that outgrows its oxygen supply and recruits new blood vessels from a parent vessel.

    The scales are coupled: tumour cells and vessel tips are agents on a grid, and oxygen and VEGF are fields on a
    lattice of the same shape. The tumour starts far from the parent vessel along the left edge, so its cells become
    hypoxic and secrete VEGF, which draws tips out of the vessel. The new vessels bring oxygen and the tumour grows.

    Args:
        width:
            The number of columns.

        height:
            The number of rows.

        n_sprouts:
            The number of tips on the parent vessel.

        radius:
            The radius of the initial tumour, centred three quarters of the way to the right.

        chemotaxis:
            How strongly VEGF draws the tips.

        random_state:
            The seed or generator of the positions of the tips.

    Returns:
        system:
            The model, with the agents `cells/tumour`, `cells/vessels`, and `cells/sprouts`, and the fields
            `tissue/tissue.oxygen` and `tissue/tissue.vegf`.

    Examples:
        >>> from skcomplex.models.biology.oncology import tumour_angiogenesis
        >>> [group.label for group in tumour_angiogenesis().systems[0].elements]
        ['tumour', 'vessels', 'sprouts']
    """
    rng = np.random.default_rng(random_state)
    center = (3 * width // 4, height // 2)
    tumour = [
        (x, y)
        for x in range(center[0] - radius, center[0] + radius + 1)
        for y in range(center[1] - radius, center[1] + radius + 1)
        if (x - center[0]) ** 2 + (y - center[1]) ** 2 <= radius**2
    ]
    tips = sorted(int(row) for row in rng.choice(height, size=n_sprouts, replace=False))
    groups = [
        GroupElement('tumour', element=TumourCellElement, size=len(tumour), variable=True, location=tumour),
        GroupElement(
            'vessels',
            element=VesselElement,
            size=height,
            variable=True,
            location=[(0, row) for row in range(height)],
        ),
        GroupElement(
            'sprouts',
            element=SproutElement,
            size=n_sprouts,
            values={'chemotaxis': chemotaxis},
            variable=True,
            location=[(0, row) for row in tips],
        ),
    ]
    tissue = FieldElement('tissue', element=TissueElement, space=LatticeSpace((width, height), boundary='reflecting'))
    return System(
        systems=[
            System('cells', elements=groups, space=LatticeSpace((width, height), boundary='fixed')),
            System('tissue', elements=[tissue], interactions=_get_tissue()),
        ],
        interactions=_get_cells(),
    )

tumour_immune_suppression(*, alpha_a=0.001, r1=0.333, r2=333.0, EMC=10000.0, EMH=10000.0, EMR=10000.0)

Return a tumour against dendritic, cytotoxic, helper, and regulatory T cells with IL-2, IL-10, and TGF-beta.

A tumour of one cell grows exponentially, then as a power of its size, and only its accessible fraction is killed. Its antigen matures dendritic cells, which recruit T cells from the memory pools, and the regulatory cells with IL-10 and TGF-beta suppress the response. A weakly antigenic tumour escapes, a moderately antigenic one oscillates, and a strongly antigenic one is held to a few cells. The book's growth rows are garbled, and the exponential rate is read as 0.333 per day and the power coefficient as 333 cells^(1/2) per day, within the book's range 100 to 1000, so the growth turns from exponential to power at 10^6 cells. The book gives no memory pools, which are taken as constant at 10^4 cells each. The other parameters are the book's, the initial immune cells are 10^-5, cells are counts, cytokines in ng/ml, and time in days.

Parameters:

Name Type Description Default
alpha_a float

The antigenicity of the tumour, in the book's range 10^-5 to 10^5.

0.001
r1 float

The exponential growth rate of the tumour.

0.333
r2 float

The power growth coefficient of the tumour.

333.0
EMC float

The memory cytotoxic T cells.

10000.0
EMH float

The memory helper T cells.

10000.0
EMR float

The memory regulatory T cells.

10000.0

Returns:

Name Type Description
system System

The model, with the tumour site.A, the dendritic cells site.EUD and site.ED, the T cells site.EPC, site.E, site.EPH, site.EH, site.EPR, and site.ER, and the cytokines site.C1, site.C2, and site.C3.

Examples:

>>> from skcomplex.models.biology.oncology import tumour_immune_suppression
>>> tumour_immune_suppression(alpha_a=1.0).elements[0].alpha_a
1.0
Source code in src/skcomplex/models/biology/oncology/_immunotherapy.py
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
@register_model(
    field='biology/oncology',
    tags=('immunotherapy', 'ode', 'immunosuppression', 'cytokines', 'antigenicity'),
    references=(BOOK_REFERENCE, 'Robertson-Tessi, El-Kareh, and Goriely 2012'),
    defaults={'until': 200.0, 'dt': 0.5, 'solver': STIFF_SOLVER},
)
def tumour_immune_suppression(
    *,
    alpha_a: float = 1e-3,
    r1: float = 0.333,
    r2: float = 333.0,
    EMC: float = 1e4,
    EMH: float = 1e4,
    EMR: float = 1e4,
) -> System:
    """Return a tumour against dendritic, cytotoxic, helper, and regulatory T cells with IL-2, IL-10, and TGF-beta.

    A tumour of one cell grows exponentially, then as a power of its size, and only its accessible fraction is killed.
    Its antigen matures dendritic cells, which recruit T cells from the memory pools, and the regulatory cells with
    IL-10 and TGF-beta suppress the response. A weakly antigenic tumour escapes, a moderately antigenic one oscillates,
    and a strongly antigenic one is held to a few cells. The book's growth rows are garbled, and the exponential rate
    is read as 0.333 per day and the power coefficient as 333 cells^(1/2) per day, within the book's range 100 to
    1000, so the growth turns from exponential to power at `10^6` cells. The book gives no memory pools, which are
    taken as constant at `10^4` cells each. The other parameters are the book's, the initial immune cells are
    `10^-5`, cells are counts, cytokines in ng/ml, and time in days.

    Args:
        alpha_a:
            The antigenicity of the tumour, in the book's range `10^-5` to `10^5`.

        r1:
            The exponential growth rate of the tumour.

        r2:
            The power growth coefficient of the tumour.

        EMC:
            The memory cytotoxic T cells.

        EMH:
            The memory helper T cells.

        EMR:
            The memory regulatory T cells.

    Returns:
        system:
            The model, with the tumour `site.A`, the dendritic cells `site.EUD` and `site.ED`, the T cells `site.EPC`,
            `site.E`, `site.EPH`, `site.EH`, `site.EPR`, and `site.ER`, and the cytokines `site.C1`, `site.C2`, and
            `site.C3`.

    Examples:
        >>> from skcomplex.models.biology.oncology import tumour_immune_suppression
        >>> tumour_immune_suppression(alpha_a=1.0).elements[0].alpha_a
        1.0
    """
    site = SuppressedTumourElement('site', alpha_a=alpha_a, r1=r1, r2=r2, EMC=EMC, EMH=EMH, EMR=EMR)

    def accessible(s: SimpleNamespace) -> Expression:
        """Return the fraction of the tumour accessible to the cytotoxic T cells."""
        fraction: Expression = s.target.A / (1 + (s.target.A ** (1 - s.target.q) / s.target.g3) ** s.target.p) ** (
            1 / s.target.p
        )
        return fraction

    def maturation(s: SimpleNamespace) -> Expression:
        """Return the maturation by IL-2 of proliferating T cells, which TGF-beta suppresses."""
        factor: Expression = hill(s.target.C1, s.target.EC1_50) / (1 + s.target.C3 / s.target.EC3_50)
        return factor

    interactions = [
        RateInteraction(
            'tumour_growth',
            target='site',
            state='A',
            rate=lambda s: s.target.A
            / ((1 / s.target.r1) ** s.target.p + (s.target.A ** (1 - s.target.n) / s.target.r2) ** s.target.p)
            ** (1 / s.target.p),
        ),
        ReactionInteraction(
            'kill',
            target='site',
            reactants={'A': 1},
            modifiers={'E': 1},
            propensity=lambda s: s.target.a1
            * accessible(s)
            * s.target.E
            / (s.target.E + accessible(s) / s.target.g1 + s.target.ER / s.target.g2)
            / (1 + s.target.C3 / s.target.C3_50),
        ),
        RateInteraction(
            'antigen_uptake',
            target='site',
            state='EUD',
            rate=lambda s: s.target.alpha_a
            * accessible(s)
            / ((1 + s.target.C2 / s.target.C2_50) * (1 + s.target.ER / s.target.ER_50)),
        ),
        ReactionInteraction(
            'licensing',
            target='site',
            reactants={'EUD': 1},
            products={'ED': 1},
            propensity=lambda s: s.target.lambda_a * s.target.EUD / (1 + s.target.EUD / s.target.EMH),
        ),
        ReactionInteraction(
            'immature_death',
            target='site',
            reactants={'EUD': 1},
            propensity=lambda s: s.target.d1 * s.target.EUD,
        ),
        ReactionInteraction(
            'licensed_death',
            target='site',
            reactants={'ED': 1},
            propensity=lambda s: s.target.d2 * s.target.ED,
        ),
        RateInteraction(
            'cytotoxic_priming',
            target='site',
            state='EPC',
            rate=lambda s: s.target.a2
            * s.target.EMC
            * s.target.ED
            / (s.target.ED + s.target.g4 * (s.target.EMC + s.target.EMH + s.target.EMR)),
        ),
        ReactionInteraction(
            'cytotoxic_precursor_death',
            target='site',
            reactants={'EPC': 1},
            propensity=lambda s: s.target.d3 * s.target.EPC,
        ),
        RateInteraction(
            'cytotoxic_maturation',
            target='site',
            state='E',
            rate=lambda s: s.target.a3 * s.target.EPC * maturation(s),
        ),
        ReactionInteraction(
            'cytotoxic_death',
            target='site',
            reactants={'E': 1},
            propensity=lambda s: s.target.d4 * s.target.E,
        ),
        RateInteraction(
            'helper_priming',
            target='site',
            state='EPH',
            rate=lambda s: s.target.a4
            * s.target.EMH
            * (s.target.ED + s.target.EUD)
            / (s.target.ED + s.target.EUD + s.target.g4 * (s.target.EMC + s.target.EMH + s.target.EMR)),
        ),
        ReactionInteraction(
            'helper_precursor_death',
            target='site',
            reactants={'EPH': 1},
            propensity=lambda s: s.target.d5 * s.target.EPH,
        ),
        RateInteraction(
            'helper_maturation',
            target='site',
            state='EH',
            rate=lambda s: s.target.a5 * s.target.EPH * maturation(s),
        ),
        ReactionInteraction(
            'conversion',
            target='site',
            reactants={'EH': 1},
            products={'ER': 1},
            modifiers={'C3': 1},
            propensity=lambda s: s.target.a6 * s.target.EH * s.target.C3 / (s.target.g5 + s.target.C3),
        ),
        ReactionInteraction(
            'helper_death',
            target='site',
            reactants={'EH': 1},
            propensity=lambda s: s.target.d6 * s.target.EH,
        ),
        RateInteraction(
            'regulatory_priming',
            target='site',
            state='EPR',
            rate=lambda s: s.target.a7
            * s.target.EMR
            * s.target.ED
            / (s.target.ED + s.target.g4 * (s.target.EMC + s.target.EMH + s.target.EMR)),
        ),
        ReactionInteraction(
            'regulatory_precursor_death',
            target='site',
            reactants={'EPR': 1},
            propensity=lambda s: s.target.d7 * s.target.EPR,
        ),
        RateInteraction(
            'regulatory_maturation',
            target='site',
            state='ER',
            rate=lambda s: s.target.a8 * s.target.EPR * hill(s.target.C1, s.target.EC1_50),
        ),
        ReactionInteraction(
            'regulatory_death',
            target='site',
            reactants={'ER': 1},
            propensity=lambda s: s.target.d8 * s.target.ER,
        ),
        RateInteraction(
            'il2_secretion',
            target='site',
            state='C1',
            rate=lambda s: s.target.a9
            * s.target.EPH
            / ((1 + s.target.C3 / s.target.CC3_50) * (1 + s.target.C2 / s.target.CC2_50)),
        ),
        ReactionInteraction(
            'il2_loss',
            target='site',
            reactants={'C1': 1},
            propensity=lambda s: s.target.C1 / s.target.tau1,
        ),
        RateInteraction(
            'regulatory_il10',
            target='site',
            state='C2',
            rate=lambda s: s.target.r3 * s.target.ER,
        ),
        RateInteraction(
            'tumour_il10',
            target='site',
            state='C2',
            rate=lambda s: s.target.r4 * s.target.A,
        ),
        ReactionInteraction(
            'il10_loss',
            target='site',
            reactants={'C2': 1},
            propensity=lambda s: s.target.C2 / s.target.tau2,
        ),
        RateInteraction(
            'regulatory_tgf_beta',
            target='site',
            state='C3',
            rate=lambda s: s.target.r5 * s.target.ER,
        ),
        RateInteraction(
            'tumour_tgf_beta',
            target='site',
            state='C3',
            rate=lambda s: s.target.r6 * s.target.A,
        ),
        ReactionInteraction(
            'tgf_beta_loss',
            target='site',
            reactants={'C3': 1},
            propensity=lambda s: s.target.C3 / s.target.tau3,
        ),
    ]
    return System(elements=[site], interactions=interactions)

vascular_core_periphery(*, Vx=0.005, xi_e=0.8, du=INHIBITOR_CLEARANCE, dose=5.0, period=7.0, width=1.0, start=0.0)

Return a tumour with a live core, a live periphery, and a necrotic core, each fed by its own vasculature.

The radius grows once the periphery is dense, cells pass from the periphery to the core as it grows, and core cells die when the core vasculature is too sparse. Starved cells release angiogenic factor, which grows both vascular compartments, and the inhibitor lowers the angiogenesis by exp(-xi_e U). The book writes the radius, core volume, and tumour volume as increments. They are read as rates, so the increment of the radius is dAr/dt and the others follow from it per unit time, which is how the bi-compartmental model of Csercsik et al. advances. The book does not give the density Vx of the surrounding vasculature, which is set to the reference vascular fraction rv_ref, nor a schedule, which is a one-day infusion of 5 mg/kg/day every week. The other parameters and the initial state are the book's, the clearance du is log(2) / 3.9 per day, lengths are in mm, volumes in mm³, time in days, and the inhibitor in mg/kg.

Parameters:

Name Type Description Default
Vx float

The vascular density of the surrounding tissue.

0.005
xi_e float

The efficiency of the inhibitor.

0.8
du float

The clearance rate of the inhibitor.

INHIBITOR_CLEARANCE
dose float

The infusion rate during a dose, 0 for no treatment.

5.0
period float

The time between the starts of doses.

7.0
width float

The duration of a dose.

1.0
start float

The time of the first dose.

0.0

Returns:

Name Type Description
system System

The model, with the radius tumour.Ar, the cells tumour.Ac, tumour.Ap, and tumour.An, the vascular volumes tumour.Vbc and tumour.Vbp, and the inhibitor tumour.U.

Examples:

>>> from skcomplex.models.biology.oncology import vascular_core_periphery
>>> vascular_core_periphery(dose=0.0).elements[0].dose
0.0
Source code in src/skcomplex/models/biology/oncology/_antiangiogenic.py
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
@register_model(
    field='biology/oncology',
    tags=('anti-angiogenic therapy', 'ode', 'angiogenesis', 'necrosis', 'dosing'),
    references=(BOOK_REFERENCE, 'Csercsik et al. 2017'),
    defaults={'until': 60.0, 'dt': 0.2, 'solver': ScipyODESolver(method='LSODA', rtol=1e-8, atol=1e-8)},
)
def vascular_core_periphery(
    *,
    Vx: float = 0.005,
    xi_e: float = 0.8,
    du: float = INHIBITOR_CLEARANCE,
    dose: float = 5.0,
    period: float = 7.0,
    width: float = 1.0,
    start: float = 0.0,
) -> System:
    """Return a tumour with a live core, a live periphery, and a necrotic core, each fed by its own vasculature.

    The radius grows once the periphery is dense, cells pass from the periphery to the core as it grows, and core cells
    die when the core vasculature is too sparse. Starved cells release angiogenic factor, which grows both vascular
    compartments, and the inhibitor lowers the angiogenesis by `exp(-xi_e U)`. The book writes the radius, core
    volume, and tumour volume as increments. They are read as rates, so the increment of the radius is `dAr/dt` and
    the others follow from it per unit time, which is how the bi-compartmental model of Csercsik et al. advances. The
    book does not give the density `Vx` of the surrounding vasculature, which is set to the reference vascular fraction
    `rv_ref`, nor a schedule, which is a one-day infusion of 5 mg/kg/day every week. The other parameters and the
    initial state are the book's, the clearance `du` is `log(2) / 3.9` per day, lengths are in mm, volumes in mm³,
    time in days, and the inhibitor in mg/kg.

    Args:
        Vx:
            The vascular density of the surrounding tissue.

        xi_e:
            The efficiency of the inhibitor.

        du:
            The clearance rate of the inhibitor.

        dose:
            The infusion rate during a dose, 0 for no treatment.

        period:
            The time between the starts of doses.

        width:
            The duration of a dose.

        start:
            The time of the first dose.

    Returns:
        system:
            The model, with the radius `tumour.Ar`, the cells `tumour.Ac`, `tumour.Ap`, and `tumour.An`, the vascular
            volumes `tumour.Vbc` and `tumour.Vbp`, and the inhibitor `tumour.U`.

    Examples:
        >>> from skcomplex.models.biology.oncology import vascular_core_periphery
        >>> vascular_core_periphery(dose=0.0).elements[0].dose
        0.0
    """
    tumour = VascularizedSpheroidElement(
        'tumour',
        Vx=Vx,
        xi_e=xi_e,
        du=du,
        dose=dose,
        period=period,
        width=width,
        start=start,
    )
    return System(elements=[tumour])

von_bertalanffy(n=1.0, *, r=2.32, p=0.918, d=0.808)

Return a tumour that grows by the balance of anabolism and catabolism, dn/dt = r n^p - d n.

The volume tends to (r / d)^(1/(1-p)). The defaults are the fit to breast cancer volumes in mm³ and days.

Parameters:

Name Type Description Default
n float

The initial volume.

1.0
r float

The growth rate.

2.32
p float

The exponent of the growth, below 1.

0.918
d float

The loss rate.

0.808

Returns:

Name Type Description
system System

The model, with the volume tumour.n.

Examples:

>>> from skcomplex.models.biology.oncology import von_bertalanffy
>>> von_bertalanffy().interactions[1].d
0.808
Source code in src/skcomplex/models/biology/oncology/_growth.py
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
@register_model(
    field='biology/oncology',
    tags=('tumour growth', 'ode', 'allometry'),
    references=(*GROWTH_REFERENCES, 'von Bertalanffy 1957'),
    defaults={'until': 80.0, 'dt': 0.4},
)
def von_bertalanffy(n: float = 1.0, *, r: float = 2.32, p: float = 0.918, d: float = 0.808) -> System:
    """Return a tumour that grows by the balance of anabolism and catabolism, `dn/dt = r n^p - d n`.

    The volume tends to `(r / d)^(1/(1-p))`. The defaults are the fit to breast cancer volumes in mm³ and days.

    Args:
        n:
            The initial volume.

        r:
            The growth rate.

        p:
            The exponent of the growth, below 1.

        d:
            The loss rate.

    Returns:
        system:
            The model, with the volume `tumour.n`.

    Examples:
        >>> from skcomplex.models.biology.oncology import von_bertalanffy
        >>> von_bertalanffy().interactions[1].d
        0.808
    """
    return System(
        elements=[PopulationElement('tumour', n=n)],
        interactions=[
            PowerLawGrowthInteraction('growth', target='tumour', r=r, p=p),
            MortalityInteraction('loss', target='tumour', d=d),
        ],
    )