def test_create_individual(self): test = self.namespace_under_test self.create_generic_gene_gina() observed_toby_age = test.get_age(self.gene['observed']) observed_tina_age = test.get_age(self.gina['observed']) self.check_property_of_individual('age', self.gene['expected']['age'], observed_toby_age, individual_label="Toby") self.check_property_of_individual('age', self.gina['expected']['age'], observed_tina_age, individual_label="Tina")
def update(self): self.time += 1 for h in self.humans: dgi.update(h) # Pull people who've changed out of human and into werewolves if dgi.is_infected(h) and not dgi.is_incubating(h): self.humans.remove(h) self.waiting_wolves.remove( h ) # See above, they are in two places and need to be removed self.werewolves.append(h) if self.debug: print(f"Individual {h} is a wolf!") if self.time % HALLOWEEN_DAY == 0: # It is october 31 if len(self.werewolves) == 0: # and there are no werewolves found_one = False possible_humans = len(self.humans) ages = [] min_age_exposure = self.min_age_werewolf_years * DAYS_YEAR while not found_one and possible_humans > 0: for h in self.humans: possible_humans -= 1 age = dgi.get_age(h) ages.append(age) if age > min_age_exposure: if age % DAYS_YEAR == HALLOWEEN_DAY: self.humans.remove(h) self.werewolves.append(h) found_one = True break if found_one: print("Found a new werewolf with a Halloween Birthday.") else: print("No cool birthdays, just taking someone.") future_wolf = None for h in self.humans: age = dgi.get_age(h) if not future_wolf and age > min_age_exposure: self.humans.remove(h) self.werewolves.append(h) future_wolf = h if future_wolf: print("Found someone old enough.") else: print("No one old enough! No outbreak!") print(ages) sys.exit() if self.enable_reporting: self.report_step()
def test_update_individual(self): test = self.namespace_under_test # self.debug = True self.create_generic_gene_gina() curr_expected_gene_age = self.gene['expected']['age'] curr_expected_gina_age = self.gina['expected']['age'] timestep_size = 1 # TODO: figure out how to set / configure this gene = self.gene['observed'] gina = self.gina['observed'] gina_became_possible_mother = test.is_possible_mother(gina) gina_ceased_potential_motherhood = False age_of_potential_motherhood = None age_of_ceased_motherhood_potential = None self.assertFalse(gina_became_possible_mother, "gina should not be a possible mother at creation.") for x in range(14600): self.check_property_of_individual('age', curr_expected_gene_age, test.get_age(gene), individual_label="gene") self.check_property_of_individual('age', curr_expected_gina_age, test.get_age(gina), individual_label="gina") if not gina_became_possible_mother: gina_became_possible_mother = test.is_possible_mother(gina) if gina_became_possible_mother: age_of_potential_motherhood = curr_expected_gina_age elif not test.is_possible_mother( gina) and not gina_ceased_potential_motherhood: gina_ceased_potential_motherhood = True age_of_ceased_motherhood_potential = curr_expected_gina_age test.update(gene) test.update(gina) curr_expected_gina_age += timestep_size curr_expected_gene_age += timestep_size self.assertTrue(gina_became_possible_mother, "gina should have become a possible mother.") if self.debug: print( f"gina became a possible mother at age {age_of_potential_motherhood}.\nm" ) self.assertTrue(gina_ceased_potential_motherhood, "gina should have ceased being a potential mother.") if self.debug: print( f"gina ceased potential motherhood at age {age_of_ceased_motherhood_potential}.\n" )
def distribute_interventions(t): """ Function to isolated distribution of interventions to individuals. Interventions are separate python modules. """ if t == close_schools_timestep: print("SCHOOL CLOSURE INTERVENTION") FROM_CHILD_TO_CHILD = 0.25 FROM_CHILD_TO_ADULT = 0.75 FROM_ADULT_TO_CHILD = 0.75 #FROM_ADULT_TO_ADULT = 0 global factors factors = [[FROM_CHILD_TO_CHILD, FROM_ADULT_TO_CHILD], [FROM_CHILD_TO_ADULT, FROM_ADULT_TO_ADULT]] if t == vaccine_disribution_timestep: for human in human_pop: hum_id = human["id"] # Below is code to give out anti-tb drugs #individual_ptr = gi.get_individual( hum_id ) #print( "Giving anti-tb drug to {0}.".format( hum_id ) ) #tdi.distribute( individual_ptr ) # Below is code to giveout ART via function that resets ART timers #give_art( hum_id ) #Below is code to give out vaccines; this should be updated to use the distribute method #print( "Giving simple vaccine to {0}.".format( hum_id ) ) #vaccine = vi.get_intervention() #gi.give_intervention( ( hum_id, vaccine ) ) if gi.get_age(hum_id) < 70 * 365: vi.distribute(gi.get_individual_for_iv(hum_id))
def expose_callback(individual_id): """ This function is the callback for exposure. It is registered with the intrahost module and then called for each individual for each timestep. This is where you decide whether an individual should get infected or not. In the limit, you could just return False here and no-one would ever get infected. If you just returned True, everyone would be infected always. The expectation is that you write some code that uses the contagion shed and does some math. To be heterogeneous, you can use the individual id. The action and prob parameters can be ignored. """ # The following code is just to demo the use of TBHIV-specific getters if gi.is_infected(individual_id): #print( "Individual {0} is apparently already infected.".format( individual_id ) ) return 0 if gi.get_immunity(individual_id) == 0: return 0 global timestep #print( "timestep = {0}, outbreak_timestep = {1}.".format( timestep, outbreak_timestep ) ) #if timestep in outbreak_timesteps: # #if gi.get_immunity( individual_id ) == 1.0 and random.random() < 0.1: # let's infect some people at random (outbreaks) # if random.random() < outbreak_coverage: # let's infect some people at random (outbreaks) # print( "Let's force-infect (outbreak) uninfected, non-immune individual based on random draw." ) # return 1 if (timestep == 1) and (individual_id == 13): return 1 # force-infect individual 13 at time 0 else: if individual_id == 0: pdb.set_trace() global contagion_buckets #global contagion_bucket_homog #print( "Exposing individual {0} to contagion {1}.".format( individual_id, contagion_bucket ) ) #HINT-y code here contagion = contagion_buckets[CHILD] + contagion_buckets[ADULT] me = ADULT if gi.get_age( individual_id) >= ADULT_CHILD_AGE_THRESHOLD else CHILD my_factor_from_child = factors[me][CHILD] my_factor_from_adult = factors[me][ADULT] contagion = (contagion_buckets[CHILD] * my_factor_from_child) + ( contagion_buckets[ADULT] * my_factor_from_adult) contagion /= len(human_pop) #print( "HINT-y math: I am an {}, exposed to contagion {}.".format( "CHILD" if me == CHILD else "ADULT", contagion ) ) #contagion = contagion_bucket_homog if gi.should_infect((individual_id, contagion)): return 1 return 0
def update(self): self.time += 1 for h in self.humans: dgi.update(h) if self.time % HALLOWEEN_DAY == 0: # It is october 31 if len(self.werewolves) == 0: # and there are no werewolves found_one = False possible_humans = len(self.humans) ages = [] min_age_exposure = self.min_age_werewolf_years * DAYS_YEAR while not found_one and possible_humans > 0: for h in self.humans: possible_humans -= 1 age = dgi.get_age(h) ages.append(age) if age > min_age_exposure: if age % DAYS_YEAR == HALLOWEEN_DAY: self.humans.remove(h) self.werewolves.append(h) found_one = True break if found_one: print("Found a new werewolf with a Halloween Birthday.") else: print("No cool birthdays, just taking someone.") future_wolf = None for h in self.humans: age = dgi.get_age(h) if not future_wolf and age > min_age_exposure: self.humans.remove(h) self.werewolves.append(h) future_wolf = h if future_wolf: print("Found someone old enough.") else: print("No one old enough! No outbreak!") print(ages) sys.exit() if self.enable_reporting: self.report_step()
def deposit_callback(contagion, individual_id): """ This function is the callback for shedding. It is registered with the intrahost module and then called for each shedding individual for each timestep. This is where you collect contagion that you want to subsequently use for transmission. Note that the individual value is only populated with non-zero values if pymod-specific SetGeneticID code is turned on in the DTK. This is only example I can think of of pymod-specific code in DTK. """ #print( "{0} depositing {1} contagion creates total of {2}.".format( individual, contagion, well_mixed_contagion_pool ) ) #print( "{0} depositing {1} contagion.".format( individual, contagion ) ) # Figure out what age bucket the individual is in. if individual_id == 0: # we need the DTK code to be built with the GeneticID used for the individual id. If not, this will be 0 pdb.set_trace() #print( "Shedding {0} into age-clan index {1}.".format( contagion, index ) ) #age_of_infection = gi.get_infection_age( individual_id ) #contagion = get_infectiousness( age_of_infection ) global contagion_buckets #global contagion_bucket_homog bucket_index = ADULT if gi.get_age(individual_id) >= 7300 else CHILD contagion_buckets[bucket_index] += contagion
def do_vitaldynamics_update(human_pop, graveyard, contagion, census_cb=None, death_cb=None): num_infected = 0 num_incubating = 0 num_active = 0 num_suscept = 0 num_recover = 0 num_people = 0 num_deaths = 0 new_graveyard = [] for human in human_pop: hum_id = human["id"] if census_cb != None: census_cb(hum_id) gi.update2( hum_id ) # this should do exposure; possible optimization would be to skip this entirely if zero contagion mcw = gi.get_mcw(hum_id) if gi.is_dead(hum_id): # somebody died print("{0} is dead.".format(hum_id)) new_graveyard.append(human) num_deaths += mcw # can't use len(graveyard) coz mcw if death_cb != None: death_cb(hum_id) num_people += mcw global fertility if fertility: ipm = gi.is_possible_mother(hum_id) ip = gi.is_pregnant(hum_id) if hum_id == 0: pdb.set_trace() age = gi.get_age(hum_id) #print( "Calling cfp with {0}, {1}, {2}, and {3}.".format( str(ipm), str(ip), str(age), str(hum_id) ) ) # TBD: Optimization? I happen to know that this is only necessary for females of a # certain age. But technically that knowledge is for nd. nd.consider_for_pregnancy((ipm, ip, hum_id, age, 1.0)) #print( str( json.loads(gi.serialize( hum_id ))["individual"]["susceptibility"] ) ) if gi.is_infected(hum_id): if is_incubating(hum_id): num_incubating += mcw else: num_infected += mcw # TBD: use_mcw elif gi.get_immunity(hum_id) != 1.0: num_recover += mcw # TBD: use mcw else: num_suscept += mcw # TBD: use mcw #if gi.has_active_infection( hum_id ): # num_active += 1 # serialize seems to be broken when you had an intervention (or at least a SimpleVaccine) #serial_man = gi.serialize( hum_id ) #if hum_id == 1: #print( json.dumps( json.loads( serial_man ), indent=4 ) ) #print( "infectiousness: " + str( json.loads( serial_man )["individual"]["infectiousness"] ) ) #print( "Updating fertility for this timestep." ) for corpse in new_graveyard: if corpse in human_pop: human_pop.pop(human_pop.index(corpse)) else: print("Exception trying to remove individual from python list: " + str(ex)) graveyard.extend(new_graveyard) nd.update_fertility() exposeds.append(num_incubating) prevalence.append(num_infected) active_prevalence.append(num_active) susceptible.append(num_suscept) recovered.append(num_recover) disdeaths.append(num_deaths)
def do_vitaldynamics_update(human_pop, graveyard, census_cb=None, death_cb=None): num_infected = 0 num_incubating = 0 num_active = 0 num_suscept = 0 num_recover = 0 new_graveyard = [] for human in human_pop: hum_id = human["id"] if census_cb != None: census_cb(hum_id) gi.update2(hum_id) # this should do exposure if gi.is_dead(hum_id): # somebody died print("{0} is dead.".format(hum_id)) new_graveyard.append(human) if death_cb != None: death_cb(hum_id) # TESTING THIS ipm = gi.is_possible_mother(hum_id) ip = gi.is_pregnant(hum_id) if hum_id == 0: pdb.set_trace() age = gi.get_age(hum_id) #print( "Calling cfp with {0}, {1}, {2}, and {3}.".format( str(ipm), str(ip), str(age), str(hum_id) ) ) nd.consider_for_pregnancy((ipm, ip, hum_id, age, 1.0)) #print( str( json.loads(gi.serialize( hum_id ))["individual"]["susceptibility"] ) ) if gi.is_infected(hum_id): if is_incubating(hum_id): num_incubating += 1 else: num_infected += 1 # TBD: use_mcw elif gi.get_immunity(hum_id) != 1.0: num_recover += 1 # TBD: use mcw else: num_suscept += 1 # TBD: use mcw #if gi.has_active_infection( hum_id ): # num_active += 1 # serialize seems to be broken when you had an intervention (or at least a SimpleVaccine) #serial_man = gi.serialize( hum_id ) #if hum_id == 1: #print( json.dumps( json.loads( serial_man ), indent=4 ) ) #print( "infectiousness: " + str( json.loads( serial_man )["individual"]["infectiousness"] ) ) #print( "Updating fertility for this timestep." ) for corpse in new_graveyard: if corpse in human_pop: human_pop.pop(human_pop.index(corpse)) else: print("Exception trying to remove individual from python list: " + str(ex)) graveyard.extend(new_graveyard) nd.update_fertility() exposeds.append(num_incubating) prevalence.append(num_infected) active_prevalence.append(num_active) susceptible.append(num_suscept) recovered.append(num_recover) disdeaths.append(len(graveyard))