Beispiel #1
0
    def get_apogee_local_times(self):

        apogees = self.get_apogees()

        indices = [time_utils.closest_index(at, self.times) for at in apogees]
        longitudes = [orbit_utils.latlon(self.pos[k])[2] for k in indices]

        local_times = [
            time_utils.local_time(a, lon)
            for a, lon in zip(apogees, longitudes)
        ]

        return local_times
Beispiel #2
0
def region_snapshots(name_template, start_time, *sim_files, **kwargs):
    """
    Create a time series of images showing the
    region of the Earth which satisfies both
    the SZA and VZA cutoffs. The images are colour
    coded as follows: green - both satisfied, 
    yellow - VZA satisfied, orange- SZA satisfied,
    red - neither satisfied.
    
    Can be used with an arbitrary number of satellites.
    
    Locators for each satellite are drawn, as well
    as a line indicating the orbit ground track.
    
    args:
    
      name_template - common part of the name for
                      the images that will be created.
                      a 0 padded number will be added
                      to this string to differentiate 
                      different images in the series
                      
      start_time - time_utils.Time instance of the start
                   time for the time series. 
                   
      sim_files - arbitrary number of strings, which give
                  the locations of the simulated data 
                  created in GMAT.
                  
      kwargs - any entry in defaults, to change the values.
               see below for descriptions of key, value pairs
    
    """
    defaults = dict(
        centre=(90., -90.),  # centre of the orthographic projection
        N=24,  # number of snapshots to create
        interval=3600,  # time interval in seconds between snapshots
        vza_cutoff=60.,  # maximum allowed VZA
        sza_cutoff=80.,  # maximum allowed SZA
        res=0.5)  # resolution of contours

    # set any keyword arguments that were given
    for key in defaults.keys():
        if key in kwargs.keys():
            globals()[key] = kwargs[key]
        else:
            globals()[key] = defaults[key]

    #print interval

    print("Creating Basemap Image")
    projection = Basemap(projection='ortho',
                         lat_0=centre[0],
                         lon_0=centre[1],
                         resolution='l')

    # set up grid points for the images
    lat = np.arange(-90. + 0.5 * res, 90., res)
    lon = np.arange(-180. + 0.5 * res, 180., res)

    lon_grid, lat_grid = np.meshgrid(lon, lat)

    # contour levels and colours
    levs = [-1, 0, 1, 2, 3]
    clevs = ['red', 'orange', 'yellow', 'lime']

    x_grid, y_grid = projection(lon_grid, lat_grid)
    vmask = np.ma.masked_greater(x_grid, 1e15).mask

    # get satellite locations for drawing the ground track
    satellites = []
    satx = []
    saty = []
    for simf in sim_files:

        # read in simulation information
        sim = orbits.Simulation(simf)

        sat = orbits.Satellite(sim)
        sun = orbits.Sun(sim)

        # save all the satellite information; the sun information
        # should be the same across all the files, so the last one can just be used
        satellites.append(sat)

        # get the satellite positions for the full interval
        t_shift = start_time.new_ref(sat.times[0])

        start = time_utils.closest_index(t_shift, sat.times)

        stop_time = t_shift + interval * (N + 1)
        stop = time_utils.closest_index(stop_time, sat.times)

        satlats, satlons = orbit_utils.latlon_arr(sat.pos[start:stop],
                                                  axis='first')[1:]
        sx, sy = projection(satlons, satlats)

        # mask locations on the opposite side of the Earth
        satx.append(np.ma.masked_greater(sx, 1e15))
        saty.append(np.ma.masked_greater(sy, 1e15))

    # time steps for the time series
    time_steps = time_utils.Time.linsteps(start_time, interval, N)

    #print time_steps

    # create the valid viewing region images
    for k, time in enumerate(time_steps):

        fig, ax = plt.subplots(figsize=(10, 10))

        # get the sat and sun positions at the specified time
        satpoints = [sat(time.new_ref(sat.times[0])) for sat in satellites]
        sunpoint = sun(time.new_ref(sun.times[0]))

        valid_grid = np.zeros((lat.size, lon.size))

        # calculate SZA and VZA
        vza = np.amin(np.array([
            zenith_angle_arr(satp, lat_grid, lon_grid) for satp in satpoints
        ]),
                      axis=0)
        sza = zenith_angle_arr(sunpoint, lat_grid, lon_grid)

        # assign values to the global grid
        valid_vza = vza < vza_cutoff
        valid_sza = sza < sza_cutoff
        valid_combined = valid_vza * valid_sza

        valid_grid[valid_sza] = 1
        valid_grid[valid_vza] = 2
        valid_grid[valid_combined] = 3

        valid_grid_masked = np.ma.array(valid_grid, mask=vmask)

        # plot the map background and contours
        projection.drawcoastlines(linewidth=0.5)
        projection.drawmeridians(np.arange(-180, 181, 30),
                                 linewidth=0.5,
                                 latmax=90.)
        projection.drawparallels(np.arange(-90, 90, 15),
                                 linewidth=0.5,
                                 latmax=90.)

        vctr = projection.contourf(x_grid,
                                   y_grid,
                                   valid_grid_masked,
                                   levs,
                                   colors=clevs)

        # draw satellite locators
        print("Drawing Satellite Locators")
        for satp in satpoints:

            satlat, satlon = orbit_utils.latlon(satp[0])[1:]
            sx, sy = projection(satlon, satlat)

            # don't draw locators if the satellite is on the other side of the Earth
            if sx < 1e15:
                locator1 = mpl.patches.Circle((sx, sy),
                                              radius=100000,
                                              ec='k',
                                              fc='k')
                locator2 = mpl.patches.Circle((sx, sy),
                                              radius=200000,
                                              ec='k',
                                              fc='none')
                ax.add_patch(locator1)
                ax.add_patch(locator2)

        # draw satellite tracks
        for sx, sy in zip(satx, saty):
            projection.plot(sx, sy, color='k', linewidth=2.)

        # add extra information to plots
        plt.figtext(
            0.5,
            0.075,
            "Maximum Allowed VZA = {v}$^\{c}$ | Maximum Allowed SZA = {s}$^\{c}$"
            .format(v=vza_cutoff, s=sza_cutoff, c='circ'),
            ha='center',
            va='center')
        plt.figtext(
            0.5,
            0.025,
            "Green - VZA & SZA satisfied | Yellow - VZA satisfied | Orange - SZA satisfied | Red - Neither satisfied",
            ha='center',
            va='center')

        plt.figtext(0.5,
                    0.975,
                    time.datetime.strftime("%d %b %Y %H:%M:%S UTC"),
                    ha='center',
                    va='center')

        # create a folder for the set of images, and save each one
        print("Saving Figure")
        figdir = '../figures/vza_orthographic/'

        folder = os.path.join(figdir, name_template)
        if not os.path.exists(folder): os.mkdir(folder)

        fname = "".join([name_template, "_{:02}.png".format(k + 1)])
        fpath = os.path.join(folder, fname)

        plt.savefig(fpath, dpi=240)
        plt.close()

    print("Finished")
