Ejemplo n.º 1
0
def plt_tsk(nc, model, figname):
    """
    Create a pcolor surface map of surface skin temperature
    :param nc: netcdf file
    :param model: the model version that is being plotted, e.g. 3km or 9km
    :param figname: full file path to save directory and save filename
    """
    tsk = nc['TSK']
    color_label = 'TSK (\N{DEGREE SIGN}C)'
    title = 'Surface Skin Temperature (\N{DEGREE SIGN}C)'

    plot_types = ['full_grid',
                  'bight']  # plot the full grid and just NY Bight area
    for pt in plot_types:
        if pt == 'full_grid':  # subset the entire grid
            tsk_sub, ax_lims, xticks, yticks = cf.subset_grid(tsk, model)
        else:  # subset just NY Bight
            new_fname = 'bight_{}'.format(figname.split('/')[-1])
            figname = '/{}/{}'.format(os.path.join(*figname.split('/')[0:-1]),
                                      new_fname)
            tsk_sub, ax_lims, xticks, yticks = cf.subset_grid(tsk, 'bight')

        fig, ax, lat, lon = cf.set_map(tsk_sub)

        # add text to the bottom of the plot
        cf.add_text(ax, nc.SIMULATION_START_DATE, nc.time_coverage_start,
                    model)

        # convert degrees K to degrees C
        tsk_sub_c = tsk_sub.values - 273.15

        # add contour lines
        contour_list = np.linspace(0, 30, 7)
        pf.add_contours(ax, lon, lat, tsk_sub_c, contour_list)

        # plot data
        # pcolormesh: coarser resolution, shows the actual resolution of the model data
        vlims = [0, 32]
        cmap = cmo.cm.thermal
        levels = MaxNLocator(nbins=16).tick_values(
            vlims[0], vlims[1])  # levels every 2 degrees C
        norm = BoundaryNorm(levels, ncolors=cmap.N, clip=True)

        kwargs = dict()
        kwargs['ttl'] = title
        kwargs['clab'] = color_label
        # kwargs['var_lims'] = vlims
        kwargs['norm_clevs'] = norm
        kwargs['extend'] = 'both'
        kwargs['cmap'] = cmap
        pf.plot_pcolormesh(fig, ax, lon, lat, tsk_sub_c, **kwargs)

        # initialize keyword arguments for map features
        kwargs = dict()
        kwargs['xticks'] = xticks
        kwargs['yticks'] = yticks
        cf.add_map_features(ax, ax_lims, **kwargs)

        plt.savefig(figname, dpi=200)
        plt.close()
Ejemplo n.º 2
0
def plt_radar(nc, subset_domain, figname):
    """
    Create filled contour surface maps of radar reflectivity
    :param nc: netcdf file
    :param subset_domain: the plotting limit domain, e.g. 3km, 9km, bight (NY Bight), full_grid, mab, nj, snj
    :param figname: full file path to save directory and save filename
    """
    radar = nc['Reflectivity']

    radar_sub, ax_lims, xticks, yticks = cf.subset_grid_wct(radar, subset_domain)

    fig, ax, lat, lon = cf.set_map(radar_sub)

    # initialize keyword arguments for map features
    kwargs = dict()
    kwargs['xticks'] = xticks
    kwargs['yticks'] = yticks

    cf.add_map_features(ax, ax_lims, **kwargs)

    title = 'Radar Reflectivity ({})'.format(radar_sub.units)

    kwargs = dict()
    kwargs['ttl'] = title
    kwargs['cmap'] = 'pyart_NWSRef'
    kwargs['clab'] = title
    kwargs['var_lims'] = [0, 72]

    # If the array is all zeros, turn the zeros to nans. Otherwise the plot will be all teal instead of white.
    if np.nanmax(radar_sub) == 0.0:
        radar_sub.values[radar_sub == 0] = np.nan

    pf.plot_pcolormesh(fig, ax, lon, lat, np.squeeze(radar_sub.values), **kwargs)

    plt.savefig(figname, dpi=200)
    plt.close()
