def plot(self, ax): # Get global u/v wind data ug, vg = self.chart.get_data(self.gfs_vars, apply_domain=False) # Get level coordinates for U/V wind components ug_lv_coord = gfs_utils.get_level_coord(ug, self.level_units) vg_lv_coord = gfs_utils.get_level_coord(vg, self.level_units) # Constrain to specified level(s) ugc = gfs_utils.get_coord_constraint(ug_lv_coord.name(), self.level) ug = ug.extract(ugc) vgc = gfs_utils.get_coord_constraint(vg_lv_coord.name(), self.level) vg = vg.extract(vgc) # Apply smoothing ug_data = wrf_smooth2d(ug.data, 6) ug.data = ug_data.data vg_data = wrf_smooth2d(vg.data, 6) vg.data = vg_data.data # Set up windspharm wind vector object w = VectorWind(ug, vg) xi = w.vorticity() div = w.divergence() # Constrain to specified domain domain_constraint = gfs_utils.get_domain_constraint(self.chart.domain) xi = xi.extract(domain_constraint) div = div.extract(domain_constraint) # Calculate strain S following Schielicke et al 2016 u_x, u_y = w.gradient(ug) v_x, v_y = w.gradient(vg) D_h = u_x + v_y # horizontal divergence Def = u_x - v_y # stretching deformation Def_s = u_y + v_x # shearing deformation ss = D_h**2 + Def**2 + Def_s**2 ss = ss.extract(domain_constraint) S = np.sqrt(ss.data) / math.sqrt(2) # Okubo-Weiss parameter # vorticity - (div + strain) okw = (div + S) - xi # Set mask to inspect O-W parameter in relevant region i.e. < 20N self.set_coord_mask(lat_max=20) # Define mask for O-W parameter mask = self.coord_mask | (okw.data < self.thres) # Apply mask okw_masked = iris.util.mask_cube(okw, mask) ax.contourf(self.lon, self.lat, okw_masked.data, **self.options)
def plot(self, ax): # Get global u/v wind data ug, vg = self.chart.get_data(self.gfs_vars, apply_domain=False) # Get level coordinates for U/V wind components ug_lv_coord = gfs_utils.get_level_coord(ug, self.level_units) vg_lv_coord = gfs_utils.get_level_coord(vg, self.level_units) # Constrain to specified level(s) ugc = gfs_utils.get_coord_constraint(ug_lv_coord.name(), self.level) ug = ug.extract(ugc) vgc = gfs_utils.get_coord_constraint(vg_lv_coord.name(), self.level) vg = vg.extract(vgc) # Apply smoothing ug_data = wrf_smooth2d(ug.data, 6) ug.data = ug_data.data vg_data = wrf_smooth2d(vg.data, 6) vg.data = vg_data.data # Set up windspharm wind vector object w = VectorWind(ug, vg) # Get divergence div = w.divergence() # Constrain to specified domain domain_constraint = gfs_utils.get_domain_constraint(self.chart.domain) div = div.extract(domain_constraint) # Mask absolute values below threshold div_masked = np.ma.masked_where( np.abs(div.data) < self.thres, div.data) # Set norm to match centre of colour scale to zero value self.options['norm'] = mcolors.TwoSlopeNorm(vmin=np.min(div_masked), vcenter=0, vmax=np.max(div_masked)) ax.contourf(self.lon, self.lat, div_masked, **self.options)
mpl.rcParams['mathtext.default'] = 'regular' # Read zonal and meridional wind components from file using the iris module. # The components are in separate files. We catch warnings here because the # files are not completely CF compliant. with warnings.catch_warnings(): warnings.simplefilter('ignore', UserWarning) uwnd = iris.load_cube(example_data_path('uwnd_mean.nc')) vwnd = iris.load_cube(example_data_path('vwnd_mean.nc')) uwnd.coord('longitude').circular = True vwnd.coord('longitude').circular = True # Create a VectorWind instance to handle the computations. w = VectorWind(uwnd, vwnd) # Compute components of rossby wave source: absolute vorticity, divergence, # irrotational (divergent) wind components, gradients of absolute vorticity. eta = w.absolutevorticity() div = w.divergence() uchi, vchi = w.irrotationalcomponent() etax, etay = w.gradient(eta) etax.units = 'm**-1 s**-1' etay.units = 'm**-1 s**-1' # Combine the components to form the Rossby wave source term. S = eta * -1. * div - (uchi * etax + vchi * etay) S.coord('longitude').attributes['circular'] = True # Pick out the field for December at 200 hPa.
from windspharm.examples import example_data_path # Read zonal and meridional wind components from file using the iris module. # The components are in separate files. We catch warnings here because the # files are not completely CF compliant. with warnings.catch_warnings(): warnings.simplefilter('ignore', UserWarning) uwnd = iris.load_cube(example_data_path('uwnd_mean.nc')) vwnd = iris.load_cube(example_data_path('vwnd_mean.nc')) uwnd.coord('longitude').circular = True vwnd.coord('longitude').circular = True # Create a VectorWind instance to handle the computation of streamfunction and # velocity potential. w = VectorWind(uwnd, vwnd) # Compute the streamfunction and velocity potential. sf, vp = w.sfvp() # Pick out the field for December. time_constraint = iris.Constraint(month='Dec') add_month(sf, 'time', name='month') add_month(vp, 'time', name='month') sf_dec = sf.extract(time_constraint) vp_dec = vp.extract(time_constraint) # Plot streamfunction. clevs = [-120, -100, -80, -60, -40, -20, 0, 20, 40, 60, 80, 100, 120] ax = plt.subplot(111, projection=ccrs.PlateCarree(central_longitude=180)) fill_sf = iplt.contourf(sf_dec * 1e-06, clevs, cmap=plt.cm.RdBu_r,
from windspharm.iris import VectorWind from windspharm.examples import example_data_path # Read zonal and meridional wind components from file using the iris module. # The components are in separate files. We catch warnings here because the # files are not completely CF compliant. with warnings.catch_warnings(): warnings.simplefilter('ignore', UserWarning) uwnd = iris.load_cube(example_data_path('uwnd_mean.nc')) vwnd = iris.load_cube(example_data_path('vwnd_mean.nc')) uwnd.coord('longitude').circular = True vwnd.coord('longitude').circular = True # Create a VectorWind instance to handle the computations. w = VectorWind(uwnd, vwnd) # Compute components of rossby wave source: absolute vorticity, divergence, # irrotational (divergent) wind components, gradients of absolute vorticity. eta = w.absolutevorticity() div = w.divergence() uchi, vchi = w.irrotationalcomponent() etax, etay = w.gradient(eta) etax.units = 'm**-1 s**-1' etay.units = 'm**-1 s**-1' # Combine the components to form the Rossby wave source term. S = eta * -1. * div - (uchi * etax + vchi * etay) S.coord('longitude').attributes['circular'] = True # Pick out the field for December at 200 hPa.
from windspharm.iris import VectorWind from windspharm.examples import example_data_path # Read zonal and meridional wind components from file using the iris module. # The components are in separate files. We catch warnings here because the # files are not completely CF compliant. with warnings.catch_warnings(): warnings.simplefilter('ignore', UserWarning) uwnd = iris.load_cube(example_data_path('uwnd_mean.nc')) vwnd = iris.load_cube(example_data_path('vwnd_mean.nc')) uwnd.coord('longitude').circular = True vwnd.coord('longitude').circular = True # Create a VectorWind instance to handle the computation of streamfunction and # velocity potential. w = VectorWind(uwnd, vwnd) # Compute the streamfunction and velocity potential. sf, vp = w.sfvp() # Pick out the field for December. time_constraint = iris.Constraint(month='Dec') add_month(sf, 'time', name='month') add_month(vp, 'time', name='month') sf_dec = sf.extract(time_constraint) vp_dec = vp.extract(time_constraint) # Plot streamfunction. clevs = [-120, -100, -80, -60, -40, -20, 0, 20, 40, 60, 80, 100, 120] ax = plt.subplot(111, projection=ccrs.PlateCarree(central_longitude=180)) fill_sf = iplt.contourf(sf_dec * 1e-06,
mons = 6 lag = 0 max_i = 35 + lag max_f = max_i + mons min_i = 11 + lag min_f = min_i + mons plt.clf() plt.ion() lsmask = iris.load_cube(ncfile_path + 'lsmask.nc')[0,0,::] lsmask.coord('latitude').guess_bounds() lsmask.coord('longitude').guess_bounds() # landmask = ~(ma.make_mask(lsmask.data.copy()) + np.zeros(temp_plv.shape)).astype(bool) # mask sea, show land # seamask = (ma.make_mask(lsmask.data.copy()) + np.zeros(temp_plv.shape)).astype(bool) # mask land, show sea uv = VectorWind(u,v) uv_div = uv.divergence() psi = uv.streamfunction() plev_b = 300 plev_t = 850 uv_uptrop_max = ta.iristropave(uv_div,plev_bottom=500,plev_top=200)[max_i:max_f,::].collapsed('time',iris.analysis.MEAN) uv_midtrop_max = ta.iristropave(uv_div,plev_bottom=850,plev_top=500)[max_i:max_f,::].collapsed('time',iris.analysis.MEAN) uv_lowtrop_max = ta.iristropave(uv_div,plev_bottom=1000,plev_top=850)[max_i:max_f,::].collapsed('time',iris.analysis.MEAN) u_uptrop_max = ta.iristropave(u,plev_bottom=500,plev_top=200)[max_i:max_f,::].collapsed('time',iris.analysis.MEAN) u_midtrop_max = ta.iristropave(u,plev_bottom=850,plev_top=500)[max_i:max_f,::].collapsed('time',iris.analysis.MEAN) u_lowtrop_max = ta.iristropave(u,plev_bottom=1000,plev_top=850)[max_i:max_f,::].collapsed('time',iris.analysis.MEAN) v_uptrop_max = ta.iristropave(v,plev_bottom=500,plev_top=200)[max_i:max_f,::].collapsed('time',iris.analysis.MEAN) v_midtrop_max = ta.iristropave(v,plev_bottom=850,plev_top=500)[max_i:max_f,::].collapsed('time',iris.analysis.MEAN)
def plot(self, ax): # Get global u/v wind data ug, vg = self.chart.get_data(self.gfs_vars, apply_domain=False) # Get level coordinates for U/V wind components ug_lv_coord = gfs_utils.get_level_coord(ug, self.level_units) vg_lv_coord = gfs_utils.get_level_coord(vg, self.level_units) # Constrain to specified level(s) ugc = gfs_utils.get_coord_constraint(ug_lv_coord.name(), self.level) ug = ug.extract(ugc) vgc = gfs_utils.get_coord_constraint(vg_lv_coord.name(), self.level) vg = vg.extract(vgc) # Apply smoothing ug_data = wrf_smooth2d(ug.data, 6) ug.data = ug_data.data vg_data = wrf_smooth2d(vg.data, 6) vg.data = vg_data.data # Set up windspharm wind vector object w = VectorWind(ug, vg) # Get nondivergent component of wind upsi, vpsi = w.nondivergentcomponent() Vpsi = VectorWind(upsi, vpsi) # Partition streamfunction vorticity into curvature and shear # components # Bell and Keyser 1993 Appendix equation A.3b # Relative curvature vorticity: # V dalpha/ds = 1/V^2[u^2 dv/dx - v^2 du/dy - uv(du/dx - dv/dy)] dupsi_dx, dupsi_dy = Vpsi.gradient(upsi) dvpsi_dx, dvpsi_dy = Vpsi.gradient(vpsi) ws = Vpsi.magnitude() vrt = (upsi**2 * dvpsi_dx - vpsi**2 * dupsi_dy - upsi * vpsi * (dupsi_dx - dvpsi_dy)) / ws**2 # Calculate advection of non-divergent curvature vorticity dvrt_dx, dvrt_dy = Vpsi.gradient(vrt) advec = -1 * (upsi * dvrt_dx + vpsi * dvrt_dy) # Second order advection term needed for masking dadv_dx, dadv_dy = Vpsi.gradient(advec) advec2 = upsi * dadv_dx + vpsi * dadv_dy # Apply domain constraint domain_constraint = gfs_utils.get_domain_constraint(self.chart.domain) upsi = upsi.extract(domain_constraint) vrt = vrt.extract(domain_constraint) advec = advec.extract(domain_constraint) advec2 = advec2.extract(domain_constraint) # Masking rules from Berry & Thorncroft 2007, Table 1 # A1. Mask streamfunction curvature vorticity to exclude AEW # ridges axes or weak systems (BT2007: K1T = 0.5 * 10^-5 s^-1) K1T = 1.5 * 10**-5 # s^-1 m1t = vrt.data <= K1T # mask for troughs m1r = vrt.data >= -K1T # mask for ridges # A2. Remove "pseudoridge" axes in nondivergent flow that is # highly cyclonically curved K2T = 0 # m s^-3 m2 = advec2.data <= K2T # A3. Removes trough axes in westerly flow K3T = 0 # m s^-1 m3 = upsi.data >= K3T trough_mask = m1t | m2 | m3 ridge_mask = m1r | ~m2 | m3 troughs = self.apply_size_mask(trough_mask, advec.data) ridges = self.apply_size_mask(ridge_mask, advec.data) # Plot troughs and ridges ax.contour(self.lon, self.lat, troughs, levels=0, **self.options) ax.contour(self.lon, self.lat, ridges, levels=0, **self.options, linestyles="dotted")