Ejemplo n.º 1
0
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')
Ejemplo n.º 3
0
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')
Ejemplo n.º 4
0
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()
Ejemplo n.º 5
0
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')
Ejemplo n.º 6
0
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()
Ejemplo n.º 7
0
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)
Ejemplo n.º 8
0
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')
Ejemplo n.º 9
0
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')
Ejemplo n.º 10
0
    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
Ejemplo n.º 11
0
"""
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']])
Ejemplo n.º 12
0
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!")
Ejemplo n.º 13
0
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!")
Ejemplo n.º 14
0
"""
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)