Beispiel #1
0
def test_smooth_n_pt_wrong_number():
    """Test the smooth_n_pt function using wrong number of points."""
    hght = np.array([[5640., 5640., 5640., 5640., 5640.],
                    [5684., 5676., 5666., 5659., 5651.],
                    [5728., 5712., 5692., 5678., 5662.],
                    [5772., 5748., 5718., 5697., 5673.],
                    [5816., 5784., 5744., 5716., 5684.]])
    with pytest.raises(ValueError):
        smooth_n_point(hght, 7)
Beispiel #2
0
def test_smooth_n_pt_wrong_number():
    """Test the smooth_n_pt function using wrong number of points."""
    hght = np.array([[5640., 5640., 5640., 5640., 5640.],
                     [5684., 5676., 5666., 5659., 5651.],
                     [5728., 5712., 5692., 5678., 5662.],
                     [5772., 5748., 5718., 5697., 5673.],
                     [5816., 5784., 5744., 5716., 5684.]])
    with pytest.raises(ValueError):
        smooth_n_point(hght, 7)
Beispiel #3
0
def test_smooth_n_pt_9_units():
    """Test the smooth_n_pt function using 9 points with units."""
    hght = np.array([[5640., 5640., 5640., 5640., 5640.],
                     [5684., 5676., 5666., 5659., 5651.],
                     [5728., 5712., 5692., 5678., 5662.],
                     [5772., 5748., 5718., 5697., 5673.],
                     [5816., 5784., 5744., 5716., 5684.]]) * units.meter
    shght = smooth_n_point(hght, 9, 1)
    s_true = np.array([[5640., 5640., 5640., 5640., 5640.],
                       [5684., 5675.5, 5666.75, 5658.75, 5651.],
                       [5728., 5711., 5693.5, 5677.5, 5662.],
                       [5772., 5746.5, 5720.25, 5696.25, 5673.],
                       [5816., 5784., 5744., 5716., 5684.]]) * units.meter
    assert_array_almost_equal(shght, s_true)
Beispiel #4
0
def test_smooth_n_pt_9_units():
    """Test the smooth_n_pt function using 9 points with units."""
    hght = np.array([[5640., 5640., 5640., 5640., 5640.],
                    [5684., 5676., 5666., 5659., 5651.],
                    [5728., 5712., 5692., 5678., 5662.],
                    [5772., 5748., 5718., 5697., 5673.],
                    [5816., 5784., 5744., 5716., 5684.]]) * units.meter
    shght = smooth_n_point(hght, 9, 1)
    s_true = np.array([[5640., 5640., 5640., 5640., 5640.],
                      [5684., 5675.5, 5666.75, 5658.75, 5651.],
                      [5728., 5711., 5693.5, 5677.5, 5662.],
                      [5772., 5746.5, 5720.25, 5696.25, 5673.],
                      [5816., 5784., 5744., 5716., 5684.]]) * units.meter
    assert_array_almost_equal(shght, s_true)
Beispiel #5
0
def test_smooth_n_pt_temperature():
    """Test the smooth_n_pt function with temperature units."""
    t = np.array([[2.73, 3.43, 6.53, 7.13, 4.83], [
        3.73, 4.93, 6.13, 6.63, 8.23
    ], [3.03, 4.83, 6.03, 7.23, 7.63], [3.33, 4.63, 7.23, 6.73, 6.23],
                  [3.93, 3.03, 7.43, 9.23, 9.23]]) * units.degC

    smooth_t = smooth_n_point(t, 9, 1)
    smooth_t_true = np.array([[2.73, 3.43, 6.53, 7.13, 4.83],
                              [3.73, 4.6425, 5.96125, 6.81124, 8.23],
                              [3.03, 4.81125, 6.1175, 6.92375, 7.63],
                              [3.33, 4.73625, 6.43, 7.3175, 6.23],
                              [3.93, 3.03, 7.43, 9.23, 9.23]]) * units.degC
    assert_array_almost_equal(smooth_t, smooth_t_true, 4)
Beispiel #6
0
def test_smooth_n_pt_5():
    """Test the smooth_n_pt function using 5 points."""
    hght = np.array([[5640., 5640., 5640., 5640., 5640.],
                    [5684., 5676., 5666., 5659., 5651.],
                    [5728., 5712., 5692., 5678., 5662.],
                    [5772., 5748., 5718., 5697., 5673.],
                    [5816., 5784., 5744., 5716., 5684.]])
    shght = smooth_n_point(hght, 5, 1)
    s_true = np.array([[5640., 5640., 5640., 5640., 5640.],
                      [5684., 5675.75, 5666.375, 5658.875, 5651.],
                      [5728., 5711.5, 5692.75, 5677.75, 5662.],
                      [5772., 5747.25, 5719.125, 5696.625, 5673.],
                      [5816., 5784., 5744., 5716., 5684.]])
    assert_array_almost_equal(shght, s_true)
Beispiel #7
0
def test_smooth_n_pt_5():
    """Test the smooth_n_pt function using 5 points."""
    hght = np.array([[5640., 5640., 5640., 5640., 5640.],
                     [5684., 5676., 5666., 5659., 5651.],
                     [5728., 5712., 5692., 5678., 5662.],
                     [5772., 5748., 5718., 5697., 5673.],
                     [5816., 5784., 5744., 5716., 5684.]])
    shght = smooth_n_point(hght, 5, 1)
    s_true = np.array([[5640., 5640., 5640., 5640., 5640.],
                       [5684., 5675.75, 5666.375, 5658.875, 5651.],
                       [5728., 5711.5, 5692.75, 5677.75, 5662.],
                       [5772., 5747.25, 5719.125, 5696.625, 5673.],
                       [5816., 5784., 5744., 5716., 5684.]])
    assert_array_almost_equal(shght, s_true)
Beispiel #8
0
def test_smooth_n_pt_9_repeat():
    """Test the smooth_n_pt function using 9 points with two passes."""
    hght = np.array([[5640., 5640., 5640., 5640., 5640.],
                    [5684., 5676., 5666., 5659., 5651.],
                    [5728., 5712., 5692., 5678., 5662.],
                    [5772., 5748., 5718., 5697., 5673.],
                    [5816., 5784., 5744., 5716., 5684.]])
    shght = smooth_n_point(hght, 9, 2)
    s_true = np.array([[5640., 5640., 5640., 5640., 5640.],
                      [5684., 5675.4375, 5666.9375, 5658.8125, 5651.],
                      [5728., 5710.875, 5693.875, 5677.625, 5662.],
                      [5772., 5746.375, 5720.625, 5696.375, 5673.],
                      [5816., 5784., 5744., 5716., 5684.]])
    assert_array_almost_equal(shght, s_true)
Beispiel #9
0
def test_smooth_n_pt_9_repeat():
    """Test the smooth_n_pt function using 9 points with two passes."""
    hght = np.array([[5640., 5640., 5640., 5640., 5640.],
                     [5684., 5676., 5666., 5659., 5651.],
                     [5728., 5712., 5692., 5678., 5662.],
                     [5772., 5748., 5718., 5697., 5673.],
                     [5816., 5784., 5744., 5716., 5684.]])
    shght = smooth_n_point(hght, 9, 2)
    s_true = np.array([[5640., 5640., 5640., 5640., 5640.],
                       [5684., 5675.4375, 5666.9375, 5658.8125, 5651.],
                       [5728., 5710.875, 5693.875, 5677.625, 5662.],
                       [5772., 5746.375, 5720.625, 5696.375, 5673.],
                       [5816., 5784., 5744., 5716., 5684.]])
    assert_array_almost_equal(shght, s_true)
Beispiel #10
0
def plot_files(dss, **args):
    # Using args we don't have to change the prototype function if we want to add other parameters!
    first = True
    for time_sel in dss.time:
        data = dss.sel(time=time_sel)
        data['prmsl'].values = mpcalc.smooth_n_point(data['prmsl'].values, n=9, passes=10)
        time, run, cum_hour = get_time_run_cum(data)
        # Build the name of the output image
        filename = subfolder_images[projection] + '/' + variable_name + '_%s.png' % cum_hour

        cs = args['ax'].contourf(args['x'], args['y'],
                                 data['geop'],
                                 extend='both', 
                                 cmap=args['cmap'],
                                 levels=args['levels_gph'])

        c = args['ax'].contour(args['x'], args['y'],
                               data['prmsl'], 
                               levels=args['levels_mslp'],
                               colors='white', 
                               linewidths=1.5)

        labels = args['ax'].clabel(c, c.levels, inline=True, fmt='%4.0f', 
                                   fontsize=6)

        maxlabels = plot_maxmin_points(args['ax'], args['x'], args['y'], data['prmsl'],
                                        'max', 100, symbol='H', color='royalblue', random=True)
        minlabels = plot_maxmin_points(args['ax'], args['x'], args['y'], data['prmsl'],
                                        'min', 100, symbol='L', color='coral', random=True)

        an_fc = annotation_forecast(args['ax'], time)
        an_var = annotation(args['ax'], 
            'Geopotential height @500hPa [m] and MSLP (hPa)',
             loc='lower left', fontsize=6)
        an_run = annotation_run(args['ax'], run)
        logo = add_logo_on_map(ax=args['ax'],
                                zoom=0.1, pos=(0.95, 0.08))

        if first:
            plt.colorbar(cs, orientation='horizontal', label='Geopotential height [m]', pad=0.03, fraction=0.04)

        if debug:
            plt.show(block=True)
        else:
            plt.savefig(filename, **options_savefig)        

        remove_collections([c, cs, labels, an_fc, an_var, an_run, maxlabels, minlabels, logo])

        first = False 
Beispiel #11
0
def test_smooth_n_pt_5(array_type):
    """Test the smooth_n_pt function using 5 points."""
    hght = np.array([[5640., 5640., 5640., 5640., 5640.],
                     [5684., 5676., 5666., 5659., 5651.],
                     [5728., 5712., 5692., 5678., 5662.],
                     [5772., 5748., 5718., 5697., 5673.],
                     [5816., 5784., 5744., 5716., 5684.]])
    mask = np.zeros_like(hght)
    mask[::2, ::2] = 1
    hght = array_type(hght, '', mask=mask)

    shght = smooth_n_point(hght, 5, 1)
    s_true = array_type([[5640., 5640., 5640., 5640., 5640.],
                         [5684., 5675.75, 5666.375, 5658.875, 5651.],
                         [5728., 5711.5, 5692.75, 5677.75, 5662.],
                         [5772., 5747.25, 5719.125, 5696.625, 5673.],
                         [5816., 5784., 5744., 5716., 5684.]], '')
    assert_array_almost_equal(shght, s_true)
