Example #1
0
def plot_APWP(APWPlats,APWPlongs,A95,colour='blue',meridian=-100):
    #generates a polar plot of the smoothed APWP when sent the columns from the pandas dataframe generated by generate_APWP
    #pandas Dataframe columns not readable by Basemap initially...
    longs=np.array(APWPlongs, dtype='float')
    lats=np.array(APWPlats, dtype='float')
    errors=np.array(A95, dtype='float')
    m = Basemap(projection='nplaea',boundinglat=60,lon_0=meridian,resolution='l')
    m.drawcoastlines(linewidth=0.25)
    m.fillcontinents(color='lightgrey')
    parallels = np.arange(-90.,90.,30.)
    m.drawparallels(parallels)
    meridians = np.arange(0.,360.,30.)
    m.drawmeridians(meridians)
    plt_line(longs,lats,m,colour)
    plt_points(longs,lats,m,colour)
    for i in range(len(errors)):
        m.ellipse(longs[i],lats[i],errors[i],errors[i],0.)
        #ell_x,ell_y=make_ellipse(lats[i],longs[i], errors[i])
	#plt_line(ell_x,ell_y,m,colour)
    return m
Example #2
0
def plot_sky(ra,
             dec,
             data=None,
             pix_shape='ellipse',
             nside=16,
             label='',
             projection='eck4',
             cmap='jet',
             hide_galactic_plane=False,
             discrete_colors=True,
             center_longitude=0,
             radius=2.,
             epsi=0.2,
             alpha_tile=0.5,
             min_color=1,
             max_color=5,
             nsteps=5):
    """
    Routine that reads ra and dec with the proper units (requires astropy units) and makes an all-sky plot of the desired
    data.
    Requires Basemap installed and astropy.units
    
    Parameters
    ----------

        ra : array of :class: `astropy.angle`
             Right ascension with units.
        dec : array of :class: `astropy.angle`
             Declination with units.
        data : array of :class: `float or int`
             Weights to use (for example the tile-pass or values of E(B-V)).
        pix_shape : :class: `string`
             Desired shape of the pixels on the plot. It can take the values 'ellipse', 'healpix', and 'square'
             nside : int, it controls the number of pixels with healpix and square pixels. For healpix the whole celestial sphere is
             divided into 12*nside**2 pixels, for square pixels it is divided into 16*nside**2.
        label : :class: `string`, optional
             label for the colorbar.
        projection : :class: `string`, optional
             projection scheme used to show the map. 'eck4', 'kav7', and 'moll' recommended for full sky maps: Default 'eck4'.
        cmap : :class: `string`, optional
             name of the matplotlib colormap to use. Default 'jet'.
        hide_galactic_plane : :class: `bool`, optional
             if True it hides the galactic plane in the plot, if False it shows it. Default False.
        discrete_colors : :class: `bool`, optional
             if True it uses the data to create a linear discrete color-scale.
        center_longitude : :class: `float`, optional
             center longitude for the plot in degrees. Default 0.
        radius : :class: `float`, optional
             radius of the circle in degrees. Default 2.
        epsi : :class: `float`, optional
             it prevents ellipses to wrap around the edges. Only ellipses with |ra-180-center_longitude|>radius+epsi are plotted. If
             you want to plot all the ellipses set epsi to -radius (some ellipses may wrap around the edges). Default 0.2
        alpha_tile : :class: `float`, optional
             value between 0 and 1 of transparency for the ellipses. 1 Opaque, 0 transparent.
        min_color : :class: `float`, optional
             minimum value of the color scale if discrete_colors=True. Default 1
        max_color : :class: `float`, optional
             maximum value of the color scale if discrete_colors=True. Default 5
        nsteps : :class: `int`, optional
             number of intervals on the color scale if discrete_colors=True. Default 5

    Returns
    -------
    :class:`matplotlib.axes.Axes` 
        The Axes object for the plot. It creates a figure if there was no previous figure and if data is not provided it returns counts per square-degree if healpix
            or square pixels are created. If you choose the option ellipse it plots as many ellipses as ra,dec points provided (it may be slow).
    """
    from matplotlib.collections import PolyCollection
    from astropy.coordinates import SkyCoord
    import matplotlib.pyplot as plt
    import astropy.units as u
    import matplotlib.cm as cm
    import numpy as np
    from matplotlib.patches import Polygon
    from mpl_toolkits.basemap import pyproj
    from mpl_toolkits.basemap import Basemap
    import matplotlib as mpl

    #---------
    # Add ellipses to Basemap
    #--------

    class Basemap(Basemap):
        #Code from http://stackoverflow.com/questions/8161144/drawing-ellipses-on-matplotlib-basemap-projections
        #It adds ellipses to the class Basemap to use in plotsky. This is only used in plotsky and includes the basemap
        #dependencies.
        def ellipse(self, x0, y0, a, b, n, ax=None, **kwargs):
            ax = kwargs.pop('ax', None) or self._check_ax()
            g = pyproj.Geod(a=self.rmajor, b=self.rminor)
            azf, azb, dist = g.inv([x0, x0], [y0, y0], [x0 + a, x0],
                                   [y0, y0 + b])
            tsid = dist[0] * dist[1]  # a * b
            seg = [self(x0 + a, y0)]
            AZ = np.linspace(azf[0], 360. + azf[0], n)
            for i, az in enumerate(AZ):
                # Skips segments along equator (Geod can't handle equatorial arcs).
                if np.allclose(0., y0) and (np.allclose(90., az)
                                            or np.allclose(270., az)):
                    continue

                # In polar coordinates, with the origin at the center of the
                # ellipse and with the angular coordinate ``az`` measured from the
                # major axis, the ellipse's equation  is [1]:
                #
                #                           a * b
                # r(az) = ------------------------------------------
                #         ((b * cos(az))**2 + (a * sin(az))**2)**0.5
                #
                # Azymuth angle in radial coordinates and corrected for reference
                # angle.
                azr = 2. * np.pi / 360. * (az + 90.)
                A = dist[0] * np.sin(azr)
                B = dist[1] * np.cos(azr)
                r = tsid / (B**2. + A**2.)**0.5
                lon, lat, azb = g.fwd(x0, y0, az, r)
                x, y = self(lon, lat)

                # Add segment if it is in the map projection region.
                if x < 1e20 and y < 1e20:
                    seg.append((x, y))

            poly = Polygon(seg, **kwargs)
            ax.add_patch(poly)

            # Set axes limits to fit map region.
            self.set_axes_limits(ax=ax)

            return poly

    ra = ra.to(u.deg).value
    dec = dec.to(u.deg).value
    if pix_shape not in ['ellipse', 'healpix', 'square']:
        print('Pixel shape invalid, try ellipse, healpix or square')
    if discrete_colors:
        if (data is None):
            print('Error discrete_colors expects data!=None')
        else:
            # define the colormap
            cmap = plt.get_cmap(cmap)
            cmaplist = [cmap(i) for i in range(cmap.N)]
            cmap = cmap.from_list('Custom cmap', cmaplist, cmap.N)
            # define the bins and normalize
            bounds = np.linspace(min_color, max_color, nsteps)
            norm = mpl.colors.BoundaryNorm(bounds, cmap.N)
    else:
        cmap = plt.get_cmap(cmap)
        norm = None
    if (pix_shape == 'healpix'):
        import healpy as hp
        # get pixel area in degrees
        pixel_area = hp.pixelfunc.nside2pixarea(nside, degrees=True)
        #avoid pixels which may cause polygons to wrap around workaround
        drawing_mask = np.logical_and(
            np.fabs(ra - 180 - center_longitude) >
            2 * np.sqrt(pixel_area) + epsi,
            np.fabs(ra + 180 - center_longitude) >
            2 * np.sqrt(pixel_area) + epsi)
        ra = ra[drawing_mask]
        dec = dec[drawing_mask]
        if data != None:
            data = data[drawing_mask]
        # find healpixels associated with input vectors
        pixels = hp.ang2pix(nside, 0.5 * np.pi - np.radians(dec),
                            np.radians(ra))
        # find unique pixels
        unique_pixels = np.unique(pixels)
        # count number of points in each pixel
        bincounts = np.bincount(pixels)
        # if no data provided, show counts per sq degree
        # otherwise, show mean per pixel
        if data is None:
            values = bincounts[unique_pixels] / pixel_area
        else:
            weighted_counts = np.bincount(pixels, weights=data)
            values = weighted_counts[unique_pixels] / bincounts[unique_pixels]
        # find pixel boundaries
        corners = hp.boundaries(nside, unique_pixels, step=1)
        corner_theta, corner_phi = hp.vec2ang(corners.transpose(0, 2, 1))
        corner_ra, corner_dec = np.degrees(corner_phi), np.degrees(
            np.pi / 2 - corner_theta)
        # set up basemap
        m = Basemap(projection=projection,
                    lon_0=center_longitude,
                    resolution='c',
                    celestial=True)
        m.drawmeridians(np.arange(0, 360, 60),
                        labels=[0, 0, 1, 0],
                        labelstyle='+/-')
        m.drawparallels(np.arange(-90, 90, 15),
                        labels=[1, 0, 0, 0],
                        labelstyle='+/-')
        m.drawmapboundary()
        # convert sky coords to map coords
        x, y = m(corner_ra, corner_dec)
        # regroup into pixel corners
        verts = np.array([x.reshape(-1, 4), y.reshape(-1,
                                                      4)]).transpose(1, 2, 0)
        # Make the collection and add it to the plot.
        coll = PolyCollection(verts,
                              array=values,
                              cmap=cmap,
                              norm=norm,
                              edgecolors='none')
        plt.gca().add_collection(coll)
        plt.gca().autoscale_view()
        if not hide_galactic_plane:
            # generate vector in galactic coordinates and convert to equatorial coordinates
            galactic_l = np.linspace(0, 2 * np.pi, 1000)
            galactic_plane = SkyCoord(l=galactic_l * u.radian,
                                      b=np.zeros_like(galactic_l) * u.radian,
                                      frame='galactic').fk5
            # project to map coordinates
            galactic_x, galactic_y = m(galactic_plane.ra.degree,
                                       galactic_plane.dec.degree)
            m.scatter(galactic_x, galactic_y, marker='.', s=2, c='k')
        # Add a colorbar for the PolyCollection
        plt.colorbar(coll,
                     orientation='horizontal',
                     cmap=cmap,
                     norm=norm,
                     spacing='proportional',
                     pad=0.01,
                     aspect=40,
                     label=label)
    if (pix_shape == 'square'):
        nx, ny = 4 * nside, 4 * nside

        ra_bins = np.linspace(-180 + center_longitude, 180 + center_longitude,
                              nx + 1)
        cth_bins = np.linspace(-1., 1., ny + 1)
        ra[ra > 180 + center_longitude] = ra[ra > 180 + center_longitude] - 360
        if data == None:
            weights = np.ones(len(ra))
        else:
            weights = data
        density, _, _ = np.histogram2d(ra,
                                       np.sin(dec * np.pi / 180.),
                                       [ra_bins, cth_bins],
                                       weights=weights)
        ra_bins_2d, cth_bins_2d = np.meshgrid(ra_bins, cth_bins)
        m = Basemap(projection=projection,
                    lon_0=center_longitude,
                    resolution='l',
                    celestial=True)
        m.drawmeridians(np.arange(0, 360, 60),
                        labels=[0, 0, 1, 0],
                        labelstyle='+/-')
        m.drawparallels(np.arange(-90, 90, 15),
                        labels=[1, 0, 0, 0],
                        labelstyle='+/-')
        m.drawmapboundary()
        xs, ys = m(ra_bins_2d, np.arcsin(cth_bins_2d) * 180 / np.pi)
        new_density = np.ma.masked_where(density == 0, density).T
        pcm = plt.pcolormesh(xs, ys, new_density, cmap=cmap, norm=norm)
        plt.colorbar(pcm,
                     orientation='horizontal',
                     cmap=cmap,
                     norm=norm,
                     spacing='proportional',
                     pad=0.04,
                     label=label)
        if not hide_galactic_plane:
            # generate vector in galactic coordinates and convert to equatorial coordinates
            galactic_l = np.linspace(0, 2 * np.pi, 1000)
            galactic_plane = SkyCoord(l=galactic_l * u.radian,
                                      b=np.zeros_like(galactic_l) * u.radian,
                                      frame='galactic').fk5
            # project to map coordinates
            galactic_x, galactic_y = m(galactic_plane.ra.degree,
                                       galactic_plane.dec.degree)
            m.scatter(galactic_x, galactic_y, marker='.', s=2, c='k')
    if (pix_shape == 'ellipse'):
        m = Basemap(projection=projection,
                    lon_0=center_longitude,
                    resolution='l',
                    celestial=True)
        m.drawmeridians(np.arange(0, 360, 60),
                        labels=[0, 0, 1, 0],
                        labelstyle='+/-')
        m.drawparallels(np.arange(-90, 90, 15),
                        labels=[1, 0, 0, 0],
                        labelstyle='+/-')
        m.drawmapboundary()
        if not hide_galactic_plane:
            # generate vector in galactic coordinates and convert to equatorial coordinates
            galactic_l = np.linspace(0, 2 * np.pi, 1000)
            galactic_plane = SkyCoord(l=galactic_l * u.radian,
                                      b=np.zeros_like(galactic_l) * u.radian,
                                      frame='galactic').fk5
            # project to map coordinates
            galactic_x, galactic_y = m(galactic_plane.ra.degree,
                                       galactic_plane.dec.degree)
            m.scatter(galactic_x, galactic_y, marker='.', s=2, c='k')
        if data == None:
            weights = np.ones(len(ra))
        else:
            weights = data
        ax = plt.gca()
        cmm = cm.ScalarMappable(norm=norm, cmap=cmap)
        color_array = cmm.to_rgba(weights)
        for i in range(0, len(ra)):
            if (np.fabs(ra[i] - 180 - center_longitude) > radius + epsi and
                    np.fabs(ra[i] + 180 - center_longitude) > radius + epsi):
                poly = m.ellipse(ra[i],
                                 dec[i],
                                 radius,
                                 radius,
                                 8,
                                 facecolor=color_array[i],
                                 zorder=10,
                                 alpha=alpha_tile)
        plt.colorbar(plt.imshow(np.array([(1, 2), (3, 4), (0, 6)]),
                                cmap=cmap,
                                norm=norm),
                     orientation='horizontal',
                     cmap=cmap,
                     norm=norm,
                     spacing='proportional',
                     pad=0.04,
                     label=label)
    axis = plt.gca()
    return axis