Beispiel #3
0
def combined(sim_file, lattice_files, datetime, centre, xco2_lims=None, map_bkgd='bluemarble', cmap='jet', out='show', **kwargs):
    """
    Create a combined plot 
    """

    _, (xco2_ax, cld_ax, ret_ax) = plt.subplots(nrows=1, ncols=3, figsize=(15,8))
    
    
    ##############################################################
    
    plt.sca(xco2_ax)
    
    
    xco2, xco2_lats, xco2_lons = ec_cas.global_XCO2(datetime)
    
    proj_xco2 = Basemap(projection='ortho', lat_0=centre[0], lon_0=centre[1], resolution='l')
    
    proj_xco2.drawcoastlines(linewidth=0.75)
    proj_xco2.drawcountries(linewidth=0.5)
    proj_xco2.drawmeridians(np.arange(-180, 181, 30), latmax=90, linewidth=0.5)
    proj_xco2.drawparallels(np.arange(-90, 91, 15), latmax=90, linewidth=0.5)
    
    
    lon, lat = np.meshgrid(xco2_lons, xco2_lats)
    x,y = proj_xco2(lon, lat)
    
    xco2_mask = np.ma.masked_greater(x, 1e15).mask
    xco2_masked = np.ma.array(xco2, mask=xco2_mask)
    
    if xco2_lims:
        vmin_xco2, vmax_xco2 = xco2_lims
    else:
        vmin_xco2 = xco2.min() // 1.
        vmax_xco2 = xco2.max() // 1. + 1.
    
    sm_xco2 = ScalarMappable(Normalize(vmin=vmin_xco2, vmax=vmax_xco2), cmap=cmap)
    levs_xco2 = np.linspace(vmin_xco2, vmax_xco2, 256)
    clevs_xco2 = [sm_xco2.to_rgba(lev) for lev in levs_xco2]
    
    xco2_ctr = plt.contourf(x, y, xco2_masked, levs_xco2, colors=clevs_xco2, extend='both')
    
    xco2_cbar = plt.colorbar(xco2_ctr, orientation='horizontal', fraction=0.1, aspect=40)
    xco2_cbar.set_label('Xco$_2$ [ppm]')
    xco2_cbar.set_ticks(np.arange(vmin_xco2, vmax_xco2 + 1, 1))
    
    plt.title(datetime.strftime('EC-CAS Run %d %b %Y %H:%M:%S'))
    
    
    ##############################################################
    
    plt.sca(cld_ax)
    
    
    mission = retrievals.Mission(sim_file, *lattice_files, **kwargs)
    
    obs_time = time_utils.Time(datetime, mission.satellite.times[0].ref)        
        
    # find the closest apogee point to obs_time
    apogees = mission.satellite.get_apogees()
    apogee_ind = time_utils.closest_index(obs_time, apogees)
    
    # create the ObservationPeriod instance, and generate the Retrieval instances
    obs = retrievals.ObservationPeriod(mission, apogees[apogee_ind], mission.lattice_files[apogee_ind%2])
    obs.main_filter()
    obs.generate_retrievals()
    
    # find the closest segment of the observation period
    obs_ind = time_utils.closest_index(obs_time, obs.obs_middle)
    
    # clat, clon = centre
    proj_cld = Basemap(projection='ortho', lat_0=centre[0], lon_0=centre[1], resolution='c')
    
    # draw cloud data that was used to determine FOV locations
    obs.cloud_collection.show_clouds_ortho(obs.cloud_times[obs_ind], centre, map_bkgd=map_bkgd, out='')
    
    proj_cld.nightshade(datetime)
    
    # draw a red border around each of the selected FOVs
    for ret in obs.retrievals[obs_ind]:
        
        lats = np.concatenate([ret.pixel_lats[:,0], ret.pixel_lats[-1,:], ret.pixel_lats[::-1,-1], ret.pixel_lats[0,::-1]])
        lons = np.concatenate([ret.pixel_lons[:,0], ret.pixel_lons[-1,:], ret.pixel_lons[::-1,-1], ret.pixel_lons[0,::-1]])
        
        x,y = proj_cld(lons, lats)
        coords = np.vstack([x,y]).T
        
        if not np.sum(coords > 1e15):
        
            p = Polygon(coords, fill=False, edgecolor='r', zorder=10)
            plt.gca().add_patch(p)
        
    plt.title('FoV Selections {0} - {1} UTC'.format(obs.obs_times[obs_ind].strf('%d %B %Y %H:%M'), obs.obs_times[obs_ind+1].strf('%H:%M')))
    
    
    ##############################################################
    
    plt.sca(ret_ax)
    
    
    proj_ret = Basemap(projection='ortho', lat_0=centre[0], lon_0=centre[1], resolution='l')
    
    if map_bkgd == 'bluemarble':
        proj_ret.bluemarble()
    elif map_bkgd == 'etopo':
        proj_ret.etopo()
    elif map_bkgd == 'mask':
        proj_ret.drawlsmask(land_color='limegreen', ocean_color='dodgerblue', resolution='l')
        
        proj_ret.drawcoastlines(linewidth=0.75)
        proj_ret.drawcountries(linewidth=0.5)
        proj_ret.drawmeridians(np.arange(-180, 181, 30), latmax=90, linewidth=0.5)
        proj_ret.drawparallels(np.arange(-90, 91, 15), latmax=90, linewidth=0.5)
    else:
        raise ValueError('invalid map background specification')
    
    proj_ret.nightshade(datetime)
    
    
    sm_ret = ScalarMappable(Normalize(vmin=vmin_xco2, vmax=vmax_xco2), cmap=cmap)
    levs_ret = np.linspace(vmin_xco2, vmax_xco2, 256)
    clevs_ret = [sm_ret.to_rgba(lev) for lev in levs_ret]
    
    xco2_interp = RegularGridInterpolator((xco2_lats, xco2_lons), xco2, bounds_error=False, fill_value=None)
    
    for ret in obs.retrievals[obs_ind]:
                
        x,y = proj_ret(ret.pixel_lons, ret.pixel_lats)
                
        if not np.sum(x > 1e15):
        
            latlon_arr = np.dstack([ret.pixel_lats, ret.pixel_lons])
            xco2_ret = xco2_interp(latlon_arr)
            
            retmask = ret.valid_retrievals == 0
            xco2_ret_masked = np.ma.array(xco2_ret, mask=retmask)
            
            ret_ctr = plt.contourf(x, y, xco2_ret_masked, levs_ret, colors=clevs_ret, extend='both')
        
    
    ret_cbar = plt.colorbar(ret_ctr, orientation='horizontal', fraction=0.1, aspect=40)
    ret_cbar.set_label('Xco$_2$ [ppm]')
    ret_cbar.set_ticks(np.arange(vmin_xco2, vmax_xco2 + 1, 1))
    
    plt.title('AIM-North Retrievals {0} - {1} UTC'.format(obs.obs_times[obs_ind].strf('%d %B %Y %H:%M'), obs.obs_times[obs_ind+1].strf('%H:%M')))   
            
    
    ##############################################################
    
    
    plt.suptitle('AIM-North Observing Strategy')
    plt.subplots_adjust(wspace=0.05, left=0.05, right=0.95, top=1., bottom=0.1)
    
    cld_ax.set_position([0.35, 0.2525, 0.3, 0.675])
        
    
    if out == 'show':
        plt.show()
    elif out == '':
        pass
    else:
        plt.savefig(os.path.join('../figures/combined_plots/', out))
        plt.close()
