def transmission_success(self, person, contact_strength): days_infected = self.day - self.infection_start_date[person] likelihood = self.serial_interval_distribution[days_infected] if person in self.symptomatic_infecteds: likelihood *= 1.6 else: likelihood *= 0.8 return probtools.random_event(1 - (1 - likelihood)**contact_strength)
def event(self,etype,person,**kwargs): if etype == 'quarantined': self.quarantined[person] = True self.quarantine_end_day[person] = self.quarantine_days + self.day self.quarantine_start_day[person] = self.day self.registrar.register_departure(person) self._record_state_change(person,'quarantined') return elif etype == 'dequarantined': del self.quarantined[person] self.registrar.register_return(person) self._record_state_change(person,'dequarantined') return elif etype == 'removed': self.removed[person] = True if person in self.symptomatic_infecteds: del self.symptomatic_infecteds[person] del self.infected[person] del self.infection_start_date[person] if 'artificial' not in kwargs: self.average_transmissions *= self.completed_infections self.completed_infections += 1 self.average_transmissions += self.infection_transmissions[person] self.average_transmissions /= self.completed_infections self._record_state_change(person,'removed') return elif etype == 'infected': del self.susceptible[person] self.infected[person] = True self.infection_start_date[person] = self.day self.infection_detectable_day[person] = self.day + self.days_indetectable self.infection_transmissions[person] = 0 if probtools.random_event(self.symptomatic_fraction): self.symptomatic_infecteds[person] = True self.symptomatic_day[person] = self.day + self.incubation_picker.draw() self.infection_end_day[person] = self.day + self.recovery_days self._record_state_change(person,'infected') return elif etype == 'new person': if person in self.registrar.student_data: pstring = 'student ' + str(self.registrar.student_data[person]['cohort']) else: pstring = 'instructor' self.susceptible[person] = True self.person_state[person] = ('nonquarantined','susceptible',pstring) self.all_individuals[person] = True self._record_state_change(person,None) if 'infected' in kwargs and kwargs['infected'] == True: self.event('infected',person,infected_by=None,message='Initially Infected') elif 'removed' in kwargs and kwargs['removed'] == True: self.event('infected',person,infected_by=None,artificial=True,message='Infection-Pending Initial Removal') self.event('removed',person,artificial=True,message='Initially Removed') return raise Exception('Unknown event',etype)
def execute_main_step(self): self.day += 1 self.registrar.update_query_system() self.tests_performed_today = 0 self.contact_traces_performed_today = 0 self.positive_tests_today = 0 if self.quarantining: for person in self.all_individuals: if probtools.random_event(self.daily_testing_fraction): result = self.testing_queue.add(person, abort_if=self.quarantined) for person in self.testing_queue: test_result = self.get_test_result( person) # Need to change so that all tests are forced if test_result > 0 and person not in self.quarantined: self.event('quarantined', person, message='Quarantined on Positive Test Result') if test_result > 0 and self.contact_tracing: self.contact_tracing_queue.add(person) for person in self.symptomatic_infecteds: if self.day == self.symptomatic_day[person]: if person not in self.quarantined: self.event('quarantined', person, message='Quarantined on Reported Symptoms') if self.contact_tracing: self.contact_tracing_queue.add(person) to_be_released = {} for person in self.quarantined: if self.day == self.quarantine_end_day[person]: to_be_released[person] = True for person in to_be_released: self.event('dequarantined', person, message='Released from Quarantine today') to_be_removed = {} for person in self.infected: if self.day == self.infection_end_day[person]: to_be_removed[person] = True for person in to_be_removed: self.event('removed', person, message='Removed from infection') if self.contact_tracing: for person in self.contact_tracing_queue: self.contact_traces_performed_today += 1 first_trace_day = self.day - self.contact_tracing_days post_trace_day = self.day if person in self.quarantined: post_trace_day = min(post_trace_day, self.quarantine_start_day[person] + 1) for trace_day in range(first_trace_day, post_trace_day): identified_contacts = self.registrar.query_contacts( person, trace_day - self.day) for found_individual in identified_contacts: if found_individual in self.all_individuals and found_individual not in self.quarantined: actions = probtools.random_threshold({ 'test': self.contact_tracing_testing_rate, 'quarantine': self.contact_tracing_quarantine_rate }) if 'test' in actions: self.testing_queue.add( found_individual, abort_if=self.quarantined) if 'quarantine' in actions and found_individual not in self.quarantined: self.event( 'quarantined', found_individual, message='Quarantined on Contact Trace') to_be_infected = {} for person in self.infected: if person not in self.quarantined: contact_information = self.registrar.query_transmit(person) for potential_infected in contact_information: if potential_infected in self.susceptible and potential_infected not in self.quarantined and potential_infected not in to_be_infected and self.transmission_success( person, contact_information[potential_infected]): to_be_infected[potential_infected] = person self.infection_transmissions[person] += 1 for person in to_be_infected: self.event('infected', person, infected_by=to_be_infected[person], message='Infection by transmission') new_cases_to_create = self.daily_outside_cases if type(new_cases_to_create) == list: new_cases_to_create = probtools.list_select(new_cases_to_create) for index in range(new_cases_to_create): person = probtools.list_select(list(self.susceptible.keys())) if person is not None and person not in self.quarantined: self.event('infected', person, infected_by=None, message='infected by outside source') self.recorded_info[ 'tests_performed_today'] = self.tests_performed_today self.recorded_info[ 'contact_traces_performed_today'] = self.contact_traces_performed_today self.recorded_info['positive_tests_today'] = self.positive_tests_today self.recorded_info['day'] = self.day self.recorded_info['R'] = self.average_transmissions for key, value in self.registrar.get_attendance().items(): self.recorded_info[key] = value