Ejemplo n.º 3
0
def plt_2m_temp(nc, model, figname, lease_areas=None):
    """
    Create a pcolor surface map of air temperature at 2m with contours
    :param nc: netcdf file
    :param model: the model version that is being plotted, e.g. 3km or 9km
    :param figname: full file path to save directory and save filename
    :param lease_areas: optional dictionary containing lat/lon coordinates for wind energy lease area polygon
    """
    lease_areas = lease_areas or None

    t2 = nc['T2']
    color_label = 'Air Temperature (\N{DEGREE SIGN}F)'

    plot_types = ['full_grid',
                  'bight']  # plot the full grid and just NY Bight area
    for pt in plot_types:
        if pt == 'full_grid':  # subset the entire grid
            t2_sub, ax_lims, xticks, yticks = cf.subset_grid(t2, model)
        else:  # subset just NY Bight
            new_fname = 'bight_{}'.format(figname.split('/')[-1])
            figname = '/{}/{}'.format(os.path.join(*figname.split('/')[0:-1]),
                                      new_fname)
            t2_sub, ax_lims, xticks, yticks = cf.subset_grid(t2, 'bight')

        fig, ax, lat, lon = cf.set_map(t2_sub)

        # add text to the bottom of the plot
        cf.add_text(ax, nc.SIMULATION_START_DATE, nc.time_coverage_start,
                    model)

        # initialize keyword arguments for map features
        kwargs = dict()
        kwargs['xticks'] = xticks
        kwargs['yticks'] = yticks
        cf.add_map_features(ax, ax_lims, **kwargs)

        if lease_areas:
            pf.add_lease_area_polygon(ax, lease_areas, 'magenta')

        # convert K to F
        d = np.squeeze(t2_sub.values) * 9 / 5 - 459.67

        # add contour lines
        contour_list = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
        pf.add_contours(ax, lon, lat, d, contour_list)

        # plot data
        # pcolormesh: coarser resolution, shows the actual resolution of the model data
        vlims = [-20, 110]
        cmap = plt.get_cmap('jet')
        # levels = MaxNLocator(nbins=30).tick_values(vlims[0], vlims[1])  # levels every 5 degrees F
        levels = MaxNLocator(nbins=65).tick_values(
            vlims[0], vlims[1])  # levels every 2 degrees F
        norm = BoundaryNorm(levels, ncolors=cmap.N, clip=True)

        kwargs = dict()
        kwargs['ttl'] = '2m {}'.format(color_label)
        kwargs['clab'] = color_label
        # kwargs['var_lims'] = vlims
        kwargs['norm_clevs'] = norm
        kwargs['extend'] = 'both'
        pf.plot_pcolormesh(fig, ax, lon, lat, d, **kwargs)

        # # contourf: smooths the resolution of the model data, plots are less pixelated
        # kwargs = dict()
        # kwargs['ttl'] = '2m {}'.format(color_label)
        # kwargs['clab'] = color_label
        # kwargs['var_lims'] = [-20, 110]
        # kwargs['cbar_ticks'] = np.linspace(-20, 100, 7)
        #
        # levels = np.arange(-20, 110.5, .5)
        # pf.plot_contourf(fig, ax, lon, lat, d, levels, **kwargs)

        plt.savefig(figname, dpi=200)
        plt.close()