Beispiel #4
0
def combined_all_ghgs(sim_file, lattice_files, datetime, centre, xco2_lims=None, xco_lims=None, xch4_lims=None, map_bkgd='bluemarble', cmap='jet', out='show', **kwargs):

    fig = plt.figure(figsize=(15,12))
    
    xco2_ax = fig.add_subplot(231)
    xco_ax = fig.add_subplot(232)
    xch4_ax = fig.add_subplot(233)
    cld_ax = fig.add_subplot(223)
    ret_ax = fig.add_subplot(224)
    
    
    #####################################
    
    plt.sca(xco2_ax)
    
    
    xco2, xco2_lats, xco2_lons = ec_cas.global_XCO2(datetime)
    
    proj_xco2 = Basemap(projection='ortho', lat_0=centre[0], lon_0=centre[1], resolution='l')
    
    proj_xco2.drawcoastlines(linewidth=0.75)
    proj_xco2.drawcountries(linewidth=0.5)
    proj_xco2.drawmeridians(np.arange(-180, 181, 30), latmax=90, linewidth=0.5)
    proj_xco2.drawparallels(np.arange(-90, 91, 15), latmax=90, linewidth=0.5)
    
    
    lon, lat = np.meshgrid(xco2_lons, xco2_lats)
    x,y = proj_xco2(lon, lat)
    
    xco2_mask = np.ma.masked_greater(x, 1e15).mask
    xco2_masked = np.ma.array(xco2, mask=xco2_mask)
    
    if xco2_lims:
        vmin_xco2, vmax_xco2 = xco2_lims
    else:
        vmin_xco2 = xco2_masked.min() // 1.
        vmax_xco2 = xco2_masked.max() // 1. + 1.
    
    sm_xco2 = ScalarMappable(Normalize(vmin=vmin_xco2, vmax=vmax_xco2), cmap=cmap)
    levs_xco2 = np.linspace(vmin_xco2, vmax_xco2, 256)
    clevs_xco2 = [sm_xco2.to_rgba(lev) for lev in levs_xco2]
    
    xco2_ctr = plt.contourf(x, y, xco2_masked, levs_xco2, colors=clevs_xco2, extend='both')
    
    xco2_cbar = plt.colorbar(xco2_ctr, orientation='vertical', fraction=0.05, aspect=40, shrink=0.75)
    xco2_cbar.set_label('XCO$_2$ [ppm]')
    xco2_cbar.set_ticks(np.arange(vmin_xco2, vmax_xco2+0.25, 0.5))
    
    plt.title(datetime.strftime('XCO$_2$ %d %b %Y %H:%M:%S'))
    
    
    ######################################
    
    plt.sca(xco_ax)
    
    xco, xch4, xlats, xlons = ec_cas.global_ghg(datetime)
    
    proj_xco = Basemap(projection='ortho', lat_0=centre[0], lon_0=centre[1], resolution='l')
    
    proj_xco.drawcoastlines(linewidth=0.75)
    proj_xco.drawcountries(linewidth=0.5)
    proj_xco.drawmeridians(np.arange(-180, 181, 30), latmax=90, linewidth=0.5)
    proj_xco.drawparallels(np.arange(-90, 91, 15), latmax=90, linewidth=0.5)
    
    
    lon, lat = np.meshgrid(xlons, xlats)
    x,y = proj_xco(lon, lat)
    
    xco_mask = np.ma.masked_greater(x, 1e15).mask
    xco_masked = np.ma.array(xco, mask=xco_mask)
    
    if xco_lims:
        vmin_xco, vmax_xco = xco_lims
    else:
        vmin_xco = xco_masked.min() // 1.
        vmax_xco = xco_masked.max() // 1. + 1.
    
    sm_xco = ScalarMappable(Normalize(vmin=vmin_xco, vmax=vmax_xco), cmap=cmap)
    levs_xco = np.linspace(vmin_xco, vmax_xco, 256)
    clevs_xco = [sm_xco.to_rgba(lev) for lev in levs_xco]
    
    xco_ctr = plt.contourf(x, y, xco_masked, levs_xco, colors=clevs_xco, extend='both')
    
    xco_cbar = plt.colorbar(xco_ctr, orientation='vertical', fraction=0.1, aspect=40, shrink=0.75)
    xco_cbar.set_label('XCO [ppb]')
    xco_cbar.set_ticks(np.int64(np.arange(vmin_xco, vmax_xco+1, 10)))
    
    plt.title(datetime.strftime('XCO %d %b %Y %H:%M:%S'))
    
    
    #######################################
    
    plt.sca(xch4_ax)
    
    proj_xch4 = Basemap(projection='ortho', lat_0=centre[0], lon_0=centre[1], resolution='l')
    
    proj_xch4.drawcoastlines(linewidth=0.75)
    proj_xch4.drawcountries(linewidth=0.5)
    proj_xch4.drawmeridians(np.arange(-180, 181, 30), latmax=90, linewidth=0.5)
    proj_xch4.drawparallels(np.arange(-90, 91, 15), latmax=90, linewidth=0.5)
    
    
    lon, lat = np.meshgrid(xlons, xlats)
    x,y = proj_xch4(lon, lat)
    
    xch4_mask = np.ma.masked_greater(x, 1e15).mask
    xch4_masked = np.ma.array(xch4, mask=xch4_mask)
    
    if xch4_lims:
        vmin_xch4, vmax_xch4 = xch4_lims
    else:
        vmin_xch4 = xch4_masked.min() // 1.
        vmax_xch4 = xch4_masked.max() // 1. + 1.
    
    sm_xch4 = ScalarMappable(Normalize(vmin=vmin_xch4, vmax=vmax_xch4), cmap=cmap)
    levs_xch4 = np.linspace(vmin_xch4, vmax_xch4, 256)
    clevs_xch4 = [sm_xch4.to_rgba(lev) for lev in levs_xch4]
    
    xch4_ctr = plt.contourf(x, y, xch4_masked, levs_xch4, colors=clevs_xch4, extend='both')
    
    xch4_cbar = plt.colorbar(xch4_ctr, orientation='vertical', fraction=0.1, aspect=40, shrink=0.75)
    xch4_cbar.set_label('XCH$_4$ [ppb]')
    xch4_cbar.set_ticks(np.int64(np.arange(vmin_xch4, vmax_xch4 + 1, 20)))
    
    plt.title(datetime.strftime('XCH$_4$ %d %b %Y %H:%M:%S'))
    
    
    ##############################################################
    
    plt.sca(cld_ax)
    
    
    mission = retrievals.Mission(sim_file, *lattice_files, **kwargs)
    
    obs_time = time_utils.Time(datetime, mission.satellite.times[0].ref)        
        
    # find the closest apogee point to obs_time
    apogees = mission.satellite.get_apogees()
    apogee_ind = time_utils.closest_index(obs_time, apogees)
    
    # create the ObservationPeriod instance, and generate the Retrieval instances
    obs = retrievals.ObservationPeriod(mission, apogees[apogee_ind], mission.lattice_files[apogee_ind%2])
    obs.main_filter()
    obs.generate_retrievals()
    
    # find the closest segment of the observation period
    obs_ind = time_utils.closest_index(obs_time, obs.obs_middle)
    
    clat, clon = centre
    proj_cld = Basemap(projection='ortho', lat_0=centre[0], lon_0=centre[1], resolution='c')
    
    # draw cloud data that was used to determine FOV locations
    obs.cloud_collection.show_clouds_ortho(obs.cloud_times[obs_ind], centre, map_bkgd=map_bkgd, out='')
    
    proj_cld.nightshade(datetime)
    
    # draw a red border around each of the selected FOVs
    for ret in obs.retrievals[obs_ind]:
        
        lats = np.concatenate([ret.pixel_lats[:,0], ret.pixel_lats[-1,:], ret.pixel_lats[::-1,-1], ret.pixel_lats[0,::-1]])
        lons = np.concatenate([ret.pixel_lons[:,0], ret.pixel_lons[-1,:], ret.pixel_lons[::-1,-1], ret.pixel_lons[0,::-1]])
        
        x,y = proj_cld(lons, lats)
        coords = np.vstack([x,y]).T
        
        if not np.sum(coords > 1e15):
        
            p = Polygon(coords, fill=False, edgecolor='r', zorder=10)
            plt.gca().add_patch(p)
        
    plt.title('FoV Selections {0} - {1} UTC'.format(obs.obs_times[obs_ind].strf('%d %B %Y %H:%M'), obs.obs_times[obs_ind+1].strf('%H:%M')))
    
    
    ##############################################################
    
    plt.sca(ret_ax)
    
    
    proj_ret = Basemap(projection='ortho', lat_0=centre[0], lon_0=centre[1], resolution='l')
    
    if map_bkgd == 'bluemarble':
        proj_ret.bluemarble()
    elif map_bkgd == 'etopo':
        proj_ret.etopo()
    elif map_bkgd == 'mask':
        proj_ret.drawlsmask(land_color='limegreen', ocean_color='dodgerblue', resolution='l')
        
        proj_ret.drawcoastlines(linewidth=0.75)
        proj_ret.drawcountries(linewidth=0.5)
        proj_ret.drawmeridians(np.arange(-180, 181, 30), latmax=90, linewidth=0.5)
        proj_ret.drawparallels(np.arange(-90, 91, 15), latmax=90, linewidth=0.5)
    else:
        raise ValueError('invalid map background specification')
    
    proj_ret.nightshade(datetime)
    
    
    
    for ret in obs.retrievals[obs_ind]:
                
        x,y = proj_ret(ret.pixel_lons, ret.pixel_lats)
                
        if not np.sum(x > 1e15):
        
            
            ret_mask = ret.valid_retrievals == 0
            ret_masked = np.ma.array(np.ones(ret.pixel_lats.shape), mask=ret_mask)
            
            ret_ctr = plt.contourf(x, y, ret_masked, [0,1], colors=['red'], extend='both')
        
    
    plt.title('AIM-North Retrievals {0} - {1} UTC'.format(obs.obs_times[obs_ind].strf('%d %B %Y %H:%M'), obs.obs_times[obs_ind+1].strf('%H:%M')))   
            
    ##############################################################
    
    plt.subplots_adjust(left=0.01, right=0.95, bottom=0.025, top = 0.975, wspace=0.175, hspace=0.1)
    
    if out == 'show':
        plt.show()
    elif out == '':
        pass
    else:
        plt.savefig(os.path.join('../figures/combined_plots/', out))
        plt.close()
