From efc41c069c69be36f529c0d0e39a107cb8192e1c Mon Sep 17 00:00:00 2001 From: irina babayan Date: Mon, 31 Oct 2022 18:53:43 -0400 Subject: [PATCH 01/14] Updating vax branch to include Immunization History class. --- .../immunization_history_parameters.toml | 19 +++++ config_files/main.toml | 20 +++-- cv19/immunization_history.py | 76 +++++++++++++++++++ cv19/interaction_sites.py | 20 ++--- cv19/person.py | 54 ++----------- cv19/population.py | 50 +++++++++--- cv19/simulation.py | 42 +++++++++- 7 files changed, 203 insertions(+), 78 deletions(-) create mode 100644 config_files/immunization_history_parameters.toml create mode 100644 cv19/immunization_history.py diff --git a/config_files/immunization_history_parameters.toml b/config_files/immunization_history_parameters.toml new file mode 100644 index 0000000..00574b4 --- /dev/null +++ b/config_files/immunization_history_parameters.toml @@ -0,0 +1,19 @@ +[vaccine_max_efficacy] +Pfizer = 0.913 +Moderna = 0.941 +AZ = 0.76 + +[vaccine_immunity_buildup_days] +Pfizer = 14 +Moderna = 14 +AZ = 14 + +[vaccine_efficacy_min_day] +Pfizer = 180 +Moderna = 180 +AZ = 180 + +[long_term_vaccine_eff] +Pfizer = 0.7 +Moderna = 0.7 +AZ = 0.7 diff --git a/config_files/main.toml b/config_files/main.toml index 2cb4418..e7b6d30 100644 --- a/config_files/main.toml +++ b/config_files/main.toml @@ -1,19 +1,28 @@ [simulation_data] disease_config_file = "disease.toml" +immunization_history_config_file = "immunization_history_parameters.toml" nDays = 100 nPop = 10000 vis_default_virus_type = "alpha" student_default_virus_type = "alpha" num_students = 2000 max_num_res_students = 500 -v0 = 0 N_VIS_OPTION = [0, 1, 2, 3] N_VIS_PROB = [0.7, 0.17, 0.08, 0.05] vis_age_upper = 60 vis_age_lower = 16 -inf_students_upper = 20 -inf_students_lower = 2 +inf_students_upper = 2 +inf_students_lower = 0 num_vaccinations = 0 + [simulation_data.v0_parameters] + v0 = 10000 + v0_interval_start_day = -30 + v0_interval_end_day = 0 + + [simulation_data.vaccine_type] + Pfizer = 0.6 + Moderna = 0.35 + AZ = 0.05 [simulation_data.variants] general = 10 @@ -34,11 +43,6 @@ num_vaccinations = 0 FOOD = 0.1 RES = 1 - [simulation_data.vaccine_type] - Pfizer = 0.6 - Moderna = 0.35 - AZ = 0.05 - [policy_data] initial_mask_mandate = true mask_trigger = 0.3 diff --git a/cv19/immunization_history.py b/cv19/immunization_history.py new file mode 100644 index 0000000..eb212fe --- /dev/null +++ b/cv19/immunization_history.py @@ -0,0 +1,76 @@ +class Immunization_History: + + def __init__(self, vaccine_type=None, vaccine_max_efficacy=None, vaccine_immunity_buildup_days=None, long_term_vaccine_eff=None, vaccine_efficacy_min_day=None): + ''' + A class designed to keep track of a Person's vaccination history and vaccination parameters. + + Holds the parameters from immunization_history_parameters.toml corresponding to the Person's vaccine type, + as well as the attributes listed below. + + Attributes + ---------- + vaccinated: :obj:`bool` + A variable indicating whether or not the person is vaccinated. + list_of_vaccination_dates: :obj:`list` of int + A list of a Person's vaccination dates (corresponding to day in simulation). + ''' + + self.vaccinated = False + self.list_of_vaccination_dates = list() + self.vaccine_type = vaccine_type + self.vaccine_max_efficacy = vaccine_max_efficacy + self.vaccine_immunity_buildup_days = vaccine_immunity_buildup_days + self.long_term_vaccine_eff = long_term_vaccine_eff + self.vaccine_efficacy_min_day = vaccine_efficacy_min_day + + def is_vaccinated(self): + '''Method to retrieve if a person is vaccinated. Returns True if vaccinated, False if not. + + Returns + ------- + self.vaccinated: :obj:`bool` + ''' + return self.vaccinated + + def set_vaccinated(self, day): + '''Method to set a person to be vaccinated. + + Parameters + ---------- + day: int + The day in the simulation when a person is vaccinated. + + Returns + ------- + self.vaccinated: :obj:`bool` + ''' + self.vaccinated_day = day + self.list_of_vaccination_dates.append(self.vaccinated_day) + self.vaccinated = True + + def vaccine_efficacy(self, day): + '''Method to determines what the efficiency of the vaccine based on the type of vaccine administered. + + Returns + ------- + self.sim_obj.vaccine_eff[self.vaccine_type]: :obj:`float` + ''' + + if self.vaccinated: + + days_since_vaccination = day - self.list_of_vaccination_dates[-1] + if (days_since_vaccination) == 0: + self.current_vax_eff = 0 + elif (days_since_vaccination) <= self.vaccine_immunity_buildup_days: + self.current_vax_eff = ((self.vaccine_max_efficacy) / (self.vaccine_immunity_buildup_days)) * days_since_vaccination + elif (days_since_vaccination) >= self.vaccine_efficacy_min_day: + self.current_vax_eff = self.long_term_vaccine_eff + else: + self.current_vax_eff = (-(self.vaccine_max_efficacy - self.long_term_vaccine_eff) / (self.vaccine_efficacy_min_day - self.vaccine_immunity_buildup_days)) + self.current_vax_eff *= days_since_vaccination + self.current_vax_eff += self.vaccine_max_efficacy + + return self.current_vax_eff + + else: + return 0 diff --git a/cv19/interaction_sites.py b/cv19/interaction_sites.py index b55db76..da8a87a 100644 --- a/cv19/interaction_sites.py +++ b/cv19/interaction_sites.py @@ -466,7 +466,7 @@ def site_interaction(self, will_go_array, day, personal, grade_code): if person_1_infected != person_2_infected: # Have an interaction between those people - did_infect = self.interact(p1_obj, p2_obj) + did_infect = self.interact(p1_obj, p2_obj, day) if did_infect: if person_1_infected: new_infections[person_2_index] = True @@ -522,7 +522,7 @@ def calc_interactions(self, site_day_pop): return number_of_interactions - def interact(self, person_1, person_2): + def interact(self, person_1, person_2, day): '''Method that models the interaction between two people. Parameters @@ -563,11 +563,11 @@ def interact(self, person_1, person_2): if p2_mask: spread_prob *= (1 - P2_OUTWARD_EFF) - p1_vaccinated1 = person_1.is_vaccinated() - p2_vaccinated1 = person_2.is_vaccinated() + p1_vaccinated1 = person_1.immunization_history_obj.is_vaccinated() + p2_vaccinated1 = person_2.immunization_history_obj.is_vaccinated() - p1_vaccine_eff = person_1.vaccine_type_efficiency() if p1_vaccinated1 else 0 - p2_vaccine_eff = person_2.vaccine_type_efficiency() if p2_vaccinated1 else 0 + p1_vaccine_eff = person_1.immunization_history_obj.vaccine_efficacy(day) if p1_vaccinated1 else 0 + p2_vaccine_eff = person_2.immunization_history_obj.vaccine_efficacy(day) if p2_vaccinated1 else 0 spread_prob *= ((1 - p1_vaccine_eff) * (1 - p2_vaccine_eff)) @@ -612,8 +612,8 @@ def house_interact(self, day): virus_name = self.variant_code_map[virus_id] infection_chance = self.base_infection_spread_prob[virus_name] * self.house_infection_spread_factor - person_vaccinated = housemembers[person].is_vaccinated() - person_vaccine_eff = housemembers[person].vaccine_type_efficiency() if person_vaccinated else 0 + person_vaccinated = housemembers[person].immunization_history_obj.is_vaccinated() + person_vaccine_eff = housemembers[person].immunization_history_obj.vaccine_efficacy(day) if person_vaccinated else 0 infection_chance *= (1 - person_vaccine_eff) caught_infection = random() < infection_chance @@ -664,8 +664,8 @@ def student_house_interact(self, day): virus_name = self.variant_code_map[virus_id] infection_chance = self.base_infection_spread_prob[virus_name] * self.house_infection_spread_factor - person_vaccinated = housemembers[person].is_vaccinated() - person_vaccine_eff = housemembers[person].vaccine_type_efficiency() if person_vaccinated else 0 + person_vaccinated = housemembers[person].immunization_history_obj.is_vaccinated() + person_vaccine_eff = housemembers[person].immunization_history_obj.vaccine_efficacy(day) if person_vaccinated else 0 infection_chance *= (1 - person_vaccine_eff) caught_infection = random() < infection_chance if caught_infection: diff --git a/cv19/person.py b/cv19/person.py index 92f8710..64203a1 100644 --- a/cv19/person.py +++ b/cv19/person.py @@ -1,6 +1,7 @@ from random import random import numpy as np +from .immunization_history import Immunization_History class Person(object): @@ -19,7 +20,7 @@ class Person(object): def __init__(self, index, sim_obj, infected=False, recovered=False, dead=False, hospitalized=False, ICU=False, quarantined=False, quarantined_day=None, infected_day=None, recovered_day=None, death_day=None, others_infected=None, - cure_days=None, recent_infections=None, vaccinated=False, vaccine_type=None, + cure_days=None, recent_infections=None, vaccine_info=None, age=None, job=None, house_index=0, isolation_tendencies=None, case_severity=None, mask_type=None, has_mask=True, virus_type=None): '''Method to load in attributes from the provided simulation class object. @@ -45,10 +46,8 @@ def __init__(self, index, sim_obj, infected=False, recovered=False, dead=False, Determines if person is quarentined or not, defaults False. quarantined_day : int The day a person is put into quarantine, defaults None. - vaccinated : bool - Determines if a person is vaccinated or not, defaults to True. - vaccine_type : string - Determines type of vaccine received by person, defaults to None. + vaccine_info : dict + Dictionary containing vaccine parameters, defaults None. infected_day : int The day a person is infected, defaults None. recovered_day : int @@ -90,8 +89,7 @@ def __init__(self, index, sim_obj, infected=False, recovered=False, dead=False, self.others_infected = [] if others_infected is None else others_infected self.cure_days = cure_days self.recent_infections = recent_infections - self.vaccinated = vaccinated - self.vaccine_type = vaccine_type + self.immunization_history_obj = Immunization_History(**vaccine_info) self.index = index self.age = age self.job = job @@ -769,45 +767,3 @@ def update_lockdown_days(self, lockdown_level): elif self.days_in_lockdown != 0: self.days_in_lockdown -= 1 return self.days_in_lockdown - - def is_vaccinated(self): - '''Method to retrieve if a person is vaccinated. Returns True if vaccinated, False if not. - - Returns - ------- - self.vaccinated: :obj:`bool` - ''' - return self.vaccinated - - def set_vaccinated(self, day): - '''Method to set a person to be vaccinated. - - Parameters - ---------- - day: int - The day in the simulation when a person is vaccinated. - - Returns - ------- - self.vaccinated: :obj:`bool` - ''' - # Make sure person is not already vaccinated. - if not self.is_vaccinated(): - self.vaccinated_day = day - self.vaccinated = True - - def vaccine_type_efficiency(self): - '''Method to determines what the efficiency of the vaccine based on the type of vaccine administered. - - Returns - ------- - self.sim_obj.vaccine_eff[self.vaccine_type]: :obj:`float` - ''' - if self.vaccinated: - try: - return self.sim_obj.vaccine_eff[self.vaccine_type] - except KeyError as e: - raise ValueError((f"'{self.vaccine_type}' is not a valid vaccine type " - "and has no associated efficiency.")) from e - else: - return 1 diff --git a/cv19/population.py b/cv19/population.py index 018da84..3f0ee6b 100644 --- a/cv19/population.py +++ b/cv19/population.py @@ -37,7 +37,6 @@ def __init__(self, sim_obj): self.set_demographic_parameters() self.nPop = sim_obj.nPop # total population - self.v0 = sim_obj.v0 # initial vaccinated # Student parameter self.nStudents = sim_obj.num_students # full capacity ~ 24k students @@ -99,7 +98,25 @@ def __init__(self, sim_obj): mask_type_arr = np.random.choice(a=self.mask_options, p=self.mask_weights, size=self.nPop) has_mask_arr = np.random.uniform(size=self.nPop) < self.prob_has_mask + + self.v0 = sim_obj.v0_parameters["v0"] # initial vaccinated vaccine_type_arr = np.random.choice(a=self.vaccine_options, p=self.vaccine_weights, size=self.nPop) + if self.v0 > self.nPop: + self.v0 = self.nPop # make sure maximum initially vaccinated people <= population size + v0_lower = sim_obj.v0_parameters["v0_interval_start_day"] + v0_upper = sim_obj.v0_parameters["v0_interval_end_day"] + vaccination_date_arr = np.zeros(self.v0) + if v0_upper <= 0: + + if v0_lower < v0_upper: + vaccination_date_arr = np.random.uniform(low=v0_lower, high=v0_upper, size=self.v0) + else: + vaccination_date_arr = np.ones(self.v0) * v0_lower + else: + if v0_lower >= 0: + vaccination_date_arr = np.zeros(self.v0) + else: + vaccination_date_arr = np.random.uniform(low=v0_lower, high=0, size=self.v0) # Initialize the house index and size for the loop houseIndex = 0 @@ -111,6 +128,13 @@ def __init__(self, sim_obj): houseIndex += 1 houseSize = self.household[houseIndex] + vaccine_type = vaccine_type_arr[i] + individual_vaccine_info = {"vaccine_type": vaccine_type, + "vaccine_max_efficacy": self.vaccine_parameters["vaccine_max_efficacy"][vaccine_type], + "vaccine_immunity_buildup_days": self.vaccine_parameters["vaccine_immunity_buildup_days"][vaccine_type], + "long_term_vaccine_eff": self.vaccine_parameters["long_term_vaccine_eff"][vaccine_type], + "vaccine_efficacy_min_day": self.vaccine_parameters["vaccine_efficacy_min_day"][vaccine_type]} + # MAKE A PERSON newPerson = Person(index=i, sim_obj=sim_obj, @@ -130,8 +154,7 @@ def __init__(self, sim_obj): age=age_arr[i], job=job_arr[i], house_index=houseIndex, - vaccinated=False, - vaccine_type=vaccine_type_arr[i], + vaccine_info=individual_vaccine_info, isolation_tendencies=isolation_tend_arr[i], case_severity=case_severity_arr[i], mask_type=mask_type_arr[i], @@ -176,6 +199,13 @@ def __init__(self, sim_obj): studHouseIndex += 1 studHouseSize = self.stud_houses[studHouseIndex] + vaccine_type = vaccine_type_arr[i] + individual_vaccine_info = {"vaccine_type": vaccine_type, + "vaccine_max_efficacy": self.vaccine_parameters["vaccine_max_efficacy"][vaccine_type], + "vaccine_immunity_buildup_days": self.vaccine_parameters["vaccine_immunity_buildup_days"][vaccine_type], + "long_term_vaccine_eff": self.vaccine_parameters["long_term_vaccine_eff"][vaccine_type], + "vaccine_efficacy_min_day": self.vaccine_parameters["vaccine_efficacy_min_day"][vaccine_type]} + newStudent = Person(index=i, sim_obj=sim_obj, infected=False, @@ -194,8 +224,7 @@ def __init__(self, sim_obj): age=student_age[i - self.nPop + self.nStudents], # adjust for index inconsistency job='Student', house_index=studHouseIndex, - vaccinated=False, - vaccine_type=vaccine_type_arr[i], + vaccine_info=individual_vaccine_info, isolation_tendencies=isolation_tend_arr[i], case_severity=student_case_severity_arr[i - self.nPop + self.nStudents], # adjust for index inconsistency mask_type=mask_type_arr[i], @@ -266,8 +295,8 @@ def __init__(self, sim_obj): # Vaccinate first v0 people v_indices = sample(range(self.nPop), self.v0) - for i in v_indices: - self.population[i].set_vaccinated(day=0) + for index, i in enumerate(v_indices): + self.population[i].immunization_history_obj.set_vaccinated(day=int(vaccination_date_arr[index])) self.vaccinated[i] = i def load_attributes_from_sim_obj(self, sim_obj): @@ -302,9 +331,10 @@ def load_attributes_from_sim_obj(self, sim_obj): self.mask_weights = np.array([self.mask_type[key] for key in constants.MASK_OPTIONS]) self.mask_options = constants.MASK_OPTIONS - # format vaccine weights + # format vaccine parameters self.vaccine_weights = np.array([self.sim_obj.vaccine_type[key] for key in constants.VACCINE_OPTIONS]) self.vaccine_options = constants.VACCINE_OPTIONS + self.vaccine_parameters = sim_obj.immunization_history_parameters def set_demographic_parameters(self): '''Method to open disease parameters from the TOML file. @@ -892,7 +922,7 @@ def update_vaccinated(self, day): ''' non_vaccinated = np.array([index for index in range(self.nPop) - if not self.population[index].is_vaccinated()]) + if not self.population[index].immunization_history_obj.is_vaccinated()]) num_vacc = self.sim_obj.num_vaccinations num_to_vaccinate = num_vacc if len(non_vaccinated) >= num_vacc else len(non_vaccinated) @@ -902,7 +932,7 @@ def update_vaccinated(self, day): for index in self.to_vaccinate: person_to_vaccinate = self.population[index] - person_to_vaccinate.set_vaccinated(day) + person_to_vaccinate.immunization_history_obj.set_vaccinated(day) self.vaccinated[index] = index def change_mask_wearing(self): diff --git a/cv19/simulation.py b/cv19/simulation.py index 18747bc..5ab4109 100644 --- a/cv19/simulation.py +++ b/cv19/simulation.py @@ -78,6 +78,7 @@ def __init__(self, config_file, config_dir="", verbose=False): self.config_dir = config_dir self.load_general_parameters(config_file) self.load_disease_parameters(self.disease_config_file) + self.load_immunization_parameters(self.immunization_history_config_file) self.init_classes() # Have to initalize the classes after we have all of the parameters @@ -189,6 +190,43 @@ def load_disease_parameters(self, filename): with open(filepath, 'rb') as file: self.disease_parameters = tomli.load(file) + def load_immunization_parameters(self, config_file_name): + ''' Method to load in attributes from the immunization history configuration file. + + All parameters in the file are loaded into the object, and parameter names + are taken from dictionary keys. + + Parameters + ---------- + filename : str + Path to the immunization history configuration file. + ''' + + # If path is absolute, use it. + if Path(config_file_name).is_absolute(): + with open(config_file_name, 'rb') as file: + self.immunization_history_parameters = tomli.load(file) + + # Assume that the configuration filename is relative to path of main config. + # If not set, assume relative to working directory. + # Last attempt try relative to cv19 project directory. + else: + filepath = Path(self.config_dir, config_file_name) + try: + with open(filepath, 'rb') as file: + self.immunization_history_parameters = tomli.load(file) + + return + + except FileNotFoundError: + warnings.warn((f"Unable to find file: {filepath} " + "assuming directory is relative to main config. " + "Attempting read relative to CV19ROOT directory.")) + + filepath = Path(CV19ROOT, config_file_name) + with open(filepath, 'rb') as file: + self.immunization_history_parameters = tomli.load(file) + def init_classes(self): ''' Method that links the policy, population, and interaction sites class objects with the Simulation class (serves as pointer variables). @@ -369,7 +407,9 @@ def run(self, fail_on_rerun=True): visitor = Person(index=visitors_ind[i], sim_obj=self, infected=True, recovered=False, dead=False, hospitalized=False, ICU=False, quarantined=False, quarantined_day=None, infected_day=None, recovered_day=None, death_day=None, others_infected=None, - cure_days=None, recent_infections=None, vaccinated=False, age=vis_age[i], + cure_days=None, recent_infections=None, + vaccine_info={"vaccine_type": None, "vaccine_max_efficacy": None, + "vaccine_immunity_buildup_days": None, "long_term_vaccine_eff": None, "vaccine_efficacy_min_day": None}, age=vis_age[i], job="Visitor", house_index=None, isolation_tendencies=0.2, case_severity='Mild', has_mask=True, virus_type="alpha") self.pop.population.append(visitor) From 4c53d0907e5ec1328c05679042668706815d1509 Mon Sep 17 00:00:00 2001 From: irina babayan Date: Mon, 31 Oct 2022 20:16:37 -0400 Subject: [PATCH 02/14] Added comments throughout vaccine class changes. --- cv19/immunization_history.py | 17 +++++++++-------- cv19/person.py | 2 +- cv19/population.py | 25 ++++++++++++++----------- cv19/simulation.py | 2 +- 4 files changed, 25 insertions(+), 21 deletions(-) diff --git a/cv19/immunization_history.py b/cv19/immunization_history.py index eb212fe..e7ee4a7 100644 --- a/cv19/immunization_history.py +++ b/cv19/immunization_history.py @@ -49,11 +49,12 @@ def set_vaccinated(self, day): self.vaccinated = True def vaccine_efficacy(self, day): - '''Method to determines what the efficiency of the vaccine based on the type of vaccine administered. + '''Method to determines what the efficiency of the vaccine based on the type of vaccine administered, and other + immunization history parameters. Returns ------- - self.sim_obj.vaccine_eff[self.vaccine_type]: :obj:`float` + self.current_vax_eff: :obj:`float` ''' if self.vaccinated: @@ -61,14 +62,14 @@ def vaccine_efficacy(self, day): days_since_vaccination = day - self.list_of_vaccination_dates[-1] if (days_since_vaccination) == 0: self.current_vax_eff = 0 - elif (days_since_vaccination) <= self.vaccine_immunity_buildup_days: + elif (days_since_vaccination) <= self.vaccine_immunity_buildup_days: # linear increase of immunity self.current_vax_eff = ((self.vaccine_max_efficacy) / (self.vaccine_immunity_buildup_days)) * days_since_vaccination - elif (days_since_vaccination) >= self.vaccine_efficacy_min_day: + elif (days_since_vaccination) >= self.vaccine_efficacy_min_day: # plateau in immunity after min_day self.current_vax_eff = self.long_term_vaccine_eff - else: - self.current_vax_eff = (-(self.vaccine_max_efficacy - self.long_term_vaccine_eff) / (self.vaccine_efficacy_min_day - self.vaccine_immunity_buildup_days)) - self.current_vax_eff *= days_since_vaccination - self.current_vax_eff += self.vaccine_max_efficacy + else: # calculate linearly decreasing immunity + self.current_vax_eff = (-(self.vaccine_max_efficacy - self.long_term_vaccine_eff) / (self.vaccine_efficacy_min_day - self.vaccine_immunity_buildup_days)) # slope calculation + self.current_vax_eff *= days_since_vaccination # scale by days since vaccination + self.current_vax_eff += self.vaccine_max_efficacy # add initial value (which is the max efficacy) return self.current_vax_eff diff --git a/cv19/person.py b/cv19/person.py index 64203a1..2f591f2 100644 --- a/cv19/person.py +++ b/cv19/person.py @@ -89,7 +89,7 @@ def __init__(self, index, sim_obj, infected=False, recovered=False, dead=False, self.others_infected = [] if others_infected is None else others_infected self.cure_days = cure_days self.recent_infections = recent_infections - self.immunization_history_obj = Immunization_History(**vaccine_info) + self.immunization_history_obj = Immunization_History(**vaccine_info) # create immunization history object self.index = index self.age = age self.job = job diff --git a/cv19/population.py b/cv19/population.py index 3f0ee6b..4eb0691 100644 --- a/cv19/population.py +++ b/cv19/population.py @@ -103,19 +103,21 @@ def __init__(self, sim_obj): vaccine_type_arr = np.random.choice(a=self.vaccine_options, p=self.vaccine_weights, size=self.nPop) if self.v0 > self.nPop: self.v0 = self.nPop # make sure maximum initially vaccinated people <= population size - v0_lower = sim_obj.v0_parameters["v0_interval_start_day"] - v0_upper = sim_obj.v0_parameters["v0_interval_end_day"] - vaccination_date_arr = np.zeros(self.v0) - if v0_upper <= 0: + v0_lower = sim_obj.v0_parameters["v0_interval_start_day"] # lower bound on v0 range + v0_upper = sim_obj.v0_parameters["v0_interval_end_day"] # upper bound on v0 range + vaccination_date_arr = np.zeros(self.v0) # initialize v0 dates array + if v0_lower <= 0 and v0_upper <= 0: # v0 bounds cannot be greater than 0 - if v0_lower < v0_upper: + if v0_lower < v0_upper: # v0_lower should be smaller (more negative) than v0_upper vaccination_date_arr = np.random.uniform(low=v0_lower, high=v0_upper, size=self.v0) - else: + if v0_lower > v0_upper: # flip the bounds to set the range of v0 + vaccination_date_arr = np.random.uniform(low=v0_upper, high=v0_lower, size=self.v0) + else: # they are equal to each other: vaccination_date_arr = np.ones(self.v0) * v0_lower else: - if v0_lower >= 0: + if v0_lower >= 0: # if v0_lower is > 0, make all individuals vaccinated on day 0 vaccination_date_arr = np.zeros(self.v0) - else: + else: # if only v0_upper is > 0, set 0 as upper bound and proceed vaccination_date_arr = np.random.uniform(low=v0_lower, high=0, size=self.v0) # Initialize the house index and size for the loop @@ -128,12 +130,13 @@ def __init__(self, sim_obj): houseIndex += 1 houseSize = self.household[houseIndex] - vaccine_type = vaccine_type_arr[i] + vaccine_type = vaccine_type_arr[i] # vaccine type from vaccine type arr individual_vaccine_info = {"vaccine_type": vaccine_type, "vaccine_max_efficacy": self.vaccine_parameters["vaccine_max_efficacy"][vaccine_type], "vaccine_immunity_buildup_days": self.vaccine_parameters["vaccine_immunity_buildup_days"][vaccine_type], "long_term_vaccine_eff": self.vaccine_parameters["long_term_vaccine_eff"][vaccine_type], "vaccine_efficacy_min_day": self.vaccine_parameters["vaccine_efficacy_min_day"][vaccine_type]} + # set up dictionary of vaccination parameters for immunization history object # MAKE A PERSON newPerson = Person(index=i, @@ -204,7 +207,7 @@ def __init__(self, sim_obj): "vaccine_max_efficacy": self.vaccine_parameters["vaccine_max_efficacy"][vaccine_type], "vaccine_immunity_buildup_days": self.vaccine_parameters["vaccine_immunity_buildup_days"][vaccine_type], "long_term_vaccine_eff": self.vaccine_parameters["long_term_vaccine_eff"][vaccine_type], - "vaccine_efficacy_min_day": self.vaccine_parameters["vaccine_efficacy_min_day"][vaccine_type]} + "vaccine_efficacy_min_day": self.vaccine_parameters["vaccine_efficacy_min_day"][vaccine_type]} # set up immunization history object parameters as dictionary newStudent = Person(index=i, sim_obj=sim_obj, @@ -295,7 +298,7 @@ def __init__(self, sim_obj): # Vaccinate first v0 people v_indices = sample(range(self.nPop), self.v0) - for index, i in enumerate(v_indices): + for index, i in enumerate(v_indices): # set vaccinated date based on vaccination_date_arr self.population[i].immunization_history_obj.set_vaccinated(day=int(vaccination_date_arr[index])) self.vaccinated[i] = i diff --git a/cv19/simulation.py b/cv19/simulation.py index 5ab4109..438bdc9 100644 --- a/cv19/simulation.py +++ b/cv19/simulation.py @@ -78,7 +78,7 @@ def __init__(self, config_file, config_dir="", verbose=False): self.config_dir = config_dir self.load_general_parameters(config_file) self.load_disease_parameters(self.disease_config_file) - self.load_immunization_parameters(self.immunization_history_config_file) + self.load_immunization_parameters(self.immunization_history_config_file) # load immunization history files self.init_classes() # Have to initalize the classes after we have all of the parameters From 3eff0a5506538f137596917c0ddbe1b14525b078 Mon Sep 17 00:00:00 2001 From: irina babayan Date: Mon, 31 Oct 2022 20:30:16 -0400 Subject: [PATCH 03/14] Change how visitors' vaccine objects are initialized. --- cv19/simulation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cv19/simulation.py b/cv19/simulation.py index 438bdc9..8eb20ef 100644 --- a/cv19/simulation.py +++ b/cv19/simulation.py @@ -408,8 +408,8 @@ def run(self, fail_on_rerun=True): hospitalized=False, ICU=False, quarantined=False, quarantined_day=None, infected_day=None, recovered_day=None, death_day=None, others_infected=None, cure_days=None, recent_infections=None, - vaccine_info={"vaccine_type": None, "vaccine_max_efficacy": None, - "vaccine_immunity_buildup_days": None, "long_term_vaccine_eff": None, "vaccine_efficacy_min_day": None}, age=vis_age[i], + vaccine_info={"vaccine_type": "Pfizer", "vaccine_max_efficacy": 0.913, + "vaccine_immunity_buildup_days": 14, "long_term_vaccine_eff": 0.7, "vaccine_efficacy_min_day": 180}, age=vis_age[i], job="Visitor", house_index=None, isolation_tendencies=0.2, case_severity='Mild', has_mask=True, virus_type="alpha") self.pop.population.append(visitor) From 7e80eedfdd8342d955267fe1850b1859c1805be5 Mon Sep 17 00:00:00 2001 From: irina babayan Date: Mon, 31 Oct 2022 20:38:57 -0400 Subject: [PATCH 04/14] Add class docstring for Immunization history and fix initialization of object in person constructor. --- cv19/immunization_history.py | 25 ++++++++++++++----------- cv19/person.py | 3 ++- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/cv19/immunization_history.py b/cv19/immunization_history.py index e7ee4a7..2f924f4 100644 --- a/cv19/immunization_history.py +++ b/cv19/immunization_history.py @@ -1,18 +1,21 @@ class Immunization_History: + ''' + A class designed to keep track of a Person's vaccination history and vaccination parameters. - def __init__(self, vaccine_type=None, vaccine_max_efficacy=None, vaccine_immunity_buildup_days=None, long_term_vaccine_eff=None, vaccine_efficacy_min_day=None): - ''' - A class designed to keep track of a Person's vaccination history and vaccination parameters. + Holds the parameters from immunization_history_parameters.toml corresponding to the Person's vaccine type, + as well as the attributes listed below. - Holds the parameters from immunization_history_parameters.toml corresponding to the Person's vaccine type, - as well as the attributes listed below. + Attributes + ---------- + vaccinated: :obj:`bool` + A variable indicating whether or not the person is vaccinated. + list_of_vaccination_dates: :obj:`list` of int + A list of a Person's vaccination dates (corresponding to day in simulation). + ''' - Attributes - ---------- - vaccinated: :obj:`bool` - A variable indicating whether or not the person is vaccinated. - list_of_vaccination_dates: :obj:`list` of int - A list of a Person's vaccination dates (corresponding to day in simulation). + def __init__(self, vaccine_type=None, vaccine_max_efficacy=None, vaccine_immunity_buildup_days=None, long_term_vaccine_eff=None, vaccine_efficacy_min_day=None): + ''' + The constructor for the Immunization History class. ''' self.vaccinated = False diff --git a/cv19/person.py b/cv19/person.py index 2f591f2..d5eea17 100644 --- a/cv19/person.py +++ b/cv19/person.py @@ -89,7 +89,8 @@ def __init__(self, index, sim_obj, infected=False, recovered=False, dead=False, self.others_infected = [] if others_infected is None else others_infected self.cure_days = cure_days self.recent_infections = recent_infections - self.immunization_history_obj = Immunization_History(**vaccine_info) # create immunization history object + # create immunization history object + self.immunization_history_obj = Immunization_History(**vaccine_info) if vaccine_info != None else Immunization_History() self.index = index self.age = age self.job = job From 5e627951f7741e98f1aa0ff9f1988906fdcb965b Mon Sep 17 00:00:00 2001 From: irina babayan Date: Mon, 31 Oct 2022 20:46:33 -0400 Subject: [PATCH 05/14] Pull request issue fixes. --- cv19/person.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cv19/person.py b/cv19/person.py index d5eea17..97c568c 100644 --- a/cv19/person.py +++ b/cv19/person.py @@ -90,7 +90,7 @@ def __init__(self, index, sim_obj, infected=False, recovered=False, dead=False, self.cure_days = cure_days self.recent_infections = recent_infections # create immunization history object - self.immunization_history_obj = Immunization_History(**vaccine_info) if vaccine_info != None else Immunization_History() + self.immunization_history_obj = Immunization_History(**vaccine_info) if vaccine_info is not None else Immunization_History() self.index = index self.age = age self.job = job From 4b199cca78c4119ad2ddb0a82791e5b5bf5df4d2 Mon Sep 17 00:00:00 2001 From: irina babayan Date: Mon, 31 Oct 2022 20:48:35 -0400 Subject: [PATCH 06/14] Small fix --- cv19/immunization_history.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cv19/immunization_history.py b/cv19/immunization_history.py index 2f924f4..df497bb 100644 --- a/cv19/immunization_history.py +++ b/cv19/immunization_history.py @@ -15,7 +15,7 @@ class Immunization_History: def __init__(self, vaccine_type=None, vaccine_max_efficacy=None, vaccine_immunity_buildup_days=None, long_term_vaccine_eff=None, vaccine_efficacy_min_day=None): ''' - The constructor for the Immunization History class. + The constructor for the Immunization History class. ''' self.vaccinated = False From 274bb0847f64cb63bee0c99c2d3e299be2daa5e4 Mon Sep 17 00:00:00 2001 From: irina babayan Date: Mon, 31 Oct 2022 20:55:46 -0400 Subject: [PATCH 07/14] Amend test files to include new config files so that the code actually works ... --- test/testing_config_files/main_quarantine_1.toml | 1 + test/testing_config_files/main_quarantine_2.toml | 1 + 2 files changed, 2 insertions(+) diff --git a/test/testing_config_files/main_quarantine_1.toml b/test/testing_config_files/main_quarantine_1.toml index 8410658..28e6d21 100644 --- a/test/testing_config_files/main_quarantine_1.toml +++ b/test/testing_config_files/main_quarantine_1.toml @@ -1,5 +1,6 @@ [simulation_data] disease_config_file = "disease_quarantine_1.toml" +immunization_history_config_file = "immunization_history_parameters.toml" nDays = 50 ## needs to be at least max infectious time (29 days) + quarantine_time (14 days) nPop = 10000 vis_default_virus_type = "alpha" diff --git a/test/testing_config_files/main_quarantine_2.toml b/test/testing_config_files/main_quarantine_2.toml index e0e07a5..2dd25d2 100644 --- a/test/testing_config_files/main_quarantine_2.toml +++ b/test/testing_config_files/main_quarantine_2.toml @@ -1,5 +1,6 @@ [simulation_data] disease_config_file = "disease_quarantine_1.toml" +immunization_history_config_file = "immunization_history_parameters.toml" nDays = 30 nPop = 10000 vis_default_virus_type = "alpha" From 47a31f396aa74204b5617461450b5b82d16ea6bc Mon Sep 17 00:00:00 2001 From: irina babayan Date: Mon, 31 Oct 2022 21:03:16 -0400 Subject: [PATCH 08/14] Fix simulation unit test issue --- .../immunization_history_parameters_test.toml | 19 +++++++++++++++++++ .../main_quarantine_1.toml | 2 +- .../main_quarantine_2.toml | 2 +- 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 test/testing_config_files/immunization_history_parameters_test.toml diff --git a/test/testing_config_files/immunization_history_parameters_test.toml b/test/testing_config_files/immunization_history_parameters_test.toml new file mode 100644 index 0000000..00574b4 --- /dev/null +++ b/test/testing_config_files/immunization_history_parameters_test.toml @@ -0,0 +1,19 @@ +[vaccine_max_efficacy] +Pfizer = 0.913 +Moderna = 0.941 +AZ = 0.76 + +[vaccine_immunity_buildup_days] +Pfizer = 14 +Moderna = 14 +AZ = 14 + +[vaccine_efficacy_min_day] +Pfizer = 180 +Moderna = 180 +AZ = 180 + +[long_term_vaccine_eff] +Pfizer = 0.7 +Moderna = 0.7 +AZ = 0.7 diff --git a/test/testing_config_files/main_quarantine_1.toml b/test/testing_config_files/main_quarantine_1.toml index 28e6d21..3a6568a 100644 --- a/test/testing_config_files/main_quarantine_1.toml +++ b/test/testing_config_files/main_quarantine_1.toml @@ -1,6 +1,6 @@ [simulation_data] disease_config_file = "disease_quarantine_1.toml" -immunization_history_config_file = "immunization_history_parameters.toml" +immunization_history_config_file = "immunization_history_parameters_test.toml" nDays = 50 ## needs to be at least max infectious time (29 days) + quarantine_time (14 days) nPop = 10000 vis_default_virus_type = "alpha" diff --git a/test/testing_config_files/main_quarantine_2.toml b/test/testing_config_files/main_quarantine_2.toml index 2dd25d2..bd5bc7d 100644 --- a/test/testing_config_files/main_quarantine_2.toml +++ b/test/testing_config_files/main_quarantine_2.toml @@ -1,6 +1,6 @@ [simulation_data] disease_config_file = "disease_quarantine_1.toml" -immunization_history_config_file = "immunization_history_parameters.toml" +immunization_history_config_file = "immunization_history_parameters_test.toml" nDays = 30 nPop = 10000 vis_default_virus_type = "alpha" From 659bbf6a8cf0774096a7a7fe9b17350dab397c8e Mon Sep 17 00:00:00 2001 From: irina babayan Date: Mon, 31 Oct 2022 21:06:22 -0400 Subject: [PATCH 09/14] More unit test issues ... --- test/testing_config_files/main_quarantine_1.toml | 5 ++++- test/testing_config_files/main_quarantine_2.toml | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/test/testing_config_files/main_quarantine_1.toml b/test/testing_config_files/main_quarantine_1.toml index 3a6568a..291d138 100644 --- a/test/testing_config_files/main_quarantine_1.toml +++ b/test/testing_config_files/main_quarantine_1.toml @@ -7,7 +7,6 @@ vis_default_virus_type = "alpha" student_default_virus_type = "alpha" num_students = 2000 max_num_res_students = 500 -v0 = 0 N_VIS_OPTION = [0, 1, 2, 3] N_VIS_PROB = [0.7, 0.17, 0.08, 0.05] vis_age_upper = 60 @@ -15,6 +14,10 @@ vis_age_lower = 16 inf_students_upper = 20 inf_students_lower = 2 num_vaccinations = 0 + [simulation_data.v0_parameters] + v0 = 10000 + v0_interval_start_day = -30 + v0_interval_end_day = 0 [simulation_data.variants] general = 1000 diff --git a/test/testing_config_files/main_quarantine_2.toml b/test/testing_config_files/main_quarantine_2.toml index bd5bc7d..51d9161 100644 --- a/test/testing_config_files/main_quarantine_2.toml +++ b/test/testing_config_files/main_quarantine_2.toml @@ -7,7 +7,6 @@ vis_default_virus_type = "alpha" student_default_virus_type = "alpha" num_students = 2000 max_num_res_students = 500 -v0 = 0 N_VIS_OPTION = [0] N_VIS_PROB = [1] vis_age_upper = 60 @@ -15,6 +14,10 @@ vis_age_lower = 16 inf_students_upper = 20 inf_students_lower = 2 num_vaccinations = 0 + [simulation_data.v0_parameters] + v0 = 10000 + v0_interval_start_day = -30 + v0_interval_end_day = 0 [simulation_data.variants] general = 0 From 2a8dfaad3f163b64bf5ef864c5998b2de06c4398 Mon Sep 17 00:00:00 2001 From: irina babayan Date: Mon, 23 Jan 2023 18:43:28 -0500 Subject: [PATCH 10/14] amending pr due to feedback, small syntax and organization changes --- ...ameters.toml => immunization_history.toml} | 0 config_files/main.toml | 2 +- cv19/immunization_history.py | 24 ++++----- cv19/interaction_sites.py | 12 +++-- cv19/person.py | 2 +- cv19/population.py | 54 +++++++++++-------- cv19/simulation.py | 6 ++- 7 files changed, 56 insertions(+), 44 deletions(-) rename config_files/{immunization_history_parameters.toml => immunization_history.toml} (100%) diff --git a/config_files/immunization_history_parameters.toml b/config_files/immunization_history.toml similarity index 100% rename from config_files/immunization_history_parameters.toml rename to config_files/immunization_history.toml diff --git a/config_files/main.toml b/config_files/main.toml index e7b6d30..713a3c8 100644 --- a/config_files/main.toml +++ b/config_files/main.toml @@ -1,6 +1,6 @@ [simulation_data] disease_config_file = "disease.toml" -immunization_history_config_file = "immunization_history_parameters.toml" +immunization_history_config_file = "immunization_history.toml" nDays = 100 nPop = 10000 vis_default_virus_type = "alpha" diff --git a/cv19/immunization_history.py b/cv19/immunization_history.py index df497bb..dcf662b 100644 --- a/cv19/immunization_history.py +++ b/cv19/immunization_history.py @@ -1,4 +1,4 @@ -class Immunization_History: +class ImmunizationHistory: ''' A class designed to keep track of a Person's vaccination history and vaccination parameters. @@ -52,7 +52,7 @@ def set_vaccinated(self, day): self.vaccinated = True def vaccine_efficacy(self, day): - '''Method to determines what the efficiency of the vaccine based on the type of vaccine administered, and other + '''Method to determine what the efficiency of the vaccine based on the type of vaccine administered, and other immunization history parameters. Returns @@ -63,18 +63,18 @@ def vaccine_efficacy(self, day): if self.vaccinated: days_since_vaccination = day - self.list_of_vaccination_dates[-1] - if (days_since_vaccination) == 0: - self.current_vax_eff = 0 - elif (days_since_vaccination) <= self.vaccine_immunity_buildup_days: # linear increase of immunity - self.current_vax_eff = ((self.vaccine_max_efficacy) / (self.vaccine_immunity_buildup_days)) * days_since_vaccination - elif (days_since_vaccination) >= self.vaccine_efficacy_min_day: # plateau in immunity after min_day - self.current_vax_eff = self.long_term_vaccine_eff - else: # calculate linearly decreasing immunity - self.current_vax_eff = (-(self.vaccine_max_efficacy - self.long_term_vaccine_eff) / (self.vaccine_efficacy_min_day - self.vaccine_immunity_buildup_days)) # slope calculation + if days_since_vaccination == 0: + self.current_vaccine_eff = 0 + elif days_since_vaccination <= self.vaccine_immunity_buildup_days: # linear increase of immunity + self.current_vaccine_eff = ((self.vaccine_max_efficacy) / (self.vaccine_immunity_buildup_days)) * days_since_vaccination + elif (days_since_vaccination > self.vaccine_immunity_buildup_days) and (days_since_vaccination < self.vaccine_efficacy_min_day): # calculate linearly decreasing immunity + self.current_vaccine_eff = (-(self.vaccine_max_efficacy - self.long_term_vaccine_eff) / (self.vaccine_efficacy_min_day - self.vaccine_immunity_buildup_days)) # slope calculation self.current_vax_eff *= days_since_vaccination # scale by days since vaccination - self.current_vax_eff += self.vaccine_max_efficacy # add initial value (which is the max efficacy) + self.current_vaccine_eff += self.vaccine_max_efficacy # add initial value (which is the max efficacy) + else: # plateau in immunity after and including min_day + self.current_vaccine_eff = self.long_term_vaccine_eff - return self.current_vax_eff + return self.current_vaccine_eff else: return 0 diff --git a/cv19/interaction_sites.py b/cv19/interaction_sites.py index da8a87a..2f7197e 100644 --- a/cv19/interaction_sites.py +++ b/cv19/interaction_sites.py @@ -466,7 +466,7 @@ def site_interaction(self, will_go_array, day, personal, grade_code): if person_1_infected != person_2_infected: # Have an interaction between those people - did_infect = self.interact(p1_obj, p2_obj, day) + did_infect = self.interact(p1_obj, p2_obj, day=day) if did_infect: if person_1_infected: new_infections[person_2_index] = True @@ -531,6 +531,8 @@ def interact(self, person_1, person_2, day): First person in the two-way interaction. person_2 : :obj:`cv19.person.Person` Second person in the two-way interaction. + day : int + The day value that this function is being called on in the encompassing simulation class. Used to determine vaccine efficacy of interacting individuals. Returns ------- @@ -566,8 +568,8 @@ def interact(self, person_1, person_2, day): p1_vaccinated1 = person_1.immunization_history_obj.is_vaccinated() p2_vaccinated1 = person_2.immunization_history_obj.is_vaccinated() - p1_vaccine_eff = person_1.immunization_history_obj.vaccine_efficacy(day) if p1_vaccinated1 else 0 - p2_vaccine_eff = person_2.immunization_history_obj.vaccine_efficacy(day) if p2_vaccinated1 else 0 + p1_vaccine_eff = person_1.immunization_history_obj.vaccine_efficacy(day) + p2_vaccine_eff = person_2.immunization_history_obj.vaccine_efficacy(day) spread_prob *= ((1 - p1_vaccine_eff) * (1 - p2_vaccine_eff)) @@ -613,7 +615,7 @@ def house_interact(self, day): infection_chance = self.base_infection_spread_prob[virus_name] * self.house_infection_spread_factor person_vaccinated = housemembers[person].immunization_history_obj.is_vaccinated() - person_vaccine_eff = housemembers[person].immunization_history_obj.vaccine_efficacy(day) if person_vaccinated else 0 + person_vaccine_eff = housemembers[person].immunization_history_obj.vaccine_efficacy(day) infection_chance *= (1 - person_vaccine_eff) caught_infection = random() < infection_chance @@ -665,7 +667,7 @@ def student_house_interact(self, day): infection_chance = self.base_infection_spread_prob[virus_name] * self.house_infection_spread_factor person_vaccinated = housemembers[person].immunization_history_obj.is_vaccinated() - person_vaccine_eff = housemembers[person].immunization_history_obj.vaccine_efficacy(day) if person_vaccinated else 0 + person_vaccine_eff = housemembers[person].immunization_history_obj.vaccine_efficacy(day) infection_chance *= (1 - person_vaccine_eff) caught_infection = random() < infection_chance if caught_infection: diff --git a/cv19/person.py b/cv19/person.py index 97c568c..e09fe90 100644 --- a/cv19/person.py +++ b/cv19/person.py @@ -1,7 +1,7 @@ from random import random import numpy as np -from .immunization_history import Immunization_History +from .immunization_history import ImmunizationHistory class Person(object): diff --git a/cv19/population.py b/cv19/population.py index 4eb0691..af84296 100644 --- a/cv19/population.py +++ b/cv19/population.py @@ -98,27 +98,10 @@ def __init__(self, sim_obj): mask_type_arr = np.random.choice(a=self.mask_options, p=self.mask_weights, size=self.nPop) has_mask_arr = np.random.uniform(size=self.nPop) < self.prob_has_mask - - self.v0 = sim_obj.v0_parameters["v0"] # initial vaccinated + + #Prepare vaccination date array for population initialization vaccine_type_arr = np.random.choice(a=self.vaccine_options, p=self.vaccine_weights, size=self.nPop) - if self.v0 > self.nPop: - self.v0 = self.nPop # make sure maximum initially vaccinated people <= population size - v0_lower = sim_obj.v0_parameters["v0_interval_start_day"] # lower bound on v0 range - v0_upper = sim_obj.v0_parameters["v0_interval_end_day"] # upper bound on v0 range - vaccination_date_arr = np.zeros(self.v0) # initialize v0 dates array - if v0_lower <= 0 and v0_upper <= 0: # v0 bounds cannot be greater than 0 - - if v0_lower < v0_upper: # v0_lower should be smaller (more negative) than v0_upper - vaccination_date_arr = np.random.uniform(low=v0_lower, high=v0_upper, size=self.v0) - if v0_lower > v0_upper: # flip the bounds to set the range of v0 - vaccination_date_arr = np.random.uniform(low=v0_upper, high=v0_lower, size=self.v0) - else: # they are equal to each other: - vaccination_date_arr = np.ones(self.v0) * v0_lower - else: - if v0_lower >= 0: # if v0_lower is > 0, make all individuals vaccinated on day 0 - vaccination_date_arr = np.zeros(self.v0) - else: # if only v0_upper is > 0, set 0 as upper bound and proceed - vaccination_date_arr = np.random.uniform(low=v0_lower, high=0, size=self.v0) + vaccination_date_arr = self.set_v0_parameters(self,sim_obj) # Initialize the house index and size for the loop houseIndex = 0 @@ -298,9 +281,10 @@ def __init__(self, sim_obj): # Vaccinate first v0 people v_indices = sample(range(self.nPop), self.v0) - for index, i in enumerate(v_indices): # set vaccinated date based on vaccination_date_arr - self.population[i].immunization_history_obj.set_vaccinated(day=int(vaccination_date_arr[index])) - self.vaccinated[i] = i + for i,v in enumerate(v_indices): + # set vaccinated date based on vaccination_date_arr + self.population[v].immunization_history_obj.set_vaccinated(day=int(vaccination_date_arr[i])) + self.vaccinated[v] = v def load_attributes_from_sim_obj(self, sim_obj): '''Method to load in attributes from the provided simulation class object. @@ -373,6 +357,30 @@ def set_demographic_parameters(self): # Cast this so they can be used as ints self.house_options = [int(x) for x in constants.HOUSE_OPTIONS] + + def set_v0_parameters(self,sim_obj): + '''Method to set up initially vaccinated population array. + + Returns + ------- + vaccination_date_arr: :obj:`np.array` of :obj:`int` + ''' + + self.v0 = sim_obj.v0_parameters["v0"] # initial vaccinated + + v0_lower = sim_obj.v0_parameters["v0_interval_start_day"] # lower bound on v0 range + v0_upper = sim_obj.v0_parameters["v0_interval_end_day"] # upper bound on v0 range + vaccination_date_arr = np.zeros(self.v0) # initialize v0 dates array + + if v0_lower <= 0 and v0_upper <= 0: # v0 bounds cannot be greater than 0 + + if v0_lower < v0_upper: # v0_lower should be smaller (more negative) than v0_upper + vaccination_date_arr = np.random.uniform(low=v0_lower, high=v0_upper, size=self.v0) + + else: # they are equal to each other: + vaccination_date_arr = np.ones(self.v0) * v0_lower + + return vaccination_date_arr def get_population_size(self): '''Method to return population size. diff --git a/cv19/simulation.py b/cv19/simulation.py index 8eb20ef..3ba6c86 100644 --- a/cv19/simulation.py +++ b/cv19/simulation.py @@ -12,6 +12,7 @@ from .population import Population from .policy import Policy from .interaction_sites import InteractionSites +from .data import constants class Simulation(): @@ -403,13 +404,14 @@ def run(self, fail_on_rerun=True): num_vis = np.random.choice(a=self.N_VIS_OPTION, p=self.N_VIS_PROB) visitors_ind = [x for x in range(self.nPop, self.nPop + num_vis)] vis_age = np.random.choice(a=self.pop.age_options, p=self.pop.age_weights, size=num_vis) + vis_vaccine_type = np.random.choice(a=constants.VACCINE_OPTIONS,p=self.vaccine_type,size=num_vis) for i in range(0, num_vis): visitor = Person(index=visitors_ind[i], sim_obj=self, infected=True, recovered=False, dead=False, hospitalized=False, ICU=False, quarantined=False, quarantined_day=None, infected_day=None, recovered_day=None, death_day=None, others_infected=None, cure_days=None, recent_infections=None, - vaccine_info={"vaccine_type": "Pfizer", "vaccine_max_efficacy": 0.913, - "vaccine_immunity_buildup_days": 14, "long_term_vaccine_eff": 0.7, "vaccine_efficacy_min_day": 180}, age=vis_age[i], + vaccine_info={"vaccine_type": vis_vaccine_type[i], "vaccine_max_efficacy": self.immunization_history_parameters.vaccine_max_efficacy[vis_vaccine_type[i]], + "vaccine_immunity_buildup_days": self.immunization_history_parameters.vaccine_immunity_buildup_days[vis_vaccine_type[i]], "long_term_vaccine_eff": self.immunization_history_parameters.long_term_vaccine_eff[vis_vaccine_type[i]], "vaccine_efficacy_min_day": self.immunization_history_parameters.vaccine_efficacy_min_day[vis_vaccine_type[i]]}, age=vis_age[i], job="Visitor", house_index=None, isolation_tendencies=0.2, case_severity='Mild', has_mask=True, virus_type="alpha") self.pop.population.append(visitor) From cf4a78a29c5be594ff0f5e9a37eb66726e790f7e Mon Sep 17 00:00:00 2001 From: irina babayan Date: Mon, 30 Jan 2023 18:57:34 -0500 Subject: [PATCH 11/14] updating immunization history class --- cv19/immunization_history.py | 4 ++-- cv19/person.py | 3 +-- cv19/population.py | 4 ++-- cv19/simulation.py | 11 ++++++++--- ...eters_test.toml => immunization_history_test.toml} | 0 test/testing_config_files/main_quarantine_1.toml | 2 +- test/testing_config_files/main_quarantine_2.toml | 2 +- 7 files changed, 15 insertions(+), 11 deletions(-) rename test/testing_config_files/{immunization_history_parameters_test.toml => immunization_history_test.toml} (100%) diff --git a/cv19/immunization_history.py b/cv19/immunization_history.py index dcf662b..d05748d 100644 --- a/cv19/immunization_history.py +++ b/cv19/immunization_history.py @@ -2,7 +2,7 @@ class ImmunizationHistory: ''' A class designed to keep track of a Person's vaccination history and vaccination parameters. - Holds the parameters from immunization_history_parameters.toml corresponding to the Person's vaccine type, + Holds the parameters from immunization_history.toml corresponding to the Person's vaccine type, as well as the attributes listed below. Attributes @@ -69,7 +69,7 @@ def vaccine_efficacy(self, day): self.current_vaccine_eff = ((self.vaccine_max_efficacy) / (self.vaccine_immunity_buildup_days)) * days_since_vaccination elif (days_since_vaccination > self.vaccine_immunity_buildup_days) and (days_since_vaccination < self.vaccine_efficacy_min_day): # calculate linearly decreasing immunity self.current_vaccine_eff = (-(self.vaccine_max_efficacy - self.long_term_vaccine_eff) / (self.vaccine_efficacy_min_day - self.vaccine_immunity_buildup_days)) # slope calculation - self.current_vax_eff *= days_since_vaccination # scale by days since vaccination + self.current_vaccine_eff *= days_since_vaccination # scale by days since vaccination self.current_vaccine_eff += self.vaccine_max_efficacy # add initial value (which is the max efficacy) else: # plateau in immunity after and including min_day self.current_vaccine_eff = self.long_term_vaccine_eff diff --git a/cv19/person.py b/cv19/person.py index e09fe90..894b6cb 100644 --- a/cv19/person.py +++ b/cv19/person.py @@ -89,8 +89,7 @@ def __init__(self, index, sim_obj, infected=False, recovered=False, dead=False, self.others_infected = [] if others_infected is None else others_infected self.cure_days = cure_days self.recent_infections = recent_infections - # create immunization history object - self.immunization_history_obj = Immunization_History(**vaccine_info) if vaccine_info is not None else Immunization_History() + self.immunization_history_obj = ImmunizationHistory(**vaccine_info) if vaccine_info is not None else Immunization_History() self.index = index self.age = age self.job = job diff --git a/cv19/population.py b/cv19/population.py index af84296..48784eb 100644 --- a/cv19/population.py +++ b/cv19/population.py @@ -101,7 +101,7 @@ def __init__(self, sim_obj): #Prepare vaccination date array for population initialization vaccine_type_arr = np.random.choice(a=self.vaccine_options, p=self.vaccine_weights, size=self.nPop) - vaccination_date_arr = self.set_v0_parameters(self,sim_obj) + vaccination_date_arr = self.set_v0_parameters(sim_obj) # Initialize the house index and size for the loop houseIndex = 0 @@ -377,7 +377,7 @@ def set_v0_parameters(self,sim_obj): if v0_lower < v0_upper: # v0_lower should be smaller (more negative) than v0_upper vaccination_date_arr = np.random.uniform(low=v0_lower, high=v0_upper, size=self.v0) - else: # they are equal to each other: + else: # they are equal to each other: everyone is vaccinated on the same day vaccination_date_arr = np.ones(self.v0) * v0_lower return vaccination_date_arr diff --git a/cv19/simulation.py b/cv19/simulation.py index 3ba6c86..0bd7722 100644 --- a/cv19/simulation.py +++ b/cv19/simulation.py @@ -404,14 +404,19 @@ def run(self, fail_on_rerun=True): num_vis = np.random.choice(a=self.N_VIS_OPTION, p=self.N_VIS_PROB) visitors_ind = [x for x in range(self.nPop, self.nPop + num_vis)] vis_age = np.random.choice(a=self.pop.age_options, p=self.pop.age_weights, size=num_vis) - vis_vaccine_type = np.random.choice(a=constants.VACCINE_OPTIONS,p=self.vaccine_type,size=num_vis) + vaccine_weights = np.array([self.vaccine_type[key] for key in constants.VACCINE_OPTIONS]) + vis_vaccine_type = np.random.choice(a=constants.VACCINE_OPTIONS,p=vaccine_weights,size=num_vis) for i in range(0, num_vis): visitor = Person(index=visitors_ind[i], sim_obj=self, infected=True, recovered=False, dead=False, hospitalized=False, ICU=False, quarantined=False, quarantined_day=None, infected_day=None, recovered_day=None, death_day=None, others_infected=None, cure_days=None, recent_infections=None, - vaccine_info={"vaccine_type": vis_vaccine_type[i], "vaccine_max_efficacy": self.immunization_history_parameters.vaccine_max_efficacy[vis_vaccine_type[i]], - "vaccine_immunity_buildup_days": self.immunization_history_parameters.vaccine_immunity_buildup_days[vis_vaccine_type[i]], "long_term_vaccine_eff": self.immunization_history_parameters.long_term_vaccine_eff[vis_vaccine_type[i]], "vaccine_efficacy_min_day": self.immunization_history_parameters.vaccine_efficacy_min_day[vis_vaccine_type[i]]}, age=vis_age[i], + vaccine_info={"vaccine_type": vis_vaccine_type[i], + "vaccine_max_efficacy": self.immunization_history_parameters["vaccine_max_efficacy"][vis_vaccine_type[i]], + "vaccine_immunity_buildup_days": self.immunization_history_parameters["vaccine_immunity_buildup_days"][vis_vaccine_type[i]], + "long_term_vaccine_eff": self.immunization_history_parameters["long_term_vaccine_eff"][vis_vaccine_type[i]], + "vaccine_efficacy_min_day": self.immunization_history_parameters["vaccine_efficacy_min_day"][vis_vaccine_type[i]]}, + age=vis_age[i], job="Visitor", house_index=None, isolation_tendencies=0.2, case_severity='Mild', has_mask=True, virus_type="alpha") self.pop.population.append(visitor) diff --git a/test/testing_config_files/immunization_history_parameters_test.toml b/test/testing_config_files/immunization_history_test.toml similarity index 100% rename from test/testing_config_files/immunization_history_parameters_test.toml rename to test/testing_config_files/immunization_history_test.toml diff --git a/test/testing_config_files/main_quarantine_1.toml b/test/testing_config_files/main_quarantine_1.toml index 291d138..e05c872 100644 --- a/test/testing_config_files/main_quarantine_1.toml +++ b/test/testing_config_files/main_quarantine_1.toml @@ -1,6 +1,6 @@ [simulation_data] disease_config_file = "disease_quarantine_1.toml" -immunization_history_config_file = "immunization_history_parameters_test.toml" +immunization_history_config_file = "immunization_history_test.toml" nDays = 50 ## needs to be at least max infectious time (29 days) + quarantine_time (14 days) nPop = 10000 vis_default_virus_type = "alpha" diff --git a/test/testing_config_files/main_quarantine_2.toml b/test/testing_config_files/main_quarantine_2.toml index 51d9161..5abe1b6 100644 --- a/test/testing_config_files/main_quarantine_2.toml +++ b/test/testing_config_files/main_quarantine_2.toml @@ -1,6 +1,6 @@ [simulation_data] disease_config_file = "disease_quarantine_1.toml" -immunization_history_config_file = "immunization_history_parameters_test.toml" +immunization_history_config_file = "immunization_history_test.toml" nDays = 30 nPop = 10000 vis_default_virus_type = "alpha" From d14971214680eb0fd98a43c6e66222666c5cc6b7 Mon Sep 17 00:00:00 2001 From: irina babayan Date: Mon, 30 Jan 2023 19:22:58 -0500 Subject: [PATCH 12/14] updating vaccine code --- config_files/main.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config_files/main.toml b/config_files/main.toml index 713a3c8..5948269 100644 --- a/config_files/main.toml +++ b/config_files/main.toml @@ -1,7 +1,7 @@ [simulation_data] disease_config_file = "disease.toml" immunization_history_config_file = "immunization_history.toml" -nDays = 100 +nDays = 50 nPop = 10000 vis_default_virus_type = "alpha" student_default_virus_type = "alpha" @@ -13,9 +13,9 @@ vis_age_upper = 60 vis_age_lower = 16 inf_students_upper = 2 inf_students_lower = 0 -num_vaccinations = 0 +num_vaccinations = 100 [simulation_data.v0_parameters] - v0 = 10000 + v0 = 1000 v0_interval_start_day = -30 v0_interval_end_day = 0 From 894165aa6d7c584c26697f092592789609dde6e7 Mon Sep 17 00:00:00 2001 From: irina babayan Date: Mon, 13 Feb 2023 18:02:40 -0500 Subject: [PATCH 13/14] amending immunization history class again, based on github errors --- cv19/immunization_history.py | 29 +++++++++++++--------- cv19/interaction_sites.py | 11 +++------ cv19/person.py | 47 +----------------------------------- cv19/population.py | 31 +++++++++++++----------- cv19/simulation.py | 15 +++++++----- 5 files changed, 47 insertions(+), 86 deletions(-) diff --git a/cv19/immunization_history.py b/cv19/immunization_history.py index d05748d..f427bd3 100644 --- a/cv19/immunization_history.py +++ b/cv19/immunization_history.py @@ -1,5 +1,5 @@ class ImmunizationHistory: - ''' + """ A class designed to keep track of a Person's vaccination history and vaccination parameters. Holds the parameters from immunization_history.toml corresponding to the Person's vaccine type, @@ -11,12 +11,12 @@ class ImmunizationHistory: A variable indicating whether or not the person is vaccinated. list_of_vaccination_dates: :obj:`list` of int A list of a Person's vaccination dates (corresponding to day in simulation). - ''' + """ def __init__(self, vaccine_type=None, vaccine_max_efficacy=None, vaccine_immunity_buildup_days=None, long_term_vaccine_eff=None, vaccine_efficacy_min_day=None): - ''' + """ The constructor for the Immunization History class. - ''' + """ self.vaccinated = False self.list_of_vaccination_dates = list() @@ -27,16 +27,16 @@ def __init__(self, vaccine_type=None, vaccine_max_efficacy=None, vaccine_immunit self.vaccine_efficacy_min_day = vaccine_efficacy_min_day def is_vaccinated(self): - '''Method to retrieve if a person is vaccinated. Returns True if vaccinated, False if not. + """Method to retrieve if a person is vaccinated. Returns True if vaccinated, False if not. Returns ------- self.vaccinated: :obj:`bool` - ''' + """ return self.vaccinated def set_vaccinated(self, day): - '''Method to set a person to be vaccinated. + """Method to set a person to be vaccinated. Parameters ---------- @@ -46,19 +46,24 @@ def set_vaccinated(self, day): Returns ------- self.vaccinated: :obj:`bool` - ''' + """ self.vaccinated_day = day self.list_of_vaccination_dates.append(self.vaccinated_day) self.vaccinated = True def vaccine_efficacy(self, day): - '''Method to determine what the efficiency of the vaccine based on the type of vaccine administered, and other + """Method to determine what the efficiency of the vaccine based on the type of vaccine administered, and other immunization history parameters. + + Parameters + ---------- + day: int + The day in the simulation when a person is vaccinated. Returns ------- - self.current_vax_eff: :obj:`float` - ''' + self.current_vaccine_eff: :obj:`float` + """ if self.vaccinated: @@ -71,7 +76,7 @@ def vaccine_efficacy(self, day): self.current_vaccine_eff = (-(self.vaccine_max_efficacy - self.long_term_vaccine_eff) / (self.vaccine_efficacy_min_day - self.vaccine_immunity_buildup_days)) # slope calculation self.current_vaccine_eff *= days_since_vaccination # scale by days since vaccination self.current_vaccine_eff += self.vaccine_max_efficacy # add initial value (which is the max efficacy) - else: # plateau in immunity after and including min_day + else: # plateau in immunity after and including min_day self.current_vaccine_eff = self.long_term_vaccine_eff return self.current_vaccine_eff diff --git a/cv19/interaction_sites.py b/cv19/interaction_sites.py index bcac694..01e0208 100644 --- a/cv19/interaction_sites.py +++ b/cv19/interaction_sites.py @@ -524,15 +524,10 @@ def calc_interactions(self, site_day_pop): size=site_day_pop)).astype(int) return number_of_interactions - -<<<<<<< HEAD + def interact(self, person_1, person_2, day): - '''Method that models the interaction between two people. -======= - def interact(self, person_1, person_2): - """Method that models the interaction between two people. ->>>>>>> 1f6c4b90cdb6c9bea98ba08dee7c1b6d5b383210 - + """ + Method that models the interaction between two people. Parameters ---------- person_1 : :obj:`cv19.person.Person` diff --git a/cv19/person.py b/cv19/person.py index e784480..8f185b3 100644 --- a/cv19/person.py +++ b/cv19/person.py @@ -89,7 +89,7 @@ def __init__(self, index, sim_obj, infected=False, recovered=False, dead=False, self.others_infected = [] if others_infected is None else others_infected self.cure_days = cure_days self.recent_infections = recent_infections - self.immunization_history_obj = ImmunizationHistory(**vaccine_info) if vaccine_info is not None else Immunization_History() + self.immunization_history_obj = ImmunizationHistory(**vaccine_info) if vaccine_info is not None else ImmunizationHistory() self.index = index self.age = age self.job = job @@ -767,48 +767,3 @@ def update_lockdown_days(self, lockdown_level): elif self.days_in_lockdown != 0: self.days_in_lockdown -= 1 return self.days_in_lockdown -<<<<<<< HEAD -======= - - def is_vaccinated(self): - """Method to retrieve if a person is vaccinated. Returns True if vaccinated, False if not. - - Returns - ------- - self.vaccinated: :obj:`bool` - """ - return self.vaccinated - - def set_vaccinated(self, day): - """Method to set a person to be vaccinated. - - Parameters - ---------- - day: int - The day in the simulation when a person is vaccinated. - - Returns - ------- - self.vaccinated: :obj:`bool` - """ - # Make sure person is not already vaccinated. - if not self.is_vaccinated(): - self.vaccinated_day = day - self.vaccinated = True - - def vaccine_type_efficiency(self): - """Method to determines what the efficiency of the vaccine based on the type of vaccine administered. - - Returns - ------- - self.sim_obj.vaccine_eff[self.vaccine_type]: :obj:`float` - """ - if self.vaccinated: - try: - return self.sim_obj.vaccine_eff[self.vaccine_type] - except KeyError as e: - raise ValueError((f"'{self.vaccine_type}' is not a valid vaccine type " - "and has no associated efficiency.")) from e - else: - return 1 ->>>>>>> 1f6c4b90cdb6c9bea98ba08dee7c1b6d5b383210 diff --git a/cv19/population.py b/cv19/population.py index 76f73c0..c6c4a36 100644 --- a/cv19/population.py +++ b/cv19/population.py @@ -98,8 +98,7 @@ def __init__(self, sim_obj): mask_type_arr = np.random.choice(a=self.mask_options, p=self.mask_weights, size=self.nPop) has_mask_arr = np.random.uniform(size=self.nPop) < self.prob_has_mask - - #Prepare vaccination date array for population initialization + # Prepare vaccination date array for population initialization vaccine_type_arr = np.random.choice(a=self.vaccine_options, p=self.vaccine_weights, size=self.nPop) vaccination_date_arr = self.set_v0_parameters(sim_obj) @@ -281,8 +280,8 @@ def __init__(self, sim_obj): # Vaccinate first v0 people v_indices = sample(range(self.nPop), self.v0) - for i,v in enumerate(v_indices): - # set vaccinated date based on vaccination_date_arr + for i, v in enumerate(v_indices): + # set vaccinated date based on vaccination_date_arr self.population[v].immunization_history_obj.set_vaccinated(day=int(vaccination_date_arr[i])) self.vaccinated[v] = v @@ -357,29 +356,33 @@ def set_demographic_parameters(self): # Cast this so they can be used as ints self.house_options = [int(x) for x in constants.HOUSE_OPTIONS] - - def set_v0_parameters(self,sim_obj): - '''Method to set up initially vaccinated population array. - + + def set_v0_parameters(self, sim_obj): + """Method to set up initially vaccinated population array. + + Parameters + ---------- + sim_obj : :obj:`cv19.simulation.simulation` + The encompassing simulation object hosting the simulation. + Returns ------- vaccination_date_arr: :obj:`np.array` of :obj:`int` - ''' - + """ + self.v0 = sim_obj.v0_parameters["v0"] # initial vaccinated - v0_lower = sim_obj.v0_parameters["v0_interval_start_day"] # lower bound on v0 range v0_upper = sim_obj.v0_parameters["v0_interval_end_day"] # upper bound on v0 range vaccination_date_arr = np.zeros(self.v0) # initialize v0 dates array - + if v0_lower <= 0 and v0_upper <= 0: # v0 bounds cannot be greater than 0 if v0_lower < v0_upper: # v0_lower should be smaller (more negative) than v0_upper vaccination_date_arr = np.random.uniform(low=v0_lower, high=v0_upper, size=self.v0) - + else: # they are equal to each other: everyone is vaccinated on the same day vaccination_date_arr = np.ones(self.v0) * v0_lower - + return vaccination_date_arr def get_population_size(self): diff --git a/cv19/simulation.py b/cv19/simulation.py index 96d43e6..a1c6d2a 100644 --- a/cv19/simulation.py +++ b/cv19/simulation.py @@ -58,12 +58,14 @@ def __init__(self, config_file, config_dir="", config_override_data=None, verbos self.config_dir = config_dir self.load_general_parameters(config_file) -<<<<<<< HEAD + + +<< << << < HEAD self.load_disease_parameters(self.disease_config_file) self.load_immunization_parameters(self.immunization_history_config_file) # load immunization history files -======= +== == == = self.load_disease_parameters(self.disease_config_file, config_override_data) ->>>>>>> 1f6c4b90cdb6c9bea98ba08dee7c1b6d5b383210 +>>>>>> > 1f6c4b90cdb6c9bea98ba08dee7c1b6d5b383210 self.init_classes() # Have to initalize the classes after we have all of the parameters @@ -160,7 +162,7 @@ def load_disease_parameters(self, filename, config_override_data): self.disease_parameters = tomli.load(file) def load_immunization_parameters(self, config_file_name): - ''' Method to load in attributes from the immunization history configuration file. + """Method to load in attributes from the immunization history configuration file. All parameters in the file are loaded into the object, and parameter names are taken from dictionary keys. @@ -169,7 +171,7 @@ def load_immunization_parameters(self, config_file_name): ---------- filename : str Path to the immunization history configuration file. - ''' + """ # If path is absolute, use it. if Path(config_file_name).is_absolute(): @@ -381,7 +383,8 @@ def run(self, fail_on_rerun=True): visitors_ind = [x for x in range(self.nPop, self.nPop + num_vis)] vis_age = np.random.choice(a=self.pop.age_options, p=self.pop.age_weights, size=num_vis) vaccine_weights = np.array([self.vaccine_type[key] for key in constants.VACCINE_OPTIONS]) - vis_vaccine_type = np.random.choice(a=constants.VACCINE_OPTIONS,p=vaccine_weights,size=num_vis) + vis_vaccine_type = np.random.choice(a=constants.VACCINE_OPTIONS, + p=vaccine_weights,size=num_vis) for i in range(0, num_vis): visitor = Person(index=visitors_ind[i], sim_obj=self, infected=True, recovered=False, dead=False, hospitalized=False, ICU=False, quarantined=False, quarantined_day=None, infected_day=None, From 42d3695afcba338894f247192e3fd214d553ec0d Mon Sep 17 00:00:00 2001 From: irina babayan Date: Mon, 13 Feb 2023 20:16:50 -0500 Subject: [PATCH 14/14] fix error from merge --- config_files/main.toml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/config_files/main.toml b/config_files/main.toml index 21c2c30..6d3b47f 100644 --- a/config_files/main.toml +++ b/config_files/main.toml @@ -1,13 +1,6 @@ [simulation_data] disease_config_file = "disease.toml" -<<<<<<< HEAD -<<<<<<< HEAD immunization_history_config_file = "immunization_history.toml" -======= ->>>>>>> 1f6c4b90cdb6c9bea98ba08dee7c1b6d5b383210 -======= -immunization_history_config_file = "immunization_history.toml" ->>>>>>> d56b42831eb98225ce7c0db87b339d0189f3dc1d nDays = 50 nPop = 10000 vis_default_virus_type = "alpha"