def test_plotting(): torun = [ 'hex2rgb', 'arraycolors', 'gridcolors', 'surf3d', 'bar3d', ] if 'hex2rgb' in torun: c1 = sc.hex2rgb('#fff') c2 = sc.hex2rgb('fabcd8') print(c1) print(c2) if 'arraycolors' in torun: n = 1000 ncols = 5 arr = pl.rand(n, ncols) for c in range(ncols): arr[:, c] += c x = pl.rand(n) y = pl.rand(n) colors = sc.arraycolors(arr) if doplot: pl.figure(figsize=(20, 16)) for c in range(ncols): pl.scatter(x + c, y, s=50, c=colors[:, c]) if 'gridcolors' in torun: colors_a = sc.gridcolors(ncolors=8, demo=doplot) colors_b = sc.gridcolors(ncolors=18, demo=doplot) colors_c = sc.gridcolors(ncolors=28, demo=doplot) print('\n8 colors:', colors_a) print('\n18 colors:', colors_b) print('\n28 colors:', colors_c) if 'surf3d' in torun: data = pl.randn(50, 50) smoothdata = sc.smooth(data, 20) if doplot: sc.surf3d(smoothdata) if 'bar3d' in torun: data = pl.rand(20, 20) smoothdata = sc.smooth(data) if doplot: sc.bar3d(smoothdata) return pl.gcf()
def test_smooth(): data = pl.randn(200, 100) smoothdata = sc.smooth(data, 10) if doplot: pl.subplot(1, 2, 1) pl.pcolor(data) pl.subplot(1, 2, 2) pl.pcolor(smoothdata) return smoothdata
def compute_r_eff(self, method='daily', smoothing=2, window=7): ''' Effective reproductive number based on number of people each person infected. Args: method (str): 'instant' uses daily infections, 'infectious' counts from the date infectious, 'outcome' counts from the date recovered/dead smoothing (int): the number of steps to smooth over for the 'daily' method window (int): the size of the window used for 'infectious' and 'outcome' calculations (larger values are more accurate but less precise) Returns: r_eff (array): the r_eff results array ''' # Initialize arrays to hold sources and targets infected each day sources = np.zeros(self.npts) targets = np.zeros(self.npts) window = int(window) # Default method -- calculate the daily infections if method == 'daily': # Find the dates that everyone became infectious and recovered, and hence calculate infectious duration recov_inds = self.people.defined('date_recovered') dead_inds = self.people.defined('date_dead') date_recov = self.people.date_recovered[recov_inds] date_dead = self.people.date_dead[dead_inds] date_outcome = np.concatenate((date_recov, date_dead)) inds = np.concatenate((recov_inds, dead_inds)) date_inf = self.people.date_infectious[inds] mean_inf = date_outcome.mean() - date_inf.mean() # Calculate R_eff as the mean infectious duration times the number of new infectious divided by the number of infectious people on a given day raw_values = mean_inf * self.results['new_infections'].values / ( self.results['n_infectious'].values + 1e-6) len_raw = len(raw_values) # Calculate the number of raw values if len_raw >= 3: # Can't smooth arrays shorter than this since the default smoothing kernel has length 3 initial_period = self['dur']['exp2inf']['par1'] + self['dur'][ 'asym2rec'][ 'par1'] # Approximate the duration of the seed infections for averaging initial_period = int(min( len_raw, initial_period)) # Ensure we don't have too many points for ind in range( initial_period): # Loop over each of the initial inds raw_values[ind] = raw_values[ind:initial_period].mean( ) # Replace these values with their average values = sc.smooth(raw_values, smoothing) values[: smoothing] = raw_values[: smoothing] # To avoid numerical effects, replace the beginning and end with the original values[-smoothing:] = raw_values[-smoothing:] else: values = raw_values # Alternate (traditional) method -- count from the date of infection or outcome elif method in ['infectious', 'outcome']: # Store a mapping from each source to their date source_dates = {} for t in self.tvec: # Sources are easy -- count up the arrays for all the people who became infections on that day if method == 'infectious': inds = cvu.true( t == self.people.date_infectious ) # Find people who became infectious on this timestep elif method == 'outcome': recov_inds = cvu.true( t == self.people.date_recovered ) # Find people who recovered on this timestep dead_inds = cvu.true( t == self.people.date_dead ) # Find people who died on this timestep inds = np.concatenate((recov_inds, dead_inds)) sources[t] = len(inds) # Create the mapping from sources to dates for ind in inds: source_dates[ind] = t # Targets are hard -- loop over the transmission tree for transdict in self.people.infection_log: source = transdict['source'] if source is not None and source in source_dates: # Skip seed infections and people with e.g. recovery after the end of the sim source_date = source_dates[source] targets[source_date] += 1 # for ind in inds: # targets[t] += len(self.people.transtree.targets[ind]) # Populate the array -- to avoid divide-by-zero, skip indices that are 0 r_eff = np.divide(targets, sources, out=np.full(self.npts, np.nan), where=sources > 0) # Use stored weights calculate the moving average over the window of timesteps, n num = np.nancumsum(r_eff * sources) num[window:] = num[window:] - num[:-window] den = np.cumsum(sources) den[window:] = den[window:] - den[:-window] values = np.divide(num, den, out=np.full(self.npts, np.nan), where=den > 0) # Method not recognized else: errormsg = f'Method must be "daily", "infected", or "outcome", not "{method}"' raise ValueError(errormsg) # Set the values and return self.results['r_eff'].values[:] = values return self.results['r_eff'].values
""" Version: 2019jan10 """ import pylab as pl import sciris as sc torun = [ 'smooth', ] if 'doplot' not in locals(): doplot = True if 'smooth' in torun: data = pl.randn(200, 100) smoothdata = sc.smooth(data, 10) if doplot: pl.subplot(1, 2, 1) pl.pcolor(data) pl.subplot(1, 2, 2) pl.pcolor(smoothdata)
def compute_r_eff(self, method='daily', smoothing=2, window=7): ''' Effective reproductive number based on number of people each person infected. Args: method (str): 'instant' uses daily infections, 'infectious' counts from the date infectious, 'outcome' counts from the date recovered/dead smoothing (int): the number of steps to smooth over for the 'daily' method window (int): the size of the window used for 'infectious' and 'outcome' calculations (larger values are more accurate but less precise) Returns: r_eff (array): the r_eff results array ''' # Initialize arrays to hold sources and targets infected each day sources = np.zeros(self.npts) targets = np.zeros(self.npts) window = int(window) # Default method -- calculate the daily infections if method == 'daily': # Find the dates that everyone became infectious and recovered, and hence calculate infectious duration recov_inds = self.people.defined('date_recovered') dead_inds = self.people.defined('date_dead') date_recov = self.people.date_recovered[recov_inds] date_dead = self.people.date_dead[dead_inds] date_outcome = np.concatenate((date_recov, date_dead)) inds = np.concatenate((recov_inds, dead_inds)) date_inf = self.people.date_infectious[inds] mean_inf = date_outcome.mean() - date_inf.mean() # Calculate R_eff as the mean infectious duration times the number of new infectious divided by the number of infectious people on a given day values = mean_inf * self.results['new_infections'].values / ( self.results['n_infectious'].values + 1e-6) if len(values) >= 3: # Can't smooth arrays shorter than this values = sc.smooth(values, smoothing) # Alternate (traditional) method -- count from the date of infection or outcome elif method in ['infectious', 'outcome']: for t in self.tvec: # Sources are easy -- count up the arrays if method == 'infectious': inds = cvu.true( t == self.people.date_infectious ) # Find people who became infectious on this timestep elif method == 'outcome': recov_inds = cvu.true( t == self.people.date_recovered ) # Find people who recovered on this timestep dead_inds = cvu.true( t == self.people.date_dead ) # Find people who died on this timestep inds = np.concatenate((recov_inds, dead_inds)) sources[t] = len(inds) # Targets are hard -- loop over the transmission tree for ind in inds: targets[t] += len(self.people.transtree.targets[ind]) # Populate the array -- to avoid divide-by-zero, skip indices that are 0 inds = sc.findinds(sources > 0) r_eff = np.zeros(self.npts) * np.nan r_eff[inds] = targets[inds] / sources[inds] # Use stored weights calculate the moving average over the window of timesteps, n num = np.nancumsum(r_eff * sources) num[window:] = num[window:] - num[:-window] den = np.cumsum(sources) den[window:] = den[window:] - den[:-window] # Avoid dividing by zero values = np.zeros(num.shape) * np.nan ind = den > 0 values[ind] = num[ind] / den[ind] # Method not recognized else: errormsg = f'Method must be "daily", "infected", or "outcome", not "{method}"' raise ValueError(errormsg) # Set the values and return self.results['r_eff'].values[:] = values return self.results['r_eff'].values
pars={}) for key, val in row.items(): rowdict['pars'][key] = val json.append(rowdict) sc.savejson(f'{dbname}.json', json, indent=2) saveobj = False if saveobj: # Smaller file, but less portable sc.saveobj(f'{dbname}.obj', json) # Plot the trend in best mismatch over time if plot_trend: mismatch = sc.dcp(df['mismatch'].values) best_mismatch = np.zeros(len(mismatch)) for i in range(len(mismatch)): best_mismatch[i] = mismatch[:i + 1].min() smoothed_mismatch = sc.smooth(mismatch) pl.figure(figsize=(16, 12), dpi=120) ax1 = pl.subplot(2, 1, 1) pl.plot(mismatch, alpha=0.2, label='Original') pl.plot(smoothed_mismatch, lw=3, label='Smoothed') pl.plot(best_mismatch, lw=3, label='Best') ax2 = pl.subplot(2, 1, 2) max_mismatch = mismatch.min() * best_thresh inds = cv.true(mismatch <= max_mismatch) pl.plot(best_mismatch, lw=3, label='Best') pl.scatter(inds, mismatch[inds], c=mismatch[inds], label='Usable indices')