Beispiel #5
0
def FoV_selections(sim_file,
                   lattice_files,
                   datetime,
                   centre,
                   map_bkgd='bluemarble',
                   out='show',
                   **mission_params):
    """
    Plots the fields of view chosen by the intelligent pointing algorithm onto a map.
    
    Args:
    - sim_file: GMAT output file path to use
    - lattice_files: list - List of lattice files used for the mission
    - datetime: dt.datetime instance - Time at which to plot points
    - center: tuple: (latitude, longitude) to be used as the center of an orthographic projection
    - map_bkgd: Background to plot on the map
    - out: either 'save' or 'show. Saves or shows the figure
    
    mission_params:
    - kwargs for retrievals.Mission instance.
    """

    mission = retrievals.Mission(sim_file, *lattice_files, **mission_params)

    obs_time = time_utils.Time(datetime, mission.satellite.times[0].ref)

    # find the closest apogee point to obs_time
    apogees = mission.satellite.get_apogees()
    apogee_ind = time_utils.closest_index(obs_time, apogees)

    # create the ObservationPeriod instance, and generate the Retrieval instances
    obs = retrievals.ObservationPeriod(
        mission, apogees[apogee_ind],
        mission.lattice_files[apogee_ind % len(lattice_files)])
    obs.main_filter()
    obs.generate_retrievals()
    print(len(obs.retrievals))

    # find the closest segment of the observation period
    obs_ind = time_utils.closest_index(obs_time, obs.obs_middle)

    proj_cld = Basemap(projection='ortho',
                       lat_0=centre[0],
                       lon_0=centre[1],
                       resolution='c')
    proj_cld.drawcoastlines()
    proj_cld.drawcountries()
    # draw cloud data that was used to determine FOV locations
    obs.cloud_collection.show_clouds_ortho(obs.cloud_times[obs_ind],
                                           centre,
                                           map_bkgd=map_bkgd,
                                           out='')

    proj_cld.nightshade(datetime)

    # draw a red border around each of the selected FOVs
    for ret in obs.retrievals[obs_ind]:

        lats = np.concatenate([
            ret.pixel_lats[:, 0], ret.pixel_lats[-1, :],
            ret.pixel_lats[::-1, -1], ret.pixel_lats[0, ::-1]
        ])
        lons = np.concatenate([
            ret.pixel_lons[:, 0], ret.pixel_lons[-1, :],
            ret.pixel_lons[::-1, -1], ret.pixel_lons[0, ::-1]
        ])

        x, y = proj_cld(lons, lats)
        coords = np.vstack([x, y]).T

        if not np.sum(coords > 1e15):

            p = Polygon(coords, fill=False, edgecolor='r', zorder=10)
            plt.gca().add_patch(p)

    plt.title('FoV Selections {0} - {1} UTC'.format(
        obs.obs_times[obs_ind].strf('%d %B %Y %H:%M'),
        obs.obs_times[obs_ind + 1].strf('%H:%M')))

    if out == 'show':
        plt.show()
    elif out == '':
        pass
    else:
        plt.savefig(out)
        plt.close()
