Skip to content

Commit

Permalink
Merge pull request #52 from djgroen/immune
Browse files Browse the repository at this point in the history
Preseeded Immunity
  • Loading branch information
djgroen committed Dec 7, 2023
2 parents 06d9645 + 3271919 commit 2989b1a
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 6 deletions.
1 change: 1 addition & 0 deletions covid_data/disease_covid19.yml
Expand Up @@ -43,6 +43,7 @@ incubation_period: 4 # https://www.ams.edu.sg/view-pdf.aspx?file=media%5c5558_fi
# Fei Zhou et al. The Lancet vol. 395.
period_to_hospitalisation: 14.0 #this is period to ICU.
immunity_duration: 273.0
immunity_fraction: 0.0
mutations:
alpha:
infection_rate: 0.112
Expand Down
1 change: 1 addition & 0 deletions covid_data/disease_measles.yml
Expand Up @@ -30,6 +30,7 @@ mild_recovery_period: 14.0 # Mild measles cases may have a shorter recovery
incubation_period: 10.0 # Measles' incubation period, from virus exposure to symptom onset, is around 10 to 14 days (range: 7 to 21 days).
period_to_hospitalisation: 7.0 # The time to hospitalisation varies; severe cases may require it within days, while mild cases may not need hospitalisation.
immunity_duration: 9125.0 # Natural immunity after measles recovery is usually lifelong, but waning immunity can occur over decades. MMR vaccination provides long-lasting immunity, often for life.
immunity_fraction: 0.8 # The initial fraction of the population that is immune to measles due to vaccination or prior infection.
genotypes:
D4:
infection_rate: 0.12
Expand Down
4 changes: 4 additions & 0 deletions facs/base/disease.py
Expand Up @@ -23,6 +23,7 @@ class Disease:
mortality_period: float
period_to_hospitalisation: float
immunity_duration: float
immunity_fraction: float

hospital: list[float] = field(default_factory=list, init=False, repr=False)
mortality: list[float] = field(default_factory=list, init=False, repr=False)
Expand Down Expand Up @@ -54,6 +55,9 @@ def __post_init__(self):
if getattr(self, attr) == 0:
warnings.warn(f"{attr} is zero", RuntimeWarning)

if self.immunity_fraction < 0 or self.immunity_fraction > 1:
raise ValueError("Immunity fraction must be between 0 and 1")

def array_sanity_check(self, array: list[list[float]], name: str):
"""Sanity check for Hospitalisation and Mortality parameters."""

Expand Down
11 changes: 10 additions & 1 deletion facs/base/person.py
Expand Up @@ -11,6 +11,7 @@
import numpy as np
import yaml

from facs.readers.read_disease_yml import read_disease_yml
from .needs import Needs
from .location_types import building_types_dict, building_types_data
from .utils import (
Expand All @@ -26,6 +27,7 @@
from .house import House
from .household import Household
from .location import Location
from .disease import Disease


needs = Needs("covid_data/needs.csv", list(building_types_dict.keys()))
Expand All @@ -34,6 +36,9 @@
vac_data = yaml.safe_load(f)
antivax_chance = vac_data["antivax_fraction"]

immune_duration = read_disease_yml("covid_data/disease_covid19.yml").immunity_duration
immunity_fraction = read_disease_yml("covid_data/disease_covid19.yml").immunity_fraction


@dataclass
class Person:
Expand Down Expand Up @@ -69,6 +74,10 @@ def __post_init__(self):
if np.random.rand() < antivax_chance: # 5% are antivaxxers.
self.antivax = True

if np.random.rand() < 0.5: # 50% immune initially
self.status = "immune"
self.phase_duration = np.random.poisson(immune_duration)

self.age = np.random.choice(91, p=self.ages) # age in years
self.job = np.random.choice(4, 1, p=[0.865, 0.015, 0.08, 0.04])[0]
# 0=default, 1=teacher (1.5%), 2=shop worker (8%), 3=health worker (4%)
Expand Down Expand Up @@ -210,7 +219,7 @@ def recover(self, e, location):
e.time, self.location.location_x, self.location.location_x, location, e.rank
)

def progress_condition(self, e, t, disease):
def progress_condition(self, e, t, disease: Disease):
"""Progress the condition of a person."""
if self.status_change_time > t:
return
Expand Down
9 changes: 5 additions & 4 deletions facs/readers/read_disease_yml.py
Expand Up @@ -19,11 +19,12 @@ def read_disease_yml(ymlfile: str) -> Disease:
data["mortality_period"],
data["period_to_hospitalisation"],
data["immunity_duration"],
data["immunity_fraction"],
)

disease.add_mortality_chances(data["mortality"])
disease.add_hospitalisation_chances(data["hospitalised"])

if "mutations" in data:
# Handle mutations
disease.add_mutations(data["mutations"])
Expand All @@ -32,7 +33,7 @@ def read_disease_yml(ymlfile: str) -> Disease:
disease.add_genotypes(data["genotypes"])
else:
print("No mutations or genotypes provided")

print(disease)

return disease
23 changes: 22 additions & 1 deletion tests/test_disease.py
Expand Up @@ -20,6 +20,7 @@ def disease():
mortality_period=20.0,
period_to_hospitalisation=25.0,
immunity_duration=30.0,
immunity_fraction=0.5,
)


Expand All @@ -30,7 +31,7 @@ def test_disease_initialization(disease: Disease):
repr(disease) == "Disease(infection_rate=0.05, "
"incubation_period=5.0, mild_recovery_period=10.0, "
"recovery_period=15.0, mortality_period=20.0, "
"period_to_hospitalisation=25.0, immunity_duration=30.0)"
"period_to_hospitalisation=25.0, immunity_duration=30.0, immunity_fraction=0.5)"
)


Expand Down Expand Up @@ -86,6 +87,7 @@ def test_disease_initialisation_warn_zero_parameters():
mortality_period=20.0,
period_to_hospitalisation=25.0,
immunity_duration=30.0,
immunity_fraction=0.5,
)


Expand All @@ -101,6 +103,7 @@ def test_disease_initialisation_fail_negative_parameters():
mortality_period=20.0,
period_to_hospitalisation=25.0,
immunity_duration=30.0,
immunity_fraction=0.5,
)


Expand All @@ -116,6 +119,23 @@ def test_disease_initialisation_fail_string_parameters():
mortality_period=20.0,
period_to_hospitalisation=25.0,
immunity_duration=30.0,
immunity_fraction=0.5,
)


def test_disease_initialisation_invalid_immunity_fraction():
"""Test Disease initialization with string parameters."""

with pytest.raises(TypeError):
Disease(
infection_rate="0.05",
incubation_period=5.0,
mild_recovery_period=10.0,
recovery_period=15.0,
mortality_period=20.0,
period_to_hospitalisation=25.0,
immunity_duration=30.0,
immunity_fraction=1.5,
)


Expand All @@ -131,6 +151,7 @@ def test_disease_initialisation_fail_list_parameters():
mortality_period=20.0,
period_to_hospitalisation=25.0,
immunity_duration=30.0,
immunity_fraction=0.5,
)


Expand Down
2 changes: 2 additions & 0 deletions tests/test_household.py
Expand Up @@ -106,6 +106,8 @@ def test_evolve(mock_probability, sample_house, sample_ages):

household = Household(sample_house, sample_ages, size=3)
household.agents[0].status = "infectious"
household.agents[1].status = "susceptible"
household.agents[2].status = "susceptible"
household.evolve(eco, disease)

assert mock_probability.call_count == 2
Expand Down

0 comments on commit 2989b1a

Please sign in to comment.