Example #3
0
def plot_fp_act(FP_ID, 
                FP_utilize_df, 
                act_track_data, 
                flight_plan_data, 
                feed_track = None, 
                pred_track = None, 
                pred_track_mu = None,
                pred_track_cov = None,
                k = 9, 
                nstd = 3,
                sort = True,
                plot_weather_info = False,
                **kwargs):
    # TODO: plot error ellipse
    ori_lat = 29.98333333; ori_lon = -95.33333333
    des_lat = 42.36666667; des_lon = -71
    
    fig = plt.figure(figsize=(8,6))
    m = Basemap(llcrnrlon = -100,llcrnrlat = 27,urcrnrlon = -68,urcrnrlat = 46,projection='merc')
    m.drawmapboundary(fill_color='#8aeaff')
    m.fillcontinents(color='#c5c5c5', lake_color='#8aeaff')
    m.drawcoastlines(linewidth=0.5)
    m.drawcountries(linewidth=0.5)
    m.drawstates(linewidth=0.5)
    m.drawparallels(np.arange(10.,35.,5.))
    m.drawmeridians(np.arange(-120.,-80.,10.))
    
    x1, y1 = m(ori_lon, ori_lat)
    x2, y2 = m(des_lon, des_lat)
    plt.plot(x1,y1, 'r*', ms = 15, zorder = 10)
    plt.plot(x2,y2, 'r*', ms = 15, zorder = 10)

    fid_fp1 = FP_utilize_df.loc[FP_utilize_df.FLT_PLAN_ID == FP_ID, 'FID'].values
    print('%d flights filed flight plan %s'%(fid_fp1.shape[0], FP_ID))
    plot_track = act_track_data.loc[act_track_data.FID.isin(fid_fp1)]
    plot_fp = flight_plan_data.loc[flight_plan_data.FLT_PLAN_ID_REAL == FP_ID]
    x_fp, y_fp = m(plot_fp.LONGITUDE.values, plot_fp.LATITUDE.values)
    
    feed_x, feed_y = m(feed_track.Lon.values, feed_track.Lat.values)
    feed, = plt.plot(feed_x, feed_y, 'o-', ms = 4, linewidth = 3, color='g', label = 'Feed tracks', zorder = 9)
    
    for gpidx, gp in plot_track.groupby('FID'):
        x,y = m(gp.Lon.values, gp.Lat.values)
        actual, = plt.plot(x,y,'--', linewidth = 2, color='b', label = 'Actual Tracks', zorder = 8)
    fp, = plt.plot(x_fp, y_fp, '-', linewidth = 2, color='r', label = 'Flight Plans', zorder = 5)
    
    if pred_track is not None:
        if sort:
            x, y = m(pred_track[k][pred_track[k][:,3].argsort()][:, 1], pred_track[k][pred_track[k][:,3].argsort()][:, 0])
        else:
            x, y = m(pred_track[k, :, 1], pred_track[k, :, 0])
        pred_fig, = plt.plot(x,y, 'o--', ms = 3, zorder = 7)
    if pred_track_mu is not None:
        if sort:
            x, y = m(pred_track_mu[k][pred_track_mu[k][:,3].argsort()][:, 1], 
                     pred_track_mu[k][pred_track_mu[k][:,3].argsort()][:, 0])
        else:
            x, y = m(pred_track_mu[k][:, 1], pred_track_mu[k][:, 0])
        plt.plot(x,y, 'mo--', ms = 4, zorder = 7, label = 'Predicted tracks')

    if pred_track_cov is not None:
        for t in range(pred_track_mu[k].shape[0]):
            lon_a = np.sqrt(pred_track_cov[k, t, 1, 1]) * nstd
            lat_b = np.sqrt(pred_track_cov[k, t, 0, 0]) * nstd
            # assume independency