Ejemplo n.º 4
0
def plt_power(nc, model, ht, figname, lease_areas=None):
    """
    Create pseudocolor surface maps of estimated wind power at 160m.
    :param nc: netcdf file
    :param model: the model version that is being plotted, e.g. 3km or 9km
    :param ht: wind speed height to plot, e.g. 160m
    :param figname: full file path to save directory and save filename
    :param lease_areas: optional dictionary containing lat/lon coordinates for wind energy lease area polygon
    """
    power_curve = '/home/lgarzio/rucool/bpu/wrf/wrf_lw15mw_power_15001max.csv'  # on server, max is set to 15001
    pc = pd.read_csv(power_curve)
    turbine = power_curve.split('/')[-1].split('_')[1].split('lw')[-1].upper()
    lease_areas = lease_areas or None

    if ht == '10m':
        u = nc['U10']
        v = nc['V10']
    else:
        u = nc.sel(height=int(ht[0:-1]))['U']
        v = nc.sel(height=int(ht[0:-1]))['V']

    color_label = f'Estimated {turbine} Wind Power (kW)'

    plot_types = ['full_grid', 'bight']
    for pt in plot_types:
        if pt == 'full_grid':  # subset the entire grid
            u_sub, _, _, _ = cf.subset_grid(u, model)
            v_sub, ax_lims, xticks, yticks = cf.subset_grid(v, model)
        else:  # subset just NY Bight
            new_fname = 'bight_{}'.format(figname.split('/')[-1])
            figname = '/{}/{}'.format(os.path.join(*figname.split('/')[0:-1]),
                                      new_fname)
            u_sub, _, _, _ = cf.subset_grid(u, 'bight')
            v_sub, ax_lims, xticks, yticks = cf.subset_grid(v, 'bight')

        fig, ax, lat, lon = cf.set_map(u_sub)

        # add text to the bottom of the plot
        cf.add_text(ax, nc.SIMULATION_START_DATE, nc.time_coverage_start,
                    model)

        # initialize keyword arguments for map features
        kwargs = dict()
        kwargs['xticks'] = xticks
        kwargs['yticks'] = yticks
        cf.add_map_features(ax, ax_lims, **kwargs)

        if lease_areas:
            pf.add_lease_area_polygon(ax, lease_areas, 'magenta')

        # calculate wind speed from u and v
        speed = cf.wind_uv_to_spd(u_sub, v_sub)

        # calculate wind power
        power = xr.DataArray(np.interp(speed, pc['Wind Speed'], pc['Power']),
                             coords=speed.coords)

        # add contours
        contour_list = [15000]
        pf.add_contours(ax, lon, lat, power, contour_list)

        # set color map
        cmap = plt.get_cmap('OrRd')
        levels = list(np.arange(0, 15001, 1000))

        # plot data
        # pcolormesh: coarser resolution, shows the actual resolution of the model data
        norm = BoundaryNorm(levels, ncolors=cmap.N, clip=True)

        kwargs = dict()
        kwargs['ttl'] = '{} {}'.format(ht, color_label)
        kwargs['cmap'] = cmap
        kwargs['clab'] = color_label
        kwargs['norm_clevs'] = norm
        kwargs['extend'] = 'neither'
        pf.plot_pcolormesh(fig, ax, lon, lat, power, **kwargs)

        # add power values of 15000 as another layer
        power_copy = power.copy()
        custom_color = ["#67000d"]  # dark red
        custom_colormap = ListedColormap(custom_color)
        mask = np.logical_and(power_copy.values < 15001,
                              power_copy.values < 15001)
        power_copy.values[mask] = np.nan
        ax.pcolormesh(lon,
                      lat,
                      power_copy,
                      cmap=custom_colormap,
                      transform=ccrs.PlateCarree())

        plt.savefig(figname, dpi=200)
        plt.close()
