def test_vorticity_asym(): """Test vorticity calculation with a complicated field.""" u = np.array([[2, 4, 8], [0, 2, 2], [4, 6, 8]]) * units('m/s') v = np.array([[6, 4, 8], [2, 6, 0], [2, 2, 6]]) * units('m/s') vort = vorticity(u, v, 1 * units.meters, 2 * units.meters, dim_order='yx') true_vort = np.array([[-2.5, 3.5, 13.], [8.5, -1.5, -11.], [-5.5, -1.5, 0.]]) / units.sec assert_array_equal(vort, true_vort) # Now try for xy ordered vort = vorticity(u.T, v.T, 1 * units.meters, 2 * units.meters, dim_order='xy') assert_array_equal(vort, true_vort.T)
def test_vorticity(): """Test vorticity for simple case.""" a = np.arange(3) u = np.c_[a, a, a] * units('m/s') v = vorticity(u, u, 1 * units.meter, 1 * units.meter, dim_order='xy') true_v = np.ones_like(u) / units.sec assert_array_equal(v, true_v)
def test_zero_vorticity(): """Test vorticity calculation when zeros should be returned.""" a = np.arange(3) u = np.c_[a, a, a] * units('m/s') v = vorticity(u, u.T, 1 * units.meter, 1 * units.meter, dim_order='xy') true_v = np.zeros_like(u) / units.sec assert_array_equal(v, true_v)
def kinematics(u, v, thetae, dx, dy, lats, smooth=False, sigma=1): ''' Use metpy functions to calculate various kinematics, given 2d numpy arrays as inputs. X and y grid spacing, as well as a 2d array of latitudes is also required. Option to smooth the thetae field before calculating front diagnostics (recommended), with addition "sigma" parameter controlling the smoothness (see scipy docs) ''' if smooth: thetae = gaussian_filter(thetae, sigma) #Kinematics ddy_thetae = mpcalc.first_derivative(thetae, delta=dy, axis=0) ddx_thetae = mpcalc.first_derivative(thetae, delta=dx, axis=1) mag_thetae = np.sqrt(ddx_thetae**2 + ddy_thetae**2) div = mpcalc.divergence(u, v, dx, dy) strch_def = mpcalc.stretching_deformation(u, v, dx, dy) shear_def = mpcalc.shearing_deformation(u, v, dx, dy) tot_def = mpcalc.total_deformation(u, v, dx, dy) psi = 0.5 * np.arctan2(shear_def, strch_def) beta = np.arcsin( (-ddx_thetae * np.cos(psi) - ddy_thetae * np.sin(psi)) / mag_thetae) vo = mpcalc.vorticity(u, v, dx, dy) conv = -div * 1e5 F = np.array(0.5 * mag_thetae * (tot_def * np.cos(2 * beta) - div) * 1.08e4 * 1e5) Fn = np.array(0.5 * mag_thetae * (div - tot_def * np.cos(2 * beta)) * 1.08e4 * 1e5) Fs = np.array(0.5 * mag_thetae * (vo + tot_def * np.sin(2 * beta)) * 1.08e4 * 1e5) icon = np.array(0.5 * (tot_def - div) * 1e5) vgt = np.array(np.sqrt(div**2 + vo**2 + tot_def**2) * 1e5) #TFP ddx_thetae_scaled = ddx_thetae / mag_thetae ddy_thetae_scaled = ddy_thetae / mag_thetae ddy_mag_thetae = -1 * mpcalc.first_derivative(mag_thetae, delta=dy, axis=0) ddx_mag_thetae = -1 * mpcalc.first_derivative(mag_thetae, delta=dx, axis=1) tfp = ddx_mag_thetae * ddx_thetae_scaled + ddy_mag_thetae * ddy_thetae_scaled ddy_tfp = mpcalc.first_derivative(tfp, delta=dy, axis=0) ddx_tfp = mpcalc.first_derivative(tfp, delta=dx, axis=1) mag_tfp = np.sqrt(ddx_tfp**2 + ddy_tfp**2) v_f = (u * units.units("m/s")) * (ddx_tfp / mag_tfp) + ( v * units.units("m/s")) * (ddy_tfp / mag_tfp) #Extra condition ddy_ddy_mag_te = mpcalc.first_derivative(-1 * ddy_mag_thetae, delta=dy, axis=0) ddx_ddx_mag_te = mpcalc.first_derivative(-1 * ddx_mag_thetae, delta=dx, axis=1) cond = ddy_ddy_mag_te + ddx_ddx_mag_te return [F, Fn, Fs, icon, vgt, conv, vo*1e5, \ np.array(tfp.to("km^-2")*(100*100)), np.array(mag_thetae.to("km^-1"))*100, np.array(v_f), thetae, cond]
def compute_vorticity(dset, uvar='10u', vvar='10v'): dx, dy = mpcalc.lat_lon_grid_deltas(dset['lon'], dset['lat']) vort = mpcalc.vorticity(dset[uvar], dset[vvar], dx[None, :, :], dy[None, :, :]) vort = xr.DataArray(vort.magnitude, coords=dset[uvar].coords, attrs={ 'standard_name': 'vorticity', 'units': vort.units }, name='vort') return xr.merge([dset, vort])
def 500hPa_GFS_vorticity(lon_west, lon_east, lat_south, lat_north): LATEST_DATA.variables('Geopotential_height_isobaric', 'u-component_of_wind_isobaric', 'v-component_of_wind_isobaric').add_lonlat() LATEST_DATA.lonlat_box(lon_west, lon_east, lat_south, lat_north) LATEST_DATA.vertical_level(50000) DATA = NCSS_DATA.get_data(LATEST_DATA) DTIME = DATA.variables['Geopotential_height_isobaric'].dimensions[0] DLAT = DATA.variables['Geopotential_height_isobaric'].dimensions[2] DLON = DATA.variables['Geopotential_height_isobaric'].dimensions[3] LAT = DATA.variables[DLAT][:] LON = DATA.variables[DLON][:] TIMES = DATA.variables[DTIME] VTIMES = num2date(TIMES[:], TIMES.units) H500 = DATA.variables['Geopotential_height_isobaric'][0, 0, :, :] U500 = DATA.variables['u-component_of_wind_isobaric'][0, 0, :, :]*units('m/s') V500 = DATA.variables['v-component_of_wind_isobaric'][0, 0, :, :]*units('m/s') DTIME = DATA.variables['Geopotential_height_isobaric'].dimensions[:] f = mpcalc.coriolis_parameter(np.deg2rad(LAT)).to(units('1/sec')) DX, DY = mpcalc.lat_lon_grid_spacing(LON, LAT) VORT500 = mpcalc.vorticity(U500, V500, DX, DY, dim_order='YX') VORT500 = (VORT500*(units('1/s')))
def metpy_read_wrf(tidx, froms, froms0, fwrf, lons_out, lats_out): wrfin = Dataset(fwrf) ds = xr.Dataset() slp = getvar(wrfin, "slp", timeidx=tidx) ds['slp'] = smooth2d(slp, 3, cenweight=4) lats, lons = latlon_coords(slp) ds['lats'] = lats ds['lons'] = lons landmask = extract_vars(wrfin, timeidx=tidx, varnames=["LANDMASK"]).get("LANDMASK") u10 = extract_vars(wrfin, timeidx=tidx, varnames=["U10"]).get("U10") v10 = extract_vars(wrfin, timeidx=tidx, varnames=["V10"]).get("V10") ds['u10'] = u10.where(landmask == 0) ds['v10'] = v10.where(landmask == 0) latent = extract_vars(wrfin, timeidx=tidx, varnames=["LH"]).get("LH") ds['latent'] = smooth2d(latent, 3, cenweight=4) #latent.where(landmask==0) t2m = extract_vars(wrfin, timeidx=tidx, varnames=["T2"]).get("T2") - 273.15 ds['t2m'] = smooth2d(t2m, 3, cenweight=4) sst = extract_vars(wrfin, timeidx=tidx, varnames=["SST"]).get("SST") ds['sst'] = sst.where(landmask == 0) romsin = xr.open_dataset(froms) romsin = romsin.rename({"lat_rho": "lat", "lon_rho": "lon"}) romsin = romsin.isel(ocean_time=tidx) ds['sst_5m'] = romsin.isel(z_r=0).temp ds['water_temp'] = romsin.temp ds['water_ucur'] = romsin.ucur / 100 ds['water_vcur'] = romsin.vcur / 100 ds.water_ucur.attrs['units'] = 'm/s' ds.water_vcur.attrs['units'] = 'm/s' romsin = xr.open_dataset(froms0) romsin = romsin.rename({"lat_rho": "lat", "lon_rho": "lon"}) romsin = romsin.isel(ocean_time=tidx) ds['h'] = romsin.h mld = get_oml_depth(froms0, t_in=tidx) mld = smooth2d(mld, 3, cenweight=4) ds['oml_depth'] = xr.DataArray(mld, ds.sst_5m.coords, ds.sst_5m.dims, ds.sst_5m.attrs) ds['oml_depth2'] = ds.oml_depth.where(ds.h > 20) ds = ds.drop(['XLONG', 'XLAT', 'XTIME', 'Time']) ds = ds.rename({'south_north': 'eta_rho', 'west_east': 'xi_rho'}) interp_method = 'bilinear' ds_out = xr.Dataset({ 'lat': (['lat'], lats_out), 'lon': (['lon'], lons_out) }) regridder = xe.Regridder(ds, ds_out, interp_method) regridder.clean_weight_file() ds = regridder(ds) ds = ds.squeeze() dxy = 10000. ds = ds.metpy.parse_cf().squeeze() utau, vtau = wind_stress(to_np(ds.u10), to_np(ds.v10)) ds['u_tau'] = xr.DataArray(utau, ds.u10.coords, ds.u10.dims, ds.u10.attrs) ds['v_tau'] = xr.DataArray(vtau, ds.v10.coords, ds.v10.dims, ds.v10.attrs) curl = mpcalc.vorticity(utau * units('m/s'), utau * units('m/s'), dx=dxy * units.meter, dy=dxy * units.meter) ds['wind_stress_curl'] = xr.DataArray(np.array(curl), ds.u10.coords, ds.u10.dims, ds.u10.attrs) div = [] for z in range(len(ds.z_r)): div0 = mpcalc.divergence(ds.water_ucur.isel(z_r=z) * units('m/s'), ds.water_vcur.isel(z_r=z) * units('m/s'), dx=dxy * units.meter, dy=dxy * units.meter) div.append(div0) ds['cur_div'] = xr.DataArray(div, ds.water_ucur.coords, ds.water_ucur.dims, ds.water_ucur.attrs) div = mpcalc.divergence(ds.water_ucur.isel(z_r=2) * units('m/s'), ds.water_vcur.isel(z_r=2) * units('m/s'), dx=dxy * units.meter, dy=dxy * units.meter) ds['surf_cur_div'] = xr.DataArray(np.array(div), ds.u10.coords, ds.u10.dims, ds.u10.attrs) print(ds) return ds
def draw_vort_high(uwind, vwind, lon, lat, vort=None, gh=None, skip_vector=None, smooth_factor=1.0, map_region=None, title_kwargs={}, outfile=None): """ Draw high vorticity. Args: uwind (np.array): u wind component, 2D array, [nlat, nlon] vwind (np.array): v wind component, 2D array, [nlat, nlon] lon (np.array): longitude, 1D array, [nlon] lat (np.array): latitude, 1D array, [nlat] vort (np.array, optional): vorticity component, 2D array, [nlat, nlon] gh (np.array): geopotential height, 2D array, [nlat, nlon] skip_vector (integer): skip grid number for vector plot smooth_factor (float): smooth factor for vorticity, larger for smoother. map_region (list or tuple): the map region limit, [lonmin, lonmax, latmin, latmax] title_kwargs (dictionaly, optional): keyword arguments for _get_title function. """ # check default parameters if skip_vector is None: skip_vector = util.get_skip_vector(lon, lat, map_region) # put data into fields wind_field = util.minput_2d_vector(uwind, vwind, lon, lat, skip=skip_vector) if vort is None: dx, dy = calc.lat_lon_grid_deltas(lon, lat) vort = calc.vorticity(uwind * units.meter / units.second, vwind * units.meter / units.second, dx, dy) vort = ndimage.gaussian_filter(vort, sigma=smooth_factor, order=0) * 10**5 vort_field = util.minput_2d(vort, lon, lat, { 'long_name': 'vorticity', 'units': 's-1' }) if gh is not None: gh_feild = util.minput_2d(gh, lon, lat, { 'long_name': 'height', 'units': 'gpm' }) # # set up visual parameters # plots = [] # Setting the coordinates of the geographical area if map_region is None: china_map = map_set.get_mmap(name='CHINA_CYLINDRICAL', subpage_frame_thickness=5) else: china_map = map_set.get_mmap(name='CHINA_REGION_CYLINDRICAL', map_region=map_region, subpage_frame_thickness=5) plots.append(china_map) # Background Coaslines coastlines = map_set.get_mcoast(name='COAST_FILL') plots.append(coastlines) # Define the shading contour vort_contour = magics.mcont( legend='on', contour_level_selection_type='level_list', contour_level_list=[ -200.0, -100.0, -75.0, -50.0, -30.0, -20.0, -15.0, -13.0, -11.0, -9.0, -7.0, -5.0, -3.0, -1.0, 1.0, 3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0, 20.0, 30.0, 50.0, 75.0, 100.0, 200.0 ], contour_shade='on', contour="off", contour_shade_method='area_fill', contour_shade_colour_method='list', contour_shade_colour_list=[ "rgb(0,0,0.3)", "rgb(0,0,0.5)", "rgb(0,0,0.7)", "rgb(0,0,0.9)", "rgb(0,0.15,1)", "rgb(0,0.3,1)", "rgb(0,0.45,1)", "rgb(0,0.6,1)", "rgb(0,0.75,1)", "rgb(0,0.85,1)", "rgb(0.2,0.95,1)", "rgb(0.45,1,1)", "rgb(0.75,1,1)", "none", "rgb(1,1,0)", "rgb(1,0.9,0)", "rgb(1,0.8,0)", "rgb(1,0.7,0)", "rgb(1,0.6,0)", "rgb(1,0.5,0)", "rgb(1,0.4,0)", "rgb(1,0.3,0)", "rgb(1,0.15,0)", "rgb(0.9,0,0)", "rgb(0.7,0,0)", "rgb(0.5,0,0)", "rgb(0.3,0,0)" ], contour_reference_level=8., contour_highlight='off', contour_hilo='off', contour_label='off') plots.extend([vort_field, vort_contour]) # Define the wind vector wind_vector = common._get_wind_flags() plots.extend([wind_field, wind_vector]) # Define the simple contouring for gh if gh is not None: gh_contour = common._get_gh_contour() plots.extend([gh_feild, gh_contour]) # Add a legend legend = common._get_legend(china_map, title="Vorticity [s^-1]") plots.append(legend) # Add the title title_kwargs = check_kwargs(title_kwargs, 'head', "500hPa Relative vorticity | Wind | GH") title = common._get_title(**title_kwargs) plots.append(title) # Add china province china_coastlines = map_set.get_mcoast(name='PROVINCE') plots.append(china_coastlines) # final plot return util.magics_plot(plots, outfile)
ugrad, vgrad = mpcalc.wind_components(grad_mag * units('m/s'), wdir) # Calculate Ageostrophic wind uageo = ugrad - ugeo vageo = vgrad - vgeo # Compute QVectors uqvect, vqvect = mpcalc.q_vector(ugeo, vgeo, T * units.degC, 500 * units.hPa, dx, dy) # Calculate divergence of the ageostrophic wind div = mpcalc.divergence(uageo, vageo, dx, dy, dim_order='yx') # Calculate Relative Vorticity Advection relvor = mpcalc.vorticity(ugeo, vgeo, dx, dy, dim_order='yx') adv = mpcalc.advection(relvor, (ugeo, vgeo), (dx, dy), dim_order='yx') ###################################################################### # Create figure containing Geopotential Heights, Temperature, Divergence # of the Ageostrophic Wind, Relative Vorticity Advection (shaded), # geostrphic wind barbs, and Q-vectors. # fig = plt.figure(figsize=(10, 10)) ax = plt.subplot(111) # Plot Geopotential Height Contours cs = ax.contour(lons, lats, Z, range(0, 12000, 120), colors='k') plt.clabel(cs, fmt='%d')
hght_500 = ndimage.gaussian_filter(hght_500, sigma=3, order=0) * units.meter uwnd_500 = units('m/s') * ds.variables['u-component_of_wind_isobaric'][ 0, lev_500, :, :] vwnd_500 = units('m/s') * ds.variables['v-component_of_wind_isobaric'][ 0, lev_500, :, :] ####################################### # Begin Data Calculations # ----------------------- dx, dy = mpcalc.lat_lon_grid_deltas(lon, lat) f = mpcalc.coriolis_parameter(np.deg2rad(lat)).to(units('1/sec')) avor = mpcalc.vorticity(uwnd_500, vwnd_500, dx, dy, dim_order='yx') + f avor = ndimage.gaussian_filter(avor, sigma=3, order=0) * units('1/s') vort_adv = mpcalc.advection(avor, [uwnd_500, vwnd_500], (dx, dy), dim_order='yx') * 1e9 ####################################### # Map Creation # ------------ # Set up Coordinate System for Plot and Transforms dproj = ds.variables['LambertConformal_Projection'] globe = ccrs.Globe(ellipse='sphere', semimajor_axis=dproj.earth_radius, semiminor_axis=dproj.earth_radius)
transform=proj_ccrs) #Add a color bar cbar = plt.colorbar(cs, cax=ax3, shrink=0.75, pad=0.01, ticks=clevs) print("Filled contours for 250-hPa wind") #-------------------------------------------------------------------------------------------------------- # 500-hPa smoothed vorticity #-------------------------------------------------------------------------------------------------------- #Get the data for this variable u = data['u'].sel(lev=500) v = data['v'].sel(lev=500) dx, dy = calc.lat_lon_grid_deltas(lon, lat) vort = calc.vorticity(u, v, dx, dy) smooth_vort = smooth(vort, 5.0) * 10**5 #Specify contour settings clevs = np.arange(2, 20, 1) cmap = plt.cm.autumn_r extend = "max" #Contour fill this variable norm = col.BoundaryNorm(clevs, cmap.N) cs = ax.contourf(lon, lat, smooth_vort, clevs, cmap=cmap, norm=norm,
# FIG #1: 250: JET STREAM, GEOPOTENTIAL HEIGHT, DIVERGENCE # ============================================================================= H250 = HGT_DATA.variables['hgt'][TIME_INDEX, 8, :, :] U250 = UWND_DATA.variables['uwnd'][TIME_INDEX, 8, :, :] * units('m/s') V250 = VWND_DATA.variables['vwnd'][TIME_INDEX, 8, :, :] * units('m/s') SPEED250 = mpcalc.get_wind_speed(U250, V250) DIV250 = mpcalc.divergence(U250, V250, DX, DY, dim_order='YX') DIV250 = (DIV250 * (units('1/s'))) # ============================================================================= # FIG #2: 500: VORTICITY, GEOPOTENTIAL HEIGHT, VORTICITY ADVECTION # ============================================================================= H500 = HGT_DATA.variables['hgt'][TIME_INDEX, 5, :, :] U500 = UWND_DATA.variables['uwnd'][TIME_INDEX, 5, :, :] * units('m/s') V500 = VWND_DATA.variables['vwnd'][TIME_INDEX, 5, :, :] * units('m/s') DX, DY = mpcalc.lat_lon_grid_spacing(LON, LAT) VORT500 = mpcalc.vorticity(U500, V500, DX, DY, dim_order='YX') VORT500 = (VORT500 * (units('1/s'))) VORT_ADV500 = mpcalc.advection(VORT500, [U500, V500], (DX, DY), dim_order='yx') # ============================================================================= # FIG #3: 700: Q-VECTORS+CONVERGENCE, GEOPOTENTIAL HEIGHT # ============================================================================= H700 = HGT_DATA.variables['hgt'][TIME_INDEX, 3, :, :] T700 = AIR_DATA.variables['air'][TIME_INDEX, 3, :, :] * units('kelvin') U700 = UWND_DATA.variables['uwnd'][TIME_INDEX, 3, :, :] * units('m/s') V700 = VWND_DATA.variables['vwnd'][TIME_INDEX, 3, :, :] * units('m/s') PWAT = PWAT_DATA.variables['pr_wtr'][TIME_INDEX, :, :] QVEC700 = mpcalc.q_vector(U700, V700, T700, 700 * units.mbar, DX, DY) QC700 = mpcalc.divergence(QVEC700[0], QVEC700[1], DX, DY, dim_order='yx') * (10**18) QVECX = QVEC700[0] QVECY = QVEC700[1]
def vort_criteria(ie, tstamp, coord): ''' Function defines a box of specified radius around the center of the cyclone. 1. Creates two slices in lat (yslice) and lon (xslice) directions around the center of the cyclone. Size of slice is determined by vort_radius rule. 2. Calculate dx and dy for search area via Haversine formula. create a mean dx and dy for forcing in the vorticity creation 3. Slice u and v component at 850hPa level 4. Force dx, dy, u and v to calculate vorcitiy fields around candidate. Detemine if a value in field greater than designated threshold. ''' def calc_dx_dy(longitude, latitude): ''' This definition calculates the distance between grid points that are in a latitude/longitude format. Necessary for vorticity calculations as dx changes as a function of latitude. Equation and code from: http://andrew.hedges.name/experiments/haversine/ dy should be close to 55600 m dx at pole should be 0 m dx at equator should be close to 55600 m Accepts, 1D arrays for latitude and longitude Returns: dx, dy; 2D arrays of distances between grid points in the x and y direction in meters ''' dlat = np.abs(latitude[1] - latitude[0]) * np.pi / 180 dy = 2 * (np.arctan2( np.sqrt((np.sin(dlat / 2))**2), np.sqrt(1 - (np.sin(dlat / 2))**2))) * 6371000 dy = np.ones( (latitude.shape[0], longitude.shape[0])) * dy dx = np.empty((latitude.shape)) dlon = np.abs(longitude[1] - longitude[0]) * np.pi / 180 for i in range(latitude.shape[0]): a = (np.cos(latitude[i] * np.pi / 180) * np.cos(latitude[i] * np.pi / 180) * np.sin(dlon / 2))**2 c = 2 * np.arctan2(np.sqrt(a), np.sqrt(1 - a)) dx[i] = c * 6371000 dx = np.repeat(dx[:, np.newaxis], longitude.shape, axis=1) return dx, dy #1 yslice, xslice, _ = self.vmax.box_slice( coord, npad=rules.vort_radius) lats = self._region.reg_lats[yslice] lons = self._region.reg_lons[xslice] #2 dx, dy = calc_dx_dy(lons, lats) dx = dx.mean() dy = dy.mean() #3 if self.mode == 'analysis': u = self.u850.values[ie, tstamp, yslice, xslice, 4] # ens =1, ans =4, lan=0 v = self.v850.values[ie, tstamp, yslice, xslice, 4] # ens =1, ans =4, lan=0 if self.mode == 'ensemble': u = self.u850.values[ie, tstamp, yslice, xslice, 0] # ens =1, ans =4, lan=0 v = self.v850.values[ie, tstamp, yslice, xslice, 0] # ens =1, ans =4, lan=0 #4 vort = vorticity(u, v, dx, dy).magnitude if np.any(vort > rules.vort_thresh): return coord
def test_default_order_warns(): """Test that using the default array ordering issues a warning.""" u = np.ones((3, 3)) * units('m/s') with pytest.warns(UserWarning): vorticity(u, u, 1 * units.meter, 1 * units.meter)
if interruptor == 'on': for dd in range(0, 10): ######################## LEYENDO LOS DATOS ######################### ## Se cargan los datos de la pagina datos = Dataset(enlace, 'r') lat = datos.variables[u'lat'][120:300] lon = datos.variables[u'lon'][1080:1320] hgt = datos.variables['hgtprs'][dd, 12, 120:300, 1080:1320] ugrd = datos.variables['ugrdprs'][dd, 12, 120:300, 1080:1320] vgrd = datos.variables['vgrdprs'][dd, 12, 120:300, 1080:1320] datos.close() ## calculo la vorticidad dx, dy = mpcalc.lat_lon_grid_deltas(lon, lat) f = mpcalc.coriolis_parameter(np.deg2rad(lat)).to(units('1/sec')) vor = mpcalc.vorticity(ugrd, vgrd, dx, dy, dim_order='yx') #vor = ndimage.gaussian_filter(vor, sigma=3, order=0) * units('1/sec') ####### GRAFICADO ######## fig = plt.figure(figsize=(15, 12)) ax1 = plt.subplot(1, 1, 1, projection=ccrs.PlateCarree()) ax1.set_extent([lon[0], lon[len(lon) - 1], lat[0], lat[len(lat) - 1]], crs=ccrs.PlateCarree()) # en contornos el geopotencial cs_1 = ax1.contour(lon, lat, hgt, 30, colors='black', transform=ccrs.PlateCarree()) ax1.clabel(cs_1, fmt='%2.1f', inline=True, fontsize=8)
wavenum = 6 wVerWavP = np.zeros((wavenum, nlev, numr, numth)) for ilev in range(0, nlev): wVerP = CarToPolar(to_np(wVer[ilev, :, :]), rMin, rMax, numr, numth) wVerWavP[:, ilev, :, :] = WaveDomain(wVerP, wavenum, numr, numth) # do the fourier transform # calculate the relative vorticity dx, dy = mpcalc.lat_lon_grid_deltas(lon, lat) revorVerWavP = np.zeros((wavenum, nlev, numr, numth)) for ilev in range(0, nlev): # calculate the vorticity # ?mpcalc.vorticity revorVer = mpcalc.vorticity(uVer[ilev, :, :], vVer[ilev, :, :], dx=dx, dy=dy) revorVerP = CarToPolar(to_np(revorVer), rMin, rMax, numr, numth) revorVerWavP[:, ilev, :, :] = WaveDomain(revorVerP, wavenum, numr, numth) # do the fourier transform ######################################################################## # draw the height-radius plane # Be careful, when caculating, the sequence is E-N-W-S, as to the rotation direction of quadrant # For convenience, when drawing, will use ::-1 to make the sequence is E-S-W-N, whose direction is inverse with quadrant # So the itheta=270 in data is refered to South ######################################################################## # draw the height-azimuth of azimuthal wind ir = 50 itheta = 270 #
def jp_500_hv(self, path): # 500hPa高度/風/渦度(日本域) path_fig = os.path.join(path, self.time_str1 + '.jpg') if (os.path.exists(path_fig)): return # 500hPa高度、緯度、経度の取得 height, lat, lon = self.grib2_select_jp('gh', 500) height = gaussian_filter(height, sigma=self.height_sigma) # 500hPa風の取得 wind_u, _, _ = self.grib2_select_jp('u', 500) * units('m/s') wind_v, _, _ = self.grib2_select_jp('v', 500) * units('m/s') # 渦度の計算 vort_x, vort_y = mpcalc.lat_lon_grid_deltas(lon, lat) vort_abs = mpcalc.vorticity(wind_u, wind_v, vort_x, vort_y, dim_order='yx') # 地図の描画 fig, ax = self.draw_map(self.mapcrs_jp, self.extent_jp) # カラーマップを作成する N = 140 M = 380 PuBu = np.flipud(cm.get_cmap('BuPu', N)(range(N))) YlOrRd = cm.get_cmap('YlOrRd', M)(range(M)) PuBuYlOrRd = ListedColormap(np.vstack((PuBu, YlOrRd))) # 等渦度線を引く vort_constant = ax.contourf(lon, lat, vort_abs * 10**6, np.arange(-120, 390, 30), extend='both', cmap=PuBuYlOrRd, transform=self.datacrs, alpha=0.9) # カラーバーをつける cbar = self.draw_jp_colorbar(vort_constant) cbar.set_label('VORT($10^{-6}/s$)', fontsize=self.fontsize) # 風ベクトルの表示 wind_arrow = (slice(None, None, 10), slice(None, None, 10)) ax.barbs(lon[wind_arrow], lat[wind_arrow], wind_u[wind_arrow].to('kt').m, wind_v[wind_arrow].to('kt').m, pivot='middle', color='black', alpha=0.5, transform=self.datacrs, length=10) # 等高度線を引く height_line = ax.contour(lon, lat, height, np.arange(0, 8000, 60), colors='black', transform=self.datacrs) plt.clabel(height_line, fmt='%d', fontsize=self.fontsize) # タイトルをつける self.draw_title( ax, '500hPa: HEIGHT(M), WIND ARROW(kt), VORT($10^{-6}/s$)', self.time_str2) # 大きさの調整 plt.subplots_adjust(bottom=0.05, top=0.95, left=0, right=1.0) # 保存 print(f'[{self.time_str2}] 500hPa高度/風/渦度(日本域)...{path_fig}'.format()) plt.savefig(path_fig) # 閉じる plt.close(fig=fig)
# Combine 1D latitude and longitudes into a 2D grid of locations lon_2d, lat_2d = np.meshgrid(lon, lat) # Gridshift for barbs lon_2d[lon_2d > 180] = lon_2d[lon_2d > 180] - 360 if plot_500vort: #Begin Data Calculations dx, dy = mpcalc.lat_lon_grid_deltas(lon, lat) f = mpcalc.coriolis_parameter(np.deg2rad(lat_2d)).to(units('1/sec')) ## need to set the lats this way since GFS is 1-d #avor = mpcalc.absolute_vorticity(uwnd_500,vwnd_500,dx,dy,lat[None,:,None]*units('degrees')) avor = mpcalc.vorticity(uwnd_500,vwnd_500,dx,dy) + f #smooth avor = ndimage.gaussian_filter(avor, sigma=3, order=0) * units('1/s') avor = avor.squeeze() ## remove first empty dimension ## vorticity advection #vort_adv = mpcalc.advection(avor, [uwnd_500, vwnd_500], (dx,dy)) * 1e9 ## give units to winds & smooth slightly uwnd_500 = ndimage.gaussian_filter(uwnd_500, sigma=1, order=0) * units('m/s') vwnd_500 = ndimage.gaussian_filter(vwnd_500, sigma=1, order=0) * units('m/s') ## make height plot for testing #Map Creation
def draw_composite_map(date_obj, t850, u200, v200, u500, v500, mslp, gh500, u850, v850, pwat): """ Draw synoptic composite map. Args: map_subset (int, optional): [description]. Defaults to 1. map_region (list, optional): [description]. Defaults to [70, 140, 20, 60]. """ #Get lat and lon arrays for this dataset: lat = t850.lat.values lon = t850.lon.values #======================================================================================================== # Create a Basemap plotting figure and add geography #======================================================================================================== #Create a Plate Carree projection object proj_ccrs = ccrs.Miller(central_longitude=0.0) #Create figure and axes for main plot and colorbars fig = plt.figure(figsize=(18, 12), dpi=125) gs = gridspec.GridSpec(12, 36, figure=fig) #[ytop:ybot, xleft:xright] ax = plt.subplot(gs[:, :-1], projection=proj_ccrs) #main plot ax.set_xticklabels([]) ax.set_yticklabels([]) ax2 = plt.subplot(gs[:4, -1]) #top plot ax2.set_xticklabels([]) ax2.set_yticklabels([]) ax3 = plt.subplot(gs[4:8, -1]) #bottom plot ax3.set_xticklabels([]) ax3.set_yticklabels([]) ax4 = plt.subplot(gs[8:, -1]) #bottom plot ax4.set_xticklabels([]) ax4.set_yticklabels([]) #Add political boundaries and coastlines ax.add_feature(cfeature.COASTLINE.with_scale('50m'), linewidths=1.2) ax.add_feature(cfeature.BORDERS.with_scale('50m'), linewidths=1.2) ax.add_feature(cfeature.STATES.with_scale('50m'), linewidths=0.5) #Add land/lake/ocean masking land_mask = cfeature.NaturalEarthFeature('physical', 'land', '50m', edgecolor='face', facecolor='#e6e6e6') sea_mask = cfeature.NaturalEarthFeature('physical', 'ocean', '50m', edgecolor='face', facecolor='#ffffff') lake_mask = cfeature.NaturalEarthFeature('physical', 'lakes', '50m', edgecolor='face', facecolor='#ffffff') ax.add_feature(sea_mask, zorder=0) ax.add_feature(land_mask, zorder=0) ax.add_feature(lake_mask, zorder=0) #======================================================================================================== # Fill contours #======================================================================================================== #-------------------------------------------------------------------------------------------------------- # 850-hPa temperature #-------------------------------------------------------------------------------------------------------- #Specify contour settings clevs = np.arange(-40, 40, 1) cmap = plt.cm.jet extend = "both" #Contour fill this variable norm = col.BoundaryNorm(clevs, cmap.N) cs = ax.contourf(lon, lat, t850, clevs, cmap=cmap, norm=norm, extend=extend, transform=proj_ccrs, alpha=0.1) #-------------------------------------------------------------------------------------------------------- # PWAT #-------------------------------------------------------------------------------------------------------- #Specify contour settings clevs = np.arange(20, 71, 0.5) #Define a color gradient for PWAT pwat_colors = gradient([[(255, 255, 255), 0.0], [(255, 255, 255), 20.0]], [[(205, 255, 205), 20.0], [(0, 255, 0), 34.0]], [[(0, 255, 0), 34.0], [(0, 115, 0), 67.0]]) cmap = pwat_colors.get_cmap(clevs) extend = "max" #Contour fill this variable norm = col.BoundaryNorm(clevs, cmap.N) cs = ax.contourf(lon, lat, pwat, clevs, cmap=cmap, norm=norm, extend=extend, transform=proj_ccrs, alpha=0.9) #Add a color bar cbar = plt.colorbar(cs, cax=ax2, shrink=0.75, pad=0.01, ticks=[20, 30, 40, 50, 60, 70]) #-------------------------------------------------------------------------------------------------------- # 250-hPa wind #-------------------------------------------------------------------------------------------------------- #Get the data for this variable wind = calc.wind_speed(u200, v200) #Specify contour settings clevs = [40, 50, 60, 70, 80, 90, 100, 110] cmap = col.ListedColormap([ '#99E3FB', '#47B6FB', '#0F77F7', '#AC97F5', '#A267F4', '#9126F5', '#E118F3', '#E118F3' ]) extend = "max" #Contour fill this variable norm = col.BoundaryNorm(clevs, cmap.N) cs = ax.contourf(lon, lat, wind, clevs, cmap=cmap, norm=norm, extend=extend, transform=proj_ccrs) #Add a color bar cbar = plt.colorbar(cs, cax=ax3, shrink=0.75, pad=0.01, ticks=clevs) #-------------------------------------------------------------------------------------------------------- # 500-hPa smoothed vorticity #-------------------------------------------------------------------------------------------------------- #Get the data for this variable dx, dy = calc.lat_lon_grid_deltas(lon, lat) vort = calc.vorticity(u500, v500, dx, dy) smooth_vort = smooth(vort, 5.0) * 10**5 #Specify contour settings clevs = np.arange(2, 20, 1) cmap = plt.cm.autumn_r extend = "max" #Contour fill this variable norm = col.BoundaryNorm(clevs, cmap.N) cs = ax.contourf(lon, lat, smooth_vort, clevs, cmap=cmap, norm=norm, extend=extend, transform=proj_ccrs, alpha=0.3) #Add a color bar cbar = plt.colorbar(cs, cax=ax4, shrink=0.75, pad=0.01, ticks=clevs[::2]) #======================================================================================================== # Contours #======================================================================================================== #-------------------------------------------------------------------------------------------------------- # MSLP #-------------------------------------------------------------------------------------------------------- #Specify contour settings clevs = np.arange(960, 1040 + 4, 4) style = 'solid' #Plot solid lines color = 'red' #Plot lines as gray width = 0.8 #Width of contours 0.25 #Contour this variable cs = ax.contour(lon, lat, mslp, clevs, colors=color, linewidths=width, linestyles=style, transform=proj_ccrs, alpha=0.9) #Include value labels ax.clabel(cs, inline=1, fontsize=9, fmt='%d') #-------------------------------------------------------------------------------------------------------- # Geopotential heights #-------------------------------------------------------------------------------------------------------- #Get the data for this variable gh500 = gh500 / 10.0 #Specify contour settings clevs = np.arange(480, 612, 4) style = 'solid' #Plot solid lines color = 'black' #Plot lines as gray width = 2.0 #Width of contours #Contour this variable cs = ax.contour(lon, lat, gh500, clevs, colors=color, linewidths=width, linestyles=style, transform=proj_ccrs) #Include value labels ax.clabel(cs, inline=1, fontsize=12, fmt='%d') #-------------------------------------------------------------------------------------------------------- # Surface barbs #-------------------------------------------------------------------------------------------------------- #Plot wind barbs quivers = ax.quiver(lon, lat, u850.values, v850.values, transform=proj_ccrs, regrid_shape=(38, 30), scale=820, alpha=0.5) #-------------------------------------------------------------------------------------------------------- # Label highs & lows #-------------------------------------------------------------------------------------------------------- #Label highs and lows add_mslp_label(ax, proj_ccrs, mslp, lat, lon) #======================================================================================================== # Step 6. Add map boundary, legend, plot title, then save image and close #======================================================================================================== #Add china province boundary add_china_map_2cartopy(ax, name='province') #Add custom legend from matplotlib.lines import Line2D custom_lines = [ Line2D([0], [0], color='#00A123', lw=5), Line2D([0], [0], color='#0F77F7', lw=5), Line2D([0], [0], color='#FFC000', lw=5), Line2D([0], [0], color='k', lw=2), Line2D([0], [0], color='k', lw=0.1, marker=r'$\rightarrow$', ms=20), Line2D([0], [0], color='r', lw=0.8), ] ax.legend(custom_lines, [ 'PWAT (mm)', '200-hPa Wind (m/s)', '500-hPa Vorticity', '500-hPa Height (dam)', '850-hPa Wind (m/s)', 'MSLP (hPa)' ], loc=2, prop={'size': 12}) #Format plot title title = "Synoptic Composite \nValid: " + dt.datetime.strftime( date_obj, '%Y-%m-%d %H%M UTC') st = plt.suptitle(title, fontweight='bold', fontsize=16) st.set_y(0.92) #Return figuration return (fig)