def piecewise_linear(x, rng, NUM_PEOPLE): """"This function samples the piecewise linear viral_load model""" viral_loads = [] for person in range(NUM_PEOPLE): plateau_height, plateau_start, plateau_end, recovered = _sample_viral_load_piecewise(rng) viral_load = [] for time_sample in x: if time_sample < plateau_start: cur_viral_load = plateau_height * time_sample / plateau_start elif time_sample < plateau_end: cur_viral_load = plateau_height else: cur_viral_load = plateau_height - plateau_height * (time_sample - plateau_end) / (recovered - plateau_end) if cur_viral_load < 0: cur_viral_load = np.array([0.]) viral_load.append(cur_viral_load) viral_loads.append(np.array(viral_load, dtype=float).flatten()) viral_loads = np.array(viral_loads) return viral_loads
def __init__(self, env, name, age, rng, infection_timestamp, household, workplace, profession, rho=0.3, gamma=0.21, symptoms=[], test_results=None): self.last_date = env.timestamp.date() self.env = env self._events = [] self.name = f"human:{name}" self.rng = rng self.profession = profession self.is_healthcare_worker = True if profession == "healthcare" else False self.assign_household(household) self.workplace = workplace self.rho = rho self.gamma = gamma self.age = age self.sex = _get_random_sex(self.rng) self.preexisting_conditions = _get_preexisting_conditions(self.age, self.sex, self.rng) age_modifier = 2 if self.age > 40 or self.age < 12 else 2 # &carefulness if self.rng.rand() < P_CAREFUL_PERSON: self.carefulness = (round(self.rng.normal(55, 10)) + self.age/2) / 100 else: self.carefulness = (round(self.rng.normal(25, 10)) + self.age/2) / 100 self.has_app = self.rng.rand() < (P_HAS_APP / age_modifier) + (self.carefulness / 2) # logged info can be quite different self.has_logged_info = self.has_app and self.rng.rand() < self.carefulness self.obs_is_healthcare_worker = True if self.is_healthcare_worker and rng.random()<0.9 else False # 90% of the time, healthcare workers will declare it self.obs_age = self.age if self.has_app and self.has_logged_info else None self.obs_sex = self.sex if self.has_app and self.has_logged_info else None self.obs_preexisting_conditions = self.preexisting_conditions if self.has_app and self.has_logged_info else None self.rest_at_home = False # to track mobility due to symptoms self.visits = Visits() self.travelled_recently = self.rng.rand() > 0.9 # &symptoms, &viral-load # probability of being asymptomatic is basically 50%, but a bit less if you're older and a bit more if you're younger self.is_asymptomatic = self.rng.rand() < (BASELINE_P_ASYMPTOMATIC - (self.age - 50) * 0.5) / 100 self.asymptomatic_infection_ratio = ASYMPTOMATIC_INFECTION_RATIO if self.is_asymptomatic else 0.0 # draw a beta with the distribution in documents self.viral_load_plateau_height, self.viral_load_plateau_start, self.viral_load_plateau_end, self.viral_load_recovered = _sample_viral_load_piecewise(rng, age=age) self.infectiousness_onset_days = self.rng.normal(loc=INFECTIOUSNESS_ONSET_DAYS_AVG, scale=INFECTIOUSNESS_ONSET_DAYS_STD) self.incubation_days = self.infectiousness_onset_days + self.viral_load_plateau_start + self.rng.normal(loc=SYMPTOM_ONSET_WRT_VIRAL_LOAD_PEAK_AVG, scale=SYMPTOM_ONSET_WRT_VIRAL_LOAD_PEAK_STD) self.recovery_days = self.infectiousness_onset_days + self.viral_load_recovered self.test_result, self.test_type = None, None # Indicates whether this person will show severe signs of illness. self.infection_timestamp = infection_timestamp self.cold_timestamp = self.env.timestamp if self.rng.random() < P_COLD else None self.flu_timestamp = self.env.timestamp if self.rng.random() < P_FLU else None # different from asymptomatic self.recovered_timestamp = datetime.datetime.min self.is_immune = False # different from asymptomatic self.can_get_really_sick = self.rng.random() >= 0.8 + (age/100) self.can_get_extremely_sick = self.can_get_really_sick and self.rng.random() >= 0.7 # &severe; 30% of severe cases need ICU self.never_recovers = self.rng.random() <= P_NEVER_RECOVERS[min(math.floor(self.age/10),8)] self.obs_hospitalized = False self.obs_in_icu = False # counters and memory self.r0 = [] self.has_logged_symptoms = False self.has_logged_test = False self.last_state = self.state self.n_infectious_contacts = 0 self.last_date_to_check_symptoms = self.env.timestamp.date() # symptoms self.symptom_start_time = None self.all_cold_symptoms = _get_cold_symptoms_v2(self.age, self.rng, self.carefulness, self.preexisting_conditions, self.can_get_really_sick, self.can_get_extremely_sick) self.all_flu_symptoms = _get_flu_symptoms_v2(self.age, self.rng, self.carefulness, self.preexisting_conditions, self.can_get_really_sick, self.can_get_extremely_sick) self.all_covid_symptoms = _get_covid_symptoms(self.viral_load_plateau_start, self.viral_load_plateau_end, self.viral_load_recovered, age=self.age, incubation_days=self.incubation_days, really_sick=self.can_get_really_sick, extremely_sick=self.can_get_extremely_sick, rng=self.rng, preexisting_conditions=self.preexisting_conditions) self.all_symptoms, self.cold_symptoms, self.flu_symptoms, self.covid_symptoms = [], [], [], [] # habits self.avg_shopping_time = _draw_random_discreet_gaussian(AVG_SHOP_TIME_MINUTES, SCALE_SHOP_TIME_MINUTES, self.rng) self.scale_shopping_time = _draw_random_discreet_gaussian(AVG_SCALE_SHOP_TIME_MINUTES, SCALE_SCALE_SHOP_TIME_MINUTES, self.rng) self.avg_exercise_time = _draw_random_discreet_gaussian(AVG_EXERCISE_MINUTES, SCALE_EXERCISE_MINUTES, self.rng) self.scale_exercise_time = _draw_random_discreet_gaussian(AVG_SCALE_EXERCISE_MINUTES, SCALE_SCALE_EXERCISE_MINUTES, self.rng) self.avg_working_minutes = _draw_random_discreet_gaussian(AVG_WORKING_MINUTES, SCALE_WORKING_MINUTES, self.rng) self.scale_working_minutes = _draw_random_discreet_gaussian(AVG_SCALE_WORKING_MINUTES, SCALE_SCALE_WORKING_MINUTES, self.rng) self.avg_hospital_hours = _draw_random_discreet_gaussian(AVG_HOSPITAL_HOURS, SCALE_HOSPITAL_HOURS, self.rng) self.scale_hospital_hours = _draw_random_discreet_gaussian(AVG_SCALE_HOSPITAL_HOURS, SCALE_SCALE_HOSPITAL_HOURS, self.rng) self.avg_misc_time = _draw_random_discreet_gaussian(AVG_MISC_MINUTES, SCALE_MISC_MINUTES, self.rng) self.scale_misc_time = _draw_random_discreet_gaussian(AVG_SCALE_MISC_MINUTES, SCALE_SCALE_MISC_MINUTES, self.rng) #getting the number of shopping days and hours from a distribution self.number_of_shopping_days = _draw_random_discreet_gaussian(AVG_NUM_SHOPPING_DAYS, SCALE_NUM_SHOPPING_DAYS, self.rng) self.number_of_shopping_hours = _draw_random_discreet_gaussian(AVG_NUM_SHOPPING_HOURS, SCALE_NUM_SHOPPING_HOURS, self.rng) #getting the number of exercise days and hours from a distribution self.number_of_exercise_days = _draw_random_discreet_gaussian(AVG_NUM_EXERCISE_DAYS, SCALE_NUM_EXERCISE_DAYS, self.rng) self.number_of_exercise_hours = _draw_random_discreet_gaussian(AVG_NUM_EXERCISE_HOURS, SCALE_NUM_EXERCISE_HOURS, self.rng) #Multiple shopping days and hours self.shopping_days = self.rng.choice(range(7), self.number_of_shopping_days) self.shopping_hours = self.rng.choice(range(7, 20), self.number_of_shopping_hours) #Multiple exercise days and hours self.exercise_days = self.rng.choice(range(7), self.number_of_exercise_days) self.exercise_hours = self.rng.choice(range(7, 20), self.number_of_exercise_hours) #Limiting the number of hours spent shopping per week self.max_shop_per_week = _draw_random_discreet_gaussian(AVG_MAX_NUM_SHOP_PER_WEEK, SCALE_MAX_NUM_SHOP_PER_WEEK, self.rng) self.count_shop=0 # Limiting the number of hours spent exercising per week self.max_exercise_per_week = _draw_random_discreet_gaussian(AVG_MAX_NUM_EXERCISE_PER_WEEK, SCALE_MAX_NUM_EXERCISE_PER_WEEK, self.rng) self.count_exercise=0 self.work_start_hour = self.rng.choice(range(7, 12), 3)
def __init__(self, env, name, age, rng, infection_timestamp, household, workplace, rho=0.3, gamma=0.21, symptoms=[], test_results=None): self.env = env self.events = [] self.name = name self.rng = rng self.age = _get_random_age(self.rng) self.sex = _get_random_sex(self.rng) self.preexisting_conditions = _get_preexisting_conditions( self.age, self.sex, self.rng) self.household = household self.workplace = workplace self.location = household self.rho = rho self.gamma = gamma self.visits = Visits() self.travelled_recently = self.rng.rand() > 0.9 # &carefullness if self.rng.rand() < P_CAREFUL_PERSON: self.carefullness = round(self.rng.normal(55, 10)) + self.age / 2 else: self.carefullness = round(self.rng.normal(25, 10)) + self.age / 2 age_modifier = 1 if self.age > 40 or self.age < 12: age_modifier = 2 self.has_cold = self.rng.rand() < P_COLD * age_modifier self.has_flu = self.rng.rand() < P_FLU * age_modifier self.has_app = self.rng.rand() < (P_HAS_APP / age_modifier) + ( self.carefullness / 2) self.incubation_days = _draw_random_discreet_gaussian( AVG_INCUBATION_DAYS, SCALE_INCUBATION_DAYS, self.rng) # Indicates whether this person will show severe signs of illness. self.infection_timestamp = infection_timestamp self.recovered_timestamp = datetime.datetime.min self.really_sick = self.is_exposed and self.rng.random() >= 0.9 self.extremely_sick = self.really_sick and self.rng.random( ) >= 0.7 # &severe; 30% of severe cases need ICU self.never_recovers = self.rng.random() >= 0.99 # &symptoms, &viral-load # probability of being asymptomatic is basically 50%, but a bit less if you're older # and a bit more if you're younger self.is_asymptomatic = self.rng.rand() > (BASELINE_P_ASYMPTOMATIC - (self.age - 50) * 0.5) / 100 self.asymptomatic_infection_ratio = 0.0 if self.is_asymptomatic: self.asymptomatic_infection_ratio = ASYMPTOMATIC_INFECTION_RATIO # draw a beta with the distribution in documents self.recovery_days = _draw_random_discreet_gaussian( AVG_RECOVERY_DAYS, SCALE_RECOVERY_DAYS, self.rng) # make it IQR &recovery self.viral_load_plateau_height, self.viral_load_plateau_start, self.viral_load_plateau_end, self.viral_load_recovered = _sample_viral_load_piecewise( rng, age=age) self.all_symptoms_array = _get_all_symptoms_array( np.ndarray.item(self.viral_load_plateau_start), np.ndarray.item(self.viral_load_plateau_end), np.ndarray.item(self.viral_load_recovered), age=self.age, incubation_days=self.incubation_days, really_sick=self.really_sick, extremely_sick=self.extremely_sick, rng=self.rng, preexisting_conditions=self.preexisting_conditions) # counters and memory self.r0 = [] self.has_logged_symptoms = False self.has_logged_test = False self.n_infectious_contacts = 0 self.last_state = self.state # habits self.avg_shopping_time = _draw_random_discreet_gaussian( AVG_SHOP_TIME_MINUTES, SCALE_SHOP_TIME_MINUTES, self.rng) self.scale_shopping_time = _draw_random_discreet_gaussian( AVG_SCALE_SHOP_TIME_MINUTES, SCALE_SCALE_SHOP_TIME_MINUTES, self.rng) self.avg_exercise_time = _draw_random_discreet_gaussian( AVG_EXERCISE_MINUTES, SCALE_EXERCISE_MINUTES, self.rng) self.scale_exercise_time = _draw_random_discreet_gaussian( AVG_SCALE_EXERCISE_MINUTES, SCALE_SCALE_EXERCISE_MINUTES, self.rng) self.avg_working_hours = _draw_random_discreet_gaussian( AVG_WORKING_MINUTES, SCALE_WORKING_MINUTES, self.rng) self.scale_working_hours = _draw_random_discreet_gaussian( AVG_SCALE_WORKING_MINUTES, SCALE_SCALE_WORKING_MINUTES, self.rng) self.avg_misc_time = _draw_random_discreet_gaussian( AVG_MISC_MINUTES, SCALE_MISC_MINUTES, self.rng) self.scale_misc_time = _draw_random_discreet_gaussian( AVG_SCALE_MISC_MINUTES, SCALE_SCALE_MISC_MINUTES, self.rng) #getting the number of shopping days and hours from a distribution self.number_of_shopping_days = _draw_random_discreet_gaussian( AVG_NUM_SHOPPING_DAYS, SCALE_NUM_SHOPPING_DAYS, self.rng) self.number_of_shopping_hours = _draw_random_discreet_gaussian( AVG_NUM_SHOPPING_HOURS, SCALE_NUM_SHOPPING_HOURS, self.rng) #getting the number of exercise days and hours from a distribution self.number_of_exercise_days = _draw_random_discreet_gaussian( AVG_NUM_EXERCISE_DAYS, SCALE_NUM_EXERCISE_DAYS, self.rng) self.number_of_exercise_hours = _draw_random_discreet_gaussian( AVG_NUM_EXERCISE_HOURS, SCALE_NUM_EXERCISE_HOURS, self.rng) #Multiple shopping days and hours self.shopping_days = self.rng.choice(range(7), self.number_of_shopping_days) self.shopping_hours = self.rng.choice(range(7, 20), self.number_of_shopping_hours) #Multiple exercise days and hours self.exercise_days = self.rng.choice(range(7), self.number_of_exercise_days) self.exercise_hours = self.rng.choice(range(7, 20), self.number_of_exercise_hours) #Limiting the number of hours spent shopping per week self.max_shop_per_week = _draw_random_discreet_gaussian( AVG_MAX_NUM_SHOP_PER_WEEK, SCALE_MAX_NUM_SHOP_PER_WEEK, self.rng) self.count_shop = 0 #Limiting the number of hours spent exercising per week self.max_exercise_per_week = _draw_random_discreet_gaussian( AVG_MAX_NUM_EXERCISE_PER_WEEK, SCALE_MAX_NUM_EXERCISE_PER_WEEK, self.rng) self.count_exercise = 0 self.work_start_hour = self.rng.choice(range(7, 12))