def test_advection_2d_asym(): """Test advection in asymmetric varying 2D field.""" u = np.arange(9).reshape(3, 3) * units('m/s') v = 2 * u s = np.array([[1, 2, 4], [4, 8, 4], [8, 6, 4]]) * units.kelvin a = advection(s, [u, v], (2 * units.meter, 1 * units.meter), dim_order='yx') truth = np.array([[0, -12.75, -2], [-27., -16., 10.], [-42, 35, 8]]) * units('K/sec') assert_array_equal(a, truth) # Now try xy ordered a = advection(s.T, [u.T, v.T], (2 * units.meter, 1 * units.meter), dim_order='xy') assert_array_equal(a, truth.T)
def temperature_advection(temp, wind, delta): r""" """ temp_advect = calc.advection(temp, wind, delta) return temp_advect
def test_advection_2d_uniform(): """Test advection for uniform 2D field.""" u = np.ones((3, 3)) * units('m/s') s = np.ones_like(u) * units.kelvin a = advection(s, [u, u], (1 * units.meter, 1 * units.meter)) truth = np.zeros_like(u) * units('K/sec') assert_array_equal(a, truth)
def test_advection_1d(): """Test advection calculation with varying wind and field.""" u = np.array([1, 2, 3]) * units('m/s') s = np.array([1, 2, 3]) * units('Pa') a = advection(s, u, (1 * units.meter, ), dim_order='xy') truth = np.array([-1, -2, -3]) * units('Pa/sec') assert_array_equal(a, truth)
def test_advection_uniform(): """Test advection calculation for a uniform 1D field.""" u = np.ones((3, )) * units('m/s') s = np.ones_like(u) * units.kelvin a = advection(s, u, (1 * units.meter, ), dim_order='xy') truth = np.zeros_like(u) * units('K/sec') assert_array_equal(a, truth)
def test_advection_uniform(): """Test advection calculation for a uniform 1D field.""" u = np.ones((3,)) * units('m/s') s = np.ones_like(u) * units.kelvin a = advection(s, u, (1 * units.meter,)) truth = np.zeros_like(u) * units('K/sec') assert_array_equal(a, truth)
def test_advection_1d_uniform_wind(): """Test advection for simple 1D case with uniform wind.""" u = np.ones((3,)) * units('m/s') s = np.array([1, 2, 3]) * units('kg') a = advection(s, u, (1 * units.meter,)) truth = -np.ones_like(u) * units('kg/sec') assert_array_equal(a, truth)
def test_advection_1d_uniform_wind(): """Test advection for simple 1D case with uniform wind.""" u = np.ones((3, )) * units('m/s') s = np.array([1, 2, 3]) * units('kg') a = advection(s, u, (1 * units.meter, ), dim_order='xy') truth = -np.ones_like(u) * units('kg/sec') assert_array_equal(a, truth)
def test_advection_1d(): """Test advection calculation with varying wind and field.""" u = np.array([1, 2, 3]) * units('m/s') s = np.array([1, 2, 3]) * units('Pa') a = advection(s, u, (1 * units.meter,)) truth = np.array([-1, -2, -3]) * units('Pa/sec') assert_array_equal(a, truth)
def test_advection_2d(): """Test advection in varying 2D field.""" u = np.ones((3, 3)) * units('m/s') v = 2 * np.ones((3, 3)) * units('m/s') s = np.array([[1, 2, 1], [2, 4, 2], [1, 2, 1]]) * units.kelvin a = advection(s, [u, v], (1 * units.meter, 1 * units.meter), dim_order='xy') truth = np.array([[-6, -4, 2], [-8, 0, 8], [-2, 4, 6]]) * units('K/sec') assert_array_equal(a, truth)
def test_advection_2d(): """Test advection in varying 2D field.""" u = np.ones((3, 3)) * units('m/s') v = 2 * np.ones((3, 3)) * units('m/s') s = np.array([[1, 2, 1], [2, 4, 2], [1, 2, 1]]) * units.kelvin a = advection(s, [u, v], (1 * units.meter, 1 * units.meter)) truth = np.array([[-3, -2, 1], [-4, 0, 4], [-1, 2, 3]]) * units('K/sec') assert_array_equal(a, truth)
def advection(variable, u_da, v_da, units_wind='m/s'): """ Calcula la advección en base a un dataarray de u y un dataarray de v en m/s """ lats = u_da.lat lons = u_da.lon u = u_da.values * units['m/s'] v = v_da.values * units['m/s'] dx, dy = mpcalc.lat_lon_grid_deltas(lons, lats) return mpcalc.advection(variable, [u, v], (dx, dy), dim_order='yx')
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) datacrs = ccrs.LambertConformal( central_latitude=dproj.latitude_of_projection_origin, central_longitude=dproj.longitude_of_central_meridian, standard_parallels=[dproj.standard_parallel], globe=globe)
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') # Plot Temperature Contours
uwnd_500 = ds.variables['u_wind'][0, lev_500, :, :] * units('m/s') vwnd_500 = ds.variables['v_wind'][0, lev_500, :, :] * units('m/s') ####################################### # Begin Data Calculations # ----------------------- dx, dy = calc_dx_dy(lon, lat) f = coriolis_parameter(np.deg2rad(lat)).to(units('1/sec')) avor = v_vorticity(uwnd_500.T, vwnd_500.T, dx.T, dy.T).T + f avor = ndimage.gaussian_filter(avor, sigma=3, order=0) * units('1/s') vort_adv = advection(avor.T, [uwnd_500.T, vwnd_500.T], (dx.T, dy.T)).T * 1e9 ####################################### # Map Creation # ------------ # Set up Coordinate System for Plot and Transforms dproj = ds.variables['Lambert_Conformal'] globe = ccrs.Globe(ellipse='sphere', semimajor_axis=dproj.earth_radius, semiminor_axis=dproj.earth_radius) datacrs = ccrs.LambertConformal( central_latitude=dproj.latitude_of_projection_origin, central_longitude=dproj.longitude_of_central_meridian, standard_parallels=[dproj.standard_parallel], globe=globe)
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
# 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 ############################################### # Begin data calculations # ----------------------- # Use helper function defined above to calculate distance # between lat/lon grid points dx, dy = calc_dx_dy(lon_var, lat_var) # Calculate temperature advection using metpy function adv = advection(temp_850.T * units.kelvin, [u_wind_850.T, v_wind_850.T], (dx.T, dy.T)).T * units('K/sec') # Smooth heights and advection a little # Be sure to only put in a 2D lat/lon or Y/X array for smoothing Z_850 = ndimage.gaussian_filter(hght_850, sigma=3, order=0) * units.meter adv = ndimage.gaussian_filter(adv, sigma=3, order=0) * units('K/sec') ############################################### # Begin map creation # ------------------ # Set Projection of Data datacrs = ccrs.PlateCarree() # Set Projection of Plot plotcrs = ccrs.LambertConformal(central_latitude=[30, 60],
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] # ============================================================================= # FIG #4: 850: GEOPOTENTIAL HEIGHT, TEMP, WINDS, TEMP-ADVECTION, FRONTOGENESIS
def Miller_Composite_Chart(initial_time=None, fhour=24, day_back=0, model='GRAPES_GFS', map_ratio=19 / 9, zoom_ratio=20, cntr_pnt=[102, 34], 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='700'), utl.Cassandra_dir(data_type='high', data_source=model, var_name='UGRD', lvl='300'), utl.Cassandra_dir(data_type='high', data_source=model, var_name='VGRD', lvl='300'), utl.Cassandra_dir(data_type='high', data_source=model, var_name='UGRD', lvl='500'), utl.Cassandra_dir(data_type='high', data_source=model, var_name='VGRD', lvl='500'), utl.Cassandra_dir(data_type='high', data_source=model, var_name='UGRD', lvl='850'), utl.Cassandra_dir(data_type='high', data_source=model, var_name='VGRD', lvl='850'), utl.Cassandra_dir(data_type='high', data_source=model, var_name='TMP', lvl='700'), utl.Cassandra_dir(data_type='high', data_source=model, var_name='HGT', lvl='500'), utl.Cassandra_dir(data_type='surface', data_source=model, var_name='BLI'), utl.Cassandra_dir(data_type='surface', data_source=model, var_name='Td2m'), utl.Cassandra_dir(data_type='surface', data_source=model, var_name='PRMSL') ] except KeyError: raise ValueError('Can not find all directories needed') # get filename if (initial_time != None): filename = utl.model_filename(initial_time, fhour) filename2 = utl.model_filename(initial_time, fhour - 12) else: filename = utl.filename_day_back_model(day_back=day_back, fhour=fhour) filename2 = utl.filename_day_back_model(day_back=day_back, fhour=fhour - 12) # retrieve data from micaps server rh_700 = get_model_grid(directory=data_dir[0], filename=filename) if rh_700 is None: return u_300 = get_model_grid(directory=data_dir[1], filename=filename) if u_300 is None: return v_300 = get_model_grid(directory=data_dir[2], filename=filename) if v_300 is None: return u_500 = get_model_grid(directory=data_dir[3], filename=filename) if u_500 is None: return v_500 = get_model_grid(directory=data_dir[4], filename=filename) if v_500 is None: return u_850 = get_model_grid(directory=data_dir[5], filename=filename) if u_850 is None: return v_850 = get_model_grid(directory=data_dir[6], filename=filename) if v_850 is None: return t_700 = get_model_grid(directory=data_dir[7], filename=filename) if t_700 is None: return hgt_500 = get_model_grid(directory=data_dir[8], filename=filename) if hgt_500 is None: return hgt_500_2 = get_model_grid(directory=data_dir[8], filename=filename2) if hgt_500_2 is None: return BLI = get_model_grid(directory=data_dir[9], filename=filename) if BLI is None: return Td2m = get_model_grid(directory=data_dir[10], filename=filename) if Td2m is None: return PRMSL = get_model_grid(directory=data_dir[11], filename=filename) if PRMSL is None: return PRMSL2 = get_model_grid(directory=data_dir[11], filename=filename2) if PRMSL2 is None: return lats = np.squeeze(rh_700['lat'].values) lons = np.squeeze(rh_700['lon'].values) x, y = np.meshgrid(rh_700['lon'], rh_700['lat']) tmp_700 = t_700['data'].values.squeeze() * units('degC') u_300 = (u_300['data'].values.squeeze() * units.meter / units.second).to('kt') v_300 = (v_300['data'].values.squeeze() * units.meter / units.second).to('kt') u_500 = (u_500['data'].values.squeeze() * units.meter / units.second).to('kt') v_500 = (v_500['data'].values.squeeze() * units.meter / units.second).to('kt') u_850 = (u_850['data'].values.squeeze() * units.meter / units.second).to('kt') v_850 = (v_850['data'].values.squeeze() * units.meter / units.second).to('kt') hgt_500 = (hgt_500['data'].values.squeeze()) * 10 / 9.8 * units.meter rh_700 = rh_700['data'].values.squeeze() lifted_index = BLI['data'].values.squeeze() * units.kelvin Td_sfc = Td2m['data'].values.squeeze() * units('degC') dx, dy = mpcalc.lat_lon_grid_deltas(lons, lats) avor_500 = mpcalc.absolute_vorticity(u_500, v_500, dx, dy, y * units.degree) pmsl = PRMSL['data'].values.squeeze() * units('hPa') hgt_500_2 = (hgt_500_2['data'].values.squeeze()) * 10 / 9.8 * units.meter pmsl2 = PRMSL2['data'].values.squeeze() * units('hPa') # 500 hPa CVA vort_adv_500 = mpcalc.advection( avor_500, [u_500.to('m/s'), v_500.to('m/s')], (dx, dy), dim_order='yx') * 1e9 vort_adv_500_smooth = gaussian_filter(vort_adv_500, 4) wspd_300 = gaussian_filter(mpcalc.wind_speed(u_300, v_300), 5) wspd_500 = gaussian_filter(mpcalc.wind_speed(u_500, v_500), 5) wspd_850 = gaussian_filter(mpcalc.wind_speed(u_850, v_850), 5) Td_dep_700 = tmp_700 - mpcalc.dewpoint_rh(tmp_700, rh_700 / 100.) pmsl_change = pmsl - pmsl2 hgt_500_change = hgt_500 - hgt_500_2 mask_500 = ma.masked_less_equal(wspd_500, 0.66 * np.max(wspd_500)).mask u_500[mask_500] = np.nan v_500[mask_500] = np.nan # 300 hPa mask_300 = ma.masked_less_equal(wspd_300, 0.66 * np.max(wspd_300)).mask u_300[mask_300] = np.nan v_300[mask_300] = np.nan # 850 hPa mask_850 = ma.masked_less_equal(wspd_850, 0.66 * np.max(wspd_850)).mask u_850[mask_850] = np.nan v_850[mask_850] = np.nan # prepare data 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)) fcst_info = { 'lon': lons, 'lat': lats, 'fhour': fhour, 'model': model, 'init_time': t_700.coords['forecast_reference_time'].values } synthetical_graphics.draw_Miller_Composite_Chart( fcst_info=fcst_info, u_300=u_300, v_300=v_300, u_500=u_500, v_500=v_500, u_850=u_850, v_850=v_850, pmsl_change=pmsl_change, hgt_500_change=hgt_500_change, Td_dep_700=Td_dep_700, Td_sfc=Td_sfc, pmsl=pmsl, lifted_index=lifted_index, vort_adv_500_smooth=vort_adv_500_smooth, map_extent=map_extent, add_china=True, city=False, south_China_sea=True, output_dir=None, Global=False)
def metpy_temp_adv(fname, plevels, tidx): ds = xr.open_dataset(fname).metpy.parse_cf().squeeze() ds = ds.isel(Time=tidx) print(ds) dx, dy = mpcalc.lat_lon_grid_deltas(ds.lon.values * units('degrees_E'), ds.lat.values * units('degrees_N')) plevels_unit = plevels * units.hPa 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') 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(var), coords=coords, dims=dims) # Calculate temperature advection using metpy function for i, plev in enumerate(plevs): uqvect, vqvect = mpcalc.q_vector(u[i, :, :], v[i, :, :], th[i, :, :], plev * units.hPa, dx, dy) #uqvect, vqvect = mpcalc.q_vector(u[i,:,:], v[i,:,:], th.to('degC')[i,:,:], plev*units.hPa, dx, dy) q_div = -2 * mpcalc.divergence(uqvect, vqvect, dx, dy, dim_order='yx') ds1['uq_{:03d}'.format(plev)] = xr.DataArray( np.array(uqvect), coords=[ds.lat.values, ds.lon.values], dims=["lat", "lon"]) ds1['vq_{:03d}'.format(plev)] = xr.DataArray( np.array(vqvect), coords=[ds.lat.values, ds.lon.values], dims=["lat", "lon"]) ds1['q_div_{:03d}'.format(plev)] = xr.DataArray( np.array(q_div), coords=[ds.lat.values, ds.lon.values], dims=["lat", "lon"]) # adv = mpcalc.advection(tk[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['tk_adv_{:03d}'.format(plev)] = xr.DataArray(np.array(adv), coords=[ds.lat.values,ds.lon.values], dims=["lat","lon"]) # # adv = mpcalc.advection(th[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['th_adv_{:03d}'.format(plev)] = xr.DataArray(np.array(adv), coords=[ds.lat.values,ds.lon.values], dims=["lat","lon"]) # 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['Time'] = ds.Time 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['t2m'] = xr.DataArray(ds.t2m.values, coords=[ds.lat.values, ds.lon.values], dims=["lat", "lon"]) ds1['th2'] = xr.DataArray(ds.th2.values, coords=[ds.lat.values, ds.lon.values], dims=["lat", "lon"]) ds1['mask'] = xr.DataArray(ds.mask.values, coords=[ds.lat.values, ds.lon.values], dims=["lat", "lon"]) ds1['u10'] = xr.DataArray(ds.u10.values, coords=[ds.lat.values, ds.lon.values], dims=["lat", "lon"]) ds1['v10'] = xr.DataArray(ds.v10.values, coords=[ds.lat.values, ds.lon.values], dims=["lat", "lon"]) ds1['slp'] = xr.DataArray(ds.slp.values, coords=[ds.lat.values, ds.lon.values], dims=["lat", "lon"]) ds1['rain'] = xr.DataArray(ds.rain.values, 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"]) #ds1['latent'] = xr.DataArray(ds.latent.values, coords=[ds.lat.values,ds.lon.values], dims=["lat","lon"]) #ds1['acclatent'] = xr.DataArray(ds.acclatent.values, coords=[ds.lat.values,ds.lon.values], dims=["lat","lon"]) return ds1
# Get time in a nice datetime object format vtime = ds.time.values.astype('datetime64[ms]').astype('O')[0] ###################################################################### # Differential Temperature Advection Calculation # ---------------------------------------------- # # Use MetPy advection funtion to calculate temperature advection at 700 # and 300 hPa, then manually compute the differential between those two # layers. The differential temperature advection is then valid at 500 hPa # (due to centered differencing) and is the same level that height changes # due to absolute vorticity advection is commonly assessed. # # Use MetPy advection function to calculate temperature advection at two levels tadv_700 = mpcalc.advection(tmpk_700, (uwnd_700, vwnd_700), (dx, dy), dim_order='yx').to_base_units() tadv_300 = mpcalc.advection(tmpk_300, (uwnd_300, vwnd_300), (dx, dy), dim_order='yx').to_base_units() # Centered finite difference to calculate differential temperature advection diff_tadv = ((tadv_700 - tadv_300) / (400 * units.hPa)).to_base_units() ###################################################################### # Make Four Panel Plot # -------------------- # # A four panel plot is produced to illustrate the temperature fields at # two levels (700 and 300 hPa), which are common fields to be plotted. # Then a panel containing the evaluated temperature advection at 700 hPa # and differential temperature advection between 700 and 300 hPa. Of # meteorological significance is the difference between these two
def Miller_Composite_Chart(initTime=None, fhour=24, day_back=0, model='GRAPES_GFS', map_ratio=14 / 9, zoom_ratio=20, cntr_pnt=[104, 34], data_source='MICAPS', Global=False, south_China_sea=True, area=None, city=False, output_dir=None, **kwargs): # micaps data directory if (data_source == 'MICAPS'): try: data_dir = [ utl.Cassandra_dir(data_type='high', data_source=model, var_name='RH', lvl='700'), utl.Cassandra_dir(data_type='high', data_source=model, var_name='UGRD', lvl='300'), utl.Cassandra_dir(data_type='high', data_source=model, var_name='VGRD', lvl='300'), utl.Cassandra_dir(data_type='high', data_source=model, var_name='UGRD', lvl='500'), utl.Cassandra_dir(data_type='high', data_source=model, var_name='VGRD', lvl='500'), utl.Cassandra_dir(data_type='high', data_source=model, var_name='UGRD', lvl='850'), utl.Cassandra_dir(data_type='high', data_source=model, var_name='VGRD', lvl='850'), utl.Cassandra_dir(data_type='high', data_source=model, var_name='TMP', lvl='700'), utl.Cassandra_dir(data_type='high', data_source=model, var_name='HGT', lvl='500'), utl.Cassandra_dir(data_type='surface', data_source=model, var_name='BLI'), utl.Cassandra_dir(data_type='surface', data_source=model, var_name='Td2m'), utl.Cassandra_dir(data_type='surface', data_source=model, var_name='PRMSL') ] except KeyError: raise ValueError('Can not find all directories needed') # get filename if (initTime != None): filename = utl.model_filename(initTime, fhour) filename2 = utl.model_filename(initTime, fhour - 12) else: filename = utl.filename_day_back_model(day_back=day_back, fhour=fhour) filename2 = utl.filename_day_back_model(day_back=day_back, fhour=fhour - 12) # retrieve data from micaps server rh_700 = MICAPS_IO.get_model_grid(directory=data_dir[0], filename=filename) if rh_700 is None: return u_300 = MICAPS_IO.get_model_grid(directory=data_dir[1], filename=filename) if u_300 is None: return v_300 = MICAPS_IO.get_model_grid(directory=data_dir[2], filename=filename) if v_300 is None: return u_500 = MICAPS_IO.get_model_grid(directory=data_dir[3], filename=filename) if u_500 is None: return v_500 = MICAPS_IO.get_model_grid(directory=data_dir[4], filename=filename) if v_500 is None: return u_850 = MICAPS_IO.get_model_grid(directory=data_dir[5], filename=filename) if u_850 is None: return v_850 = MICAPS_IO.get_model_grid(directory=data_dir[6], filename=filename) if v_850 is None: return t_700 = MICAPS_IO.get_model_grid(directory=data_dir[7], filename=filename) if t_700 is None: return hgt_500 = MICAPS_IO.get_model_grid(directory=data_dir[8], filename=filename) if hgt_500 is None: return hgt_500_2 = MICAPS_IO.get_model_grid(directory=data_dir[8], filename=filename2) if hgt_500_2 is None: return BLI = MICAPS_IO.get_model_grid(directory=data_dir[9], filename=filename) if BLI is None: return Td2m = MICAPS_IO.get_model_grid(directory=data_dir[10], filename=filename) if Td2m is None: return PRMSL = MICAPS_IO.get_model_grid(directory=data_dir[11], filename=filename) if PRMSL is None: return PRMSL2 = MICAPS_IO.get_model_grid(directory=data_dir[11], filename=filename2) if PRMSL2 is None: return if (data_source == 'CIMISS'): # get filename if (initTime != None): filename = utl.model_filename(initTime, fhour, UTC=True) filename2 = utl.model_filename(initTime, fhour - 12, UTC=True) else: filename = utl.filename_day_back_model(day_back=day_back, fhour=fhour, UTC=True) filename2 = utl.filename_day_back_model(day_back=day_back, fhour=fhour - 12, UTC=True) try: # retrieve data from CIMISS server rh_700 = CMISS_IO.cimiss_model_by_time( '20' + filename[0:8], valid_time=fhour, data_code=utl.CMISS_data_code(data_source=model, var_name='RHU'), fcst_level=700, fcst_ele="RHU", units='%') if rh_700 is None: return hgt_500 = CMISS_IO.cimiss_model_by_time( '20' + filename[0:8], valid_time=fhour, data_code=utl.CMISS_data_code(data_source=model, var_name='GPH'), fcst_level=500, fcst_ele="GPH", units='gpm') if hgt_500 is None: return hgt_500['data'].values = hgt_500['data'].values / 10. hgt_500_2 = CMISS_IO.cimiss_model_by_time( '20' + filename2[0:8], valid_time=fhour, data_code=utl.CMISS_data_code(data_source=model, var_name='GPH'), fcst_level=500, fcst_ele="GPH", units='gpm') if hgt_500_2 is None: return hgt_500_2['data'].values = hgt_500_2['data'].values / 10. u_300 = CMISS_IO.cimiss_model_by_time( '20' + filename[0:8], valid_time=fhour, data_code=utl.CMISS_data_code(data_source=model, var_name='WIU'), fcst_level=300, fcst_ele="WIU", units='m/s') if u_300 is None: return v_300 = CMISS_IO.cimiss_model_by_time( '20' + filename[0:8], valid_time=fhour, data_code=utl.CMISS_data_code(data_source=model, var_name='WIV'), fcst_level=300, fcst_ele="WIV", units='m/s') if v_300 is None: return u_500 = CMISS_IO.cimiss_model_by_time( '20' + filename[0:8], valid_time=fhour, data_code=utl.CMISS_data_code(data_source=model, var_name='WIU'), fcst_level=500, fcst_ele="WIU", units='m/s') if u_500 is None: return v_500 = CMISS_IO.cimiss_model_by_time( '20' + filename[0:8], valid_time=fhour, data_code=utl.CMISS_data_code(data_source=model, var_name='WIV'), fcst_level=500, fcst_ele="WIV", units='m/s') if v_500 is None: return u_850 = CMISS_IO.cimiss_model_by_time( '20' + filename[0:8], valid_time=fhour, data_code=utl.CMISS_data_code(data_source=model, var_name='WIU'), fcst_level=850, fcst_ele="WIU", units='m/s') if u_850 is None: return v_850 = CMISS_IO.cimiss_model_by_time( '20' + filename[0:8], valid_time=fhour, data_code=utl.CMISS_data_code(data_source=model, var_name='WIV'), fcst_level=850, fcst_ele="WIV", units='m/s') if v_850 is None: return BLI = CMISS_IO.cimiss_model_by_time('20' + filename2[0:8], valid_time=fhour, data_code=utl.CMISS_data_code( data_source=model, var_name='PLI'), fcst_level=0, fcst_ele="PLI", units='Pa') if BLI is None: return #1000hPa 露点温度代替2m露点温度 Td2m = CMISS_IO.cimiss_model_by_time('20' + filename2[0:8], valid_time=fhour, data_code=utl.CMISS_data_code( data_source=model, var_name='DPT'), fcst_level=1000, fcst_ele="DPT", units='Pa') if Td2m is None: return Td2m['data'].values = Td2m['data'].values - 273.15 if (model == 'ECMWF'): PRMSL = CMISS_IO.cimiss_model_by_time( '20' + filename[0:8], valid_time=fhour, data_code=utl.CMISS_data_code(data_source=model, var_name='GSSP'), fcst_level=0, fcst_ele="GSSP", units='Pa') else: PRMSL = CMISS_IO.cimiss_model_by_time( '20' + filename[0:8], valid_time=fhour, data_code=utl.CMISS_data_code(data_source=model, var_name='SSP'), fcst_level=0, fcst_ele="SSP", units='Pa') t_700 = CMISS_IO.cimiss_model_by_time( '20' + filename[0:8], valid_time=fhour, data_code=utl.CMISS_data_code(data_source=model, var_name='TEM'), fcst_level=700, fcst_ele="TEM", units='K') if t_700 is None: return t_700['data'].values = t_700['data'].values - 273.15 if PRMSL is None: return PRMSL['data'] = PRMSL['data'] / 100. if (model == 'ECMWF'): PRMSL2 = CMISS_IO.cimiss_model_by_time( '20' + filename2[0:8], valid_time=fhour, data_code=utl.CMISS_data_code(data_source=model, var_name='GSSP'), fcst_level=0, fcst_ele="GSSP", units='Pa') else: PRMSL2 = CMISS_IO.cimiss_model_by_time( '20' + filename2[0:8], valid_time=fhour, data_code=utl.CMISS_data_code(data_source=model, var_name='SSP'), fcst_level=0, fcst_ele="SSP", units='Pa') if PRMSL2 is None: return PRMSL2['data'] = PRMSL2['data'] / 100. except KeyError: raise ValueError('Can not find all data needed') lats = np.squeeze(rh_700['lat'].values) lons = np.squeeze(rh_700['lon'].values) x, y = np.meshgrid(rh_700['lon'], rh_700['lat']) tmp_700 = t_700['data'].values.squeeze() * units('degC') u_300 = (u_300['data'].values.squeeze() * units.meter / units.second).to('kt') v_300 = (v_300['data'].values.squeeze() * units.meter / units.second).to('kt') u_500 = (u_500['data'].values.squeeze() * units.meter / units.second).to('kt') v_500 = (v_500['data'].values.squeeze() * units.meter / units.second).to('kt') u_850 = (u_850['data'].values.squeeze() * units.meter / units.second).to('kt') v_850 = (v_850['data'].values.squeeze() * units.meter / units.second).to('kt') hgt_500 = (hgt_500['data'].values.squeeze()) * 10 / 9.8 * units.meter rh_700 = rh_700['data'].values.squeeze() lifted_index = BLI['data'].values.squeeze() * units.kelvin Td_sfc = Td2m['data'].values.squeeze() * units('degC') dx, dy = mpcalc.lat_lon_grid_deltas(lons, lats) avor_500 = mpcalc.absolute_vorticity(u_500, v_500, dx, dy, y * units.degree) pmsl = PRMSL['data'].values.squeeze() * units('hPa') hgt_500_2 = (hgt_500_2['data'].values.squeeze()) * 10 / 9.8 * units.meter pmsl2 = PRMSL2['data'].values.squeeze() * units('hPa') # 500 hPa CVA vort_adv_500 = mpcalc.advection( avor_500, [u_500.to('m/s'), v_500.to('m/s')], (dx, dy), dim_order='yx') * 1e9 vort_adv_500_smooth = gaussian_filter(vort_adv_500, 4) wspd_300 = gaussian_filter(mpcalc.wind_speed(u_300, v_300), 5) wspd_500 = gaussian_filter(mpcalc.wind_speed(u_500, v_500), 5) wspd_850 = gaussian_filter(mpcalc.wind_speed(u_850, v_850), 5) Td_dep_700 = tmp_700 - mpcalc.dewpoint_rh(tmp_700, rh_700 / 100.) pmsl_change = pmsl - pmsl2 hgt_500_change = hgt_500 - hgt_500_2 mask_500 = ma.masked_less_equal(wspd_500, 0.66 * np.max(wspd_500)).mask u_500[mask_500] = np.nan v_500[mask_500] = np.nan # 300 hPa mask_300 = ma.masked_less_equal(wspd_300, 0.66 * np.max(wspd_300)).mask u_300[mask_300] = np.nan v_300[mask_300] = np.nan # 850 hPa mask_850 = ma.masked_less_equal(wspd_850, 0.66 * np.max(wspd_850)).mask u_850[mask_850] = np.nan v_850[mask_850] = np.nan # prepare data 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 fcst_info = { 'lon': lons, 'lat': lats, 'forecast_period': fhour, 'model': model, 'forecast_reference_time': t_700.coords['forecast_reference_time'].values } synthetical_graphics.draw_Miller_Composite_Chart( fcst_info=fcst_info, u_300=u_300, v_300=v_300, u_500=u_500, v_500=v_500, u_850=u_850, v_850=v_850, pmsl_change=pmsl_change, hgt_500_change=hgt_500_change, Td_dep_700=Td_dep_700, Td_sfc=Td_sfc, pmsl=pmsl, lifted_index=lifted_index, vort_adv_500_smooth=vort_adv_500_smooth, map_extent=map_extent, add_china=True, city=city, south_China_sea=south_China_sea, output_dir=output_dir, Global=False)
# 500-hPa cyclonic vorticity advection # # Surface-based Lifted Index # # The axis of the 300-hPa, 500-hPa, and 850-hPa jets # # Surface dewpoint # # 700-hPa dewpoint depression # # 12-hr surface pressure falls and 500-hPa height changes # 500 hPa CVA dx, dy = mpcalc.lat_lon_grid_deltas(lon, lat) vort_adv_500 = mpcalc.advection( avor_500, [u_500.to('m/s'), v_500.to('m/s')], (dx, dy), dim_order='yx') * 1e9 vort_adv_500_smooth = gaussian_filter(vort_adv_500, 4) #################################### # For the jet axes, we will calculate the windspeed at each level, and plot the highest values wspd_300 = gaussian_filter(mpcalc.wind_speed(u_300, v_300), 5) wspd_500 = gaussian_filter(mpcalc.wind_speed(u_500, v_500), 5) wspd_850 = gaussian_filter(mpcalc.wind_speed(u_850, v_850), 5) ################################ # 700-hPa dewpoint depression will be calculated from Temperature_isobaric and RH Td_dep_700 = tmp_700 - mpcalc.dewpoint_rh(tmp_700, rh_700 / 100.) ###################################### # 12-hr surface pressure falls and 500-hPa height changes
# 500-hPa cyclonic vorticity advection # # Surface-based Lifted Index # # The axis of the 300-hPa, 500-hPa, and 850-hPa jets # # Surface dewpoint # # 700-hPa dewpoint depression # # 12-hr surface pressure falls and 500-hPa height changes # 500 hPa CVA dx, dy = calc_dx_dy(lon, lat) vort_adv_500 = mcalc.advection( avor_500, [v_500.to('m/s'), u_500.to('m/s')], (dy, dx), dim_order='yx') * 1e9 vort_adv_500_smooth = gaussian_filter(vort_adv_500, 4) #################################### # For the jet axes, we will calculate the windspeed at each level, and plot the highest values wspd_300 = gaussian_filter(mcalc.get_wind_speed(u_300, v_300), 5) wspd_500 = gaussian_filter(mcalc.get_wind_speed(u_500, v_500), 5) wspd_850 = gaussian_filter(mcalc.get_wind_speed(u_850, v_850), 5) ################################# # 850-hPa dewpoint will be calculated from RH and temperature Td_850 = mcalc.dewpoint_rh(tmp_850, rh_850 / 100.) ################################ # 700-hPa dewpoint depression will be calculated from temperature and RH
# 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 ############################################### # Begin data calculations # ----------------------- # Use helper function defined above to calculate distance # between lat/lon grid points dx, dy = mpcalc.lat_lon_grid_deltas(lon_var, lat_var) # Calculate temperature advection using metpy function adv = mpcalc.advection(temp_850 * units.kelvin, [u_wind_850, v_wind_850], (dx, dy), dim_order='yx') * units('K/sec') # Smooth heights and advection a little # Be sure to only put in a 2D lat/lon or Y/X array for smoothing Z_850 = ndimage.gaussian_filter(hght_850, sigma=3, order=0) * units.meter adv = ndimage.gaussian_filter(adv, sigma=3, order=0) * units('K/sec') ############################################### # Begin map creation # ------------------ # Set Projection of Data datacrs = ccrs.PlateCarree() # Set Projection of Plot