def __init__(self, school, sim): self.school = school zero_vec = [0] * sim.npts ppl = sim.people pop_scale = sim.pars['pop_scale'] student_uids = cv.itruei(ppl.student_flag, self.school.uids) teacher_uids = cv.itruei(ppl.teacher_flag, self.school.uids) staff_uids = cv.itruei(ppl.staff_flag, self.school.uids) self.num_school_days = 0 self.num = { 'students': len(student_uids) * pop_scale, 'teachers': len(teacher_uids) * pop_scale, 'staff': len(staff_uids) * pop_scale, } # Initialize results arrays base_result = { key: sc.dcp(zero_vec) for key in ['students', 'teachers', 'staff'] } self.infectious = sc.dcp(base_result) self.infectious_arrive_at_school = sc.dcp(base_result) self.infectious_stay_at_school = sc.dcp(base_result) self.newly_exposed = sc.dcp(base_result) self.scheduled = sc.dcp(base_result) self.in_person = sc.dcp(base_result)
def __init__(self, school, testing, sim): ''' Initialize testing. ''' self.school = school self.testing = [] if testing is None else sc.dcp(testing) for test in self.testing: if 'is_antigen' not in test: test['is_antigen'] = False self.n_tested = {'PCR': 0, 'Antigen': 0} for test in self.testing: # Determine from test start_day and repeat which sim times to test on start_t = sim.day(test['start_date']) if test['repeat'] == None: # Easy - one time test test['t_vec'] = [start_t] else: test['t_vec'] = list( range(start_t, sim.pars['n_days'], test['repeat'])) # Determine uids to include uids = [] ppl = sim.people if 'students' in test['groups']: uids.append(cv.itruei(ppl.student_flag, self.school.uids)) if 'staff' in test['groups']: uids.append(cv.itruei(ppl.staff_flag, self.school.uids)) if 'teachers' in test['groups']: uids.append(cv.itruei(ppl.teacher_flag, self.school.uids)) test['uids'] = np.concatenate(uids)
def antigen_test(self, inds, sym7d_sens=1.0, other_sens=1.0, specificity=1, loss_prob=0.0, sim=None): ''' Adapted from the test() method on sim.people to do antigen testing. Main change is that sensitivity is now broken into those symptomatic in the past week and others. Args: inds: indices of who to test sym7d_sens (float): probability of a true positive in a recently symptomatic individual (7d) other_sens (float): probability of a true positive in others loss_prob (float): probability of loss to follow-up delay (int): number of days before test results are ready ''' ppl = sim.people t = sim.t inds = np.unique(inds) # Antigen tests don't count towards stats (yet) #ppl.tested[inds] = True #ppl.date_tested[inds] = t # Only keep the last time they tested #ppl.date_results[inds] = t + delay # Keep date when next results will be returned is_infectious_not_dx = cv.itruei(ppl.infectious * ~ppl.diagnosed, inds) symp = cv.itruei(ppl.symptomatic, is_infectious_not_dx) recently_symp_inds = symp[t - ppl.date_symptomatic[symp] < 7] other_inds = np.setdiff1d(is_infectious_not_dx, recently_symp_inds) is_inf_pos = np.concatenate(( cv.binomial_filter( sym7d_sens, recently_symp_inds), # Higher sensitivity for <7 days cv.binomial_filter(other_sens, other_inds) # Lower sensitivity of otheres )) not_lost = cv.n_binomial(1.0 - loss_prob, len(is_inf_pos)) true_positive_uids = is_inf_pos[not_lost] # Store the date the person will be diagnosed, as well as the date they took the test which will come back positive # Not for antigen tests? date_diagnosed would interfere with later PCR. #ppl.date_diagnosed[true_positive_uids] = t + delay #ppl.date_pos_test[true_positive_uids] = t # False positivies if specificity < 1: non_infectious_uids = np.setdiff1d(inds, is_infectious_not_dx) false_positive_uids = cv.binomial_filter(1 - specificity, non_infectious_uids) else: false_positive_uids = np.empty(0, dtype=np.int64) # At low prevalence, true_positive_uids will likely outnumber false_positive_uids return np.concatenate((true_positive_uids, false_positive_uids))
def __init__(self, sim, uids, layer): super().__init__(uids, layer) self.students = cv.itruei(sim.people.student_flag, self.uids) self.staff = cv.itruei(sim.people.staff_flag, self.uids) self.teachers = cv.itruei(sim.people.teacher_flag, self.uids) self.A_base_layer, self.B_base_layer = self.split_layer() self.schedule = { 'Monday': 'A', 'Tuesday': 'A', 'Wednesday': 'distance', 'Thursday': 'B', 'Friday': 'B', 'Saturday': 'weekend', 'Sunday': 'weekend', }
def test_indexing(): # Definitions farr = np.array([1.5, 0, 0, 1, 1, 0]) # Float array barr = np.array(farr, dtype=bool) # Boolean array darr = np.array([0, np.nan, 1, np.nan, 0, np.nan]) # Defined/undefined array inds = np.array([0, 10, 20, 30, 40, 50]) # Indices inds2 = np.array([1, 2, 3, 4]) # Skip first and last index # Test true, false, defined, and undefined assert cv.true(farr).tolist() == [0, 3, 4] assert cv.false(farr).tolist() == [1, 2, 5] assert cv.defined(darr).tolist() == [0, 2, 4] assert cv.undefined(darr).tolist() == [1, 3, 5] # Test with indexing assert cv.itrue(barr, inds).tolist() == [0, 30, 40] assert cv.ifalse(barr, inds).tolist() == [10, 20, 50] assert cv.idefined(darr, inds).tolist() == [0, 20, 40] assert cv.iundefined(darr, inds).tolist() == [10, 30, 50] # Test with double indexing assert cv.itruei(barr, inds2).tolist() == [3, 4] assert cv.ifalsei(barr, inds2).tolist() == [1, 2] assert cv.idefinedi(darr, inds2).tolist() == [2, 4] assert cv.iundefinedi(darr, inds2).tolist() == [1, 3] return
def initialize(self, sim): ''' Find the schools and seed infections ''' for st in self.s_types: self.school_ids[st] = sim.people.school_types[st] for sid in self.school_ids[st]: sch_uids = np.array(sim.people.schools[sid]) if self.choose_students: s_uids = cv.itruei(sim.people.student_flag, sch_uids) else: s_uids = sch_uids choices = cv.choose(len(s_uids), self.n_infections) self.seed_inds[st] += s_uids[choices].tolist() return
def update(self, sim): ''' Called on each day to update school statistics ''' t = sim.t ppl = sim.people rescale = sim.rescale_vec[t] if self.school.ct_mgr.school_day: self.num_school_days += 1 student_uids = cv.itruei(ppl.student_flag, self.school.uids) teacher_uids = cv.itruei(ppl.teacher_flag, self.school.uids) staff_uids = cv.itruei(ppl.staff_flag, self.school.uids) infectious_ids = {} for group, ids in zip(['students', 'teachers', 'staff'], [student_uids, teacher_uids, staff_uids]): infectious_ids[group] = cv.true(ppl.infectious[ids]) self.infectious[group][t] = len(infectious_ids[group]) * rescale self.newly_exposed[group][t] = len( cv.true(ppl.date_exposed[ids] == t - 1)) * rescale self.scheduled[group][t] = len( np.intersect1d(self.school.scheduled_uids, ids)) * rescale # Scheduled self.in_person[group][t] = len( np.intersect1d(self.school.uids_passed_screening, ids)) * rescale # Post-screening # Tracing statistics to compare against previous work: # if len(self.school.uids_arriving_at_school) > 0: # school_infectious = cv.itrue(ppl.infectious[self.school.uids_arriving_at_school], self.school.uids_arriving_at_school) # else: # school_infectious = np.empty(0, dtype='int64') # Options here: (TODO - avoid code replication) # 1. Use ids of students who arrived as school (pre-screening): self.school.uids_arriving_at_school (pre-screening) # 2. Use ids of students who passed screening: self.school.uids_passed_screening # First "infectious_arrive_at_school" assumes there is a transmission risk even pre-screening (e.g. bus) n_students_at_school = len( cv.itruei(ppl.student_flag * ppl.infectious, self.school.uids_arriving_at_school)) n_teachers_at_school = len( cv.itruei(ppl.teacher_flag * ppl.infectious, self.school.uids_arriving_at_school)) n_staff_at_school = len( cv.itruei(ppl.staff_flag * ppl.infectious, self.school.uids_arriving_at_school)) for group, count in zip( ['students', 'teachers', 'staff'], [n_students_at_school, n_teachers_at_school, n_staff_at_school]): self.infectious_arrive_at_school[group][t] = count * rescale # Second "infectious_stay_at_school" effectively assumes "screen-positive" kids would be kept home from school in the first place n_students_passedscreening = len( cv.itruei(ppl.student_flag * ppl.infectious, self.school.uids_passed_screening)) n_teachers_passedscreening = len( cv.itruei(ppl.teacher_flag * ppl.infectious, self.school.uids_passed_screening)) n_staff_passedscreening = len( cv.itruei(ppl.staff_flag * ppl.infectious, self.school.uids_passed_screening)) for group, count in zip(['students', 'teachers', 'staff'], [ n_students_passedscreening, n_teachers_passedscreening, n_staff_passedscreening ]): self.infectious_stay_at_school[group][t] = count * rescale