def apply(self, sim): '''Some of this code is also borrowed from interventions.test_prob''' t = sim.t if t < self.start_day: return elif self.end_day is not None and t > self.end_day: return #Find all agents that display COVID-like symptoms symp_notMitigate = sim.people.symptomatic * ~sim.people.diagnosed testRecorded = cvu.false(np.isnan(sim.people.date_tested)) pendingTest = testRecorded[ sim.t - sim.people.date_tested[testRecorded] < self.test_delay] symp_notMitigate[pendingTest] = False if self.ili_prev is None: covidLikeInds = cvu.true(symp_notMitigate) else: rel_t = t - self.start_day ili_indices = cvu.n_binomial(self.ili_prev[rel_t], sim['pop_size']) covidLikeInds = cvu.true( np.logical_or(ili_indices, symp_notMitigate)) reportedInds = cvu.binomial_filter(self.symp_prob, covidLikeInds) #Quarantine and test the selected indices sim.people.quarantine(reportedInds) sim.people.test(reportedInds, self.test_sensitivity, 0.0, self.test_delay, True) sim.results['new_tests'][t] += int( len(reportedInds) * sim['pop_scale'] / sim.rescale_vec[t] ) # If we're using dynamic scaling, we have to scale by pop_scale, not rescale_vec return
def apply(self, sim): ''' Perform testing ''' t = sim.t if t < self.start_day: return elif self.end_day is not None and t > self.end_day: return # Define symptomatics, accounting for ILI prevalence symp_inds = cvu.true(sim.people.symptomatic) if self.ili_prev is not None: rel_t = t - self.start_day if rel_t < len(self.ili_prev): n_ili = int( self.ili_prev[rel_t] * sim['pop_size']) # Number with ILI symptoms on this day ili_inds = cvu.choose( sim['pop_size'], n_ili ) # Give some people some symptoms, assuming that this is independent of COVID symptomaticity... symp_inds = np.unique(np.concatenate((symp_inds, ili_inds)), 0) # Define asymptomatics: those who neither have COVID symptoms nor ILI symptoms asymp_inds = np.setdiff1d(np.arange(sim['pop_size']), symp_inds) # Handle quarantine and other testing criteria quar_inds = cvu.true(sim.people.quarantined) symp_quar_inds = np.intersect1d(quar_inds, symp_inds) asymp_quar_inds = np.intersect1d(quar_inds, asymp_inds) if self.subtarget is not None: subtarget_inds = self.subtarget['inds'] diag_inds = cvu.true(sim.people.diagnosed) # Construct the testing probabilities piece by piece -- complicated, since need to do it in the right order test_probs = np.zeros( sim.n) # Begin by assigning equal testing probability to everyone test_probs[symp_inds] = self.symp_prob # People with symptoms test_probs[asymp_inds] = self.asymp_prob # People without symptoms test_probs[ symp_quar_inds] = self.symp_quar_prob # People with symptoms in quarantine test_probs[ asymp_quar_inds] = self.asymp_quar_prob # People without symptoms in quarantine if self.subtarget is not None: subtarget_inds, subtarget_vals = get_subtargets( self.subtarget, sim) test_probs[ subtarget_inds] = subtarget_vals # People being explicitly subtargeted test_probs[diag_inds] = 0.0 # People who are diagnosed don't test test_inds = cvu.binomial_arr(test_probs).nonzero()[ 0] # Finally, calculate who actually tests sim.people.test(test_inds, test_sensitivity=self.test_sensitivity, loss_prob=self.loss_prob, test_delay=self.test_delay) sim.results['new_tests'][t] += int( len(test_inds) * sim['pop_scale'] / sim.rescale_vec[t] ) # If we're using dynamic scaling, we have to scale by pop_scale, not rescale_vec return
def apply(self, sim): t = sim.t if t < self.start_day: return elif self.end_day is not None and t > self.end_day: return severe_inds = cvu.true(sim.people.severe) sim.people.quarantine(severe_inds) sim.results['new_quarantined'][t] += len(severe_inds) # print(f'{severe_inds} put into quarantine due to severe symptoms.') return
def apply(self, sim): ''' Perform vaccination ''' t = sim.t if t < self.start_day: return elif self.end_day is not None and t > self.end_day: return # Check that there are still vaccines rel_t = t - self.start_day if rel_t < len(self.daily_vaccines): n_vaccines = sc.randround(self.daily_vaccines[rel_t] / sim.rescale_vec[t]) else: return vacc_probs = np.ones( sim.n ) # Begin by assigning equal vaccine weight (converted to a probability) to everyone if self.subtarget is not None: subtarget_inds, subtarget_vals = get_subtargets( self.subtarget, sim) vacc_probs[ subtarget_inds] = subtarget_vals # People being explicitly subtargeted # First dose # Don't give dose to people who have had at least one dose vacc_inds = cvu.true(self.vaccinations > 0) vacc_probs[vacc_inds] = 0.0 # Now choose who gets vaccinated and vaccinate them n_vaccines = min(n_vaccines, (vacc_probs != 0).sum()) all_vacc_inds = cvu.choose_w(probs=vacc_probs, n=n_vaccines, unique=True) # Choose who actually tests sim.results['new_doses'][t] += len(all_vacc_inds) self.vaccinations[all_vacc_inds] = 1 self.delay_days[all_vacc_inds] = self.delay self.first_dates[all_vacc_inds] = sim.t # Calculate the effect per person vacc_eff = self.cumulative[0] # Pull out corresponding effect sizes rel_sus_eff = 0.5 + 0.5 * self.rel_sus rel_symp_eff = 0.5 + 0.5 * self.rel_symp # Apply the vaccine to people #sim.people.rel_sus[all_vacc_inds] *= rel_sus_eff #sim.people.symp_prob[all_vacc_inds] *= rel_symp_eff sim.people.rel_sus[ all_vacc_inds] = self.orig_rel_sus[all_vacc_inds] * rel_sus_eff sim.people.symp_prob[ all_vacc_inds] = self.orig_symp_prob[all_vacc_inds] * rel_symp_eff all_vacc_inds2 = cvu.true( (self.vaccinations == 1) * (self.delay_days > 0) * (self.first_dates > 0) * (self.first_dates + self.delay_days == sim.t)) rel_sus_eff2 = self.rel_sus rel_symp_eff2 = self.rel_symp #sim.people.rel_sus[all_vacc_inds2] *= rel_sus_eff2 #sim.people.symp_prob[all_vacc_inds2] *= rel_symp_eff2 sim.people.rel_sus[ all_vacc_inds2] = self.orig_rel_sus[all_vacc_inds2] * rel_sus_eff2 sim.people.symp_prob[all_vacc_inds2] = self.orig_symp_prob[ all_vacc_inds2] * rel_symp_eff2 self.vaccinations[all_vacc_inds2] = 2 sim.results['new_doses'][t] += len(all_vacc_inds2)
def apply(self, sim): ''' Perform vaccination ''' t = sim.t if t < self.start_day: return elif self.end_day is not None and t > self.end_day: return # Check that there are still vaccines rel_t = t - self.start_day if rel_t < len(self.daily_vaccines): n_vaccines = sc.randround(self.daily_vaccines[rel_t]/sim.rescale_vec[t]) # Correct for scaling that may be applied by rounding to the nearest number of tests if not (n_vaccines and np.isfinite(n_vaccines)): # If there are no doses today, abort early return else: if sim.rescale_vec[t] != sim['pop_scale']: raise RuntimeError('bad rescale time') else: return vacc_probs = np.ones(sim.n) # Begin by assigning equal vaccine weight (converted to a probability) to everyone # Remove minors ppl = sim.people inds0 = cv.true(ppl.age <= 18) vacc_probs[inds0] *= 0 # add age priority inds1 = cv.true(ppl.age >= self.age_priority) vacc_probs[inds1] *= 10 # Handle scheduling # first dose: vacc_probs[self.vaccinations == 0] *= self.dose_priority[0] # time between first and second dose: no_dose = [sim.t < (d[0] + self.delay) if len(d) > 0 else False for d in self.vaccination_dates] vacc_probs[no_dose] *= 0 # time available for second dose: second_dose = [sim.t >= (d[0] + self.delay) if len(d) > 0 else False for d in self.vaccination_dates] vacc_probs[second_dose] *= self.dose_priority[1] # Don't give dose 2 people who have had more than 1 vacc_inds = cvu.true(self.vaccinations > 1) vacc_probs[vacc_inds] = 0.0 # Now choose who gets vaccinated and vaccinate them n_vaccines = min(n_vaccines, (vacc_probs!=0).sum()) # Don't try to vaccinate more people than have nonzero vaccination probability all_vacc_inds = cvu.choose_w(probs=vacc_probs, n=n_vaccines, unique=True) # Choose who actually tests sim.results['new_doses'][t] += len(all_vacc_inds) # Did the vaccine take? vacc_take_inds = all_vacc_inds[np.logical_or(cvu.n_binomial(self.take_prob, len(all_vacc_inds)) & (self.vaccinations[all_vacc_inds] == 0), self.vaccine_take[all_vacc_inds] & (self.vaccinations[all_vacc_inds] == 1))] self.vaccine_take[vacc_take_inds] = True # Calculate the effect per person vacc_doses = self.vaccinations[vacc_take_inds] # Calculate current doses eff_doses = np.minimum(vacc_doses, len(self.cumulative) - 1) # Convert to a valid index vacc_eff = self.cumulative[eff_doses] # Pull out corresponding effect sizes rel_trans_eff = (1.0 - vacc_eff) + vacc_eff * self.rel_trans rel_symp_eff = (1.0 - vacc_eff) + vacc_eff * self.rel_symp # Apply the vaccine to people sim.people.rel_trans[vacc_take_inds] = self.orig_rel_trans[vacc_take_inds]*rel_trans_eff sim.people.symp_prob[vacc_take_inds] = self.orig_symp_prob[vacc_take_inds]*rel_symp_eff self.vaccinations[all_vacc_inds] += 1 for v_ind in all_vacc_inds: self.vaccination_dates[v_ind].append(sim.t) return
def apply(self, sim): t = sim.t if t < self.start_day: return elif self.end_day is not None and t > self.end_day: return # Check that there are still tests rel_t = t - self.start_day if rel_t < len(self.daily_tests): n_tests = int( self.daily_tests[rel_t] / sim.rescale_vec[t]) # Number of tests for this day -- rescaled if not (n_tests and pl.isfinite(n_tests) ): # If there are no tests today, abort early return else: sim.results['new_tests'][t] += n_tests else: return test_probs = np.ones( sim.n) # Begin by assigning equal testing probability to everyone # Handle symptomatic testing, taking into account prevalence of ILI symptoms symp_inds = cvu.true(sim.people.symptomatic) if self.ili_prev is not None: if rel_t < len(self.ili_prev): n_ili = int( self.ili_prev[rel_t] * sim['pop_size']) # Number with ILI symptoms on this day ili_inds = cvu.choose( sim['pop_size'], n_ili ) # Give some people some symptoms. Assuming that this is independent of COVID symptomaticity... symp_inds = np.unique(np.concatenate((symp_inds, ili_inds)), 0) test_probs[symp_inds] *= self.symp_test # Handle quarantine testing quar_inds = cvu.true(sim.people.quarantined) test_probs[quar_inds] *= self.quar_test # Handle any other user-specified testing criteria if self.subtarget is not None: subtarget_inds, subtarget_vals = cv.get_subtargets( self.subtarget, sim) test_probs[ subtarget_inds] = test_probs[subtarget_inds] * subtarget_vals # Don't re-diagnose people diag_inds = cvu.true(sim.people.diagnosed) test_probs[diag_inds] = 0. # Now choose who gets tested and test them test_inds = cvu.choose_w(probs=test_probs, n=n_tests, unique=False) sim.people.test(test_inds, self.sensitivity, loss_prob=self.loss_prob, test_delay=self.test_delay) return
interventions = [cv.change_beta([30, 90], [0.3, 1])] sim = cv.Sim( use_waning=True, analyzers=cv.snapshot(90), pars=pars, interventions=interventions, ) sim.run() # Number of people exposed during the first wave: snap = sim.get_analyzer() d1 = 90 people0 = snap.get(d1) people1 = sim.people trial_arm_size = len(cvu.true(people0.n_infections > 0)) control_arm_size = len(cvu.true(people0.n_infections == 0)) trial_not_infected = len( cvu.true((people0.n_infections > 0) * (people1.n_infections == people0.n_infections))) trial_infected = len( cvu.true((people0.n_infections > 0) * (people1.n_infections > people0.n_infections))) control_not_infected = len( cvu.true((people0.n_infections == 0) * (people1.n_infections == 0))) control_infected = len( cvu.true((people0.n_infections == 0) * (people1.n_infections > 0))) p_inf_trial = trial_infected / trial_arm_size
def apply(self, sim): ''' Perform vaccination ''' if sim.t in self.days: if self.exact: unvacc_inds = sc.findinds(~sim.people.vaccinated * ~sim.people.dead) if self.subtarget is not None: #TODO: This block needs some modification subtarget_inds, subtarget_vals = get_subtargets( self.subtarget, sim) if len(subtarget_vals): vacc_probs[ subtarget_inds] = subtarget_vals # People being explicitly subtargeted else: # if self.exact < 1: # indToSample = round(self.prob * sim['pop_size']) # vacc_inds = npr.choice(unvacc_inds,indToSample,replace = False) # Assign equal vaccination probability to everyone # else: # vacc_inds = np.array(range(sim['pop_size'])) indToSample = round(self.prob * sim['pop_size']) vacc_inds = npr.choice( unvacc_inds, indToSample, replace=False ) # Assign equal vaccination probability to everyone else: vacc_probs = np.zeros(sim['pop_size']) unvacc_inds = sc.findinds(~sim.people.vaccinated) if self.subtarget is not None: subtarget_inds, subtarget_vals = get_subtargets( self.subtarget, sim) if len(subtarget_vals): vacc_probs[ subtarget_inds] = subtarget_vals # People being explicitly subtargeted else: vacc_probs[ unvacc_inds] = self.prob # Assign equal vaccination probability to everyone vacc_probs[cvu.true( sim.people.dead)] *= 0.0 # Do not vaccinate dead people vacc_inds = cvu.true(cvu.binomial_arr( vacc_probs)) # Calculate who actually gets vaccinated if len(vacc_inds): self.vaccinated[sim.t] = vacc_inds sim.people.flows['new_vaccinations'] += len(vacc_inds) sim.people.flows['new_vaccinated'] += len(vacc_inds) #self.first_dose_nab_days[sim.t] = vacc_inds self.vaccinations[vacc_inds] += 1 if self.p.interval is not None: self.second_dose_days[sim.t] = vacc_inds #self.second_dose_nab_days[sim.t] = vacc_inds self.vaccinations[vacc_inds] += 1 # Update vaccine attributes in sim sim.people.vaccinated[vacc_inds] = True sim.people.vaccine_source[vacc_inds] = self.index self.vaccination_dates[vacc_inds] = sim.t # Update vaccine attributes in sim sim.people.vaccinations[vacc_inds] = self.vaccinations[ vacc_inds] sim.people.date_vaccinated[vacc_inds] = sim.t cvim.init_nab(sim.people, vacc_inds, prior_inf=False) if self.p.interval is not None: #If it's a two-dose vaccine, we need to call this function again so that the boost is implemented cvim.init_nab(sim.people, vacc_inds, prior_inf=False) return
def create(self, sim): if not (len(self.pools) != 0 and self.lock): self.pools = {} dormCounter = 0 for dormName, dorm in sim.dorms.items(): currentTotalFloor = max(dorm['f']) + 1 for i in range(currentTotalFloor): samplesToTake = int( round(self.sampleProportion * (dorm['f'] == i).sum())) if samplesToTake < 1: if self.assureCoverage: samplesToTake = 1 else: continue newPool = np.array([-1] * samplesToTake) if "suite" in dorm.dormType: uniqueRooms = set(dorm['b'][dorm['f'] == i]) else: uniqueRooms = set(dorm['r'][dorm['f'] == i]) if samplesToTake < len(uniqueRooms): sampledRooms = random.sample(uniqueRooms, samplesToTake) else: j = 1 while len(uniqueRooms ) < samplesToTake - len(uniqueRooms) * j: j += 1 sampledRooms = list(uniqueRooms) * j sampledRooms += random.sample( uniqueRooms, samplesToTake - len(uniqueRooms) * j) poolCounter = 0 for room in sampledRooms: resample = True if "suite" in dorm.dormType: targetedAgents = np.array( list( set(cvu.true(dorm['b'] == room)) - set(newPool))) else: targetedAgents = np.array( list( set(cvu.true(dorm['r'] == room)) - set(newPool))) breakOuter = False while resample: while len(targetedAgents) == 0: #uniqueRooms doubles as a collection of rooms that could be sampled. If we know that #no agent associated with a room fits the desired criteria, the room is removed. uniqueRooms -= set([room]) #If there are no more rooms that fit the desired criterion, quit searching. if len(uniqueRooms) == 0: breakOuter = True candidate = -1 break if len(uniqueRooms) > len(sampledRooms): possibleRooms = uniqueRooms - set( sampledRooms) room = random.sample(possibleRooms, 1)[0] else: room = random.sample(uniqueRooms, 1)[0] if "suite" in dorm.dormType: targetedAgents = np.array( list( set(cvu.true(dorm['b'] == room)) - set(newPool))) else: targetedAgents = np.array( list( set(cvu.true(dorm['r'] == room)) - set(newPool))) if breakOuter: break candidate = np.random.choice(targetedAgents) resample = False if self.skipQuarantine: resample = resample or sim.people.quarantined[ candidate + sim.dorm_offsets[dormCounter]] or ( sim.people.diagnosed[ candidate + sim.dorm_offsets[dormCounter]] * ~sim.people.recovered[ candidate + sim.dorm_offsets[dormCounter]]) if self.skipDiagnosed: resample = resample or sim.people.diagnosed[ candidate + sim.dorm_offsets[dormCounter]] #Remove the candidate from targetedAgents so that if a resample is necessary, the #rejected agent will not be selected again. targetedAgents = targetedAgents[ targetedAgents != candidate] newPool[poolCounter] = candidate poolCounter += 1 self.pools[dormName + "_Floor" + str(i)] = newPool[ newPool != -1] + sim.dorm_offsets[dormCounter] dormCounter += 1 if self.collapse: self.pools = np.concatenate(list(self.pools.values())) return self.pools
def apply(self, sim): ''' Perform vaccination ''' if sim.t >= np.min(self.days): # Vaccinate people with their first dose vacc_inds = np.array( [], dtype=int) # Initialize in case no one gets their first dose for ind in find_day(self.days, sim.t, interv=self, sim=sim): vacc_probs = np.zeros(sim['pop_size']) unvacc_inds = sc.findinds(~sim.people.vaccinated) if self.subtarget is not None: subtarget_inds, subtarget_vals = get_subtargets( self.subtarget, sim) if len(subtarget_vals): vacc_probs[ subtarget_inds] = subtarget_vals # People being explicitly subtargeted else: vacc_probs[ unvacc_inds] = self.prob # Assign equal vaccination probability to everyone vacc_probs[cvu.true( sim.people.dead)] *= 0.0 # Do not vaccinate dead people vacc_inds = cvu.true(cvu.binomial_arr( vacc_probs)) # Calculate who actually gets vaccinated if len(vacc_inds): self.vaccinated[sim.t] = vacc_inds sim.people.flows['new_vaccinations'] += len(vacc_inds) sim.people.flows['new_vaccinated'] += len(vacc_inds) if self.p.interval is not None: next_dose_day = sim.t + self.p.interval if next_dose_day < sim['n_days']: self.second_dose_days[next_dose_day] = vacc_inds next_nab_day = sim.t + self.p.nab_interval if next_nab_day < sim['n_days']: self.first_dose_nab_days[next_nab_day] = vacc_inds else: self.first_dose_nab_days[sim.t] = vacc_inds # Also, if appropriate, vaccinate people with their second dose vacc_inds_dose2 = self.second_dose_days[sim.t] if vacc_inds_dose2 is not None: next_nab_day = sim.t + self.p.nab_interval if next_nab_day < sim['n_days']: self.second_dose_nab_days[next_nab_day] = vacc_inds_dose2 vacc_inds = np.concatenate((vacc_inds, vacc_inds_dose2), axis=None) sim.people.flows['new_vaccinations'] += len(vacc_inds_dose2) # Update vaccine attributes in sim if len(vacc_inds): sim.people.vaccinated[vacc_inds] = True sim.people.vaccine_source[vacc_inds] = self.index self.vaccinations[vacc_inds] += 1 self.vaccination_dates[vacc_inds] = sim.t # Update vaccine attributes in sim sim.people.vaccinations[vacc_inds] = self.vaccinations[ vacc_inds] # check whose nabs kick in today and then init_nabs for them! vaccine_nabs_first_dose_inds = self.first_dose_nab_days[sim.t] vaccine_nabs_second_dose_inds = self.second_dose_nab_days[sim.t] vaccine_nabs_inds = [ vaccine_nabs_first_dose_inds, vaccine_nabs_second_dose_inds ] for vaccinees in vaccine_nabs_inds: if vaccinees is not None: sim.people.date_vaccinated[vaccinees] = sim.t cvi.init_nab(sim.people, vaccinees, prior_inf=False) return
def make_dorm_contacts(sim, layers): ''' This function is analogous to population.make_microstructured_contacts, but it incorporates the structure of SimCampus.dorms. ''' pop_size = sim['pop_size'] #For convenience contacts_list = [{c: [] for c in layers} for p in range(pop_size)] # Pre-populate if 'b' in layers: #Determine the number of contacts for each person in each layer all at once. Room contacts always occur. bathroomContacts = cvu.n_poisson(sim['contacts']['b'], pop_size) if 'f' in layers: floorContacts = cvu.n_poisson(sim['contacts']['f'], pop_size) if 'c' in layers: #This statement was used before the addition of the grad student feature. It is being kept until the end of debugging. #communityContacts = cvu.n_poisson(sim['contacts']['c'], pop_size) communityContacts = np.concatenate( (cvu.n_poisson(sim['contacts']['c'], sim.dorm_offsets[-1]), cvu.n_poisson(sim.nonResContacts, sim.nonResidentEndIndex - sim.dorm_offsets[-1]), cvu.n_poisson(sim.gradContactScale * sim.nonResContacts, pop_size - sim.nonResidentEndIndex))) if sim.debug and sim.t > 0: sim.nonResContactsCounter += communityContacts[ sim.dorm_offsets[-1]:sim.nonResidentEndIndex].sum() #nonResContacts = communityContacts[sim.dorm_offsets[-1]:sim.nonResidentEndIndex].sum() #print("\nTime: " + str(sim.t)) #print("Total Contacts: " + str(len(communityContacts))) sim.nonGradDiff += communityContacts[sim.dorm_offsets[-1]:sim. nonResidentEndIndex].sum() #print("Non-Resident Contacts: " + str(communityContacts[sim.dorm_offsets[-1]:sim.nonResidentEndIndex].sum())) sim.nonGradDiff -= communityContacts[sim.nonResidentEndIndex:].sum() #print("Grad Contacts: " + str(communityContacts[sim.nonResidentEndIndex:].sum()) + '\n') dormIndex = 0 currentDorm = sim.dorms[dormIndex] i = 0 #Form contact networks for residential students while i < sim.dorm_offsets[-1]: if i >= sim.dorm_offsets[dormIndex + 1]: dormIndex += 1 currentDorm = sim.dorms[dormIndex] if 'r' in layers: j = currentDorm['r'][i - sim.dorm_offsets[dormIndex]] contacts_list[i]['r'] = cvu.true( currentDorm['r'] == j ) + sim.dorm_offsets[ dormIndex] #This is really inefficient but it will do for now if 'b' in layers: j = currentDorm['b'][i - sim.dorm_offsets[dormIndex]] bathroomMates = cvu.true(currentDorm['b'] == j) subIndices = cvu.choose_r(len(bathroomMates), bathroomContacts[i]) contacts_list[i][ 'b'] = bathroomMates[subIndices] + sim.dorm_offsets[dormIndex] if 'f' in layers: j = currentDorm['f'][i - sim.dorm_offsets[dormIndex]] floorMates = cvu.true(currentDorm['f'] == j) subIndices = cvu.choose_r(len(floorMates), floorContacts[i]) contacts_list[i][ 'f'] = floorMates[subIndices] + sim.dorm_offsets[dormIndex] if 'c' in layers: contacts_list[i]['c'] = create_community_contacts( sim, i, communityContacts[i]) i += 1 #Form contact networks for non-residential students while i < pop_size: #Non-residential students can only have community contacts b/c they have no dorm assignments if 'c' in layers: contacts_list[i]['c'] = create_community_contacts( sim, i, communityContacts[i]) i += 1 return (contacts_list)