Ejemplo n.º 5
0
def plt_solar(nc, model, figname, lease_areas=None):
    """
    Create pcolor surface maps of total, diffuse, and direct shortwave flux with contours
    :param nc: netcdf file
    :param model: the model version that is being plotted, e.g. 3km or 9km
    :param figname: full file path to save directory and save filename
    :param lease_areas: optional dictionary containing lat/lon coordinates for wind energy lease area polygon
    """
    lease_areas = lease_areas or None

    varname = figname.split('/')[-1].split('_')[0]

    if varname == 'swdown':
        solar = nc['SWDOWN']
        title = r'Total Shortwave Flux (W $\rm m^{-2}$)'
    elif varname == 'diffuse':
        solar = nc['SWDOWN'] * nc['DIFFUSE_FRAC']
        title = r'Diffuse Shortwave Flux (W $\rm m^{-2}$)'
    elif varname == 'direct':
        solar = nc['SWDOWN'] * (1 - nc['DIFFUSE_FRAC'])
        title = r'Direct Shortwave Flux (W $\rm m^{-2}$)'

    plot_types = ['full_grid',
                  'bight']  # plot the full grid and just NY Bight area
    for pt in plot_types:
        if pt == 'full_grid':  # subset the entire grid
            solar_sub, ax_lims, xticks, yticks = cf.subset_grid(solar, model)
        else:  # subset just NY Bight
            new_fname = 'bight_{}'.format(figname.split('/')[-1])
            figname = '/{}/{}'.format(os.path.join(*figname.split('/')[0:-1]),
                                      new_fname)
            solar_sub, ax_lims, xticks, yticks = cf.subset_grid(solar, 'bight')

        fig, ax, lat, lon = cf.set_map(solar_sub)

        # add text to the bottom of the plot
        cf.add_text(ax, nc.SIMULATION_START_DATE, nc.time_coverage_start,
                    model)

        # initialize keyword arguments for map features
        kwargs = dict()
        kwargs['xticks'] = xticks
        kwargs['yticks'] = yticks

        # for diffuse shortwave flux, make state and coastline edgecolor gray, and make wind energy lease area magenta
        # for total and direct, change the state and coastline edgecolor to gray, and make wind energy lease area
        # magenta if solar radiation is beneath a certain threshold
        mingray = 100  # minimum average value for making the state/coastlines gray
        if varname == 'diffuse':
            kwargs['ecolor'] = '#525252'
            cf.add_map_features(ax, ax_lims, **kwargs)
            lease_area_color = 'magenta'
        else:
            if np.nanmean(solar_sub) < mingray:
                kwargs['ecolor'] = '#525252'
                cf.add_map_features(ax, ax_lims, **kwargs)
                lease_area_color = 'magenta'
            else:
                cf.add_map_features(ax, ax_lims, **kwargs)
                lease_area_color = '#252525'  # #252525 is very close to black

        if lease_areas:
            pf.add_lease_area_polygon(ax, lease_areas, lease_area_color)

        color_label = r'Surface Downwelling Shortwave Flux (W $\rm m^{-2}$)'  # \rm removes the italics
        contour_list = np.linspace(200, 1000, 5)

        # add contour lines
        pf.add_contours(ax, lon, lat, solar_sub, contour_list)

        # plot data
        # pcolormesh: coarser resolution, shows the actual resolution of the model data
        vlims = [0, 1200]
        cmap = plt.get_cmap(plt.cm.CMRmap)
        #levels = MaxNLocator(nbins=14).tick_values(vlims[0], vlims[1])  # every 100 W m-2
        levels = MaxNLocator(nbins=25).tick_values(vlims[0],
                                                   vlims[1])  # every 50 W m-2
        norm = BoundaryNorm(levels, ncolors=cmap.N, clip=True)

        kwargs = dict()
        kwargs['ttl'] = title
        kwargs['cmap'] = cmap
        kwargs['clab'] = color_label
        # kwargs['var_lims'] = vlims
        kwargs['norm_clevs'] = norm
        pf.plot_pcolormesh(fig, ax, lon, lat, solar_sub, **kwargs)

        plt.savefig(figname, dpi=200)
        plt.close()
