Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Capacity influence #23

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions covidsimulation/age_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
DEFAULT_HYGIENE_MAX_ADHERENCE = 0.99
DEFAULT_HYGIENE_SHAPE = 3.0
DEFAULT_CHANCE_OF_DIAGNOSIS_IF_MODERATE = 0.5
DEFAULT_CAUTIONARY_ICU_FRACTION = 0.5

@dataclass
class AgeGroup:
Expand All @@ -28,3 +29,9 @@ class AgeGroup:
hygiene_max_adherence: float = DEFAULT_HYGIENE_MAX_ADHERENCE
hygiene_shape: float = DEFAULT_HYGIENE_SHAPE
chance_of_diagnosis_if_moderate: float = DEFAULT_CHANCE_OF_DIAGNOSIS_IF_MODERATE
max_capacity_for_cautionary_icu: float = 0.0
cautionary_icu_fraction: float = DEFAULT_CAUTIONARY_ICU_FRACTION
min_capacity_for_icu_avoidance: float = 1.0
icu_avoidance_fraction: float = 0.0
min_capacity_for_premature_death: float = 1.0
premature_death_fraction: float = 0.0
110 changes: 88 additions & 22 deletions covidsimulation/simulation.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ cpdef enum Outcome:
INTENSIVE_CARE = 5
VENTILATION = 6
DEATH = 7
PREMATURE_DEATH = 8


cpdef enum Age:
Expand Down Expand Up @@ -79,25 +80,79 @@ cdef extern from *:
long c_mod(long x, int m)



cdef int get_outcome(np.ndarray severity):
cdef int get_raw_outcome(np.ndarray severity):
cdef double p = (rand() / (RAND_MAX + 1.0))
if p > severity[0]:
return Outcome.NO_INFECTION
elif p > severity[1]:
return Outcome.NO_SYMPTOMS
elif p > severity[2]:
return Outcome.MILD
elif p > severity[3]:
return Outcome.MODERATE
elif p > severity[4]:
return Outcome.SEVERE
elif p > severity[5]:
return Outcome.INTENSIVE_CARE
elif p > severity[6]:
return Outcome.VENTILATION
cdef double[:] severity_view = severity
cdef int i
for i in range(Outcome.DEATH):
if p > severity_view[i]:
return i
return Outcome.DEATH


cdef float get_icu_capacity_fraction(Person person):
cdef object icu = person.senv.icu
return float(icu.count) / float(icu.capacity)


cdef int get_outcome_for_severe(Person person):
cdef capacity_fraction = get_icu_capacity_fraction(person)
cdef object age_group = person.age_group
cdef float max_capacity_for_cautionary_icu = age_group.max_capacity_for_cautionary_icu
if capacity_fraction > max_capacity_for_cautionary_icu:
return Outcome.SEVERE
if max_capacity_for_cautionary_icu * get_uniform() < capacity_fraction:
return Outcome.SEVERE
if get_uniform() > age_group.cautionary_icu_fraction:
return Outcome.SEVERE
return Outcome.INTENSIVE_CARE


cdef int get_outcome_for_icu(Person person):
cdef capacity_fraction
cdef float min_capacity_for_icu_avoidance
cdef object age_group = person.age_group
cdef float icu_avoidance_fraction = age_group.icu_avoidance_fraction
if icu_avoidance_fraction:
capacity_fraction = get_icu_capacity_fraction(person)
min_capacity_for_icu_avoidance = age_group.min_capacity_for_icu_avoidance
if capacity_fraction > min_capacity_for_icu_avoidance:
if (
get_uniform() * (1.0 - min_capacity_for_icu_avoidance) <
icu_avoidance_fraction * (min(1.0, capacity_fraction) - min_capacity_for_icu_avoidance)
):
return Outcome.SEVERE
return Outcome.INTENSIVE_CARE


cdef int get_outcome_for_ventilation_or_death(Person person, int previous_outcome):
cdef capacity_fraction
cdef float min_capacity_for_premature_death
cdef object age_group = person.age_group
cdef float premature_death_fraction = age_group.premature_death_fraction
if premature_death_fraction:
capacity_fraction = get_icu_capacity_fraction(person)
min_capacity_for_premature_death = age_group.min_capacity_for_premature_death
if capacity_fraction > min_capacity_for_premature_death:
if (
get_uniform() * (1.0 - min_capacity_for_premature_death) <
premature_death_fraction * (min(1.0, capacity_fraction) - min_capacity_for_premature_death)
):
return Outcome.PREMATURE_DEATH
return previous_outcome


cdef int get_outcome(Person person):
cdef int raw_outcome = get_raw_outcome(person.age_group.severity)
if raw_outcome < Outcome.SEVERE:
return raw_outcome
if raw_outcome == Outcome.SEVERE:
return get_outcome_for_severe(person)
if raw_outcome == Outcome.INTENSIVE_CARE:
return get_outcome_for_icu(person)
return get_outcome_for_ventilation_or_death(person, raw_outcome)


LOCALITY = 60 # The bigger this constant, the higher will be the probability of finding someone geographically closer


Expand Down Expand Up @@ -380,7 +435,7 @@ cdef class Person:
return False
self.susceptible = False
self.infection_date = self.env.now
cdef size_t expected_outcome = get_outcome(self.age_group.severity)
cdef size_t expected_outcome = get_outcome(self)
if expected_outcome == Outcome.NO_INFECTION:
return False
else:
Expand All @@ -406,19 +461,25 @@ cdef class Person:
self.contagious = False

cdef void configure_evolution(self):
if self.expected_outcome == Outcome.DEATH:
if self.expected_outcome == Outcome.MODERATE:
self.configure_evolution_moderate_at_home()
elif self.expected_outcome == Outcome.SEVERE:
self.configure_evolution_hospitalization()
elif self.expected_outcome == Outcome.DEATH:
self.configure_evolution_death()
elif self.expected_outcome == Outcome.VENTILATION:
self.configure_evolution_ventilation()
elif self.expected_outcome == Outcome.INTENSIVE_CARE:
self.configure_evolution_icu()
elif self.expected_outcome == Outcome.SEVERE:
self.configure_evolution_hospitalization()
elif self.expected_outcome == Outcome.MODERATE:
self.configure_evolution_moderate_at_home()
elif self.expected_outcome == Outcome.PREMATURE_DEATH:
self.configure_evolution_premature_death()
else:
self.configure_evolution_mild_at_home()

cdef void configure_evolution_premature_death(self):
time_until_outcome = np.random.weibull(2) * 6 # 6 dias
self.process(self.run_premature_death(time_until_outcome))

cdef void configure_evolution_death(self):
time_until_outcome = np.random.weibull(2) * 17 # 15 dias
time_until_hospitalization = time_until_outcome * 0.4 # 6 dias
Expand Down Expand Up @@ -485,6 +546,11 @@ cdef class Person:
yield self.timeout(time_for_confirmation)
self.confirmed_death = True

def run_premature_death(self, time_until_outcome):
yield self.timeout(time_until_outcome)
self.request_diagnosis()
yield from self.run_death(0)

def run_hospitalization(self, time_until_hospitalization):
yield self.timeout(time_until_hospitalization)
if self.dead:
Expand Down