def main(close=True, show=True, save=False): """Generate all plots. args close: close any open plots. show: display new plots on screen save: write new plots to a file returns None """ print(f"\nRunning module \"{__name__}\" ...") N = c.num_days() print("There are a total of %d days" % (N)) print("The earleiest date is %s" % (c.ind2datetime(0))) print("The latest date is %s" % (c.ind2datetime(N-1))) if close: _num = c.next_fig_num(close) close = False s.main(close=close, show=show, save=save) ts.main(close=close, show=show, save=save) rs.main(close=close, show=show, save=save) fr.main(close=close, show=show, save=save) lp.main(close=close, show=show, save=save) hp.main(close=close, show=show, save=save) bp.main(close=close, show=show, save=save) dr.main(close=close, show=show, save=save)
def main(close=True, show=True, save=False, file_names=("Fig9.pdf",)): """Plots to be used in the paper.""" print(f"\nRunning module \"{__name__}\" ...") cases = c.get_data("cases", "US") cases_padded, pad_sz = c.extrapolate(cases) f0, f1 = 1/7.0, 1/8.0 y_el_1 = ellip_bf(cases_padded, f0, f1)[pad_sz:-pad_sz] H = ellip_spec(f0, f1, 1024) y_fft_1 = c.apply_spectrum(cases_padded, H)[pad_sz:-pad_sz] start = 40 print("plot #1 begins on date: %s" % c.ind2datetime(start)) y_label = lambda x, p: "%.0fk" % (x/1000) x = np.arange(0, max(cases[start:].shape), 1) dz = np.zeros(len(x)) num = c.next_fig_num(close) fig, (ax3) = plt.subplots(1, 1, figsize=(5, 3.294), num=num) ax3.fill_between(x, cases[start:], dz, alpha=0.1, color="#000000", label="daily cases") ax3.plot(x, y_el_1[start:], linewidth=1.25, label="elliptic high-pass #1", linestyle=(0,(2,1))) ax3.plot(x, y_fft_1[start:], linewidth=1.25, label="FFT high-pass #1", linestyle=(0,(9,9))) ax3.set(xlabel='time [days]', ylabel='daily new cases') ax3.get_yaxis().set_major_formatter(ticker.FuncFormatter(y_label)) ax3.grid(True, alpha=0.2) ax3.axis([min(x), max(x), -15000, 80000]) ax3.legend(loc='upper left', prop={'size': 9}, handlelength=2) plt.tight_layout() if show: plt.show(block=False) if save: c.save_fig(fig, file_names[0])
def main(N=3, close=True, show=True, save=False, file_names=("Fig3.pdf", )): """Reconstruct the waveform with 1, 2, or 3 sinusoids. Then search for min and max, provided that the harmonics sufficiently big. args N (int): The number of harmonics to consider (1, 2, or 3). close (bool): True if existing plots will be closed. show (bool): True if the plot will be displayed on screen. save (bool): True if the plot will be saved to file. returns None """ print(f"\nRunning module \"{__name__}\" ...") # some input variables start = 70 end = c.num_days( ) - 5 # allowing five days for revisions to be made to the repo fft_pts = 2**19 print("Analysis date range: %s - %s" % (c.ind2datetime(start), c.ind2datetime(end))) print("Analysis window size: %d" % (end - start)) print("FFT size: 2^%d = %d points" % (np.log2(fft_pts), fft_pts)) # The frequencies we are interested in. f = np.array([[1 / 7, 2 / 7, 3 / 7]])[:, :N] # List of countries to be included in the plots and print out. countries = ["US", "Mexico", "Argentina", "United Kingdom", "Brazil"] # The datetime at which the integrated derivative begins (time is 12:00 noon). t_ref = c.ind2datetime( start) # for FFT derivative plus symbolic integration print("Reference time for the integrated derivative: %s" % t_ref) num_days = 21 # number of days to synthesize step_sz = 20 / (24 * 60 * 60) # step size for synthesis (20 seconds) xs = np.array([np.arange(0, num_days, step_sz)]) # time-axis for calculating sinusoids x = xs[0] + c.days2decimals(t_ref) # time-axis for plotting sinusoids print("Step size for resynthesis: %1.4f seconds" % (step_sz * 24 * 60 * 60)) print() # This will be the main data object of interest. phf = {"cases": dict(), "deaths": dict()} for rt in phf: for country in countries: data = c.get_data(rt, "global", country=country, state=None) d_dt_data = c.deriv_fft(data)[start:end] # FFT derivative Z = np.fft.fft(d_dt_data, n=int(fft_pts)) / fft_pts # spectrum of derivative H_f = Z[(fft_pts * f + 0.5).astype(np.int)] # freqs. of interest theta = np.angle(H_f) # phase angles m = np.abs(H_f) # magnitudes y = (m / (2 * np.pi * f)) * np.sin( 2 * np.pi * xs.T * f + theta) # Compute integrated sinusoids y_sum = np.sum(y, 1) # Sum sinusoids y_sum = y_sum - (np.max(y_sum) + np.min(y_sum)) / 2 # align vertically for plot y_sum = y_sum / max(np.abs(y_sum)) # normalize for plot phf[rt][country] = y_sum # Collect the data # Text summary of results text_summary(phf, t_ref, xs) # Plot if show or save: make_plot(phf, x, countries, close=close, show=show, save=save, file_name=file_names[0])
def main(close=True, show=True, save=False, file_names=( "Fig10.pdf", "Fig11.pdf", "FigUnused_BP.pdf", )): """Plots to be used in the paper.""" print(f"\nRunning module \"{__name__}\" ...") cases = c.get_data("cases", "US") deaths = c.get_data("deaths", "US") # Extrapolation cases_padded, pad_sz = c.extrapolate(cases) deaths_padded, pad_sz = c.extrapolate(deaths) numPts = 1024 # first plot wp, ws = [1 / 8.0, 1 / 6.0], [1 / 9.0, 1 / 5.0] y_el_1 = ellip_bf(cases_padded, wp, ws)[pad_sz:-pad_sz] # elliptic H_1 = ellip_spec(wp, ws, numPts) y_fft_1 = c.apply_spectrum(cases_padded, H_1)[pad_sz:-pad_sz] # FFT start1 = 40 print("plot #1 begins on date: %s" % c.ind2datetime(start1)) y1_lables = lambda x, p: "%.0fk" % (x / 1000) x1 = np.arange(0, max(cases[start1:].shape), 1) dz = np.zeros(len(x1)) num = c.next_fig_num(close) fig1, (ax1) = plt.subplots(1, 1, figsize=(5, 3.294), num=num) ax1.fill_between(x1, cases[start1:], dz, alpha=0.1, color="#000000", label="daily deaths") ax1.plot(x1, y_el_1[start1:], linewidth=1.25, label="elliptic band-pass #1", linestyle=(0, (2, 1))) ax1.plot(x1, y_fft_1[start1:], linewidth=1.25, label="FFT band-pass #1", linestyle=(0, (9, 9))) ax1.get_yaxis().set_major_formatter(ticker.FuncFormatter(y1_lables)) ax1.grid(True, alpha=0.2) ax1.legend(loc='upper left', prop={'size': 9}, handlelength=2) ax1.set(xlabel='time [days]') ax1.set(ylabel='daily new cases') ax1.axis([0, max(y_fft_1[start1:].shape) - 1, -15000, 80000]) plt.tight_layout() # second plot wp, ws = [1 / 19, 1 / 9.0], [1 / 21.0, 1 / 8.0] y_el_2 = ellip_bf(deaths_padded, wp, ws)[pad_sz:-pad_sz] # elliptic H_2 = ellip_spec(wp, ws, numPts) y_fft_2 = c.apply_spectrum(deaths_padded, H_2)[pad_sz:-pad_sz] start3 = 100 print("plot #2 begins on date: %s" % c.ind2datetime(start3)) y3_lables = lambda x, p: "%.1fk" % (x / 1000) x3 = np.arange(0, max(deaths[start3:].shape), 1) dz = np.zeros(len(x3)) num += 1 fig3, (ax3) = plt.subplots(1, 1, figsize=(5, 3.3), num=num) ax3.fill_between(x3, deaths[start3:], dz, alpha=0.1, color="#000000", label="daily deaths") ax3.plot(x3, y_el_2[start3:], linewidth=1.25, label="elliptic band-pass #2", linestyle=(0, (2, 1))) ax3.plot(x3, y_fft_2[start3:], linewidth=1.25, label="FFT band-pass #2", linestyle=(0, (9, 9))) ax3.get_yaxis().set_major_formatter(ticker.FuncFormatter(y3_lables)) ax3.grid(True, alpha=0.2) ax3.legend(loc='upper right', prop={'size': 9}, handlelength=2) ax3.set(xlabel='time [days]') ax3.set(ylabel='daily new deaths') ax3.axis([0, max(y_fft_2[start3:].shape) - 1, -250, 2500]) plt.tight_layout() # third plot - To check if second plot contains any energy leaking # in from bandwidth associated with the seven-day oscillation. f = np.arange(0, numPts) / numPts d_dt_deaths = c.deriv_fft(deaths) Z = np.abs(np.fft.fft(d_dt_deaths, n=int(numPts)) / numPts) norm_val = np.max( Z[int(numPts * 0.1 + 0.5):int(numPts * 0.5 + 0.5)]) # normalize to max value above 0.1 and 0.5 Z_deaths = Z / norm_val dz = np.zeros(len(f)) num += 1 sbStyle = (0, (1, 1)) pbStyle = (0, (2, 1)) fig4, (ax4) = plt.subplots(1, 1, figsize=(6, 3.3), num=num) ax4.plot(np.array([wp[0]] * 2), np.array([-999, 999]), '#666666', linewidth=1.25, linestyle=pbStyle, label="\"pass-band\"") ax4.plot(np.array([wp[1]] * 2), np.array([-999, 999]), '#666666', linewidth=1.25, linestyle=pbStyle) ax4.plot(np.array([ws[0]] * 2), np.array([-999, 999]), '#bbbbbb', linewidth=1.25, linestyle=sbStyle, label="\"stop-band\"") ax4.plot(np.array([ws[1]] * 2), np.array([-999, 999]), '#bbbbbb', linewidth=1.25, linestyle=sbStyle) ax4.fill_between(f, Z_deaths, dz, label="full spectrum", color="#555500", alpha=0.1) ax4.plot(f, Z_deaths * np.abs(H_2), label="plotted spectrum", linewidth=1.25, linestyle=(0, ())) ax4.set(title="The spectrum plotted for \"Band-Pass #2\"", xlabel='frequency [1/day]', ylabel='magnitude [1]') ax4.title.set_size(10) ax4.axis([0, 0.5, -0.0, 1.05]) ax4.legend(loc='upper right', prop={'size': 9}, handlelength=2, framealpha=0.92) plt.tight_layout() if show: plt.show(block=False) if save: c.save_fig(fig1, file_names[0]) c.save_fig(fig3, file_names[1]) c.save_fig(fig4, file_names[2])
def main(close=True, show=True, save=False, file_names=("Fig1.pdf",)): """Create and save frequency spectrum plot for time series (deaths and cases).""" print(f"\nRunning module \"{__name__}\" ...") # some variables # countries = ["United Kingdom", "Brazil", "US", "Mexico", "South Africa", "Russia"] # countries = ["United Kingdom", "Brazil", "US", "Mexico", "Argentina", "Kenya"] countries = ["United Kingdom", "Brazil", "US", "Mexico", "Argentina", "Switzerland"] start = 65 end = c.num_days() print("total days: %d, date range: %s, %s" % (end-start, c.ind2datetime(start), c.ind2datetime(end))) print("end-start/7 = %f, (end-start)/3.5 = %f" % ((end-start)/7.0, (end-start)/3.5)) # Create the data p_data = dict() for country in countries: cases = c.get_data("cases", "global", country=country) deaths = c.get_data("deaths", "global", country=country) f, Z_cases = process_data(cases, start, end) f, Z_deaths = process_data(deaths, start, end) p_data[country] = {"cases": Z_cases, "deaths": Z_deaths, "f": f} # Plot the data axis = [0, 0.5, -0.0, 1.05] num = c.next_fig_num(close) fig = plt.figure(figsize=(10.25, 3), num=num) fStyle = (0,(1,1)) for row in range(2): for col in range(3): country = countries[col + row*3] sub_p_data = p_data[country] Z_cases = sub_p_data["cases"] Z_deaths = sub_p_data["deaths"] f = sub_p_data["f"] ax0 = plt.subplot2grid((2, 3), (row, col), colspan=1) ax0.plot(np.array([1/7, 1/7]), np.array([-999, 999]), '#bbbbbb', linewidth=1.0, linestyle=fStyle) ax0.plot(np.array([2/7, 2/7]), np.array([-999, 999]), '#bbbbbb', linewidth=1.0, linestyle=fStyle) ax0.plot(np.array([3/7, 3/7]), np.array([-999, 999]), '#bbbbbb', linewidth=1.0, linestyle=fStyle) ax0.plot(f, Z_cases, label="cases", linewidth=1.25) ax0.plot(f, Z_deaths, label="deaths", linewidth=1.25, linestyle=(0,(7,1))) ax0.set(title=country) ax0.title.set_size(10) ax0.get_xaxis().set_tick_params(direction='in') ax0.get_yaxis().set_tick_params(direction='in') ax0.axis(axis) if row == 1: ax0.set(xlabel='frequency [1/day]') else: ax0.set_xticklabels('') if col == 0: ax0.set(ylabel='magnitude') else: ax0.set_yticklabels('') if (row, col) == (0, 2): ax0.legend(bbox_to_anchor=(1.05, 1.3), loc='upper right', prop={'size': 9}, handlelength=2, framealpha=0.92) plt.tight_layout() if show: plt.show(block=False) if save: c.save_fig(fig, file_names[0])
def main(close=True, show=True, save=False, file_names=("Fig6.pdf", "Fig7.pdf", "Fig8.pdf",)): """Plots to be used in the paper.""" print(f"\nRunning module \"{__name__}\" ...") deaths = c.get_data("deaths", "US") deaths_padded, pad_sz = c.extrapolate(deaths) m_ave = seven_day_ave_manual(deaths_padded)[pad_sz-3:-(pad_sz-3)] # moving average wp, ws = 1/9, 1/8 y_el_1 = ellip_bf(deaths_padded, wp, ws)[pad_sz:-pad_sz] # elliptic H = ellip_spec(wp, ws, 1024) y_fft_1 = c.apply_spectrum(deaths_padded, H)[pad_sz:-pad_sz] # FFT wp, ws = 1/21, 1/19 y_el_2 = ellip_bf(deaths_padded, wp, ws)[pad_sz:-pad_sz] # elliptic H = ellip_spec(wp, ws, 1024) y_fft_2 = c.apply_spectrum(deaths_padded, H)[pad_sz:-pad_sz] # FFT start = 100 print("plots #1, #2, and #3 begin on date: %s" % c.ind2datetime(start)) y_lables = lambda x, p: "%.1fk" % (x/1000) x = np.arange(0, max(deaths[start:].shape), 1) dz = np.zeros(len(x)) num = c.next_fig_num(close) fig1, (ax1) = plt.subplots(1, 1, figsize=(5, 3), num=num) ax1.fill_between(x, deaths[start:], dz, alpha=0.1, color="#000000", label="daily deaths") ax1.plot(x, m_ave[start:], linewidth=1.25, label="moving average") ax1.set(xlabel='time [days]', ylabel='daily new deaths') ax1.get_yaxis().set_major_formatter(ticker.FuncFormatter(y_lables)) ax1.grid(True, alpha=0.2) ax1.axis([min(x), max(x), 0, 2500]) ax1.legend(loc='upper right', prop={'size': 9}, handlelength=2) plt.tight_layout() y_lables = lambda x, p: "%.1fk" % (x/1000) x = np.arange(0, max(deaths[start:].shape), 1) dz = np.zeros(len(x)) num += 1 fig2, (ax2) = plt.subplots(1, 1, figsize=(5, 3), num=num) ax2.fill_between(x, deaths[start:], dz, alpha=0.1, color="#000000", label="daily deaths") ax2.plot(x, y_el_1[start:], linewidth=1.25, label="elliptic low-pass #1", linestyle=(0,(2,1))) ax2.plot(x, y_fft_1[start:], linewidth=1.25, label="FFT low-pass #1", linestyle=(0,(9,9))) ax2.set(xlabel='time [days]', ylabel='daily new deaths') ax2.get_yaxis().set_major_formatter(ticker.FuncFormatter(y_lables)) ax2.grid(True, alpha=0.2) ax2.axis([min(x), max(x), 0, 2500]) ax2.legend(loc='upper right', prop={'size': 9}, handlelength=2) plt.tight_layout() y_lables = lambda x, p: "%.1fk" % (x/1000) x = np.arange(0, max(deaths[start:].shape), 1) dz = np.zeros(len(x)) num += 1 fig4, (ax4) = plt.subplots(1, 1, figsize=(5, 3), num=num) ax4.fill_between(x, deaths[start:], dz, alpha=0.1, color="#000000", label="daily deaths") ax4.plot(x, y_el_2[start:], linewidth=1.25, label="elliptic low-pass #2", linestyle=(0,(2,1))) ax4.plot(x, y_fft_2[start:], linewidth=1.25, label="FFT low-pass #2", linestyle=(0,(9,9))) ax4.set(xlabel='time [days]', ylabel='daily new deaths') ax4.get_yaxis().set_major_formatter(ticker.FuncFormatter(y_lables)) ax4.grid(True, alpha=0.2) ax4.axis([min(x), max(x), 0, 2500]) ax4.legend(loc='upper right', prop={'size': 9}, handlelength=2) plt.tight_layout() if show: plt.show(block=False) if save: c.save_fig(fig1, file_names[0]) c.save_fig(fig2, file_names[1]) c.save_fig(fig4, file_names[2])
def main(close=True, show=True, save=False, rt="deaths", region="global", country="Brazil", state=None, file_names=("Fig2.pdf", )): """time segment FFT analysis. keyword args close: close plots (boolean) show: show plots (boolean) save: save plots (boolean) rt: record type ("deaths" or "cases") region: global or US country: country name state: name of US State returns None """ print(f"\nRunning module \"{__name__}\" ...") start = 35 data = c.get_data(rt, region, country=country, state=state) data = data[start:] data_d_dt = c.deriv_fft(data) winSz = 25 print("time-spectrum start date: %s" % (c.ind2datetime(start))) print("initial window center: %s" % (c.ind2datetime(start + winSz / 2))) print("final window center: %s" % (c.ind2datetime(start + len(data) - 1 - winSz / 2))) print("sliding window size: %d" % (winSz)) N = 1024 # % pts in FFT numSamps = len(data) numHops = numSamps - winSz # 1 sample hops (sliding window) # set frequency range used for plotting minFreq = 0.0 maxFreq = 0.5 minFreq_ind = int(N * minFreq + 0.5) maxFreq_ind = int(N * maxFreq + 0.5) # set frequency range used for normnalization normCutMinFreq = 0.1 normCutMaxFreq = 0.5 normCutMinFreq_ind = int(N * normCutMinFreq + 0.5) normCutMaxFreq_ind = int(N * normCutMaxFreq + 0.5) Z = np.zeros([numHops, maxFreq_ind - minFreq_ind]) Z_hanning = np.zeros([numHops, maxFreq_ind - minFreq_ind]) Z_d_dt = np.zeros([numHops, maxFreq_ind - minFreq_ind]) b_start = 0 b_stop = winSz for n in range(numHops): xr = data[b_start:b_stop] X = np.fft.fft(xr, n=N) / N X = np.abs(X[:N // 2]) Z[n] = X[minFreq_ind:maxFreq_ind] / np.max( X[normCutMinFreq_ind:normCutMaxFreq_ind]) xr = data[b_start:b_stop] X = np.fft.fft(xr * np.hanning(winSz), n=N) / N X = np.abs(X[:N // 2]) Z_hanning[n] = X[minFreq_ind:maxFreq_ind] / np.max( X[normCutMinFreq_ind:normCutMaxFreq_ind]) xr = data_d_dt[b_start:b_stop] X = np.fft.fft(xr, n=N) / N X = np.abs(X[:N // 2]) Z_d_dt[n] = X[minFreq_ind:maxFreq_ind] / np.max( X[normCutMinFreq_ind:normCutMaxFreq_ind]) b_start += 1 b_stop += 1 # clip values that exceed unity. Z = np.clip(Z, 0, 1) Z_hanning = np.clip(Z_hanning, 0, 1) Z_d_dt = np.clip(Z_d_dt, 0, 1) # interp = None # smallest size interp = 'sinc' colors = cm.Blues_r # colors = cm.magma # largest size, percetual color map # colors = cm.gray # smallest size xMin = winSz * 0.5 xMax = winSz * 0.5 + Z.shape[0] num = c.next_fig_num(close) fig = plt.figure(figsize=(10.25, 2.3), num=num) # -------------------------------------------------------------- ax0 = plt.subplot2grid((1, 3), (0, 0)) ax0.imshow(np.flipud(Z.transpose(1, 0)), interpolation=interp, cmap=colors, extent=(xMin, xMax, minFreq, maxFreq), aspect='auto') ax0.set(xlabel='time [days]', title="Square Window", ylabel='frequency [1/day]') ax0.title.set_size(10) ax0.yaxis.set_major_locator(plt.MultipleLocator(0.1)) # -------------------------------------------------------------- ax1 = plt.subplot2grid((1, 3), (0, 1)) ax1.imshow(np.flipud(Z_hanning.transpose(1, 0)), interpolation=interp, cmap=colors, extent=(xMin, xMax, minFreq, maxFreq), aspect='auto') ax1.set(xlabel='time [days]', title="Hanning Window") ax1.title.set_size(10) ax1.set_yticklabels('') ax1.tick_params(axis=u'y', which=u'both', length=0) # -------------------------------------------------------------- ax2 = plt.subplot2grid((1, 3), (0, 2)) ax2.imshow(np.flipud(Z_d_dt.transpose(1, 0)), interpolation=interp, cmap=colors, extent=(xMin, xMax, minFreq, maxFreq), aspect='auto') ax2.set(xlabel='time [days]', title="Square Window of Derivative") ax2.title.set_size(10) ax2.set_yticklabels('') ax2.tick_params(axis=u'y', which=u'both', length=0) plt.tight_layout() if show: plt.show(block=False) if save: c.save_fig(fig, file_names[0])