def plt_windsp(nc, model, ht, figname, lease_areas=None):
    """
    Create pseudocolor surface maps of wind speed with quivers indicating wind direction.
    :param nc: netcdf file
    :param model: the model version that is being plotted, e.g. 3km or 9km
    :param ht: wind speed height to plot, e.g. 10m, 80m, 160m
    :param figname: full file path to save directory and save filename
    :param lease_areas: optional dictionary containing lat/lon coordinates for wind energy lease area polygon
    """
    lease_areas = lease_areas or None

    if ht == '10m':
        u = nc['U10']
        v = nc['V10']
    else:
        u = nc.sel(height=int(ht[0:-1]))['U']
        v = nc.sel(height=int(ht[0:-1]))['V']

    color_label = 'Wind Speed (knots)'

    # define the subsetting for the quivers on the map based on model and height
    quiver_subset = dict(_3km=dict(_10m=11, _80m=12, _160m=13),
                         _9km=dict(_10m=4, _80m=5, _160m=6),
                         bight_3km=dict(_10m=6, _80m=6, _160m=7),
                         bight_9km=dict(_10m=2, _80m=2, _160m=3))

    plot_types = ['full_grid', 'bight']
    for pt in plot_types:
        if pt == 'full_grid':  # subset the entire grid
            u_sub, _, _, _ = cf.subset_grid(u, model)
            v_sub, ax_lims, xticks, yticks = cf.subset_grid(v, model)
            qs = quiver_subset['_{}'.format(model)]['_{}'.format(ht)]
        else:  # subset just NY Bight
            new_fname = 'bight_{}'.format(figname.split('/')[-1])
            figname = '/{}/{}'.format(os.path.join(*figname.split('/')[0:-1]),
                                      new_fname)
            u_sub, _, _, _ = cf.subset_grid(u, 'bight')
            v_sub, ax_lims, xticks, yticks = cf.subset_grid(v, 'bight')
            qs = quiver_subset['bight_{}'.format(model)]['_{}'.format(ht)]

        fig, ax, lat, lon = cf.set_map(u_sub)

        # add text to the bottom of the plot
        cf.add_text(ax, nc.SIMULATION_START_DATE, nc.time_coverage_start,
                    model)

        # initialize keyword arguments for map features
        kwargs = dict()
        kwargs['xticks'] = xticks
        kwargs['yticks'] = yticks
        cf.add_map_features(ax, ax_lims, **kwargs)

        if lease_areas:
            pf.add_lease_area_polygon(ax, lease_areas, 'magenta')

        # convert wind speeds from m/s to knots
        u_sub = np.squeeze(u_sub.values) * 1.94384
        v_sub = np.squeeze(v_sub.values) * 1.94384

        # standardize the vectors so they only represent direction
        u_sub_standardize = u_sub / cf.wind_uv_to_spd(u_sub, v_sub)
        v_sub_standardize = v_sub / cf.wind_uv_to_spd(u_sub, v_sub)

        # calculate wind speed from u and v
        speed = cf.wind_uv_to_spd(u_sub, v_sub)

        # mask vectors if wind speed is < 2
        mask = speed < 2
        u_sub_standardize[mask] = np.nan
        v_sub_standardize[mask] = np.nan

        # add contours
        contour_list = [5, 10, 15, 20]
        pf.add_contours(ax, lon, lat, speed, contour_list)

        # plot data
        # pcolormesh: coarser resolution, shows the actual resolution of the model data
        cmap = plt.get_cmap('turbo')
        vlims = [0, 20]
        levels = MaxNLocator(nbins=20).tick_values(vlims[0],
                                                   vlims[1])  # every 2 knots
        norm = BoundaryNorm(levels, ncolors=cmap.N, clip=True)

        kwargs = dict()
        kwargs['ttl'] = 'Wind Speed ({}) Wind Ops'.format(ht)
        kwargs['cmap'] = cmap
        kwargs['clab'] = color_label
        kwargs['norm_clevs'] = norm
        kwargs['extend'] = 'neither'
        pf.plot_pcolormesh(fig, ax, lon, lat, speed, **kwargs)

        ax.quiver(lon[::qs, ::qs],
                  lat[::qs, ::qs],
                  u_sub_standardize[::qs, ::qs],
                  v_sub_standardize[::qs, ::qs],
                  scale=50,
                  width=.002,
                  headlength=4,
                  transform=ccrs.PlateCarree())

        plt.savefig(figname, dpi=200)
        plt.close()