#             cov_width, cov_height, cov_theta = get_cov_ellipse_wh(predicted_tracks_cov[k, t, :2, :2], nstd = 3)
            centre_lon, centre_lat = (pred_track_mu[k, t, 1], pred_track_mu[k, t, 0])
            poly = m.ellipse(centre_lon, 
                             centre_lat, 
                             lon_a,
                             lat_b, 
                             50, 
                             facecolor='green', zorder=6, alpha=0.25)

    plt.legend(fontsize = 12, loc = 2)

    if plot_weather_info:
        grbs_common_info_file = kwargs.get('grbs_common_info_file', '/media/storage/DATA/filtered_weather_data/grbs_common_info.npz')
        wind_file_root = kwargs.get('wind_file_root', '../../DATA/filtered_weather_data/namanl_small_npz/')
        wx_file_root = kwargs.get('wx_file_root', '../../DATA/NCWF/gridded_storm_hourly/')
        resolution = kwargs.get('resolution', 50)
        wind_scale = kwargs.get('wind_scale', 1000)

        wind_fname_list = [os.path.join(wind_file_root, wf) for wf in np.unique(plot_track['wind_fname'])]
        wx_file_time = plot_track['wx_fname'].values
        wx_file_time = np.unique(wx_file_time[~pd.isnull(wx_file_time)])

        wx_fname_list = [os.path.join(wx_file_root, wf.replace('-', '_').replace(' ', '_').replace(':', '')[:15] + 'Z.npz') for wf in wx_file_time]
        _ = plot_wx(m, 
                    wind_fname_list = wind_fname_list, 
                    wx_fname_list = wx_fname_list, 
                    grbs_common_info_file = grbs_common_info_file,
                    resolution = resolution, 
                    wind_scale = wind_scale)
    plt.show()
    return plot_track, m