def main(): # implementation of a particle filter for robot pose estimation print "Reading landmark positions" landmarks = read_world("../data/world.dat") print "Reading sensor data" sensor_readings = read_sensor_data("../data/sensor_data.dat") #initialize the particles map_limits = [-1, 12, 0, 10] particles = initialize_particles(700, map_limits) #run particle filter for timestep in range(len(sensor_readings) / 2): #plot the current state plot_state(particles, landmarks, map_limits) #predict particles by sampling from motion model with odometry info new_particles = sample_motion_model( sensor_readings[timestep, 'odometry'], particles) #calculate importance weights according to sensor model weights = eval_sensor_model(sensor_readings[timestep, 'sensor'], new_particles, landmarks) #resample new particle set according to their importance weights particles = resample_particles(new_particles, weights) plt.show('hold')
def main(): # implementation of an extended Kalman filter for robot pose estimation print("Reading landmark positions") landmarks = read_world("../data/world.dat") print("Reading sensor data") sensor_readings = read_sensor_data("../data/sensor_data.dat") #initialize belief mu = [0.0, 0.0, 0.0] sigma = np.array([[1.0, 0.0, 0.0],\ [0.0, 1.0, 0.0],\ [0.0, 0.0, 1.0]]) map_limits = [-1, 12, -1, 10] #run kalman filter for timestep in range(len(sensor_readings) // 2): #plot the current state plot_state(mu, sigma, landmarks, map_limits) #perform prediction step mu, sigma = prediction_step(sensor_readings[timestep, 'odometry'], mu, sigma) #perform correction step mu, sigma = correction_step(sensor_readings[timestep, 'sensor'], mu, sigma, landmarks) plt.show('hold')
def main(): print("Reading landmark positions") landmarks = read_world("src/fastSLAM_data/world.dat") print("Reading sensor data") sensor_readings = read_sensor_data("src/fastSLAM_data/sensor_data.dat") #plot preferences, interactive plotting mode plt.axis([-1, 12, 0, 10]) plt.ion() plt.show() num_particles = 100 num_landmarks = len(landmarks) #create particle set particles = initialize_particles(num_particles, num_landmarks) #run FastSLAM for timestep in range(int(len(sensor_readings) / 2)): #predict particles by sampling from motion model with odometry info sample_motion_model(sensor_readings[timestep, 'odometry'], particles) #evaluate sensor model to update landmarks and calculate particle weights eval_sensor_model(sensor_readings[timestep, 'sensor'], particles) #plot filter state plot_state(particles, landmarks) #calculate new set of equally weighted particles particles = resample_particles(particles) plt.show('hold')
def main(): # implementation of a particle filter for robot pose estimation print("Reading landmark positions") #add random seed for generating comparable pseudo random numbers np.random.seed(123) #plot preferences, interactive plotting mode #plt.axis([-1, 12, 0, 10]) plt.ion() plt.show() #{1: [2.0, 1.0], 2: [0.0, 4.0], 3: [2.0, 7.0], 4: [9.0, 2.0], 5: [10.0, 5.0],...} landmarks = read_world("../data/world.dat") print("Reading sensor data") sensor_readings = read_sensor_data("../data/sensor_data.dat") #initialize the particles map_limits = [-1, 12, 0, 10] pf = ParticleFilter(1000, map_limits, landmarks) #run particle filter for timestep in range(len(sensor_readings) // 2): #plot the current state pf.visualization(sensor_readings[timestep, 'odometry']) #predict particles by sampling from motion model with odometry info pf.predict(sensor_readings[timestep, 'odometry']) #calculate importance weights according to sensor model pf.update(sensor_readings[timestep, 'sensor']) #resample new particle set according to their importance weights pf.resample_particles()
def main(): print "Reading landmark positions" landmarks = read_world("../map/landmarks_sim.dat") print "Reading sensor data" sensor_readings = read_sensor_data("../map/sensor_data_car.dat") print "Reading Ground truth Odometry" odom_readings = read_odom("../map/odom_trajectory_car.dat") # initialize the particles map_limits = [0, 320, 0, 350] particles = initialize_particles(args.particles, map_limits) curr_pose_x = [] curr_pose_y = [] cov_noise = np.array([[0.01, 0, 0],[0,0.01,0],[0,0,0.01]]) vis = Visualization(landmarks, map_limits, sensor_readings, odom_readings) for timestep in range(len(sensor_readings) / 2): # plot_state(particles, landmarks, map_limits) # curr_mean = mean_pose(particles) # curr_pose_x.append(curr_mean[0]) # curr_pose_y.append(curr_mean[1]) # plot_trajectories_v3( sensor_readings[timestep, 'sensor'], curr_mean ,landmarks, map_limits) new_particles = sample_motion_model(sensor_readings[timestep, 'odometry'], particles) curr_mean = mean_pose(new_particles) curr_pose_x.append(curr_mean[0]) curr_pose_y.append(curr_mean[1]) vis.robot_environment(timestep, new_particles, curr_mean) # predict particles by sampling from motion model with odometry info # if timestep==0: # new_particles =particles # errors = data_association(sensor_readings[timestep, 'sensor'], new_particles, particles, landmarks, args.DA, cov_noise, sensor_readings[timestep, 'odometry']) # else: # errors = data_association(sensor_readings[timestep, 'sensor'], new_particles, particles, landmarks, args.DA, cov_noise, sensor_readings[timestep, 'odometry']) weights = eval_sensor_model(sensor_readings[timestep, 'sensor'], new_particles, landmarks) # weights = weighting_model(errors) particles = resample_particles(new_particles, weights) print("Current TimeStep: ", timestep) raw_input("Press Enter to continue...") plot_trajectories(odom_readings, curr_pose_x,curr_pose_y ,landmarks, map_limits) plot_on_maps(curr_pose_x, curr_pose_y) plt.show('hold')
def main(): # implementation of a particle filter for robot pose estimation # Read landmarks ## The returned dict contains a list of landmarks each with the ## following information: {id, [x, y]} print("Reading landmark positions") landmarks = read_world("../data/world.dat") # Read sensor data ## The data contains {odometry,sensor} data accessed as: ## odometry_data = sensor_readings[timestep, 'odometry'] ## sensor_data = sensor_readings[timestep, 'sensor'] print("Reading sensor data") sensor_readings = read_sensor_data("../data/sensor_data.dat") #initialize the particles map_limits = [-1, 12, 0, 10] particles = initialize_particles(1000, map_limits) #run particle filter for timestep in range(int(len(sensor_readings) / 2)): #plot the current state plot_state(particles, landmarks, map_limits) #predict particles by sampling from motion model with odometry info new_particles = sample_motion_model( sensor_readings[timestep, 'odometry'], particles) ##print(f'new_particles: \n{new_particles}') #calculate importance weights according to sensor model weights = eval_sensor_model(sensor_readings[timestep, 'sensor'], new_particles, landmarks) ##print(f'weights: {weights}') #resample new particle set according to their importance weights particles = resample_particles(new_particles, weights) plt.show()
def mainPA(): print("--- efve Reading landmark positions") landmarks = read_world("../data/world.dat") print("Reading sensor data") sensor_readings = read_sensor_data("../data/sensor_data.dat") num_particles = 10 num_landmarks = len(landmarks) #create particle set particles = initialize_particles(num_particles, num_landmarks) bestParticle = None #run FastSLAM for timestep in range(int(len(sensor_readings) / 2)): #predict particles by sampling from motion model with odometry info sample_motion_model(sensor_readings[timestep, 'odometry'], particles) #evaluate sensor model to update landmarks and calculate particle weights eval_sensor_model(sensor_readings[timestep, 'sensor'], particles) #plot filter state #plot_state(particles, landmarks) bestParticle = best_particle(particles) #calculate new set of equally weighted particles particles = resample_particles(particles) #plt.show() #print('real word data landmarks ') #print(landmarks) #print('Best particle estimate ') #print(bestParticle['landmarks']) rmse = RMSE(bestParticle['landmarks'], landmarks) print('rmse : ', rmse)
def main(): # implementation of a particle filter for robot pose estimation print("Reading landmark positions") landmarks = read_world("src/pf_data/world.dat") print("Reading sensor data") sensor_readings = read_sensor_data("src/pf_data/sensor_data.dat") #initialize the particles map_limits = [-1, 12, 0, 10] particles = initialize_particles(1000, map_limits) #add random seed for generating comparable pseudo random numbers np.random.seed(123) #plot preferences, interactive plotting mode plt.axis([-1, 12, 0, 10]) plt.ion() plt.show() #run particle filter for timestep in range(int(len(sensor_readings)/2)): #plot the current state plot_state(particles, landmarks, map_limits) #predict particles by sampling from motion model with odometry info new_particles = sample_motion_model(sensor_readings[timestep,'odometry'], particles) #calculate importance weights according to sensor model weights = eval_sensor_model(sensor_readings[timestep, 'sensor'], new_particles, landmarks) #resample new particle set according to their importance weights particles = resample_particles(new_particles, weights) plt.show('hold')
def main(): # implementation of an extended Kalman filter for robot pose estimation print("Reading landmark positions") landmarks = read_world("../data/world.dat") print("Reading sensor data") sensor_readings = read_sensor_data("../data/sensor_data.dat") #initialize belief mu = np.array([0.0, 0.0, 0.0]) sigma = np.array([[1.0, 0.0, 0.0],\ [0.0, 1.0, 0.0],\ [0.0, 0.0, 1.0]]) map_limits = [-1, 12, -1, 10] motion_model = MotionModel() observation_model = ObservationModel() Localization = EKF(motion_model, observation_model) #run kalman filter for timestep in range(len(sensor_readings) // 2): #plot the current state plot_state(mu, sigma, landmarks, map_limits) #perform prediction step odometry = sensor_readings[timestep, 'odometry'] u = np.array([odometry['r1'], odometry['t'], odometry['r2']]) # delta_rot1, delta_trans, delta_rot2 mu, sigma = Localization(mu, sigma, u, sensor_readings[timestep, 'sensor'], landmarks) plt.show('hold')
def initialize_particles_landmarks(self, num_particles): print "Reading landmark positions" landmarks = read_world("../map/landmarks_sim.dat") # randomly initialize the particles inside the map limits particles = [] if self.init_mode == 'rand' and self.data_type == 'car': for i in range(num_particles): particle = dict() # draw x,y and theta coordinate from uniform distribution inside map limits particle['x'] = np.random.uniform(self.map_limits[0], self.map_limits[1]) particle['y'] = np.random.uniform(self.map_limits[2], self.map_limits[3]) particle['theta'] = np.random.uniform(-np.pi, np.pi) particle['errors'] = [] particle['weight'] = 1.0 / num_particles particles.append(particle) if self.init_mode == 'set' and self.data_type == 'car': for i in range(num_particles): particle = dict() # draw x,y and theta coordinate from car starting position """zed straight""" #particle['x'], particle['y'] = 177.03757970060997,72.711216426459998 #particle['theta'] = 1.3540745849092297 # ([106.67983715984272, 259.16103693684363], -1.4253166861206177) """pg loop""" # particle['x'], particle['y'] = 106.67983715984272, 259.16103693684363 # particle['theta'] = -1.4253166861206177 """pg corner""" particle['x'], particle[ 'y'] = 126.36463623279457, 197.40703201640946 particle['theta'] = 3.077658478440323 """zed loop""" # particle['x'], particle['y'] = 112.21525525427808, 249.03124386039127 # particle['theta'] = -0.8590560204044709 particle['errors'] = [] particle['weight'] = 1.0 / num_particles particles.append(particle) if self.init_mode == 'rand' and self.data_type == 'sim': for i in range(num_particles): particle = dict() particle['x'] = np.random.uniform(self.map_limits[0], self.map_limits[1]) particle['y'] = np.random.uniform(self.map_limits[2], self.map_limits[3]) particle['theta'] = np.random.uniform(-np.pi, np.pi) particle['errors'] = [] particle['weight'] = 1.0 / num_particles particles.append(particle) if self.init_mode == 'set' and self.data_type == 'sim': for i in range(num_particles): particle = dict() # Initial Position known particle['x'] = 160.52209863 particle['y'] = 7.05611139535 particle['theta'] = 0 particle['errors'] = [] particle['weight'] = 1.0 / num_particles particles.append(particle) return particles, landmarks
""" COVID-19 case data is retrieved from Johns Hopkins CSSE: https://github.com/CSSEGISandData/COVID-19 """ #Avoid re-reading case data if it's already stored in memory try: cases except: if read_from_local == True: cases = pickle.load(open('cases_world.pickle','rb')) dates = cases['dates'] del cases['dates'] else: output = read_data.read_world(worldometers=worldometers) dates = output['dates'] cases = output['cases'] #======================================================================================================== # Create plot based on type #======================================================================================================== #Create figure fig,ax = plt.subplots(figsize=(9,6),dpi=125) #Total count key_0 = [k for k in cases.keys()][0] total_count = np.array([0.0 for i in cases[key_0]['date']]) total_count_row = np.array([0.0 for i in cases[key_0]['date']])
def plot_chart(plot_type=None): #======================================================================================================== # User-defined settings #======================================================================================================== #Whether to save image or display. "directory_path" string is ignored if setting==False. save_image = { 'setting': True, 'directory_path': "/Users/Steve/Desktop/UFlorida/3-Code/COVID/COVID-19" } #What to plot (confirmed, confirmed_normalized, deaths, recovered, active, daily) if plot_type == None: plot_type = "recovered" #Include Mainland China? mainland_china = True #Plot total numbers? plot_total = True #Over how many days should the doubling rate be calculated? lag_days = 7 #Additional settings settings = { 'log_y': True, #Use logarithmic y-axis? 'condensed_plot': True, #Condensed plot? (small dots and narrow lines) 'highlight_country': 'us', #Highlight country? 'number_of_countries': 20, #Limit number of countries plotted? } #======================================================================================================== # Get COVID-19 case data #======================================================================================================== #Z-Order: # 2-highlighted trend # 3-total trends # 4-country dots # 5-highlighted country dot # 6-total dots """ COVID-19 case data is retrieved from Johns Hopkins CSSE: https://github.com/CSSEGISandData/COVID-19 """ #Avoid re-reading case data if it's already stored in memory try: cases except: print("--> Reading in COVID-19 case data from Johns Hopkins CSSE") output = read_data.read_world() dates = output['dates'] cases = output['cases'] #======================================================================================================== # Create plot based on type #======================================================================================================== max_value = 0 max_doubling = -6 min_doubling = 6 lag_index = -lag_days - 1 highlighted_series = [] top_cases = [{'cases': 0}] * 5 top_neg_cases = [{'cases': 0}] * 5 top_rates = [{'rate': -20}] * 10 top_neg_rates = [{'rate': 20}] * 10 country_text_color = 'k' #Create figure fig, ax = plt.subplots(figsize=(9, 6), dpi=125) #Total count total_count = np.array([0.0 for i in cases['mainland china']['date']]) total_count_raw = np.array([0.0 for i in cases['mainland china']['date']]) #Iterate through every region sorted_keys = [ y[1] for y in sorted([(np.nanmax(cases[x][plot_type]), x) for x in cases.keys()]) ][::-1] sorted_value = [ y[0] for y in sorted([(np.nanmax(cases[x][plot_type]), x) for x in cases.keys()]) ][::-1] for idx, (key, value) in enumerate(zip(sorted_keys, sorted_value)): end_day = cases[key][plot_type][-1] start_day = cases[key][plot_type][lag_index] day_after_start = cases[key][plot_type][lag_index + 1] doubling_rate = 999 inverse_doubling_rate = 999 if end_day > 1: if start_day > 0 and end_day != start_day and start_day != day_after_start: doubling_rate = lag_days * np.log(2) / np.log( end_day / start_day) inverse_doubling_rate = 1 / doubling_rate #Special handling for China if mainland_china == False and key == 'mainland china': continue #Total count if key != 'mainland china': total_count_raw += np.array(cases[key][plot_type]) total_count += np.array(cases[key][plot_type]) #Plot countries, including highlighted country if applicable. if inverse_doubling_rate != 999: if 'highlight_country' in settings.keys( ) and settings['highlight_country'].lower() == key.lower(): highlight_color = 'red' highlight_key = f"{key.title()}" if key.lower() == 'us' or key.lower() == 'uk': highlight_key = f"{key.title().upper()}" highlight_doubling = f"{doubling_rate:.1f}" highlight_total = f"{end_day}" kwargs = {'zorder': 5, 'color': highlight_color} ax.scatter(inverse_doubling_rate, end_day, **kwargs) highlighted_series = cases[key][plot_type] else: country_color = 'gray' kwargs = {'zorder': 6, 'color': country_color} ax.scatter(inverse_doubling_rate, end_day, **kwargs) # Gather countries with top 5 cases, but rate is negative. if end_day > top_neg_cases[-1][ 'cases'] and inverse_doubling_rate < 0: label = { 'rate': inverse_doubling_rate, 'cases': end_day, 'name': key.title() + ' ' } if label['name'] == ' Us' or label['name'] == ' Uk': label['name'] = label['name'].upper() top_neg_cases.insert(0, label) top_neg_cases.pop(-1) if len([i for i in top_neg_cases if i['cases'] == 0]) == 0: top_neg_cases = sorted(top_neg_cases, key=itemgetter('cases'), reverse=False) # Gather countries with top 5 cases, but rate is positive. if end_day > top_cases[-1]['cases'] and inverse_doubling_rate > 0: label = { 'rate': inverse_doubling_rate, 'cases': end_day, 'name': ' ' + key.title() } if label['name'] == ' Us' or label['name'] == ' Uk': label['name'] = label['name'].upper() top_cases.insert(0, label) top_cases.pop(-1) if len([i for i in top_cases if i['cases'] == 0]) == 0: top_cases = sorted(top_cases, key=itemgetter('cases'), reverse=True) # Gather countries with top 5 doubling rates if inverse_doubling_rate > top_rates[-1]['rate'] and end_day > 100: label = { 'rate': inverse_doubling_rate, 'cases': end_day, 'name': ' ' + key.title() } if label['name'] == ' Us' or label['name'] == ' Uk': label['name'] = label['name'].upper() top_rates.insert(0, label) top_rates.pop(-1) if len([i for i in top_rates if i['rate'] == 0]) == 0: top_rates = sorted(top_rates, key=itemgetter('rate'), reverse=True) # Gather countries with bottom 5 doubling rates (cases going down) if inverse_doubling_rate < top_neg_rates[-1][ 'rate'] and end_day > 100: label = { 'rate': inverse_doubling_rate, 'cases': end_day, 'name': key.title() + ' ' } if label['name'] == ' Us' or label['name'] == ' Uk': label['name'] = label['name'].upper() top_neg_rates.insert(0, label) top_neg_rates.pop(-1) if len([i for i in top_neg_rates if i['rate'] == 0]) == 0: top_neg_rates = sorted(top_neg_rates, key=itemgetter('rate'), reverse=False) """ #Label countries reducing totals if plot_type=='active' and doubling_rate <= 0: name = key.title()+" " kwargs = {'zorder':7, 'color':country_text_color, 'ha':'right', 'va':'center', 'family':'monospace', 'fontsize':6 } ax.text(inverse_doubling_rate,end_day,name,**kwargs) """ #Output stats to terminal print( f"{key.title()}\t{start_day}->{end_day}\t{doubling_rate:.2f}") #Store values useful for the plot axes. max_value = max(max_value, end_day) max_doubling = max(max_doubling, inverse_doubling_rate) min_doubling = min(min_doubling, inverse_doubling_rate) #Label countries with top 5 cases for case in top_cases: print(case) for case in top_neg_cases: print(case) kwargs = { 'zorder': 7, 'color': country_text_color, 'ha': 'left', 'va': 'center', 'family': 'monospace', 'fontsize': 6 } neg_kwargs = { 'zorder': 7, 'color': country_text_color, 'ha': 'right', 'va': 'center', 'family': 'monospace', 'fontsize': 6 } for i in range(len(top_cases)): plt.text(top_cases[i]['rate'], top_cases[i]['cases'], top_cases[i]['name'], **kwargs) if plot_type == 'active': for i in range(len(top_neg_cases)): plt.text(top_neg_cases[i]['rate'], top_neg_cases[i]['cases'], top_neg_cases[i]['name'], **neg_kwargs) #Label countries with top 5 doubling rates for rate in top_rates: print(rate) for rate in top_neg_rates: print(rate) for i in range(len(top_rates)): plt.text(top_rates[i]['rate'], top_rates[i]['cases'], top_rates[i]['name'], **kwargs) if plot_type == 'active': plt.text(top_neg_rates[i]['rate'], top_neg_rates[i]['cases'], top_neg_rates[i]['name'], **neg_kwargs) print(f"\nRange: {1/min_doubling:.2f} to {1/max_doubling:.2f} days") #Calculate highlighted country running doubling rate if 'highlight_country' in settings.keys(): highlighted_series_doubling_rate = [] length_hs = len(highlighted_series) - lag_days for i in range(length_hs): if highlighted_series[ i + lag_days] > 100 and highlighted_series[i] > 0: highlighted_series_doubling_rate.append( 1 / (lag_days * np.log(2) / np.log(highlighted_series[i + lag_days] / highlighted_series[i]))) #Plot line of highlighted series doubling rate history if len(highlighted_series_doubling_rate) > 6: kwargs = { 'zorder': 2, 'color': highlight_color, 'lw': 1, 'markevery': [-7], 'ms': 2 } plt.plot( highlighted_series_doubling_rate, highlighted_series[-len(highlighted_series_doubling_rate):], '-o', **kwargs) #plt.plot(highlighted_series_doubling_rate,highlighted_series[-len(highlighted_series_doubling_rate):],'-o',lw=1,zorder=2,color=highlight_color,markevery=[-7],ms=2) hc_7 = True elif len(highlighted_series_doubling_rate) > 1: kwargs = {'zorder': 2, 'color': highlight_color, 'lw': 1} plt.plot( highlighted_series_doubling_rate, highlighted_series[-len(highlighted_series_doubling_rate):], **kwargs) #plt.plot(highlighted_series_doubling_rate,highlighted_series[-len(highlighted_series_doubling_rate):],lw=1,zorder=2,color=highlight_color) hc_7 = False else: hc_7 = False #Calculate world running doubling rate length = len(total_count) - lag_days total_running_doubling_rate = [] total_raw_running_doubling_rate = [] for i in range(length): if total_count_raw[i + lag_days] > 100: total_raw_running_doubling_rate.append( 1 / (lag_days * np.log(2) / np.log(total_count_raw[i + lag_days] / total_count_raw[i]))) if mainland_china == True: total_running_doubling_rate.append( 1 / (lag_days * np.log(2) / np.log(total_count[i + lag_days] / total_count[i]))) #Plot total count if plot_total == True: total_raw_doubling_rate = lag_days * np.log(2) / np.log( total_count_raw[-1] / total_count_raw[lag_index]) total_raw_inverse_doubling_rate = 1 / total_raw_doubling_rate total_raw_color = 'b' total_raw_doubling_title = f"{total_raw_doubling_rate:.1f}" total_raw_count_title = f"{int(total_count_raw[-1])}" kwargs = {'zorder': 6, 'color': total_raw_color} plt.scatter(total_raw_inverse_doubling_rate, total_count_raw[-1], **kwargs) #plt.scatter(total_raw_inverse_doubling_rate,total_count_raw[-1],zorder=6,color=total_raw_color) kwargs = { 'zorder': 3, 'lw': 1, 'color': total_raw_color, 'markevery': [-7], 'ms': 2 } plt.plot(total_raw_running_doubling_rate, total_count_raw[-len(total_raw_running_doubling_rate):], "-o", **kwargs) #plt.plot(total_raw_running_doubling_rate,total_count_raw[-len(total_raw_running_doubling_rate):],"-o",lw=1,zorder=3,color=total_raw_color,markevery=[-7],ms=2) if mainland_china == True: total_doubling_rate = lag_days * np.log(2) / np.log( total_count[-1] / total_count[lag_index]) total_inverse_doubling_rate = 1 / total_doubling_rate total_color = 'k' total_doubling_title = f"{total_doubling_rate:.1f}" total_count_title = f"{int(total_count[-1])}" kwargs = {'zorder': 6, 'color': total_color} plt.scatter(total_inverse_doubling_rate, total_count[-1], **kwargs) #plt.scatter(total_inverse_doubling_rate,total_count[-1],zorder=6,color=total_color) kwargs = { 'zorder': 3, 'lw': 1, 'color': total_color, 'markevery': [-7], 'ms': 2 } plt.plot(total_running_doubling_rate, total_count[-len(total_running_doubling_rate):], ":o", **kwargs) #plt.plot(total_running_doubling_rate,total_count[-len(total_running_doubling_rate):],":o",lw=1,zorder=3,color=total_color,markevery=[-7],ms=2) #Store values useful for the plot. max_value = max(max_value, total_count[-1]) max_doubling = max( max_doubling, 1 / (1 * np.log(2) / np.log(total_count[-1] / total_count[-2]))) min_doubling = min( min_doubling, 1 / (1 * np.log(2) / np.log(total_count[-1] / total_count[-2]))) #Plot grid and legend plt.grid() legend_title = f"Calculated from change\nbetween {cases[key]['date'][lag_index]:%b %d} and {cases[key]['date'][-1]:%b %d}" #Blank entries for legend. if 'highlight_country' in settings.keys(): plt.plot( [], [], '-o', color=highlight_color, label= f"{highlight_key} & trend after 100 cases\n Time-{highlight_doubling} days, Total-{highlight_total}" ) if plot_total == True: plt.plot( [], [], '-o', label= f'World Total (no China) & trend\n Time-{total_raw_doubling_title} days, Total-{int(total_raw_count_title)}', color=total_raw_color) if mainland_china == True: plt.plot( [], [], ':o', label= f'World Total & trend\n Time-{total_doubling_title} days, Total-{int(total_count_title)}', color=total_color) plt.scatter(np.nan, np.nan, color=country_color, label="Countries") dot_l = False if 'highlight_country' in settings.keys() and hc_7 == True: p_hc = plt.scatter([], [], color=highlight_color, s=2) if plot_total == True: p_tc = plt.scatter([], [], color=total_color, s=2) if mainland_china == True: #print("hc,tc,mc") p_tc_raw = plt.scatter([], [], color=total_raw_color, s=2) dot_h = [(p_hc, p_tc_raw, p_tc)] dot_l = ["Small dots were 7 days ago"] else: #print("hc,tc") dot_h = [(p_hc, p_tc)] dot_l = ["Small dots were 7 days ago"] else: #print("hc") dot_h = [(p_hc)] dot_l = ["Small dot was 7 days ago"] else: if plot_total == True: p_tc = plt.scatter([], [], color=total_color, s=2) if mainland_china == True: #print("tc,mc") p_tc_raw = plt.scatter([], [], color=total_raw_color, s=2) dot_h = [(p_tc_raw, p_tc)] dot_l = ["Small dots were 7 days ago"] else: #print("tc") dot_h = [(p_tc)] dot_l = ["Small dots were 7 days ago"] handles, labels = ax.get_legend_handles_labels() if dot_l: handles = handles + dot_h labels = labels + dot_l kwargs = {'loc': 2, 'prop': {'size': 8}} if plot_type != 'active': kwargs['loc'] = 1 plt.legend(handles, labels, title=legend_title, handler_map={ tuple: HandlerTuple(ndivide=None) }, **kwargs).set_zorder(51) #Format x-ticks xticks = [ 1 / -0.5, 1 / -1, 1 / -2, 1 / -3, 1 / -4, 1 / -5, 1 / -6, 1 / -7, 0, 1 / 7, 1 / 6, 1 / 5, 1 / 4, 1 / 3, 1 / 2, 1 / 1, 1 / 0.5 ] xtick_labels = [ "Halving\nEvery\nHalf-day", "Halving\nEvery\nDay", "Halving\nEvery\n2 Days", "Halving\nEvery\n3 Days", "Halving\nEvery\n4 Days", "Halving\nEvery\n5 Days", "Halving\nEvery\n6 Days", "Halving\nEvery\nWeek", "no\nchange", "Doubling\nEvery\nWeek", "Doubling\nEvery\n6 Days", "Doubling\nEvery\n5 Days", "Doubling\nEvery\n4 Days", "Doubling\nEvery\n3 Days", "Doubling\nEvery\n2 Days", "Doubling\nEvery\nDay", "Doubling\nEvery\nHalf-day" ] #Format x-axis if np.absolute(max_doubling) > np.absolute(min_doubling): left = -max_doubling - 0.1 right = max_doubling + 0.1 else: left = min_doubling - 0.1 right = -min_doubling + 0.1 if plot_type != "active": left = 0 if right < 0.333 or (left == 0 and right < 0.5): xticks = xticks[:5] + xticks[7:10] + xticks[12:] xtick_labels = xtick_labels[:5] + xtick_labels[7:10] + xtick_labels[12:] elif right < 0.5 or (left == 0 and right < 1): xticks = xticks[:4] + xticks[7:10] + xticks[13:] xtick_labels = xtick_labels[:4] + xtick_labels[7:10] + xtick_labels[13:] elif right < 1 or (left == 0 and right < 2): xticks = xticks[:3] + xticks[7:10] + xticks[14:] xtick_labels = xtick_labels[:3] + xtick_labels[7:10] + xtick_labels[14:] elif right < 2 or (left == 0 and right >= 2): xticks = xticks[:3] + xticks[7:10] + xticks[14:] xtick_labels = xtick_labels[:3] + [ xtick_labels[7], "", xtick_labels[9] ] + xtick_labels[14:] else: xticks = xticks[:3] + xticks[8] + xticks[6:] xtick_labels = xtick_labels[:3] + [""] + xtick_labels[6:] ax.set_xticks(xticks) ax.set_xticklabels(xtick_labels) plt.xlim(left, right) #Add logarithmic y-scale if 'log_y' in settings.keys() and settings['log_y'] == True: plt.yscale('log') y_locs, y_labels = plt.yticks() for i, loc in enumerate(y_locs): if loc == 1.e+00: y_labels[i] = "1" elif loc == 1.e+01: y_labels[i] = "10" elif loc == 1.e+02: y_labels[i] = "100" elif loc == 1.e+03: y_labels[i] = "1K" elif loc == 1.e+04: y_labels[i] = "10K" elif loc == 1.e+05: y_labels[i] = "100K" elif loc == 1.e+06: y_labels[i] = "1M" elif loc == 1.e+07: y_labels[i] = "10M" elif loc == 1.e+08: y_labels[i] = "100M" elif loc == 1.e+09: y_labels[i] = "1B" elif loc == 1.e+10: y_labels[i] = "10B" plt.yticks(y_locs, y_labels) plt.ylim(bottom=1) if max_value < 10: plt.ylim(top=10) elif max_value < 100: plt.ylim(top=100) elif max_value < 1000: plt.ylim(top=1000) #1K elif max_value < 10000: plt.ylim(top=10000) elif max_value < 100000: plt.ylim(top=100000) elif max_value < 1000000: plt.ylim(top=1000000) #1M elif max_value < 10000000: plt.ylim(top=10000000) elif max_value < 100000000: plt.ylim(top=100000000) elif max_value < 1000000000: plt.ylim(top=1000000000) #1B elif max_value < 10000000000: plt.ylim(top=10000000000) #Plot death comparisons from historic plagues if plot_type == "deaths": historic_deaths = read_data.historic_deaths() for pandemic in historic_deaths: deaths = pandemic['deaths'] name = pandemic['name'] years = pandemic['year'] death_label = pandemic['label'] kwargs = { 'fontsize': 5, 'family': 'monospace', 'color': 'red', 'ha': 'left', 'va': 'center', 'clip_on': True } if deaths == 850 or deaths == 1100000: kwargs['va'] = 'bottom' label_text = f" {death_label}-{name}" plt.text(0, deaths, label_text, **kwargs) #Plot titles title_string = { 'confirmed': 'Doubling Time of Cumulative COVID-19 Confirmed Cases', 'deaths': 'Doubling Time of Cumulative COVID-19 Deaths', 'recovered': 'Doubling Time of Cumulative COVID-19 Recovered Cases', 'active': 'Doubling Time of Daily COVID-19 Active Cases', 'daily': 'Doubling Time of Daily COVID-19 New Cases', } add_title = "\n(Non-Mainland China)" if mainland_china == False else "" plt.title(f"{title_string.get(plot_type)} {add_title}", fontweight='bold', loc='left') if left == 0: xlabel_text = "<--slower increase\t\t\tfaster increase-->".expandtabs() else: xlabel_text = "<--faster decrease\t\t\tfaster increase-->".expandtabs() plt.xlabel(xlabel_text, fontweight='bold') plt.ylabel("Number of Cases", fontweight='bold') #Plot attribution plt.title( f'Data from Johns Hopkins CSSE\nPlot by Stephen Mullens @srmullens\nCode adapted from Tomer Burg @burgwx', loc='right', fontsize=6) if plot_type == "active": kwargs = { 'fontweight': 'bold', 'fontsize': 8, 'ha': 'right', 'va': 'top' } active_text = "\"Active\" cases = confirmed total - recovered - deaths" plt.text(0.99, 0.99, active_text, transform=ax.transAxes, **kwargs) if plot_type == 'deaths': kwargs = {'fontsize': 5, 'ha': 'left', 'va': 'bottom'} deaths_text_short = " Historic pandemic data\n " deaths_text = "\t\t\t\t\tis from: https://www.visualcapitalist.com/history-of-pandemics-deadliest/\n Deaths totals are often under debate. COVID-19 death totals are likely underestimates.".expandtabs( ) plt.text(0, 0.01, deaths_text, transform=ax.transAxes, **kwargs) kwargs['color'] = 'red' plt.text(0, 0.01, deaths_text_short, transform=ax.transAxes, **kwargs) #Show plot and close if save_image['setting'] == True: savepath = os.path.join(save_image['directory_path'], f"{plot_type}_doubling_world.png") plt.savefig(savepath, bbox_inches='tight') else: plt.show() plt.close() #Alert script is done print("Done!")
def plot_chart(plot_type=None): #======================================================================================================== # User-defined settings #======================================================================================================== #Whether to save image or display. "directory_path" string is ignored if setting==False. save_image = { 'setting': True, 'directory_path': "full_directory_path_here" } #What to plot (confirmed, deaths, recovered, active, daily) if plot_type == None: plot_type = "active" #Include Mainland China? mainland_china = True #Plot total numbers? plot_total = True #Additional settings settings = { 'log_y': True, #Use logarithmic y-axis? 'condensed_plot': True, #Condensed plot? (small dots and narrow lines) 'highlight_country': 'us', #Highlight country? 'number_of_countries': 20, #Limit number of countries plotted? } #======================================================================================================== # Get COVID-19 case data #======================================================================================================== """ COVID-19 case data is retrieved from Johns Hopkins CSSE: https://github.com/CSSEGISandData/COVID-19 """ #Avoid re-reading case data if it's already stored in memory try: cases except: print("--> Reading in COVID-19 case data from Johns Hopkins CSSE") output = read_data.read_world() dates = output['dates'] cases = output['cases'] #======================================================================================================== # Create plot based on type #======================================================================================================== max_value = 0 #Create figure fig, ax = plt.subplots(figsize=(9, 6), dpi=125) #Total count total_count = np.array([0.0 for i in cases['mainland china']['date']]) total_count_row = np.array([0.0 for i in cases['mainland china']['date']]) #Iterate through every region sorted_keys = [ y[1] for y in sorted([(cases[x][plot_type][-1], x) for x in cases.keys()]) ][::-1] sorted_value = [ y[0] for y in sorted([(cases[x][plot_type][-1], x) for x in cases.keys()]) ][::-1] for idx, (key, value) in enumerate(zip(sorted_keys, sorted_value)): #Special handling for China if mainland_china == False and key == 'mainland china': continue #Total count total_count += np.array(cases[key][plot_type]) if key != 'mainland china': total_count_row += np.array(cases[key][plot_type]) #Skip plotting if zero if value == 0: continue #How many countries to plot? lim = 20 if 'number_of_countries' in settings.keys(): lim = settings['number_of_countries'] - 1 if lim > 20: lim = 20 #Plot type if idx > lim: pass else: mtype = '--' zord = 2 if np.nanmax(cases[key][plot_type]) > np.percentile( sorted_value, 95): mtype = '-o' zord = 3 zord = 22 - idx #Handle US & UK titles loc = key.title() if key in ['us', 'uk']: loc = key.upper() #Handle narrow plot kwargs = { 'linewidth': 1.0, 'zorder': zord, 'label': f"{loc} ({cases[key][plot_type][-1]})" } if 'condensed_plot' in settings.keys( ) and settings['condensed_plot'] == True: mtype = '-o' kwargs['linewidth'] = 0.5 kwargs['ms'] = 2 #Highlight individual country if 'highlight_country' in settings.keys( ) and settings['highlight_country'].lower() == key.lower(): kwargs['linewidth'] = 2.0 if 'ms' in kwargs.keys(): kwargs['ms'] = 4 #Plot lines plt.plot(cases[key]['date'], cases[key][plot_type], mtype, **kwargs) max_value = max(max_value, max(cases[key][plot_type])) #Plot total count if plot_total == True: kwargs = { 'zorder': 50, 'label': f'Total ({int(total_count[-1])})', 'color': 'k', 'linewidth': 2 } plt.plot(cases[key]['date'], total_count, ':', **kwargs) if mainland_china == True: kwargs['zorder'] = 2 kwargs['label'] = f'Total-China ({int(total_count_row[-1])})' kwargs['color'] = 'b' plt.plot(cases[key]['date'], total_count_row, ':', **kwargs) max_value = max(max_value, max(total_count)) #Format x-ticks ax.set_xticks(cases[key]['date'][::7]) ax.set_xticklabels(cases[key]['date'][::7]) ax.xaxis.set_major_formatter(mdates.DateFormatter('%b\n%d')) #Plot grid and legend plt.grid() kwargs = { 'loc': 2, 'title': f"Top {settings['number_of_countries']} locations plotted", 'prop': { 'size': 8 } } plt.legend(**kwargs).set_zorder(51) #Plot title title_string = { 'confirmed': 'Cumulative COVID-19 Confirmed Cases', 'deaths': 'Cumulative COVID-19 Deaths', 'recovered': 'Cumulative COVID-19 Recovered Cases', 'active': 'Daily COVID-19 Active Cases', 'daily': 'Daily COVID-19 New Cases', } add_title = "\n(Non-Mainland China)" if mainland_china == False else "" plt.title(f"{title_string.get(plot_type)} {add_title}", fontweight='bold', loc='left') plt.xlabel("Date", fontweight='bold') plt.ylabel("Number of Cases", fontweight='bold') #Add logarithmic y-scale if 'log_y' in settings.keys() and settings['log_y'] == True: plt.yscale('log') y_locs, y_labels = plt.yticks() for i, loc in enumerate(y_locs): if loc == 1.e+00: y_labels[i] = "1" elif loc == 1.e+01: y_labels[i] = "10" elif loc == 1.e+02: y_labels[i] = "100" elif loc == 1.e+03: y_labels[i] = "1K" elif loc == 1.e+04: y_labels[i] = "10K" elif loc == 1.e+05: y_labels[i] = "100K" elif loc == 1.e+06: y_labels[i] = "1M" elif loc == 1.e+07: y_labels[i] = "10M" elif loc == 1.e+08: y_labels[i] = "100M" elif loc == 1.e+09: y_labels[i] = "1B" elif loc == 1.e+10: y_labels[i] = "10B" plt.yticks(y_locs, y_labels) plt.ylim(bottom=1) if max_value < 10: plt.ylim(top=10) elif max_value < 100: plt.ylim(top=100) elif max_value < 1000: plt.ylim(top=1000) #1K elif max_value < 10000: plt.ylim(top=10000) elif max_value < 100000: plt.ylim(top=100000) elif max_value < 1000000: plt.ylim(top=1000000) #1M elif max_value < 10000000: plt.ylim(top=10000000) elif max_value < 100000000: plt.ylim(top=100000000) elif max_value < 1000000000: plt.ylim(top=1000000000) #1B elif max_value < 10000000000: plt.ylim(top=10000000000) #Plot attribution plt.title( f'Data from Johns Hopkins CSSE\nPlot by Stephen Mullens @srmullens\nCode adapted from Tomer Burg @burgwx', loc='right', fontsize=6) if plot_type == "active": kwargs = { 'fontweight': 'bold', 'ha': 'right', 'va': 'top', 'fontsize': 8 } active_text = "\"Active\" cases = confirmed total - recovered - deaths" plt.text(0.99, 0.99, active_text, transform=ax.transAxes, **kwargs) #Show plot and close if save_image['setting'] == True: savepath = os.path.join(save_image['directory_path'], f"{plot_type}_chart_world.png") plt.savefig(savepath, bbox_inches='tight') else: plt.show() plt.close() #Alert script is done print("Done!")
""" COVID-19 case data is retrieved from Johns Hopkins CSSE: https://github.com/CSSEGISandData/COVID-19 """ #Avoid re-reading case data if it's already stored in memory try: cases2 except: if read_from_local == True: cases = pickle.load(open('cases_world.pickle', 'rb')) dates = cases['dates'] del cases['dates'] else: output = read_data.read_world(negative_daily=False, worldometers=worldometers) dates = output['dates'] cases = output['cases'] if plot_end_today == True: plot_end_date = dates[-1] #Substitute US for states if us_states == True: del cases['us'] for case in cases.keys(): cases[case]['us'] = False output_us = read_data.read_us(negative_daily=False) cases_us = output_us['cases'] for case in cases_us.keys(): cases_us[case]['us'] = True cases.update(cases_us)