Beispiel #12
0
def test_smooth_n_pt_3d_units():
    """Test the smooth_n_point function with a 3D array with units."""
    hght = [[[5640.0, 5640.0, 5640.0, 5640.0, 5640.0],
             [5684.0, 5676.0, 5666.0, 5659.0, 5651.0],
             [5728.0, 5712.0, 5692.0, 5678.0, 5662.0],
             [5772.0, 5748.0, 5718.0, 5697.0, 5673.0],
             [5816.0, 5784.0, 5744.0, 5716.0, 5684.0]],
            [[6768.0, 6768.0, 6768.0, 6768.0, 6768.0],
             [6820.8, 6811.2, 6799.2, 6790.8, 6781.2],
             [6873.6, 6854.4, 6830.4, 6813.6, 6794.4],
             [6926.4, 6897.6, 6861.6, 6836.4, 6807.6],
             [6979.2, 6940.8, 6892.8, 6859.2, 6820.8]]] * units.m
    shght = smooth_n_point(hght, 9, 2)
    s_true = [[[5640., 5640., 5640., 5640., 5640.],
               [5684., 5675.4375, 5666.9375, 5658.8125, 5651.],
               [5728., 5710.875, 5693.875, 5677.625, 5662.],
               [5772., 5746.375, 5720.625, 5696.375, 5673.],
               [5816., 5784., 5744., 5716., 5684.]],
              [[6768., 6768., 6768., 6768., 6768.],
               [6820.8, 6810.525, 6800.325, 6790.575, 6781.2],
               [6873.6, 6853.05, 6832.65, 6813.15, 6794.4],
               [6926.4, 6895.65, 6864.75, 6835.65, 6807.6],
               [6979.2, 6940.8, 6892.8, 6859.2, 6820.8]]] * units.m
    assert_array_almost_equal(shght, s_true)
Beispiel #13
0
# Set subset slice for the geographic extent of data to limit download
lon_slice = slice(200, 350)
lat_slice = slice(85, 10)

# Grab lat/lon values (GFS will be 1D)
lats = ds.lat.sel(lat=lat_slice).values
lons = ds.lon.sel(lon=lon_slice).values

# Grab the pressure levels and select the data to be imported
# Need all pressure levels for Temperatures, U and V Wind, and Rel. Humidity
# Smooth with the gaussian filter from scipy
pres = ds['isobaric3'].values[:] * units('Pa')

tmpk_var = ds['Temperature_isobaric'].metpy.sel(lat=lat_slice,
                                                lon=lon_slice).squeeze()
tmpk = mpcalc.smooth_n_point(tmpk_var, 9, 2)
thta = mpcalc.potential_temperature(pres[:, None, None], tmpk)

uwnd_var = ds['u-component_of_wind_isobaric'].metpy.sel(
    lat=lat_slice, lon=lon_slice).squeeze()
vwnd_var = ds['v-component_of_wind_isobaric'].metpy.sel(
    lat=lat_slice, lon=lon_slice).squeeze()
uwnd = mpcalc.smooth_n_point(uwnd_var, 9, 2)
vwnd = mpcalc.smooth_n_point(vwnd_var, 9, 2)

# Create a clean datetime object for plotting based on time of Geopotential heights
vtime = ds.time.data[0].astype('datetime64[ms]').astype('O')

######################################################################
# Use MetPy to compute the baroclinic potential vorticity on all isobaric
# levels and other variables
                va='center',
                transform=axes[1, 0].transAxes)