Beispiel #6
0
def animate_FoV(sim_file, lattice_files, date_range, map_bkgd='mask', out='show', **mission_params):
    print("animate_FOV")
    assert type(sim_file) == str
    assert type(lattice_files) == list
    assert type(date_range) == tuple
    """
    Creates an animation (avi file) of field-of-view selections and cloud cover over time for one satellite.
    
    Args: 
    
    - sim_file: GMAT output file path to use
    - lattice_file: list - List of lattice files used for the mission. Must be given in order of W-E, starting with the first apogee
    - date_range: tuple of dt.datetime instances - (start time, end time) tuple for the animation. Requires year, month, day, hour.
    - map_bkgd: Background to plot on the map
    - out: either 'save' or 'show. Saves or shows the figure
    
    mission_params:
    - kwargs for retrievals.Mission instance.
    
    """
    
    # Set up the mission instance and find the apogees
    mission = retrievals.Mission(sim_file, *lattice_files, **mission_params)
    apogees = mission.satellite.get_apogees()
    
    # Get the start and end times and convert them from dt.datetime instances to time_utils.Time instances
    start_time = time_utils.Time(date_range[0], mission.satellite.times[0].ref)
    end_time = time_utils.Time(date_range[1], mission.satellite.times[0].ref)
    
    
    # Get the indices of the first and last apogees relevant to the time period
    apogee_start_ind = time_utils.closest_index(start_time, apogees)
    apogee_last_ind = time_utils.closest_index(end_time, apogees)

    # Empty directory to store temporary images before making the animation
    temp_dir = '../figures/animation_temp' 
    if not os.path.exists(temp_dir):
        os.mkdir(temp_dir)
    
    # Generate a retrievals.ObservationPeriod instance for every apogee in the relevant time frame
    for k in range(apogee_start_ind, apogee_last_ind + 1):
        # create the ObservationPeriod instance, and generate the Retrieval instances
        if lattice_files == []:
            lat_file = None
        else:
            lat_file = mission.lattice_files[k%len(lattice_files)]
        obs = retrievals.ObservationPeriod(mission, apogees[k], lat_file)
        obs.main_filter()
        obs.generate_retrievals()
        
        # after this point we're just plotting stuff, no actual analysis
        col = 'xkcd:red'
        lat_0 = 90
        lon_0 = -95
        map_params = {"projection": 'ortho',
                    "lat_0": lat_0,
                    "lon_0": lon_0,
                    "resolution": 'c'}
        # Plot cloud data and pointing selections for each segment of each observation period
        for i in range(len(obs.retrievals)):
            
            proj_cld = Basemap(**map_params)
            
            # draw cloud data that was used to determine FOV locations
            obs.cloud_collection.show_clouds_ortho(
                obs.cloud_times[i], (lat_0, lon_0), map_bkgd=map_bkgd, out='')
            # Draw terminator
            proj_cld.nightshade(
                obs.obs_times[i].to_datetime64().astype(dt.datetime))
            
            # Draw a bullseye at the sub-satellite point
            satx, saty = proj_cld(obs.satlon[i], obs.satlat[i])
            inner = Circle(
                (satx,saty), radius=9e4, color=col, zorder=10)
            outer = Circle(
                (satx,saty), radius=2e5, linewidth=1.5, facecolor = 'k',
                edgecolor=col, zorder = 10 )
            plt.gca().add_patch(outer)
            plt.gca().add_patch(inner)
            
            for ret in obs.retrievals[i]:
                # draw a border around each of the selected FOVs
                lats = np.concatenate([ret.pixel_lats[:,0],
                    ret.pixel_lats[-1,:],
                    ret.pixel_lats[::-1,-1],
                    ret.pixel_lats[0,::-1]])
                lons = np.concatenate([ret.pixel_lons[:,0],
                    ret.pixel_lons[-1,:],
                    ret.pixel_lons[::-1,-1],
                    ret.pixel_lons[0,::-1]])
        
                x,y = proj_cld(lons, lats)
                coords = np.vstack([x,y]).T
                
                if not np.sum(coords > 1e15):
                    p = Polygon(coords, fill=False, edgecolor=col, zorder=10,
                        antialiased = True) 
                    plt.gca().add_patch(p)

            plt.title('{0} - {1} UTC'.format(
                obs.obs_times[i].strftime('%d %B %H:%M'),
                obs.obs_times[i+1].strftime('%H:%M')))
            # Save the figure in the temporary directory
            fname = 'FoVs{0}.png'.format(
                obs.obs_times[i].strftime('%y%m%d%H:%M'))
            fpath = os.path.join(temp_dir, fname)
            plt.savefig(fpath, dpi=500)
            print('Saved figure: {0}-{1}.png'.format(
                obs.obs_times[i].strftime('%m%d%Y%H:%M'),
                obs.obs_times[i+1].strftime('%H:%M')))
            #plt.show()
            plt.close()

    # Create an animation using all the temporary images
    os.system(('mencoder -o '
               '../figures/constellationview_{0}_{1}.avi '
               'mf://../figures/animation_temp/FoVs*.png '
               '-ovc lavc -lavcopts vcodec=msmpeg4v2 -mf '
               'fps=2').format(start_time.strftime('%y%m%d'),
                              end_time.strftime('%y%m%d')))
    # Delete the temporary images
    os.system('rm ../figures/animation_temp/*.png')
    os.system('rmdir ../figures/animation_temp')