def plt_windsp(nc,
               model,
               ht,
               figname,
               lease_areas=None,
               summary=None,
               add_text=None):
    """
    Create pseudocolor surface maps of wind speed with quivers indicating wind direction.
    :param nc: netcdf file
    :param model: the model version that is being plotted, e.g. 3km or 9km
    :param ht: wind speed height in mb to plot, e.g. 925
    :param figname: full file path to save directory and save filename
    :param lease_areas: optional dictionary containing lat/lon coordinates for wind energy lease area polygon
    :param summary: optional dictionary containing locations of specific locations for seabreeze classification,
    and a list to append windspeeds at specific locations for summary output
    :param add_text: optional, add windspeed/direction values at specific locations to the figure
    """
    lease_areas = lease_areas or None
    summary = summary or None
    add_text = add_text or None

    u = nc.sel(pressure=ht)['UP']
    v = nc.sel(pressure=ht)['VP']

    color_label = 'Wind Speed (m/s)'
    quiver_subset = dict(_3km=dict(_925=12),
                         _9km=dict(_925=4),
                         bight_3km=dict(_925=6),
                         bight_9km=dict(_925=2))

    plot_types = ['full_grid', 'bight']
    for pt in plot_types:
        if pt == 'full_grid':  # subset the entire grid
            u_sub, _, _, _ = cf.subset_grid(u, model)
            v_sub, ax_lims, xticks, yticks = cf.subset_grid(v, model)
            qs = quiver_subset['_{}'.format(model)]['_{}'.format(ht)]
        else:  # subset just NY Bight
            new_fname = 'bight_{}'.format(figname.split('/')[-1])
            figname = '/{}/{}'.format(os.path.join(*figname.split('/')[0:-1]),
                                      new_fname)
            u_sub, _, _, _ = cf.subset_grid(u, 'bight')
            v_sub, ax_lims, xticks, yticks = cf.subset_grid(v, 'bight')
            qs = quiver_subset['bight_{}'.format(model)]['_{}'.format(ht)]

        fig, ax, lat, lon = cf.set_map(u_sub)

        # add text to the bottom of the plot
        cf.add_text(ax, nc.SIMULATION_START_DATE, nc.time_coverage_start,
                    model)

        # initialize keyword arguments for map features
        kwargs = dict()
        kwargs['xticks'] = xticks
        kwargs['yticks'] = yticks
        cf.add_map_features(ax, ax_lims, **kwargs)

        if lease_areas:
            pf.add_lease_area_polygon(ax, lease_areas, 'magenta')

        # convert wind speeds from m/s to knots
        # u_sub = xr.DataArray(np.squeeze(u_sub.values) * 1.94384, coords=u_sub.coords)
        # v_sub = xr.DataArray(np.squeeze(v_sub.values) * 1.94384, coords=v_sub.coords)

        # standardize the vectors so they only represent direction
        u_sub_standardize = u_sub / cf.wind_uv_to_spd(u_sub, v_sub)
        v_sub_standardize = v_sub / cf.wind_uv_to_spd(u_sub, v_sub)

        # calculate wind speed and direction from u and v
        speed = cf.wind_uv_to_spd(u_sub, v_sub)
        direction = cf.wind_uv_to_dir(u_sub, v_sub)

        # write a summary for wind speeds/directions at specified locations for seabreeze classification
        # add the windspeeds/directions to the map
        map_values = dict()
        if summary:
            tmstr = pd.to_datetime(
                nc.Time.values[0]).strftime('%Y-%m-%dT%H:%M')
            for key, coords in summary['locations'].items():
                # find the closest model grid point to the location
                a = abs(speed.XLAT - coords['lat']) + abs(speed.XLONG -
                                                          coords['lon'])
                i, j = np.unravel_index(a.argmin(), a.shape)
                sp = speed[i, j]
                d = direction[i, j]
                coords.update(ws=np.round(float(sp.values), 2))
                coords.update(direction=np.round(float(d.values), 2))
                map_values[key] = coords
                if pt == 'full_grid':
                    wrf_lat = np.round(float(sp.XLAT.values), 4)
                    wrf_lon = np.round(float(sp.XLONG.values), 4)
                    summary['rows'].append([
                        tmstr, key, coords['lat'], coords['lon'], ht, wrf_lat,
                        wrf_lon,
                        np.round(float(sp.values), 4),
                        np.round(float(d.values), 4)
                    ])

        # mask vectors if wind speed is < 1 m/s
        mask = speed.values < 1
        u_sub_standardize.values[mask] = np.nan
        v_sub_standardize.values[mask] = np.nan

        # add contours
        #contour_list = [10, 22, 34, 48, 64]
        contour_list = [5, 11, 17, 25, 32]
        pf.add_contours(ax, lon, lat, speed, contour_list)

        # plot data
        # pcolormesh: coarser resolution, shows the actual resolution of the model data
        cmap = plt.get_cmap('BuPu')
        # vlims = [0, 40]
        # levels = MaxNLocator(nbins=20).tick_values(vlims[0], vlims[1])  # every 2 knots
        vlims = [0, 25]
        levels = MaxNLocator(nbins=25).tick_values(vlims[0],
                                                   vlims[1])  # every 1 m/s
        norm = BoundaryNorm(levels, ncolors=cmap.N, clip=True)

        kwargs = dict()
        kwargs['ttl'] = '{}mb {}'.format(ht, color_label)
        kwargs['cmap'] = cmap
        kwargs['clab'] = color_label
        #kwargs['var_lims'] = vlims
        kwargs['norm_clevs'] = norm
        kwargs['extend'] = 'max'
        pf.plot_pcolormesh(fig, ax, lon, lat, speed, **kwargs)

        # # contourf: smooths the resolution of the model data, plots are less pixelated
        # kwargs = dict()
        # kwargs['ttl'] = '{} {}'.format(ht, color_label)
        # kwargs['cmap'] = cmap
        # kwargs['clab'] = color_label
        # kwargs['var_lims'] = [0, 40]
        # kwargs['cbar_ticks'] = np.linspace(0, 40, 9)
        #
        # levels = np.arange(0, 40.1, .1)
        # pf.plot_contourf(fig, ax, lon, lat, speed, levels, **kwargs)

        # subset the quivers and add as a layer
        # ax.quiver(lon[::qs, ::qs], lat[::qs, ::qs], u_sub[::qs, ::qs], v_sub[::qs, ::qs], scale=1000,
        #           width=.002, headlength=4, transform=ccrs.PlateCarree())

        ax.quiver(lon[::qs, ::qs],
                  lat[::qs, ::qs],
                  u_sub_standardize.values[::qs, ::qs],
                  v_sub_standardize.values[::qs, ::qs],
                  scale=50,
                  width=.002,
                  headlength=4,
                  transform=ccrs.PlateCarree())

        # add the seabreeze classification locations to the map
        if summary:
            if pt == 'full_grid':
                offset = 1.75
            else:
                offset = .85
            for key, values in map_values.items():
                ax.scatter(values['lon'],
                           values['lat'],
                           c='magenta',
                           s=40,
                           zorder=15,
                           transform=ccrs.PlateCarree())
                if add_text:
                    ax.text(values['lon'] - offset,
                            values['lat'],
                            '{} {}'.format(values['ws'], values['direction']),
                            transform=ccrs.PlateCarree(),
                            bbox=dict(facecolor='lightgray', alpha=1),
                            fontsize=8,
                            zorder=15)

        plt.savefig(figname, dpi=200)
        plt.close()