for i, tidx in enumerate([36, 48, 60]):

    ds1 = metpy_temp_adv(fname1, plevs, tidx)
    ds2 = metpy_temp_adv(fname2, plevs, tidx)
    ds3 = ds2 - ds1

    plev = 850

    ax = axes[0, i]

    cf = ax.contourf(ds2.lon,
                     ds2.lat,
                     mpcalc.smooth_n_point(ds2.accrain.values, 9),
                     clevs,
                     cmap=cmap,
                     norm=norm,
                     extend='max')
    #cf = ax.contourf(ds2.lon, ds2.lat, ndimage.gaussian_filter(ds2.accrain.values, sigma=3, order=0),
    #        clevs, cmap=cmap, norm=norm, extend='max')

    #cs = ax.contour(ds2.lon, ds2.lat, mpcalc.smooth_n_point(ds2.z.sel(level=plev).values/9.8, 9),
    #        np.arange(1300,1580,10), colors='grey', linewidths=1)
    #ax.clabel(cs, fontsize=7, inline=1, inline_spacing=3, fmt='%im')

    fmin = np.min(mpcalc.smooth_n_point(ds2.accrain.values, 9))
    fmax = np.max(mpcalc.smooth_n_point(ds2.accrain.values, 9))
    ax.set_title('Min/Max = {:0.1f}/{:0.1f} mm'.format(np.array(fmin),
                                                       np.array(fmax)),
Beispiel #15
0
def plot_files(dss, **args):
    first = True
    for time_sel in dss.time:
        data = dss.sel(time=time_sel)
        data['prmsl'].values = mpcalc.smooth_n_point(data['prmsl'].values,
                                                     n=9,
                                                     passes=10)
        time, run, cum_hour = get_time_run_cum(data)
        # Build the name of the output image
        filename = subfolder_images[
            projection] + '/' + variable_name + '_%s.png' % cum_hour

        cs = args['ax'].contourf(args['x'],
                                 args['y'],
                                 data['tp'],
                                 extend='max',
                                 cmap=args['cmap'],
                                 norm=args['norm'],
                                 levels=args['levels_precip'])

        c = args['ax'].contour(args['x'],
                               args['y'],
                               data['prmsl'],
                               levels=args['levels_mslp'],
                               colors='black',
                               linewidths=1.)

        labels = args['ax'].clabel(c,
                                   c.levels,
                                   inline=True,
                                   fmt='%4.0f',
                                   fontsize=6)

        maxlabels = plot_maxmin_points(args['ax'],
                                       args['x'],
                                       args['y'],
                                       data['prmsl'],
                                       'max',
                                       150,
                                       symbol='H',
                                       color='royalblue',
                                       random=True)
        minlabels = plot_maxmin_points(args['ax'],
                                       args['x'],
                                       args['y'],
                                       data['prmsl'],
                                       'min',
                                       150,
                                       symbol='L',
                                       color='coral',
                                       random=True)

        an_fc = annotation_forecast(args['ax'], time)
        an_var = annotation(args['ax'],
                            'Accumulated precipitation and MSLP [hPa]',
                            loc='lower left',
                            fontsize=6)
        an_run = annotation_run(args['ax'], run)
        logo = add_logo_on_map(ax=args['ax'], zoom=0.1, pos=(0.95, 0.08))

        if first:
            plt.colorbar(cs,
                         orientation='horizontal',
                         label='Accumulated precipitation [mm]',
                         pad=0.035,
                         fraction=0.04)

        if debug:
            plt.show(block=True)
        else:
            plt.savefig(filename, **options_savefig)

        remove_collections(
            [c, cs, labels, an_fc, an_var, an_run, logo, maxlabels, minlabels])

        first = False
Beispiel #16
0
# Add geopolitical boundaries for map reference
ax1.add_feature(cfeature.COASTLINE.with_scale('50m'))
ax1.add_feature(cfeature.LAKES.with_scale('50m'), color='black', linewidths=0.5)

# Set some titles
plt.title('Hovmoller Diagram', loc='left')
plt.title('ERA5 Reanalysis', loc='right')

# Bottom plot for Hovmoller diagram
ax2 = fig.add_subplot(gs[1, 0])
ax2.invert_yaxis()  # Reverse the time order to do oldest first

# Plot of chosen variable averaged over latitude and slightly smoothed
clevs = np.arange(-25, 25, 2.5)
cf = ax2.contourf(lons, vtimes, mpcalc.smooth_n_point(
    avg_data, 9, 2), clevs, cmap=plt.cm.bwr, extend='both')
cs = ax2.contour(lons, vtimes, mpcalc.smooth_n_point(
    avg_data, 9, 2), clevs, colors='k', linewidths=0.5)
cbar = plt.colorbar(cf, orientation='horizontal', pad=0.05, aspect=50, extendrect=True)
cbar.set_label('m $s^{-1}$')

# Make some ticks and tick labels
ax2.set_xticks([100, 120, 140, 160])
ax2.set_xticklabels(x_tick_labels)
ax2.set_yticks(vtimes[5::24])
ax2.set_yticklabels(vtimes[5::24])
ax2.yaxis.set_major_formatter(DateFormatter('%Y'))


# Set some titles
plt.title('Potential intensity (m/s)', loc='left', fontsize=10)
Beispiel #17
0
# Set subset slice for the geographic extent of data to limit download
lon_slice = slice(200, 350)
lat_slice = slice(85, 10)

# Grab lat/lon values (GFS will be 1D)
lats = ds.lat.sel(lat=lat_slice).values
lons = ds.lon.sel(lon=lon_slice).values

# Grab the pressure levels and select the data to be imported
# Need all pressure levels for Temperatures, U and V Wind, and Rel. Humidity
# Smooth with the gaussian filter from scipy
pres = ds['isobaric3'].values[:] * units('Pa')

tmpk_var = ds['Temperature_isobaric'].sel(lat=lat_slice,
                                          lon=lon_slice).values[0]
tmpk = mpcalc.smooth_n_point(tmpk_var, 9, 2) * units.K
thta = mpcalc.potential_temperature(pres[:, None, None], tmpk)

uwnd_var = ds['u-component_of_wind_isobaric'].sel(lat=lat_slice,
                                                  lon=lon_slice).values[0]
vwnd_var = ds['v-component_of_wind_isobaric'].sel(lat=lat_slice,
                                                  lon=lon_slice).values[0]
uwnd = mpcalc.smooth_n_point(uwnd_var, 9, 2) * (units.meter / units.second)
vwnd = mpcalc.smooth_n_point(vwnd_var, 9, 2) * (units.meter / units.second)

# Create a clean datetime object for plotting based on time of Geopotential heights
vtime = ds.time.data[0].astype('datetime64[ms]').astype('O')

######################################################################
# Use MetPy to compute the baroclinic potential vorticity on all isobaric
# levels and other variables
Beispiel #18
0
def plot_files(dss, **args):
    first = True
    for time_sel in dss.time:
        data = dss.sel(time=time_sel)
        data['prmsl'].values = mpcalc.smooth_n_point(data['prmsl'].values,
                                                     n=9,
                                                     passes=10)
        time, run, cum_hour = get_time_run_cum(data)
        # Build the name of the output image
        filename = subfolder_images[
            projection] + '/' + variable_name + '_%s.png' % cum_hour

        cs = args['ax'].contourf(args['x'],
                                 args['y'],
                                 data['VMAX_10M'],
                                 extend='max',
                                 cmap=args['cmap'],
                                 levels=args['levels_winds_10m'])

        c = args['ax'].contour(args['x'],
                               args['y'],
                               data['prmsl'],
                               levels=args['levels_mslp'],
                               colors='red',
                               linewidths=1.)

        labels = args['ax'].clabel(c,
                                   c.levels,
                                   inline=True,
                                   fmt='%4.0f',
                                   fontsize=6)

        maxlabels = plot_maxmin_points(args['ax'],
                                       args['x'],
                                       args['y'],
                                       data['prmsl'],
                                       'max',
                                       100,
                                       symbol='H',
                                       color='royalblue',
                                       random=True)
        minlabels = plot_maxmin_points(args['ax'],
                                       args['x'],
                                       args['y'],
                                       data['prmsl'],
                                       'min',
                                       100,
                                       symbol='L',
                                       color='coral',
                                       random=True)

        # We need to reduce the number of points before plotting the vectors,
        # these values work pretty well
        density = 15

        cv = args['ax'].quiver(args['x'][::density, ::density],
                               args['y'][::density, ::density],
                               data['10u'][::density, ::density],
                               data['10v'][::density, ::density],
                               scale=None,
                               alpha=0.5,
                               color='gray')

        an_fc = annotation_forecast(args['ax'], time)
        an_var = annotation(args['ax'],
                            '10m Winds direction and max. wind gust',
                            loc='lower left',
                            fontsize=6)
        an_run = annotation_run(args['ax'], run)
        logo = add_logo_on_map(ax=args['ax'], zoom=0.1, pos=(0.95, 0.08))

        if first:
            plt.colorbar(cs,
                         orientation='horizontal',
                         label='Wind [km/h]',
                         pad=0.03,
                         fraction=0.03)

        if debug:
            plt.show(block=True)
        else:
            plt.savefig(filename, **options_savefig)

        remove_collections([
            c, cs, labels, an_fc, an_var, an_run, cv, maxlabels, minlabels,
            logo
        ])

        first = False
def metpy_read_wrf_cross(fname, plevels, tidx_in, lons_out, lats_out, start,
                         end):

    ds = xr.open_dataset(fname).metpy.parse_cf().squeeze()
    ds = ds.isel(Time=tidx)
    print(ds)

    ds1 = xr.Dataset()

    p = units.Quantity(to_np(ds.p), 'hPa')
    z = units.Quantity(to_np(ds.z), 'meter')
    u = units.Quantity(to_np(ds.u), 'm/s')
    v = units.Quantity(to_np(ds.v), 'm/s')
    w = units.Quantity(to_np(ds.w), 'm/s')
    tk = units.Quantity(to_np(ds.tk), 'kelvin')
    th = units.Quantity(to_np(ds.th), 'kelvin')
    eth = units.Quantity(to_np(ds.eth), 'kelvin')
    wspd = units.Quantity(to_np(ds.wspd), 'm/s')
    omega = units.Quantity(to_np(ds.omega), 'Pa/s')

    plevels_unit = plevels * units.hPa
    z, u, v, w, tk, th, eth, wspd, omega = log_interpolate_1d(plevels_unit,
                                                              p,
                                                              z,
                                                              u,
                                                              v,
                                                              w,
                                                              tk,
                                                              th,
                                                              eth,
                                                              wspd,
                                                              omega,
                                                              axis=0)

    coords, dims = [plevs, ds.lat.values,
                    ds.lon.values], ["level", "lat", "lon"]
    for name, var in zip(
        ['z', 'u', 'v', 'w', 'tk', 'th', 'eth', 'wspd', 'omega'],
        [z, u, v, w, tk, th, eth, wspd, omega]):
        #g = ndimage.gaussian_filter(var, sigma=3, order=0)
        ds1[name] = xr.DataArray(to_np(mpcalc.smooth_n_point(var, 9)),
                                 coords=coords,
                                 dims=dims)

    dx, dy = mpcalc.lat_lon_grid_deltas(ds.lon.values * units('degrees_E'),
                                        ds.lat.values * units('degrees_N'))

    # Calculate temperature advection using metpy function
    for i, plev in enumerate(plevs):

        adv = mpcalc.advection(eth[i, :, :], [u[i, :, :], v[i, :, :]],
                               (dx, dy),
                               dim_order='yx') * units('K/sec')
        adv = ndimage.gaussian_filter(adv, sigma=3, order=0) * units('K/sec')
        ds1['eth_adv_{:03d}'.format(plev)] = xr.DataArray(
            np.array(adv),
            coords=[ds.lat.values, ds.lon.values],
            dims=["lat", "lon"])

        div = mpcalc.divergence(u[i, :, :], v[i, :, :], dx, dy, dim_order='yx')
        div = ndimage.gaussian_filter(div, sigma=3, order=0) * units('1/sec')
        ds1['div_{:03d}'.format(plev)] = xr.DataArray(
            np.array(div),
            coords=[ds.lat.values, ds.lon.values],
            dims=["lat", "lon"])

    ds1['accrain'] = xr.DataArray(ds.accrain.values,
                                  coords=[ds.lat.values, ds.lon.values],
                                  dims=["lat", "lon"])
    eth2 = mpcalc.equivalent_potential_temperature(
        ds.slp.values * units.hPa, ds.t2m.values * units('K'),
        ds.td2.values * units('celsius'))
    ds1['eth2'] = xr.DataArray(eth2,
                               coords=[ds.lat.values, ds.lon.values],
                               dims=["lat", "lon"])
    #ds1['sst'] = xr.DataArray(ndimage.gaussian_filter(ds.sst.values, sigma=3, order=0)-273.15, coords=[ds.lat.values,ds.lon.values], dims=["lat","lon"])
    ds1 = ds1.metpy.parse_cf().squeeze()

    cross = cross_section(ds1, start, end).set_coords(('lat', 'lon'))
    cross.u.attrs['units'] = 'm/s'
    cross.v.attrs['units'] = 'm/s'

    cross['t_wind'], cross['n_wind'] = mpcalc.cross_section_components(
        cross['u'], cross['v'])

    weights = np.cos(np.deg2rad(ds.lat))
    ds_weighted = ds.weighted(weights)
    weighted = ds_weighted.mean(("lat"))

    return ds1, cross, weighted
Beispiel #20
0
def PV_Div_uv(initial_time=None, fhour=6, day_back=0,model='ECMWF',
    map_ratio=19/9,zoom_ratio=20,cntr_pnt=[102,34],
    levels=[1000, 950, 925, 900, 850, 800, 700,600,500,400,300,250,200,100],lvl_ana=250,
    Global=False,
    south_China_sea=True,area = '全国',city=False,output_dir=None
     ):

    # micaps data directory
    try:
        data_dir = [utl.Cassandra_dir(data_type='high',data_source=model,var_name='RH',lvl=''),
                    utl.Cassandra_dir(data_type='high',data_source=model,var_name='UGRD',lvl=''),
                    utl.Cassandra_dir(data_type='high',data_source=model,var_name='VGRD',lvl=''),
                    utl.Cassandra_dir(data_type='high',data_source=model,var_name='TMP',lvl=''),
                    utl.Cassandra_dir(data_type='high',data_source=model,var_name='HGT',lvl='')]
    except KeyError:
        raise ValueError('Can not find all directories needed')

    # get filename
    if(initial_time != None):
        filename = utl.model_filename(initial_time, fhour)
    else:
        filename=utl.filename_day_back_model(day_back=day_back,fhour=fhour)
        
    # retrieve data from micaps server
    rh=get_model_3D_grid(directory=data_dir[0][0:-1],filename=filename,levels=levels, allExists=False)
    if rh is None:
        return

    u=get_model_3D_grid(directory=data_dir[1][0:-1],filename=filename,levels=levels, allExists=False)
    if u is None:
        return

    v=get_model_3D_grid(directory=data_dir[2][0:-1],filename=filename,levels=levels, allExists=False)
    if v is None:
        return

    t=get_model_3D_grid(directory=data_dir[3][0:-1],filename=filename,levels=levels, allExists=False)
    if t is None:
        return

    # get filename
    if(initial_time != None):
        filename = utl.model_filename(initial_time, fhour)
    else:
        filename=utl.filename_day_back_model(day_back=day_back,fhour=fhour)

    lats = np.squeeze(rh['lat'].values)
    lons = np.squeeze(rh['lon'].values)

    pres = np.array(levels)*100 * units('Pa')
    tmpk = mpcalc.smooth_n_point(t['data'].values.squeeze(), 9, 2)*units('degC')
    thta = mpcalc.potential_temperature(pres[:, None, None], tmpk)

    uwnd = mpcalc.smooth_n_point(u['data'].values.squeeze(), 9, 2)*units.meter/units.second
    vwnd = mpcalc.smooth_n_point(v['data'].values.squeeze(), 9, 2)*units.meter/units.second

    dx, dy = mpcalc.lat_lon_grid_deltas(lons, lats)

    # Comput the PV on all isobaric surfaces
    pv = mpcalc.potential_vorticity_baroclinic(thta, pres[:, None, None], uwnd, vwnd,
                                            dx[None, :, :], dy[None, :, :],
                                            lats[None, :, None] * units('degrees'))
    div = mpcalc.divergence(uwnd, vwnd, dx[None, :, :], dy[None, :, :], dim_order='yx')

    # prepare data
    idx_z1 = list(pres.m).index(((lvl_ana * units('hPa')).to(pres.units)).m)
    if(area != None):
        cntr_pnt,zoom_ratio=utl.get_map_area(area_name=area)

    map_extent=[0,0,0,0]
    map_extent[0]=cntr_pnt[0]-zoom_ratio*1*map_ratio
    map_extent[1]=cntr_pnt[0]+zoom_ratio*1*map_ratio
    map_extent[2]=cntr_pnt[1]-zoom_ratio*1
    map_extent[3]=cntr_pnt[1]+zoom_ratio*1

    delt_x=(map_extent[1]-map_extent[0])*0.2
    delt_y=(map_extent[3]-map_extent[2])*0.1

    #+ to solve the problem of labels on all the contours
    idx_x1 = np.where((lons > map_extent[0]-delt_x) & 
        (lons < map_extent[1]+delt_x))
    idx_y1 = np.where((lats > map_extent[2]-delt_y) & 
        (lats < map_extent[3]+delt_y))
    #- to solve the problem of labels on all the contours
    init_time = u.coords['forecast_reference_time'].values
    pv = {
        'lon': lons[idx_x1],
        'lat': lats[idx_y1],
        'data': np.array(pv)[idx_z1,idx_y1[0][0]:(idx_y1[0][-1]+1),idx_x1[0][0]:(idx_x1[0][-1]+1)],
        'lev':str(lvl_ana),
        'model':model,
        'fhour':fhour,
        'init_time':init_time}
    uv = {
        'lon': lons[idx_x1],
        'lat': lats[idx_y1],
        'udata': np.array(uwnd)[idx_z1,idx_y1[0][0]:(idx_y1[0][-1]+1),idx_x1[0][0]:(idx_x1[0][-1]+1)],
        'vdata': np.array(vwnd)[idx_z1,idx_y1[0][0]:(idx_y1[0][-1]+1),idx_x1[0][0]:(idx_x1[0][-1]+1)],
        'lev':str(lvl_ana)}
    div = {
        'lon': lons[idx_x1],
        'lat': lats[idx_y1],
        'data': np.array(div)[idx_z1,idx_y1[0][0]:(idx_y1[0][-1]+1),idx_x1[0][0]:(idx_x1[0][-1]+1)],
        'lev':str(lvl_ana)}

    synoptic_graphics.draw_PV_Div_uv(
        pv=pv, uv=uv, div=div,
        map_extent=map_extent, regrid_shape=20,
        city=city,south_China_sea=south_China_sea,
        output_dir=output_dir,Global=Global)
Beispiel #21
0
def PV_Div_uv(initTime=None,
              fhour=6,
              day_back=0,
              model='ECMWF',
              map_ratio=14 / 9,
              zoom_ratio=20,
              cntr_pnt=[104, 34],
              levels=[
                  1000, 950, 925, 900, 850, 800, 700, 600, 500, 400, 300, 250,
                  200, 100
              ],
              lvl_ana=250,
              Global=False,
              south_China_sea=True,
              area=None,
              city=False,
              output_dir=None,
              data_source='MICAPS',
              **kwargs):

    # micaps data directory
    if (area != None):
        south_China_sea = False

    # micaps data directory
    if (data_source == 'MICAPS'):
        try:
            data_dir = [
                utl.Cassandra_dir(data_type='high',
                                  data_source=model,
                                  var_name='RH',
                                  lvl=''),
                utl.Cassandra_dir(data_type='high',
                                  data_source=model,
                                  var_name='UGRD',
                                  lvl=''),
                utl.Cassandra_dir(data_type='high',
                                  data_source=model,
                                  var_name='VGRD',
                                  lvl=''),
                utl.Cassandra_dir(data_type='high',
                                  data_source=model,
                                  var_name='TMP',
                                  lvl=''),
                utl.Cassandra_dir(data_type='high',
                                  data_source=model,
                                  var_name='HGT',
                                  lvl='')
            ]
        except KeyError:
            raise ValueError('Can not find all directories needed')

        # get filename
        if (initTime != None):
            filename = utl.model_filename(initTime, fhour)
        else:
            filename = utl.filename_day_back_model(day_back=day_back,
                                                   fhour=fhour)

        # retrieve data from micaps server
        rh = MICAPS_IO.get_model_3D_grid(directory=data_dir[0][0:-1],
                                         filename=filename,
                                         levels=levels,
                                         allExists=False)
        if rh is None:
            return

        u = MICAPS_IO.get_model_3D_grid(directory=data_dir[1][0:-1],
                                        filename=filename,
                                        levels=levels,
                                        allExists=False)
        if u is None:
            return

        v = MICAPS_IO.get_model_3D_grid(directory=data_dir[2][0:-1],
                                        filename=filename,
                                        levels=levels,
                                        allExists=False)
        if v is None:
            return

        t = MICAPS_IO.get_model_3D_grid(directory=data_dir[3][0:-1],
                                        filename=filename,
                                        levels=levels,
                                        allExists=False)
        if t is None:
            return

    if (data_source == 'CIMISS'):
        # get filename
        if (initTime != None):
            filename = utl.model_filename(initTime, fhour, UTC=True)
        else:
            filename = utl.filename_day_back_model(day_back=day_back,
                                                   fhour=fhour,
                                                   UTC=True)
        try:
            # retrieve data from CIMISS server
            rh = CMISS_IO.cimiss_model_3D_grid(
                data_code=utl.CMISS_data_code(data_source=model,
                                              var_name='RHU'),
                init_time_str='20' + filename[0:8],
                valid_time=fhour,
                fcst_levels=levels,
                fcst_ele="RHU",
                units='%')
            if rh is None:
                return

            u = CMISS_IO.cimiss_model_3D_grid(
                data_code=utl.CMISS_data_code(data_source=model,
                                              var_name='WIU'),
                init_time_str='20' + filename[0:8],
                valid_time=fhour,
                fcst_levels=levels,
                fcst_ele="WIU",
                units='m/s')
            if u is None:
                return

            v = CMISS_IO.cimiss_model_3D_grid(
                data_code=utl.CMISS_data_code(data_source=model,
                                              var_name='WIV'),
                init_time_str='20' + filename[0:8],
                valid_time=fhour,
                fcst_levels=levels,
                fcst_ele="WIV",
                units='m/s')
            if v is None:
                return

            t = CMISS_IO.cimiss_model_3D_grid(
                data_code=utl.CMISS_data_code(data_source=model,
                                              var_name='TEM'),
                init_time_str='20' + filename[0:8],
                valid_time=fhour,
                fcst_levels=levels,
                fcst_ele="TEM",
                units='K')
            if t is None:
                return
            t['data'].values = t['data'].values - 273.15
            t['data'].attrs['units'] = 'C'
        except KeyError:
            raise ValueError('Can not find all data needed')

    if (area != None):
        cntr_pnt, zoom_ratio = utl.get_map_area(area_name=area)

    map_extent = [0, 0, 0, 0]
    map_extent[0] = cntr_pnt[0] - zoom_ratio * 1 * map_ratio
    map_extent[1] = cntr_pnt[0] + zoom_ratio * 1 * map_ratio
    map_extent[2] = cntr_pnt[1] - zoom_ratio * 1
    map_extent[3] = cntr_pnt[1] + zoom_ratio * 1

    delt_x = (map_extent[1] - map_extent[0]) * 0.2
    delt_y = (map_extent[3] - map_extent[2]) * 0.1

    #+ to solve the problem of labels on all the contours
    mask1 = (rh['lon'] >
             map_extent[0] - delt_x) & (rh['lon'] < map_extent[1] + delt_x) & (
                 rh['lat'] > map_extent[2] - delt_y) & (rh['lat'] <
                                                        map_extent[3] + delt_y)

    mask2 = (u['lon'] >
             map_extent[0] - delt_x) & (u['lon'] < map_extent[1] + delt_x) & (
                 u['lat'] > map_extent[2] - delt_y) & (u['lat'] <
                                                       map_extent[3] + delt_y)

    mask3 = (t['lon'] >
             map_extent[0] - delt_x) & (t['lon'] < map_extent[1] + delt_x) & (
                 t['lat'] > map_extent[2] - delt_y) & (t['lat'] <
                                                       map_extent[3] + delt_y)
    #- to solve the problem of labels on all the contours
    rh = rh.where(mask1, drop=True)
    u = u.where(mask2, drop=True)
    v = v.where(mask2, drop=True)
    t = t.where(mask3, drop=True)
    uv = xr.merge([u.rename({'data': 'u'}), v.rename({'data': 'v'})])

    lats = np.squeeze(rh['lat'].values)
    lons = np.squeeze(rh['lon'].values)

    pres = np.array(levels) * 100 * units('Pa')
    tmpk = mpcalc.smooth_n_point(
        (t['data'].values.squeeze() + 273.15), 9, 2) * units('kelvin')
    thta = mpcalc.potential_temperature(pres[:, None, None], tmpk)

    uwnd = mpcalc.smooth_n_point(u['data'].values.squeeze(), 9,
                                 2) * units.meter / units.second
    vwnd = mpcalc.smooth_n_point(v['data'].values.squeeze(), 9,
                                 2) * units.meter / units.second

    dx, dy = mpcalc.lat_lon_grid_deltas(lons, lats)

    # Comput the PV on all isobaric surfaces
    pv_raw = mpcalc.potential_vorticity_baroclinic(
        thta, pres[:, None, None], uwnd, vwnd, dx[None, :, :], dy[None, :, :],
        lats[None, :, None] * units('degrees'))
    div_raw = mpcalc.divergence(uwnd,
                                vwnd,
                                dx[None, :, :],
                                dy[None, :, :],
                                dim_order='yx')

    # prepare data
    idx_z1 = list(pres.m).index(((lvl_ana * units('hPa')).to(pres.units)).m)

    pv = rh.copy(deep=True)
    pv['data'].values = np.array(pv_raw).reshape(
        np.append(1,
                  np.array(pv_raw).shape))
    pv['data'].attrs['units'] = str(pv_raw.units)
    pv.attrs['model'] = model
    pv = pv.where(pv['level'] == lvl_ana, drop=True)

    div = u.copy(deep=True)
    div['data'].values = np.array(div_raw).reshape(
        np.append(1,
                  np.array(div_raw).shape))
    div['data'].attrs['units'] = str(div_raw.units)
    div = div.where(div['level'] == lvl_ana, drop=True)

    uv = uv.where(uv['level'] == lvl_ana, drop=True)

    synoptic_graphics.draw_PV_Div_uv(pv=pv,
                                     uv=uv,
                                     div=div,
                                     map_extent=map_extent,
                                     regrid_shape=20,
                                     city=city,
                                     south_China_sea=south_China_sea,
                                     output_dir=output_dir,
                                     Global=Global)
Beispiel #22
0
# for over North America. Data are smoothed for aesthetic reasons.
#

# Get GFS data and subset to North America for Geopotential Height and Temperature
ds = xr.open_dataset(
    'https://thredds.ucar.edu/thredds/dodsC/grib/NCEP/GFS/Global_0p5deg_ana/'
    'GFS_Global_0p5deg_ana_{0:%Y%m%d}_{0:%H}00.grib2'.format(
        date)).metpy.parse_cf()

# Geopotential height and smooth
hght = ds.Geopotential_height_isobaric.metpy.sel(vertical=level * units.hPa,
                                                 time=date,
                                                 lat=slice(70, 15),
                                                 lon=slice(
                                                     360 - 145, 360 - 50))
smooth_hght = mpcalc.smooth_n_point(hght, 9, 10)

# Temperature, smooth, and convert to Celsius
tmpk = ds.Temperature_isobaric.metpy.sel(vertical=level * units.hPa,
                                         time=date,
                                         lat=slice(70, 15),
                                         lon=slice(360 - 145, 360 - 50))
smooth_tmpc = (mpcalc.smooth_n_point(tmpk, 9, 10)).to('degC')

######################################################################
# Create DIFAX Replication
# ------------------------
#
# Plot the observational data and contours on a Lambert Conformal map and
# add features that resemble the historic DIFAX maps.
#
Beispiel #23
0
def uaPlot(data, level, date, save_dir, ds, td_option):

    custom_layout = StationPlotLayout()
    custom_layout.add_barb('eastward_wind', 'northward_wind', units='knots')
    custom_layout.add_value('NW',
                            'air_temperature',
                            fmt='.0f',
                            units='degC',
                            color='darkred')

    # Geopotential height and smooth
    hght = ds.Geopotential_height_isobaric.metpy.sel(
        vertical=level * units.hPa,
        time=date,
        lat=slice(85, 15),
        lon=slice(360 - 200, 360 - 10))
    smooth_hght = mpcalc.smooth_n_point(hght, 9, 10)

    # Temperature, smooth, and convert to Celsius
    tmpk = ds.Temperature_isobaric.metpy.sel(vertical=level * units.hPa,
                                             time=date,
                                             lat=slice(85, 15),
                                             lon=slice(360 - 200, 360 - 10))
    smooth_tmpc = (mpcalc.smooth_n_point(tmpk, 9, 10)).to('degC')

    #Calculate Theta-e
    rh = ds.Relative_humidity_isobaric.metpy.sel(vertical=level * units.hPa,
                                                 time=date,
                                                 lat=slice(85, 15),
                                                 lon=slice(
                                                     360 - 200, 360 - 10))
    td = mpcalc.dewpoint_from_relative_humidity(tmpk, rh)
    te = mpcalc.equivalent_potential_temperature(level * units.hPa, tmpk, td)
    smooth_te = mpcalc.smooth_n_point(te, 9, 10)

    #decide on the height format based on the level
    if level == 250:
        custom_layout.add_value('NE',
                                'height',
                                fmt=lambda v: format(v, '1')[1:4],
                                units='m',
                                color='black')
        cint = 120
        tint = 5
    if level == 300:
        custom_layout.add_value('NE',
                                'height',
                                fmt=lambda v: format(v, '1')[1:4],
                                units='m',
                                color='black')
        cint = 120
        tint = 5
    if level == 500:
        custom_layout.add_value('NE',
                                'height',
                                fmt=lambda v: format(v, '1')[0:3],
                                units='m',
                                color='black')
        cint = 60
        tint = 5
    if level == 700:
        custom_layout.add_value('NE',
                                'height',
                                fmt=lambda v: format(v, '1')[1:4],
                                units='m',
                                color='black')
        custom_layout.add_value('SW', 'tdd', units='degC', color='green')
        custom_layout.add_value('SE', 'thetae', units='degK', color='orange')
        temps = 'Tdd, and Theta-e'
        cint = 30
        tint = 4
    if level == 850:
        custom_layout.add_value('NE',
                                'height',
                                fmt=lambda v: format(v, '1')[1:4],
                                units='m',
                                color='black')
        if td_option == True:
            custom_layout.add_value('SW',
                                    'dew_point_temperature',
                                    units='degC',
                                    color='green')
            temps = 'Td, and Theta-e'
        if td_option == False:
            custom_layout.add_value('SW', 'tdd', units='degC', color='green')
            temps = 'Tdd, and Theta-e'
        # custom_layout.add_value('SW', 'tdd', units='degC', color='green')
        # temps = 'Tdd, and Theta-e'
        custom_layout.add_value('SE', 'thetae', units='degK', color='orange')
        cint = 30
        tint = 4
    if level == 925:
        custom_layout.add_value('NE',
                                'height',
                                fmt=lambda v: format(v, '1')[1:4],
                                units='m',
                                color='black')
        if td_option == True:
            custom_layout.add_value('SW',
                                    'dew_point_temperature',
                                    units='degC',
                                    color='green')
            temps = 'Td, and Theta-e'
        if td_option == False:
            custom_layout.add_value('SW', 'tdd', units='degC', color='green')
            temps = 'Tdd, and Theta-e'
        custom_layout.add_value('SE', 'thetae', units='degK', color='orange')
        cint = 30
        tint = 4

    globe = ccrs.Globe(ellipse='sphere',
                       semimajor_axis=6371200.,
                       semiminor_axis=6371200.)
    proj = ccrs.Stereographic(central_longitude=-105.,
                              central_latitude=90.,
                              globe=globe,
                              true_scale_latitude=60)
    # Plot the image
    fig = plt.figure(figsize=(40, 40))
    ax = fig.add_subplot(1, 1, 1, projection=proj)
    state_boundaries = feat.NaturalEarthFeature(
        category='cultural',
        name='admin_1_states_provinces_lines',
        scale='10m',
        facecolor='none')
    coastlines = feat.NaturalEarthFeature('physical',
                                          'coastline',
                                          '50m',
                                          facecolor='none')
    lakes = feat.NaturalEarthFeature('physical',
                                     'lakes',
                                     '50m',
                                     facecolor='none')
    countries = feat.NaturalEarthFeature('cultural',
                                         'admin_0_countries',
                                         '50m',
                                         facecolor='none')
    ax.add_feature(state_boundaries, zorder=2, edgecolor='grey')
    ax.add_feature(lakes, zorder=2, edgecolor='grey')
    ax.add_feature(coastlines, zorder=2, edgecolor='grey')
    ax.add_feature(lakes, zorder=2, edgecolor='grey')
    ax.add_feature(countries, zorder=2, edgecolor='grey')
    ax.coastlines(resolution='50m', zorder=2, color='grey')
    ax.set_extent([-132., -70, 26., 80.], ccrs.PlateCarree())

    stationData = dataDict(data)
    stationplot = StationPlot(ax,
                              stationData['longitude'],
                              stationData['latitude'],
                              transform=ccrs.PlateCarree(),
                              fontsize=22)
    custom_layout.plot(stationplot, stationData)

    # Plot Solid Contours of Geopotential Height
    cs = ax.contour(hght.lon,
                    hght.lat,
                    smooth_hght.m,
                    range(0, 20000, cint),
                    colors='black',
                    transform=ccrs.PlateCarree())
    clabels = plt.clabel(cs,
                         fmt='%d',
                         colors='white',
                         inline_spacing=5,
                         use_clabeltext=True,
                         fontsize=22)

    # Contour labels with black boxes and white text
    for t in clabels:
        t.set_bbox({'facecolor': 'black', 'pad': 4})
        t.set_fontweight('heavy')

    #Check levels for different contours
    if level == 250 or level == 300 or level == 500:
        # Plot Dashed Contours of Temperature
        cs2 = ax.contour(hght.lon,
                         hght.lat,
                         smooth_tmpc.m,
                         range(-60, 51, tint),
                         colors='red',
                         transform=ccrs.PlateCarree())
        clabels = plt.clabel(cs2,
                             fmt='%d',
                             colors='red',
                             inline_spacing=5,
                             use_clabeltext=True,
                             fontsize=22)
        # Set longer dashes than default
        for c in cs2.collections:
            c.set_dashes([(0, (5.0, 3.0))])
        temps = 'T'
    if level == 700 or level == 850 or level == 925:
        # Plot Dashed Contours of Temperature
        cs2 = ax.contour(hght.lon,
                         hght.lat,
                         smooth_te.m,
                         range(210, 360, tint),
                         colors='orange',
                         transform=ccrs.PlateCarree())
        clabels = plt.clabel(cs2,
                             fmt='%d',
                             colors='orange',
                             inline_spacing=5,
                             use_clabeltext=True,
                             fontsize=22)
        # Set longer dashes than default
        for c in cs2.collections:
            c.set_dashes([(0, (5.0, 3.0))])

    dpi = plt.rcParams['savefig.dpi'] = 255
    date = date + timedelta(hours=6)
    text = AnchoredText(str(level) + 'mb Wind, Heights, and ' + temps +
                        ' Valid: {0:%Y-%m-%d} {0:%H}:00UTC'.format(date),
                        loc=3,
                        frameon=True,
                        prop=dict(fontsize=22))
    ax.add_artist(text)
    plt.tight_layout()
    save_fname = '{0:%Y%m%d_%H}z_'.format(date) + str(level) + 'mb.pdf'
    plt.savefig(save_dir / save_fname, dpi=dpi, bbox_inches='tight')
lats = ds.lat.data
lons = ds.lon.data

# Grab x, y data and make 2D for wind component plotting
# because u- and v-components are grid relative
x = ds['u-component_of_wind_isobaric'].x
y = ds['u-component_of_wind_isobaric'].y

xx, yy = np.meshgrid(x, y)

# Grab Cartopy CRS from metadata for plotting wind barbs
datacrs = ds['u-component_of_wind_isobaric'].metpy.cartopy_crs

# Select and grab 500-hPa geopotential heights and wind components, smooth with gaussian_filter
level = 500 * units.hPa
hght_500 = mpcalc.smooth_n_point(
    ds.Geopotential_height_isobaric.metpy.sel(vertical=level).squeeze(), 9, 50)
uwnd_500 = mpcalc.smooth_n_point(
    ds['u-component_of_wind_isobaric'].metpy.sel(vertical=level).squeeze(), 9,
    50)
vwnd_500 = mpcalc.smooth_n_point(
    ds['v-component_of_wind_isobaric'].metpy.sel(vertical=level).squeeze(), 9,
    50)

# Compute north-relative wind components for plotting purposes
uwnd_er, vwnd_er = earth_relative_wind_components(
    ds['u-component_of_wind_isobaric'], uwnd_500, vwnd_500)

# Create a clean datetime object for plotting based on time of Geopotential heights
vtime = ds.time.data[0].astype('datetime64[ms]').astype('O')

######################################################################
Beispiel #25
0
def plot_files(dss, **args):
    first = True
    for time_sel in dss.time:
        data = dss.sel(time=time_sel)
        data['prmsl'].values = mpcalc.smooth_n_point(data['prmsl'].values,
                                                     n=9,
                                                     passes=10)
        time, run, cum_hour = get_time_run_cum(data)
        # Build the name of the output image
        filename = subfolder_images[
            projection] + '/' + variable_name + '_%s.png' % cum_hour

        cs_rain = args['ax'].contourf(args['x'],
                                      args['y'],
                                      data['rain_rate'],
                                      extend='max',
                                      cmap=args['cmap_rain'],
                                      norm=args['norm_rain'],
                                      levels=args['levels_rain'],
                                      zorder=4,
                                      antialiased=True)
        cs_snow = args['ax'].contourf(args['x'],
                                      args['y'],
                                      data['snow_rate'],
                                      extend='max',
                                      cmap=args['cmap_snow'],
                                      norm=args['norm_snow'],
                                      levels=args['levels_snow'],
                                      zorder=5)
        cs_clouds_low = args['ax'].contourf(args['x'],
                                            args['y'],
                                            data['CLCL'],
                                            extend='max',
                                            cmap=args['cmap_clouds'],
                                            levels=args['levels_clouds'],
                                            zorder=3)
        cs_clouds_high = args['ax'].contourf(args['x'],
                                             args['y'],
                                             data['CLCH'],
                                             extend='max',
                                             cmap=args['cmap_clouds_high'],
                                             levels=args['levels_clouds'],
                                             zorder=2,
                                             alpha=0.5,
                                             antialiased=True)

        c = args['ax'].contour(args['x'],
                               args['y'],
                               data['prmsl'],
                               levels=args['levels_mslp'],
                               colors='whitesmoke',
                               linewidths=1.,
                               zorder=7,
                               alpha=1.0)

        labels = args['ax'].clabel(c,
                                   c.levels,
                                   inline=True,
                                   fmt='%4.0f',
                                   fontsize=6)

        maxlabels = plot_maxmin_points(args['ax'],
                                       args['x'],
                                       args['y'],
                                       data['prmsl'],
                                       'max',
                                       150,
                                       symbol='H',
                                       color='royalblue',
                                       random=True)
        minlabels = plot_maxmin_points(args['ax'],
                                       args['x'],
                                       args['y'],
                                       data['prmsl'],
                                       'min',
                                       150,
                                       symbol='L',
                                       color='coral',
                                       random=True)

        an_fc = annotation_forecast(args['ax'], time)
        an_var = annotation(
            args['ax'],
            'Clouds (grey-low, orange-high), rain, snow and MSLP',
            loc='lower left',
            fontsize=6)
        an_run = annotation_run(args['ax'], run)
        logo = add_logo_on_map(ax=args['ax'], zoom=0.1, pos=(0.95, 0.08))

        if first:
            if projection == "it":
                x_cbar_0, y_cbar_0, x_cbar_size, y_cbar_size = 0.15, 0.2, 0.35, 0.02
                x_cbar2_0, y_cbar2_0, x_cbar2_size, y_cbar2_size = 0.55, 0.2, 0.35, 0.02
            elif projection == "de":
                x_cbar_0, y_cbar_0, x_cbar_size, y_cbar_size = 0.17, 0.06, 0.32, 0.02
                x_cbar2_0, y_cbar2_0, x_cbar2_size, y_cbar2_size = 0.55, 0.06, 0.32, 0.02
            elif projection == "nord":
                x_cbar_0, y_cbar_0, x_cbar_size, y_cbar_size = 0.15, 0.09, 0.35, 0.02
                x_cbar2_0, y_cbar2_0, x_cbar2_size, y_cbar2_size = 0.55, 0.09, 0.35, 0.02
            ax_cbar = plt.gcf().add_axes(
                [x_cbar_0, y_cbar_0, x_cbar_size, y_cbar_size])
            ax_cbar_2 = plt.gcf().add_axes(
                [x_cbar2_0, y_cbar2_0, x_cbar2_size, y_cbar2_size])
            cbar_snow = plt.gcf().colorbar(cs_snow,
                                           cax=ax_cbar,
                                           orientation='horizontal',
                                           label='Snow [cm/hr]')
            cbar_rain = plt.gcf().colorbar(cs_rain,
                                           cax=ax_cbar_2,
                                           orientation='horizontal',
                                           label='Rain [mm/hr]')
            cbar_snow.ax.tick_params(labelsize=8)
            cbar_rain.ax.tick_params(labelsize=8)

        if debug:
            plt.show(block=True)
        else:
            plt.savefig(filename, **options_savefig)

        remove_collections([
            c, cs_rain, cs_snow, cs_clouds_low, cs_clouds_high, labels, an_fc,
            an_var, an_run, maxlabels, minlabels, logo
        ])

        first = False
#

# Open dataset using xarray
ds = xr.open_dataset('https://thredds.ucar.edu/thredds/dodsC/'
                     'casestudies/python-gallery/NARR_19930313_1800.nc')

# Get lat/lon data from file
lats = ds.lat.data
lons = ds.lon.data

# Calculate variable dx, dy values for use in calculations
dx, dy = mpcalc.lat_lon_grid_deltas(lons, lats)

# Get 700-hPa data and smooth
hght_700 = mpcalc.smooth_n_point(
    ds['Geopotential_height_isobaric'].sel(isobaric1=700).data[0],
    9) * units.meter
tmpk_700 = mpcalc.smooth_n_point(
    ds['Temperature_isobaric'].sel(isobaric1=700).data[0], 9) * units.kelvin
uwnd_700 = mpcalc.smooth_n_point(
    ds['u-component_of_wind_isobaric'].sel(isobaric1=700).data[0],
    9) * (units.meter / units.seconds)
vwnd_700 = mpcalc.smooth_n_point(
    ds['v-component_of_wind_isobaric'].sel(isobaric1=700).data[0],
    9) * (units.meter / units.seconds)

# Get 300-hPa data and smooth
hght_300 = mpcalc.smooth_n_point(
    ds['Geopotential_height_isobaric'].sel(isobaric1=300).data[0],
    9) * units.meter
tmpk_300 = mpcalc.smooth_n_point(
Beispiel #27
0
                color='black',
                linewidths=0.5)

# Set some titles
plt.title('Hovmoller Diagram', loc='left')
plt.title('NCEP/NCAR Reanalysis', loc='right')

# Bottom plot for Hovmoller diagram
ax2 = fig.add_subplot(gs[1, 0])
ax2.invert_yaxis()  # Reverse the time order to do oldest first

# Plot of chosen variable averaged over latitude and slightly smoothed
clevs = np.arange(-50, 51, 5)
cf = ax2.contourf(lons,
                  vtimes,
                  mpcalc.smooth_n_point(avg_data, 9, 2),
                  clevs,
                  cmap=plt.cm.bwr,
                  extend='both')
cs = ax2.contour(lons,
                 vtimes,
                 mpcalc.smooth_n_point(avg_data, 9, 2),
                 clevs,
                 colors='k',
                 linewidths=1)
cbar = plt.colorbar(cf,
                    orientation='horizontal',
                    pad=0.04,
                    aspect=50,
                    extendrect=True)
cbar.set_label('m $s^{-1}$')
Beispiel #28
0
for i, j in product(range(3), range(3)):
    ax[i, j].axis('off')

# Gaussian Smoother
ax[0, 0].imshow(mpcalc.smooth_gaussian(raw_data, 3), vmin=0, vmax=1)
ax[0, 0].set_title('Gaussian - Low Degree')

ax[0, 1].imshow(mpcalc.smooth_gaussian(raw_data, 8), vmin=0, vmax=1)
ax[0, 1].set_title('Gaussian - High Degree')

# Rectangular Smoother
ax[0, 2].imshow(mpcalc.smooth_rectangular(raw_data, (3, 7), 2), vmin=0, vmax=1)
ax[0, 2].set_title('Rectangular - 3x7 Window\n2 Passes')

# 5-point smoother
ax[1, 0].imshow(mpcalc.smooth_n_point(raw_data, 5, 1), vmin=0, vmax=1)
ax[1, 0].set_title('5-Point - 1 Pass')

ax[1, 1].imshow(mpcalc.smooth_n_point(raw_data, 5, 4), vmin=0, vmax=1)
ax[1, 1].set_title('5-Point - 4 Passes')

# Circular Smoother
ax[1, 2].imshow(mpcalc.smooth_circular(raw_data, 2, 2), vmin=0, vmax=1)
ax[1, 2].set_title('Circular - Radius 2\n2 Passes')

# 9-point smoother
ax[2, 0].imshow(mpcalc.smooth_n_point(raw_data, 9, 1), vmin=0, vmax=1)
ax[2, 0].set_title('9-Point - 1 Pass')

ax[2, 1].imshow(mpcalc.smooth_n_point(raw_data, 9, 4), vmin=0, vmax=1)
ax[2, 1].set_title('9-Point - 4 Passes')
Beispiel #29
0
# Data Retrieval
# --------------
#
# This code retrieves the necessary data from the file and completes some
# smoothing of the geopotential height and wind fields using the SciPy
# function gaussian_filter. A nicely formated valid time (vtime) variable
# is also created.
#

# Grab lat/lon values (NAM will be 2D)
lats = ds.lat.data
lons = ds.lon.data

# Select and grab 500-hPa geopotential heights and wind components,
# smooth with gaussian_filter
hght_500 = mpcalc.smooth_n_point(
    ds.Geopotential_height_isobaric.sel(isobaric=500).data[0], 9, 50)
uwnd_500 = mpcalc.smooth_n_point(
    ds['u-component_of_wind_isobaric'].sel(isobaric=500).data[0], 9,
    50) * units('m/s')
vwnd_500 = mpcalc.smooth_n_point(
    ds['v-component_of_wind_isobaric'].sel(isobaric=500).data[0], 9,
    50) * units('m/s')

# Create a clean datetime object for plotting based on time of Geopotential heights
vtime = datetime.strptime(str(ds.time.data[0].astype('datetime64[ms]')),
                          '%Y-%m-%dT%H:%M:%S.%f')

######################################################################
# MetPy Absolute Vorticity Calculation
# ------------------------------------
#
Beispiel #30
0
    def __init__(self, datea, fhr, atcf, config):
        # Forecast fields to compute

        wnd_lev_1 = [250, 500]
        wnd_lev_2 = [350, 500]
        n_wnd_lev = len(wnd_lev_1)

        # Read steering flow parameters, or use defaults
        steerp1 = float(config['fields'].get('steer_level1', '300'))
        steerp2 = float(config['fields'].get('steer_level2', '850'))
        tcradius = float(config['fields'].get('steer_radius', '333'))

        # lat_lon info
        lat1 = float(config['fields'].get('min_lat', '0.'))
        lat2 = float(config['fields'].get('max_lat', '65.'))
        lon1 = float(config['fields'].get('min_lon', '-180.'))
        lon2 = float(config['fields'].get('max_lon', '-10.'))

        if not 'min_lat' in config:
            config.update({'min_lat': lat1})
            config.update({'max_lat': lat2})
            config.update({'min_lon': lon1})
            config.update({'max_lon': lon2})

        self.fhr = fhr
        self.atcf_files = atcf.atcf_files
        self.config = config
        self.nens = int(len(self.atcf_files))
        df_files = {}
        self.datea_str = datea
        self.datea = dt.datetime.strptime(datea, '%Y%m%d%H')
        self.datea_s = self.datea.strftime("%m%d%H%M")
        self.fff = str(self.fhr + 1000)[1:]
        datea_1 = self.datea + dt.timedelta(hours=self.fhr)
        datea_1 = datea_1.strftime("%m%d%H%M")

        self.dpp = importlib.import_module(config['io_module'])

        logging.warning("Computing hour {0} ensemble fields".format(self.fff))

        #  Obtain the ensemble lat/lon information, replace missing values with mean
        self.ens_lat, self.ens_lon = atcf.ens_lat_lon_time(self.fhr)

        e_cnt = 0
        m_lat = 0.0
        m_lon = 0.0
        for n in range(self.nens):
            if self.ens_lat[n] != atcf.missing and self.ens_lon[
                    n] != atcf.missing:
                e_cnt = e_cnt + 1
                m_lat = m_lat + self.ens_lat[n]
                m_lon = m_lon + self.ens_lon[n]

        if e_cnt > 0:
            m_lon = m_lon / e_cnt
            m_lat = m_lat / e_cnt

            for n in range(self.nens):
                if self.ens_lat[n] == atcf.missing or self.ens_lon[
                        n] == atcf.missing:
                    self.ens_lat[n] = m_lat
                    self.ens_lon[n] = m_lon

        #  Read grib file information for this forecast hour
        g1 = self.dpp.ReadGribFiles(self.datea_str, self.fhr, self.config)

        dencode = {
            'ensemble_data': {
                'dtype': 'float32'
            },
            'latitude': {
                'dtype': 'float32'
            },
            'longitude': {
                'dtype': 'float32'
            },
            'ensemble': {
                'dtype': 'int32'
            }
        }

        #  Compute steering wind components
        uoutfile = '{0}/{1}_f{2}_usteer_ens.nc'.format(config['work_dir'],
                                                       str(self.datea_str),
                                                       self.fff)
        voutfile = '{0}/{1}_f{2}_vsteer_ens.nc'.format(config['work_dir'],
                                                       str(self.datea_str),
                                                       self.fff)
        if (not os.path.isfile(uoutfile)
                or not os.path.isfile(voutfile)) and config['fields'].get(
                    'calc_uvsteer', 'True') == 'True':

            logging.warning("  Computing steering wind information")

            inpDict = {'isobaricInhPa': (steerp1, steerp2)}
            inpDict = g1.set_var_bounds('zonal_wind', inpDict)

            #  Create output arrays
            outDict = {
                'latitude': (lat1, lat2),
                'longitude': (lon1, lon2),
                'description': 'zonal steering wind',
                'units': 'm/s',
                '_FillValue': -9999.
            }
            outDict = g1.set_var_bounds('zonal_wind', outDict)
            uensmat = g1.create_ens_array('zonal_wind', self.nens, outDict)

            outDict = {
                'latitude': (lat1, lat2),
                'longitude': (lon1, lon2),
                'description': 'meridional steering wind',
                'units': 'm/s',
                '_FillValue': -9999.
            }
            outDict = g1.set_var_bounds('meridional_wind', outDict)
            vensmat = g1.create_ens_array('meridional_wind', self.nens,
                                          outDict)

            outDict = {
                'latitude': (lat1, lat2),
                'longitude': (lon1, lon2),
                'description': 'steering wind vorticity',
                'units': '1/s',
                '_FillValue': -9999.
            }
            outDict = g1.set_var_bounds('zonal_wind', outDict)
            vortmat = g1.create_ens_array('zonal_wind', self.nens, outDict)

            wencode = {
                'latitude': {
                    'dtype': 'float32'
                },
                'longitude': {
                    'dtype': 'float32'
                }
            }

            for n in range(self.nens):

                #  Read global zonal and meridional wind, write to file
                uwnd = g1.read_grib_field('zonal_wind', n, inpDict).rename('u')
                vwnd = g1.read_grib_field('meridional_wind', n,
                                          inpDict).rename('v')

                #             print(uwnd[:,0,0])
                #             print(vwnd[:,0,0])
                #             sys.exit(2)

                uwnd.to_netcdf('wind_info.nc',
                               mode='w',
                               encoding=wencode,
                               format='NETCDF3_CLASSIC')
                vwnd.to_netcdf('wind_info.nc',
                               mode='a',
                               encoding=wencode,
                               format='NETCDF3_CLASSIC')

                latvec = uwnd.latitude.values
                lonvec = uwnd.longitude.values

                if e_cnt > 0:

                    latcen = latvec[np.abs(latvec - self.ens_lat[n]).argmin()]
                    loncen = lonvec[np.abs(lonvec - self.ens_lon[n]).argmin()]

                    #  Call NCL to remove TC winds, read result from file
                    os.system('ncl -Q {0}/tc_steer.ncl tclat={1} tclon={2} tcradius={3}'.format(config['script_dir'],\
                                          str(latcen), str(loncen), str(tcradius)))

                    wfile = nc.Dataset('wind_info.nc')
                    uwnd[:, :, :] = wfile.variables['u'][:, :, :]
                    vwnd[:, :, :] = wfile.variables['v'][:, :, :]

                    os.remove('wind_info.nc')

                #  Integrate the winds over the layer to obtain the steering wind
                pres, lat, lon = uwnd.indexes.values()
                nlev = len(pres)

                uint = uwnd[0, :, :]
                uint[:, :] = 0.0
                vint = vwnd[0, :, :]
                vint[:, :] = 0.0

                for k in range(nlev - 1):

                    uint[:, :] = uint[:, :] + 0.5 * (uwnd[k, :, :] + uwnd[
                        k + 1, :, :]) * abs(pres[k + 1] - pres[k])
                    vint[:, :] = vint[:, :] + 0.5 * (vwnd[k, :, :] + vwnd[
                        k + 1, :, :]) * abs(pres[k + 1] - pres[k])

#             if pres[0] > pres[-1]:
#               uint = -np.trapz(uwnd[:,:,:], pres, axis=0) / abs(pres[-1]-pres[0])
#               vint = -np.trapz(vwnd[:,:,:], pres, axis=0) / abs(pres[-1]-pres[0])
#             else:
#               uint = np.trapz(uwnd[:,:,:], pres, axis=0) / abs(pres[-1]-pres[0])
#               vint = np.trapz(vwnd[:,:,:], pres, axis=0) / abs(pres[-1]-pres[0])

                if lat[0] > lat[-1]:
                    slat1 = lat2
                    slat2 = lat1
                else:
                    slat1 = lat1
                    slat2 = lat2

                #  Write steering flow to ensemble arrays
                uensmat[n, :, :] = np.squeeze(
                    uint.sel(latitude=slice(slat1, slat2),
                             longitude=slice(lon1,
                                             lon2))) / abs(pres[-1] - pres[0])
                vensmat[n, :, :] = np.squeeze(
                    vint.sel(latitude=slice(slat1, slat2),
                             longitude=slice(lon1,
                                             lon2))) / abs(pres[-1] - pres[0])

                #  Compute the vorticity associated with the steering wind

#             circ = VectorWind(unew, vnew).vorticity() * 1.0e5

#             vortmat[n,:,:] = np.squeeze(circ.sel(latitude=slice(lat2, lat1), longitude=slice(lon1, lon2)))

            uensmat.to_netcdf(uoutfile, encoding=dencode)
            vensmat.to_netcdf(voutfile, encoding=dencode)


#          vortmat.to_netcdf(vortfile, encoding=dencode)

        else:

            logging.warning("  Obtaining steering wind information from file")

        #  Read geopotential height from file, if ensemble file is not present
        if config['fields'].get('calc_height', 'True') == 'True':

            if 'height_levels' in config['fields']:
                height_list = json.loads(config['fields'].get('height_levels'))
            else:
                height_list = [500]

            for level in height_list:

                levstr = '%0.3i' % int(level)
                outfile = '{0}/{1}_f{2}_h{3}hPa_ens.nc'.format(
                    config['work_dir'], str(self.datea_str), self.fff, levstr)

                if not os.path.isfile(outfile):

                    logging.warning(
                        '  Computing {0} hPa height'.format(levstr))

                    vDict = {
                        'latitude': (lat1, lat2),
                        'longitude': (lon1, lon2),
                        'isobaricInhPa': (level, level),
                        'description': '{0} hPa height'.format(levstr),
                        'units': 'm',
                        '_FillValue': -9999.
                    }
                    vDict = g1.set_var_bounds('geopotential_height', vDict)
                    ensmat = g1.create_ens_array('geopotential_height',
                                                 g1.nens, vDict)

                    for n in range(g1.nens):
                        ensmat[n, :, :] = np.squeeze(
                            g1.read_grib_field('geopotential_height', n,
                                               vDict))

                    ensmat.to_netcdf(outfile, encoding=dencode)

                elif os.path.isfile(outfile):

                    logging.warning(
                        "  Obtaining {0} hPa height data from {1}".format(
                            levstr, outfile))

        #  Compute 250 hPa PV if the file does not exist
        outfile = '{0}/{1}_f{2}_pv250_ens.nc'.format(config['work_dir'],
                                                     str(self.datea_str),
                                                     self.fff)
        if (not os.path.isfile(outfile)
                and config['fields'].get('calc_pv250hPa', 'True') == 'True'):

            logging.warning("  Computing 250 hPa PV")

            vDict = {
                'latitude': (lat1, lat2),
                'longitude': (lon1, lon2),
                'isobaricInhPa': (200, 300),
                'description': '250 hPa Potential Vorticity',
                'units': 'PVU',
                '_FillValue': -9999.
            }
            vDict = g1.set_var_bounds('zonal_wind', vDict)

            ensmat = g1.create_ens_array('zonal_wind', self.nens, vDict)

            for n in range(self.nens):

                #  Read all the necessary files from file, smooth fields, so sensitivities are useful
                tmpk = g1.read_grib_field('temperature', n, vDict) * units('K')

                lats = tmpk.latitude.values * units('degrees')
                lons = tmpk.longitude.values * units('degrees')
                pres = tmpk.isobaricInhPa.values * units('hPa')

                tmpk = mpcalc.smooth_n_point(tmpk, 9, 4)

                thta = mpcalc.potential_temperature(pres[:, None, None], tmpk)

                uwnd = mpcalc.smooth_n_point(
                    g1.read_grib_field('zonal_wind', n, vDict) * units('m/s'),
                    9, 4)
                vwnd = mpcalc.smooth_n_point(
                    g1.read_grib_field('meridional_wind', n, vDict) *
                    units('m/s'), 9, 4)

                dx, dy = mpcalc.lat_lon_grid_deltas(lons,
                                                    lats,
                                                    x_dim=-1,
                                                    y_dim=-2,
                                                    geod=None)

                #  Compute PV and place in ensemble array
                pvout = mpcalc.potential_vorticity_baroclinic(
                    thta, pres[:, None, None], uwnd, vwnd, dx[None, :, :],
                    dy[None, :, :], lats[None, :, None])

                ensmat[n, :, :] = np.squeeze(pvout[np.where(
                    pres == 250 * units('hPa'))[0], :, :]) * 1.0e6

            ensmat.to_netcdf(outfile, encoding=dencode)

        elif os.path.isfile(outfile):

            logging.warning(
                "  Obtaining 250 hPa PV data from {0}".format(outfile))

        #  Compute the equivalent potential temperature (if desired and file is missing)
        if config['fields'].get('calc_theta-e', 'False') == 'True':

            if 'theta-e_levels' in config['fields']:
                thetae_list = json.loads(
                    config['fields'].get('theta-e_levels'))
            else:
                thetae_list = [700, 850]

            for level in thetae_list:

                levstr = '%0.3i' % int(level)
                outfile = '{0}/{1}_f{2}_e{3}hPa_ens.nc'.format(
                    config['work_dir'], str(self.datea_str), self.fff, levstr)

                if not os.path.isfile(outfile):

                    logging.warning(
                        '  Computing {0} hPa Theta-E'.format(levstr))

                    vDict = {
                        'latitude': (lat1, lat2),
                        'longitude': (lon1, lon2),
                        'isobaricInhPa': (level, level),
                        'description':
                        '{0} hPa Equivalent Potential Temperature'.format(
                            levstr),
                        'units':
                        'K',
                        '_FillValue':
                        -9999.
                    }
                    vDict = g1.set_var_bounds('temperature', vDict)

                    ensmat = g1.create_ens_array('temperature', g1.nens, vDict)

                    for n in range(g1.nens):

                        tmpk = g1.read_grib_field('temperature', n,
                                                  vDict) * units.K
                        pres = tmpk.isobaricInhPa.values * units.hPa

                        if g1.has_specific_humidity:
                            qvap = np.squeeze(
                                g1.read_grib_field('specific_humidity', n,
                                                   vDict))
                            tdew = mpcalc.dewpoint_from_specific_humidity(
                                pres[None, None], tmpk, qvap)
                        else:
                            relh = g1.read_grib_field('relative_humidity', n,
                                                      vDict)
                            relh = np.minimum(np.maximum(relh, 0.01),
                                              100.0) * units.percent
                            tdew = mpcalc.dewpoint_from_relative_humidity(
                                tmpk, relh)

                        ensmat[n, :, :] = np.squeeze(
                            mpcalc.equivalent_potential_temperature(
                                pres[None, None], tmpk, tdew))

                    ensmat.to_netcdf(outfile, encoding=dencode)

                elif os.path.isfile(outfile):

                    logging.warning(
                        "  Obtaining {0} hPa Theta-e data from {1}".format(
                            levstr, outfile))

        #  Compute the 500-850 hPa water vapor mixing ratio (if desired and file is missing)
        outfile = '{0}/{1}_f{2}_q500-850hPa_ens.nc'.format(
            config['work_dir'], str(self.datea_str), self.fff)
        if (not os.path.isfile(outfile) and config['fields'].get(
                'calc_q500-850hPa', 'False') == 'True'):

            logging.warning("  Computing 500-850 hPa Water Vapor")

            vDict = {
                'latitude': (lat1, lat2),
                'longitude': (lon1, lon2),
                'description': '500-850 hPa Integrated Water Vapor',
                'units': 'hPa',
                '_FillValue': -9999.
            }
            vDict = g1.set_var_bounds('temperature', vDict)

            ensmat = g1.create_ens_array('temperature', len(self.atcf_files),
                                         vDict)

            vDict = {
                'latitude': (lat1, lat2),
                'longitude': (lon1, lon2),
                'isobaricInhPa': (500, 850),
                'description': '500-850 hPa Integrated Water Vapor',
                'units': 'hPa',
                '_FillValue': -9999.
            }
            vDict = g1.set_var_bounds('temperature', vDict)

            for n in range(self.nens):

                tmpk = np.squeeze(g1.read_grib_field('temperature', n,
                                                     vDict)) * units('K')
                pres = (tmpk.isobaricInhPa.values * units.hPa).to(units.Pa)

                if g1.has_specific_humidity:
                    qvap = mpcalc.mixing_ratio_from_specific_humidity(
                        g1.read_grib_field('specific_humidity', n, vDict))
                else:
                    relh = np.minimum(
                        np.maximum(
                            g1.read_grib_field('relative_humidity', n, vDict),
                            0.01), 100.0) * units('percent')
                    qvap = mpcalc.mixing_ratio_from_relative_humidity(
                        pres[:, None, None], tmpk, relh)

                #  Integrate water vapor over the pressure levels
                ensmat[n, :, :] = np.abs(np.trapz(
                    qvap, pres, axis=0)) / mpcon.earth_gravity

            ensmat.to_netcdf(outfile, encoding=dencode)

        elif os.path.isfile(outfile):

            logging.warning(
                "  Obtaining 500-850 hPa water vapor data from {0}".format(
                    outfile))

        #  Compute wind-related forecast fields (if desired and file is missing)
        if config['fields'].get('calc_winds', 'False') == 'True':

            if 'wind_levels' in config['fields']:
                wind_list = json.loads(config['fields'].get('wind_levels'))
            else:
                wind_list = [850]

            for level in wind_list:

                levstr = '%0.3i' % int(level)
                ufile = '{0}/{1}_f{2}_u{3}hPa_ens.nc'.format(
                    config['work_dir'], str(self.datea_str), self.fff, levstr)
                vfile = '{0}/{1}_f{2}_v{3}hPa_ens.nc'.format(
                    config['work_dir'], str(self.datea_str), self.fff, levstr)

                if (not os.path.isfile(ufile)) or (not os.path.isfile(vfile)):

                    logging.warning(
                        '  Computing {0} hPa wind information'.format(levstr))

                    uDict = {
                        'latitude': (lat1, lat2),
                        'longitude': (lon1, lon2),
                        'isobaricInhPa': (level, level),
                        'description': '{0} hPa zonal wind'.format(levstr),
                        'units': 'm/s',
                        '_FillValue': -9999.
                    }
                    uDict = g1.set_var_bounds('zonal_wind', uDict)

                    uensmat = g1.create_ens_array('zonal_wind', g1.nens, uDict)

                    vDict = {
                        'latitude': (lat1, lat2),
                        'longitude': (lon1, lon2),
                        'isobaricInhPa': (level, level),
                        'description':
                        '{0} hPa meridional wind'.format(levstr),
                        'units': 'm/s',
                        '_FillValue': -9999.
                    }
                    vDict = g1.set_var_bounds('meridional_wind', vDict)

                    vensmat = g1.create_ens_array('meridional_wind', g1.nens,
                                                  vDict)

                    for n in range(g1.nens):

                        uwnd = g1.read_grib_field('zonal_wind', n,
                                                  uDict).squeeze()
                        vwnd = g1.read_grib_field('meridional_wind', n,
                                                  vDict).squeeze()

                        uensmat[n, :, :] = uwnd[:, :]
                        vensmat[n, :, :] = vwnd[:, :]

                    uensmat.to_netcdf(ufile, encoding=dencode)
                    vensmat.to_netcdf(vfile, encoding=dencode)

                elif os.path.isfile(outfile):

                    logging.warning(
                        "  Obtaining {0} hPa wind information from file".
                        format(levstr))
# Plot colorfilled RH >= 70%
clevs_relh = np.arange(70, 101, 1)
cf = ax.contourf(lons,
                 lats,
                 isentrelh[ilev],
                 clevs_relh,
                 cmap=plt.cm.Greens,
                 norm=plt.Normalize(70, 110),
                 transform=datacrs)
plt.colorbar(cf, orientation='horizontal', pad=0, aspect=50)

# Plot isobars every 50 hPa
clevs_pres = np.arange(0, 1100, 50)
cs1 = ax.contour(lons,
                 lats,
                 mpcalc.smooth_n_point(isentprs[ilev], 9),
                 clevs_pres,
                 colors='black',
                 transform=datacrs)
plt.clabel(cs1, fmt='%d', fontsize='large')

# Plot wind barbs
ax.barbs(lons,
         lats,
         isentu[ilev].m,
         isentv[ilev].m,
         pivot='middle',
         color='black',
         regrid_shape=20,
         transform=datacrs)
# Subset data based on latitude and longitude values and select only data
# from 850 hPa
#

# Set subset slice for the geographic extent of data to limit download
lon_slice = slice(200, 350)
lat_slice = slice(85, 10)

# Grab lat/lon values (GFS will be 1D)
lats = ds.lat.sel(lat=lat_slice).values
lons = ds.lon.sel(lon=lon_slice).values

# Grab data and smooth using a nine-point filter applied 50 times to grab the synoptic signal
level = 850 * units.hPa
hght_850 = mpcalc.smooth_n_point(
    ds.Geopotential_height_isobaric.metpy.sel(vertical=level,
                                              lat=lat_slice,
                                              lon=lon_slice).squeeze(), 9, 50)
tmpk_850 = mpcalc.smooth_n_point(
    ds.Temperature_isobaric.metpy.sel(vertical=level,
                                      lat=lat_slice,
                                      lon=lon_slice).squeeze(), 9, 25)
uwnd_850 = mpcalc.smooth_n_point(
    ds['u-component_of_wind_isobaric'].metpy.sel(vertical=level,
                                                 lat=lat_slice,
                                                 lon=lon_slice).squeeze(), 9,
    50)
vwnd_850 = mpcalc.smooth_n_point(
    ds['v-component_of_wind_isobaric'].metpy.sel(vertical=level,
                                                 lat=lat_slice,
                                                 lon=lon_slice).squeeze(), 9,
    50)
# Define the CRS and inset axes
data_crs = data2['accrain'].metpy.cartopy_crs
ax_inset = fig.add_axes([0.65, 0.495, 0.3, 0.3], projection=data_crs)
gl = ax_inset.gridlines(draw_labels=True,
                        linewidth=1,
                        color='gray',
                        alpha=0.5,
                        linestyle=':')
gl.xlabels_top, gl.xlabels_bottom, gl.ylabels_left, gl.ylabels_right = [
    False, True, True, False
]
gl.xformatter, gl.yformatter = [LONGITUDE_FORMATTER, LATITUDE_FORMATTER]
ax_inset.tick_params(labelsize=8)
cf = ax_inset.contourf(data['lon'],
                       data['lat'],
                       mpcalc.smooth_n_point(data['accrain'], 9),
                       levels=np.arange(-22, 26, 4),
                       cmap=drywet,
                       extend='both')
#levels=np.arange(-20,24,4), cmap=drywet, extend='both')
axins = inset_axes(ax_inset, width="5%", height="70%", loc='lower left')
cbar = fig.colorbar(cf,
                    cax=axins,
                    orientation="vertical",
                    ticks=[-18, -6, 6, 18])
cbar.ax.tick_params(which='both', direction='in')
cbar.ax.tick_params(which='both', length=0)

#ax_inset.plot(obs_lon, obs_lat, color='k', ms=10, marker='*', zorder=100, alpha=0.5 )
ax_inset.scatter([start[1], end[1]], [start[0], end[0]], c='r', zorder=2)
ax_inset.plot(cross['lon'], cross['lat'], c='r', zorder=2)
Beispiel #34
0
lats = ds.lat.data
lons = ds.lon.data

# Grab x, y data and make 2D for wind component plotting because
# u- and v-components are grid relative
x = ds['u-component_of_wind_isobaric'].x
y = ds['u-component_of_wind_isobaric'].y

xx, yy = np.meshgrid(x, y)

# Grab Cartopy CRS from metadata for plotting wind barbs
datacrs = ds['u-component_of_wind_isobaric'].metpy.cartopy_crs

# Select and grab 500-hPa geopotential heights and smooth with n-point smoother
level = 500 * units.hPa
hght_500 = mpcalc.smooth_n_point(
    ds.Geopotential_height_isobaric.metpy.sel(vertical=level).squeeze(), 9, 50)

# Select and grab 500-hPa wind components
uwnd_500 = ds['u-component_of_wind_isobaric'].metpy.sel(
    vertical=level).squeeze()
vwnd_500 = ds['v-component_of_wind_isobaric'].metpy.sel(
    vertical=level).squeeze()

# Compute north-relative wind components for plotting purposes
uwnd_er, vwnd_er = earth_relative_wind_components(uwnd_500, vwnd_500)

# Smooth wind components as desired
uwnd_er = mpcalc.smooth_n_point(uwnd_er, 9, 50)
vwnd_er = mpcalc.smooth_n_point(vwnd_er, 9, 50)

# Create a clean datetime object for plotting based on time of Geopotential heights