def test_scalar(): """Test potential_temperature accepts scalar values.""" assert_almost_equal( potential_temperature(1000. * units.mbar, 293. * units.kelvin), 293. * units.kelvin, 4) assert_almost_equal( potential_temperature(800. * units.mbar, 293. * units.kelvin), 312.2828 * units.kelvin, 4)
def pv(input_file): # Vars grib_vars = ['t','u','v'] # Load a list of datasets, one for each variable we want ds_list = [cfgrib.open_datasets(input_file,backend_kwargs={'filter_by_keys':{'typeOfLevel':'isobaricInhPa','shortName':v},'indexpath':''}) for v in grib_vars] # Flatten the list of lists to a single list of datasets ds_flat = [x.sel(isobaricInhPa=x.isobaricInhPa[x.isobaricInhPa>=100.0].values) for ds in ds_list for x in ds] # Merge the variables into a single dataset ds = xr.merge(ds_flat) # Add pressure ds['p'] = xr.DataArray(ds.isobaricInhPa.values,dims=['isobaricInhPa'],coords={'isobaricInhPa':ds.isobaricInhPa.values},attrs={'units':'hPa'}).broadcast_like(ds['t']) # Calculate potential temperature ds['theta'] = mpcalc.potential_temperature(ds['p'].metpy.convert_units('Pa'),ds['t']) # Compute baroclinic PV ds['pv'] = mpcalc.potential_vorticity_baroclinic(ds['theta'],ds['p'].metpy.convert_units('Pa'),ds['u'],ds['v'],latitude=ds.latitude)/(1.0e-6) met_data = ds['pv'].sel(isobaricInhPa=slice(float(os.environ.get('PV_LAYER_MAX_PRESSURE',1000.0)),float(os.environ.get('PV_LAYER_MIN_PRESSURE',100.0)))).mean(axis=0).values return met_data
def theta_plots(pressure, temperature, mixing_ratio): """ plots for vertical profiles of potential temperature, equivalent potential temperature, and saturated equivalent potential temperature """ p = pressure * units('mbar') T = temperature * units('degC') q = mixing_ratio * units('kilogram/kilogram') lev = find_nearest(p.magnitude, 100) Td = mpcalc.dewpoint(mpcalc.vapor_pressure(p, q)) # dewpoint theta = mpcalc.potential_temperature(p, T) theta_e = mpcalc.equivalent_potential_temperature(p, T, Td) theta_es = mpcalc.equivalent_potential_temperature(p, T, T) plt.figure(figsize=(7, 7)) plt.plot(theta[:lev], p[:lev], '-ok') plt.plot(theta_e[:lev], p[:lev], '-ob') plt.plot(theta_es[:lev], p[:lev], '-or') plt.xlabel('Temperature [K]', fontsize=12) plt.ylabel('Pressure [hpa]', fontsize=12) plt.gca().invert_yaxis() plt.legend(['$\\theta$', '$\\theta_e$', '$\\theta_{es}$'], loc=1) plt.grid() return (plt)
def add_metpy(option, filename): """ Adds the variables possible through metpy (theta, pv, n2) """ with xr.load_dataset(filename) as xin: if option.theta or option.pv: print("Adding potential temperature...") xin["pt"] = potential_temperature(xin["pressure"], xin["t"]) xin["pt"].data = np.array(xin["pt"].data) xin["pt"].attrs["units"] = "K" xin["pt"].attrs["standard_name"] = VARIABLES["pt"][2] if option.pv: print("Adding potential vorticity...") xin = xin.metpy.assign_crs(grid_mapping_name='latitude_longitude', earth_radius=6.356766e6) xin["pv"] = potential_vorticity_baroclinic(xin["pt"], xin["pressure"], xin["u"], xin["v"]) xin["pv"].data = np.array(xin["pv"].data * 10 ** 6) xin = xin.drop("metpy_crs") xin["pv"].attrs["units"] = "kelvin * meter ** 2 / kilogram / second" xin["pv"].attrs["standard_name"] = VARIABLES["pv"][2] xin["mod_pv"] = xin["pv"] * ((xin["pt"] / 360) ** (-4.5)) xin["mod_pv"].attrs["standard_name"] = VARIABLES["mod_pv"][2] if option.n2: print("Adding N2...") xin["n2"] = brunt_vaisala_frequency_squared(geopotential_to_height(xin["zh"]), xin["pt"]) xin["n2"].data = np.array(xin["n2"].data) xin["n2"].attrs["units"] = VARIABLES["n2"][1] xin["n2"].attrs["standard_name"] = "square_of_brunt_vaisala_frequency_in_air" xin.to_netcdf(filename)
def getDataFrame_UpperAir(model, station, init, hour): bufrData = BUFKIT.getBufkitData(model, station, init) if bufrData != False: # Verify data found modelSoundings = bufrData.SoundingParameters surfaceData = bufrData.SurfaceParameters[hour] soundingData = modelSoundings[hour + 1] z = [0 * units.meters] p = [surfaceData.pres] T = [surfaceData.t2ms] Td = [surfaceData.td2m] #Tw = [mpcalc.wet_bulb_temperature(surfaceData.pres, surfaceData.t2ms, surfaceData.td2m)] theta = [ mpcalc.potential_temperature(surfaceData.pres, surfaceData.t2ms) ] theta_e = [ mpcalc.equivalent_potential_temperature(surfaceData.pres, surfaceData.t2ms, surfaceData.td2m) ] u = [surfaceData.uwnd] v = [surfaceData.vwnd] for level in soundingData: z.append(level.hght) p.append(level.pres) T.append(level.tmpc) Td.append(level.dwpc) #Tw.append(mpcalc.wet_bulb_temperature(level.pres, level.tmpc, level.dwpc)) theta.append(mpcalc.potential_temperature(level.pres, level.tmpc)) theta_e.append( mpcalc.equivalent_potential_temperature( level.pres, level.tmpc, level.dwpc)) uv = mpcalc.wind_components(level.sknt, level.drct) u.append(uv[0]) v.append(uv[1]) return pd.DataFrame(list(zip(z, p, T, Td, theta, theta_e, u, v)), columns=[ 'height', 'pressure', 'temperature', 'dewpoint', 'theta', 'theta_e', 'u_wind', 'v_wind' ]) else: return False
def potential_temperature(pressure, temperature): r"""This method calls the metpy.calc function potential_temperature which takes the pint.Quantity objects containing the isobaric level value and the temperature at that level and produces the corresponding potential temperature with the reference pressure being 1000 millibars. """ return calc.potential_temperature(pressure, temperature)
def pot_temp(p, t): """ Computes potential temperature in [K] from pressure and temperature. Arguments: p -- pressure in [Pa] t -- temperature in [K] p and t can be scalars of NumPy arrays. They just have to either both scalars, or both arrays. Returns: potential temperature in [K]. """ return mpcalc.potential_temperature( units.Pa * p, units.K * t).to("K").m
def compute_theta(dset, tvar='t'): pres = dset['plev'].metpy.unit_array theta = mpcalc.potential_temperature(pres[:, None, None], dset[tvar]) theta = xr.DataArray(theta.magnitude, coords=dset[tvar].coords, attrs={ 'standard_name': 'Potential Temperature', 'units': theta.units }, name='theta') out = xr.merge([dset, theta]) out.attrs = dset.attrs return out
def pot_temp(p, t): """ Computes potential temperature in [K] from pressure and temperature. Arguments: p -- pressure in [Pa] t -- temperature in [K] p and t can be scalars of NumPy arrays. They just have to either both scalars, or both arrays. Returns: potential temperature in [K]. Same dimensions as the inputs. """ p = units.Quantity(p, "Pa") t = units.Quantity(t, "K") potential_temp = mpcalc.potential_temperature(p, t) return potential_temp
def calc_theta_from_T(T, p): """ Input : T : temperature (deg Celsius) p : pressure (hPa) Output : theta : Potential temperature values Function to estimate potential temperature from the temperature and pressure in the given dataset. This function uses MetPy's functions to get theta: (i) mpcalc.potential_temperature() """ theta = mpcalc.potential_temperature(p * units.hPa, T * units.degC).magnitude return theta
def calc_theta_from_T(dataset): """ Input : dataset : Dataset Output : theta : Potential temperature values Function to estimate potential temperature from the temperature and pressure in the given dataset. This function uses MetPy's functions to get theta: (i) mpcalc.potential_temperature() """ theta = mpcalc.potential_temperature(dataset.p.values * units.Pa, dataset.ta.values * units.kelvin).magnitude return theta
def moist_adiabat(z, SST): p = 1000 * np.exp(-9.81 * z / (287. * 270.)) * units.hPa Tp = mpcalc.moist_lapse(p, (SST - 1) * units.K) qp = 0.8 * mpcalc.saturation_mixing_ratio(p, Tp) ztrop1 = 17e3 ztrop2 = 19e3 idx1 = np.argmin((z - ztrop1)**2) idx2 = np.argmin((z - ztrop2)**2) Tp[idx1:idx2] = Tp[idx1] Tp[idx2:] = Tp[idx1] + 2e-3 * (z[idx2:] - ztrop2) * units.K thetap = mpcalc.potential_temperature(p, Tp) thicknesses = [ mpcalc.thickness_hydrostatic(p, Tp, bottom=p[i], depth=p[i] - p[i + 1]) / units.m for i in range(len(p) - 1) ] zp = np.concatenate([[0.], np.cumsum(thicknesses)]) thetaz = np.interp(z, zp, (thetap / units.K)) qz = np.interp(z, zp, qp) idxs = z < 35000 return z[idxs], np.array([float(x) for x in thetaz ])[idxs], np.array([float(x) for x in qz])[idxs]
def test_fahrenheit(): """Test that potential_temperature handles temperature values in Fahrenheit.""" assert_almost_equal(potential_temperature(800. * units.mbar, 68. * units.degF), (312.444 * units.kelvin).to(units.degF), 2)
def test_scalar(): """Test potential_temperature accepts scalar values.""" assert_almost_equal(potential_temperature(1000. * units.mbar, 293. * units.kelvin), 293. * units.kelvin, 4) assert_almost_equal(potential_temperature(800. * units.mbar, 293. * units.kelvin), 312.2828 * units.kelvin, 4)
############################## # Get the cross section, and convert lat/lon to supplementary coordinates: cross = cross_section(data, start, end).set_coords(('lat', 'lon')) ############################## # For this example, we will be plotting potential temperature, relative humidity, and # tangential/normal winds. And so, we need to calculate those, and add them to the dataset: cross['rhum'].metpy.convert_units('percent') temperature, pressure, relative_humidity = xr.broadcast( cross['air'], cross['level'], cross['rhum']) theta = mpcalc.potential_temperature(pressure, temperature) print(max(theta.flatten())) print(min(theta.flatten())) # These calculations return unit arrays, so put those back into DataArrays in our Dataset cross['Potential_temperature'] = xr.DataArray(theta, coords=temperature.coords, dims=temperature.dims, attrs={'units': theta.units}) cross['rhum'] = xr.DataArray(relative_humidity / 100, coords=relative_humidity.coords, dims=relative_humidity.dims, attrs={'units': relative_humidity.units}) cross['uwnd'].metpy.convert_units('knots') cross['vwnd'].metpy.convert_units('knots')
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 #
def scalardata(field, valid_time, targetdir=".", debug=False): # Get color map, levels, and netCDF variable name appropriate for requested variable (from fieldinfo module). info = fieldinfo[field] if debug: print("scalardata: found", field, "fieldinfo:", info) cmap = colors.ListedColormap(info['cmap']) levels = info['levels'] fvar = info['fname'][0] # Get narr file and filename. ifile = get(valid_time, targetdir=targetdir, narrtype=info['filename']) if debug: print("About to open " + ifile) nc = xarray.open_dataset(ifile) # Tried to rename vars and dimensions so metpy.parse_cf() would not warn "Found latitude/longitude values, assuming latitude_longitude for projection grid_mapping variable" # It didn't help. Only commenting out the metpy.parse_cf() line helped. # It didn't help with MetpyDeprecationWarning: Multidimensional coordinate lat assigned for axis "y". This behavior has been deprecated and will be removed in v1.0 (only one-dimensional coordinates will be available for the "y" axis) either #nc = nc.rename_vars({"gridlat_221": "lat", "gridlon_221" : "lon"}) #nc = nc.rename_dims({"gridx_221": "x", "gridy_221" : "y"}) #nc = nc.metpy.parse_cf() # TODO: figure out why filled contour didn't have .metpy.parse_cf() if fvar not in nc.variables: print(fvar, "not in", ifile, '. Try', nc.var()) sys.exit(1) # Define data array. Speed and shear derived differently. # Define 'long_name' attribute # if field[0:5] == "speed": u = nc[info['fname'][0]] v = nc[info['fname'][1]] data = u # copy metadata/coordinates from u data.values = wind_speed(u, v) data.attrs['long_name'] = "wind speed" elif field[0:3] == 'shr' and '_' in field: du, dv = shear(field, valid_time=valid_time, targetdir=targetdir, debug=debug) ws = wind_speed(du, dv) attrs = { 'long_name': 'wind shear', 'units': str(ws.units), 'verttitle': du.attrs["verttitle"] } # Use .m magnitude because you can't transfer units of pint quantity to xarray numpy array (xarray.values) data = xarray.DataArray(data=ws.m, dims=du.dims, coords=du.coords, name=field, attrs=attrs) elif field == 'theta2': pres = nc[info['fname'][0]] temp = nc[info['fname'][1]] data = pres # retain xarray metadata/coordinates theta = potential_temperature(pres, temp) data.values = theta data.attrs['units'] = str(theta.units) data.attrs['long_name'] = 'potential temperature' elif field == 'thetae2': pres = nc[info['fname'][0]] temp = nc[info['fname'][1]] dwpt = nc[info['fname'][2]] data = pres # retain xarray metadata/coordinates thetae = equivalent_potential_temperature(pres, temp, dwpt) data.values = thetae data.attrs['units'] = str(thetae.units) data.attrs['long_name'] = 'equivalent potential temperature' elif field == 'scp' or field == 'stp' or field == 'tctp': cape = nc[info['fname'][0]] cin = nc[info['fname'][1]] ifile = get(valid_time, targetdir=targetdir, narrtype=narrFlx) ncFlx = xarray.open_dataset(ifile).metpy.parse_cf() srh = ncFlx[info['fname'][2]] shear_layer = info['fname'][3] bulk_shear = scalardata(shear_layer, valid_time, targetdir=targetdir, debug=debug) lifted_condensation_level_height = scalardata('zlcl', valid_time, targetdir=targetdir, debug=debug) if field == 'scp': # In SPC help, cin is positive in SCP formulation. cin_term = -40 / cin cin_term = cin_term.where(cin < -40, other=1) scp = supercell_composite(cape, srh, bulk_shear) * cin_term.metpy.unit_array attrs = { 'units': str(scp.units), 'long_name': 'supercell composite parameter' } data = xarray.DataArray(data=scp, dims=cape.dims, coords=cape.coords, name=field, attrs=attrs) if field == 'stp': cin_term = (200 + cin) / 150 cin_term = cin_term.where(cin <= -50, other=1) cin_term = cin_term.where(cin >= -200, other=0) # CAPE, srh, bulk_shear, cin may be one vertical level, but LCL may be multiple heights. # xarray.broadcast() makes them all multiple heights with same shape, so significant_tornado doesn't # complain about expecting lat/lon 2 dimensions and getting 3 dimensions.. (cape, lifted_condensation_level_height, srh, bulk_shear, cin_term) = xarray.broadcast(cape, lifted_condensation_level_height, srh, bulk_shear, cin_term) stp = significant_tornado(cape, lifted_condensation_level_height, srh, bulk_shear) * cin_term.metpy.unit_array attrs = { 'units': str(stp.units), 'long_name': 'significant tornado parameter', 'verttitle': lifted_condensation_level_height.attrs['verttitle'] } data = xarray.DataArray(data=stp, dims=cape.dims, coords=cape.coords, name=field, attrs=attrs) if field == 'tctp': tctp = srh / (40 * munits['m**2/s**2']) * bulk_shear / ( 12 * munits['m/s']) * (2000 - lifted_condensation_level_height ) / (1400 * munits.m) # But NARR storm relative helicity (srh) is 0-3 km AGL, while original TCTP expects 0-1 km AGL. # So the shear term is too large using the NARR srh. Normalize the srh term with a larger denominator. # In STP, srh is normalized by 150 m**2/s**2. Use that. tctp_0_3kmsrh = srh / (150 * munits['m**2/s**2']) * bulk_shear / ( 12 * munits['m/s']) * (2000 - lifted_condensation_level_height ) / (1400 * munits.m) attrs = { 'units': 'dimensionless', 'long_name': 'TC tornado parameter' } data = xarray.DataArray(data=tctp_0_3kmsrh, dims=cape.dims, coords=cape.coords, name=field, attrs=attrs) elif field == 'lcl': pres = nc[info['fname'][0]] temp = nc[info['fname'][1]] dwpt = nc[info['fname'][2]] LCL_pressure, LCL_temperature = lcl(pres.fillna(pres.mean()), temp.fillna(temp.mean()), dwpt.fillna(dwpt.mean())) # convert units to string or xarray.DataArray.metpy.unit_array dies with ttributeError: 'NoneType' object has no attribute 'evaluate' attrs = { "long_name": "lifted condensation level", "units": str(LCL_pressure.units), "from": "metpy.calc.lcl" } data = xarray.DataArray(data=LCL_pressure, coords=pres.coords, dims=pres.dims, name='LCL', attrs=attrs) elif field == 'zlcl': LCL_pressure = scalardata('lcl', valid_time, targetdir=targetdir, debug=debug) ifile = get(valid_time, targetdir=targetdir, narrtype=narr3D) nc3D = xarray.open_dataset(ifile).metpy.parse_cf() hgt3D = nc3D["HGT_221_ISBL"] data = pressure_to_height(LCL_pressure, hgt3D, targetdir=targetdir) else: data = nc[fvar] data = units(data, info, debug=debug) data = vertical(data, info, debug=debug) data = temporal(data, info, debug=debug) data.attrs['field'] = field data.attrs['ifile'] = os.path.realpath(ifile) data.attrs['levels'] = levels data.attrs['cmap'] = cmap if data.min() > levels[-1] or data.max() < levels[0]: print('levels', levels, 'out of range of data', data.min(), data.max()) sys.exit(2) return data
def main(): load_start = dt.datetime.now() #Try parsing arguments using argparse parser = argparse.ArgumentParser( description='wrf non-parallel convective diagnostics processer') parser.add_argument("-m", help="Model name", required=True) parser.add_argument("-r", help="Region name (default is aus)", default="aus") parser.add_argument("-t1", help="Time start YYYYMMDDHH", required=True) parser.add_argument("-t2", help="Time end YYYYMMDDHH", required=True) parser.add_argument( "-e", help= "CMIP5 experiment name (not required if using era5, erai or barra)", default="") parser.add_argument( "--barpa_forcing_mdl", help="BARPA forcing model (erai or ACCESS1-0). Default erai.", default="erai") parser.add_argument( "--ens", help="CMIP5 ensemble name (not required if using era5, erai or barra)", default="r1i1p1") parser.add_argument("--group", help="CMIP6 modelling group name", default="") parser.add_argument("--project", help="CMIP6 modelling intercomparison project", default="CMIP") parser.add_argument("--ver6hr", help="Version on al33 for 6hr data", default="") parser.add_argument("--ver3hr", help="Version on al33 for 3hr data", default="") parser.add_argument("--issave", help="Save output (True or False, default is False)", default="False") parser.add_argument( "--ub4", help= "Where to get era5 data. Default True for ub4 project, otherwise rt52", default="True") parser.add_argument( "--outname", help= "Name of saved output. In the form *outname*_*t1*_*t2*.nc. Default behaviour is the model name", default=None) parser.add_argument( "--is_dcape", help="Should DCAPE be calculated? (1 or 0. Default is 1)", default=1) parser.add_argument( "--al33", help= "Should data be gathered from al33? Default is False, and data is gathered from r87. If True, then group is required", default="False") parser.add_argument( "--delta_t", help= "Time step spacing for ERA5 data, in hours. Default is one the minimum spacing (1 hour)", default="1") parser.add_argument( "--era5_interp", help= "Horizontally interpolate model data before calculating convective parameters", default="False") args = parser.parse_args() #Parse arguments from cmd line and set up inputs (date region model) model = args.m region = args.r t1 = args.t1 t2 = args.t2 issave = args.issave ub4 = args.ub4 al33 = args.al33 if args.outname == None: out_name = model else: out_name = args.outname is_dcape = args.is_dcape barpa_forcing_mdl = args.barpa_forcing_mdl experiment = args.e ensemble = args.ens group = args.group project = args.project ver6hr = args.ver6hr ver3hr = args.ver3hr delta_t = int(args.delta_t) era5_interp = args.era5_interp if region == "sa_small": start_lat = -38 end_lat = -26 start_lon = 132 end_lon = 142 elif region == "aus": start_lat = -44.525 end_lat = -9.975 start_lon = 111.975 end_lon = 156.275 elif region == "global": start_lat = -70 end_lat = 70 start_lon = -180 end_lon = 179.75 else: raise ValueError("INVALID REGION\n") domain = [start_lat, end_lat, start_lon, end_lon] try: time = [ dt.datetime.strptime(t1, "%Y%m%d%H"), dt.datetime.strptime(t2, "%Y%m%d%H") ] except: raise ValueError("INVALID START OR END TIME. SHOULD BE YYYYMMDDHH\n") if era5_interp == "True": era5_interp = True elif era5_interp == "False": era5_interp = False else: raise ValueError("\n INVALID era5_interp...SHOULD BE True OR False") if ub4 == "True": ub4 = True elif ub4 == "False": ub4 = False else: raise ValueError("\n INVALID ub4...SHOULD BE True OR False") if issave == "True": issave = True elif issave == "False": issave = False else: raise ValueError("\n INVALID ISSAVE...SHOULD BE True OR False") if al33 == "True": al33 = True elif al33 == "False": al33 = False else: raise ValueError("\n INVALID al33...SHOULD BE True OR False") #Load data print("LOADING DATA...") if model == "erai": ta,temp1,hur,hgt,terrain,p,ps,wap,ua,va,uas,vas,tas,ta2d,\ cp,tp,wg10,mod_cape,lon,lat,date_list = \ read_erai(domain,time) cp = cp.astype("float32", order="C") tp = tp.astype("float32", order="C") mod_cape = mod_cape.astype("float32", order="C") elif model == "era5": if ub4: ta,temp1,hur,hgt,terrain,p,ps,ua,va,uas,vas,tas,ta2d,\ cp,wg10,mod_cape,lon,lat,date_list = \ read_era5(domain,time,delta_t=delta_t) else: ta,temp1,hur,hgt,terrain,p,ps,ua,va,uas,vas,tas,ta2d,\ cp,tp,wg10,mod_cape,lon,lat,date_list = \ read_era5_rt52(domain,time,delta_t=delta_t) cp = cp.astype("float32", order="C") tp = tp.astype("float32", order="C") mod_cape = mod_cape.astype("float32", order="C") wap = np.zeros(hgt.shape) elif model == "barra": ta,temp1,hur,hgt,terrain,p,ps,wap,ua,va,uas,vas,tas,ta2d,wg10,lon,lat,date_list = \ read_barra(domain,time) elif model == "barra_fc": ta,temp1,hur,hgt,terrain,p,ps,wap,ua,va,uas,vas,tas,ta2d,wg10,lon,lat,date_list = \ read_barra_fc(domain,time) elif model == "barpa": ta,hur,hgt,terrain,p,ps,ua,va,uas,vas,tas,ta2d,wg10,lon,lat,date_list = \ read_barpa(domain, time, experiment, barpa_forcing_mdl, ensemble) wap = np.zeros(hgt.shape) temp1 = None elif model == "barra_ad": wg10,temp2,ta,temp1,hur,hgt,terrain,p,ps,wap,ua,va,uas,vas,tas,ta2d,lon,lat,date_list = \ read_barra_ad(domain, time, False) elif model in ["ACCESS1-0","ACCESS1-3","GFDL-CM3","GFDL-ESM2M","CNRM-CM5","MIROC5",\ "MRI-CGCM3","IPSL-CM5A-LR","IPSL-CM5A-MR","GFDL-ESM2G","bcc-csm1-1","MIROC-ESM",\ "BNU-ESM"]: #Check that t1 and t2 are in the same year year = np.arange(int(t1[0:4]), int(t2[0:4]) + 1) ta, hur, hgt, terrain, p_3d, ps, ua, va, uas, vas, tas, ta2d, tp, lon, lat, \ date_list = read_cmip(model, experiment, \ ensemble, year, domain, cmip_ver=5, al33=al33, group=group, ver6hr=ver6hr, ver3hr=ver3hr) wap = np.zeros(hgt.shape) wg10 = np.zeros(ps.shape) mod_cape = np.zeros(ps.shape) p = np.zeros(p_3d[0, :, 0, 0].shape) #date_list = pd.to_datetime(date_list).to_pydatetime() temp1 = None tp = tp.astype("float32", order="C") elif model in ["ACCESS-ESM1-5", "ACCESS-CM2"]: year = np.arange(int(t1[0:4]), int(t2[0:4]) + 1) ta, hur, hgt, terrain, p_3d, ps, ua, va, uas, vas, tas, ta2d, lon, lat, \ date_list = read_cmip(model, experiment,\ ensemble, year, domain, cmip_ver=6, group=group, project=project) wap = np.zeros(hgt.shape) wg10 = np.zeros(ps.shape) p = np.zeros(p_3d[0, :, 0, 0].shape) #date_list = pd.to_datetime(date_list).to_pydatetime() temp1 = None else: raise ValueError("Model not recognised") del temp1 ta = ta.astype("float32", order="C") hur = hur.astype("float32", order="C") hgt = hgt.astype("float32", order="C") terrain = terrain.astype("float32", order="C") p = p.astype("float32", order="C") ps = ps.astype("float32", order="C") wap = wap.astype("float32", order="C") ua = ua.astype("float32", order="C") va = va.astype("float32", order="C") uas = uas.astype("float32", order="C") vas = vas.astype("float32", order="C") tas = tas.astype("float32", order="C") ta2d = ta2d.astype("float32", order="C") wg10 = wg10.astype("float32", order="C") lon = lon.astype("float32", order="C") lat = lat.astype("float32", order="C") gc.collect() param = np.array([ "mu_cape", "mu_cin", "muq", "s06", "s0500", "lr700_500", "mhgt", "ta500", "tp" ]) if model in ["erai", "era5"]: param = np.concatenate([param, ["mod_cape"]]) #Option to interpolate to the ERA5 grid if era5_interp: #Interpolate model data to the ERA5 grid from era5_read import get_lat_lon_rt52 as get_era5_lat_lon era5_lon, era5_lat = get_era5_lat_lon() era5_lon_ind = np.where((era5_lon >= domain[2]) & (era5_lon <= domain[3]))[0] era5_lat_ind = np.where((era5_lat >= domain[0]) & (era5_lat <= domain[1]))[0] era5_lon = era5_lon[era5_lon_ind] era5_lat = era5_lat[era5_lat_ind] terrain = interp_era5(terrain, lon, lat, era5_lon, era5_lat, d3=False) #Set output array output_data = np.zeros( (ps.shape[0], era5_lat.shape[0], era5_lon.shape[0], len(param))) else: output_data = np.zeros( (ps.shape[0], ps.shape[1], ps.shape[2], len(param))) #Assign p levels to a 3d array, with same dimensions as input variables (ta, hgt, etc.) #If the 3d p-lvl array already exists, then declare the variable "mdl_lvl" as true. try: p_3d mdl_lvl = True full_p3d = p_3d except: mdl_lvl = False if era5_interp: p_3d = np.moveaxis(np.tile(p,[ta.shape[2],ta.shape[3],1]),[0,1,2],[1,2,0]).\ astype(np.float32) else: p_3d = np.moveaxis(np.tile(p,[era5_lat.shape[0],era5_lon.shape[0],1]),[0,1,2],[1,2,0]).\ astype(np.float32) print("LOAD TIME..." + str(dt.datetime.now() - load_start)) tot_start = dt.datetime.now() for t in np.arange(0, ta.shape[0]): cape_start = dt.datetime.now() if era5_interp: ta_t = interp_era5(ta[t], lon, lat, era5_lon, era5_lat, d3=True) hur_t = interp_era5(hur[t], lon, lat, era5_lon, era5_lat, d3=True) hgt_t = interp_era5(hgt[t], lon, lat, era5_lon, era5_lat, d3=True) ps_t = interp_era5(ps[t], lon, lat, era5_lon, era5_lat, d3=False) wap_t = interp_era5(wap[t], lon, lat, era5_lon, era5_lat, d3=True) ua_t = interp_era5(ua[t], lon, lat, era5_lon, era5_lat, d3=True) va_t = interp_era5(va[t], lon, lat, era5_lon, era5_lat, d3=True) uas_t = interp_era5(uas[t], lon, lat, era5_lon, era5_lat, d3=False) vas_t = interp_era5(vas[t], lon, lat, era5_lon, era5_lat, d3=False) tas_t = interp_era5(tas[t], lon, lat, era5_lon, era5_lat, d3=False) ta2d_t = interp_era5(ta2d[t], lon, lat, era5_lon, era5_lat, d3=False) tp_t = interp_era5(tp[t], lon, lat, era5_lon, era5_lat, d3=False) mod_cape_t = interp_era5(mod_cape[t], lon, lat, era5_lon, era5_lat, d3=False) else: ta_t = ta[t] hur_t = hur[t] hgt_t = hgt[t] ps_t = ps[t] wap_t = wap[t] ua_t = ua[t] va_t = va[t] uas_t = uas[t] vas_t = vas[t] tas_t = tas[t] ta2d_t = ta2d[t] tp_t = tp[t] mod_cape_t = mod_cape[t] print(date_list[t]) output = np.zeros((1, ps_t.shape[0], ps_t.shape[1], len(param))) if mdl_lvl: if era5_interp: p_3d = interp_era5(full_p3d[t], lon, lat, era5_lon, era5_lat, d3=True) else: p_3d = full_p3d[t] dp = get_dp(hur=hur_t, ta=ta_t, dp_mask=False) #Insert surface arrays, creating new arrays with "sfc" prefix sfc_ta = np.insert(ta_t, 0, tas_t, axis=0) sfc_hgt = np.insert(hgt_t, 0, terrain, axis=0) sfc_dp = np.insert(dp, 0, ta2d_t, axis=0) sfc_p_3d = np.insert(p_3d, 0, ps_t, axis=0) sfc_ua = np.insert(ua_t, 0, uas_t, axis=0) sfc_va = np.insert(va_t, 0, vas_t, axis=0) sfc_wap = np.insert(wap_t, 0, np.zeros(vas_t.shape), axis=0) #Sort by ascending p a,temp1,temp2 = np.meshgrid(np.arange(sfc_p_3d.shape[0]) , np.arange(sfc_p_3d.shape[1]),\ np.arange(sfc_p_3d.shape[2])) sort_inds = np.flip(np.lexsort([np.swapaxes(a, 1, 0), sfc_p_3d], axis=0), axis=0) sfc_hgt = np.take_along_axis(sfc_hgt, sort_inds, axis=0) sfc_dp = np.take_along_axis(sfc_dp, sort_inds, axis=0) sfc_p_3d = np.take_along_axis(sfc_p_3d, sort_inds, axis=0) sfc_ua = np.take_along_axis(sfc_ua, sort_inds, axis=0) sfc_va = np.take_along_axis(sfc_va, sort_inds, axis=0) sfc_ta = np.take_along_axis(sfc_ta, sort_inds, axis=0) #Calculate q and wet bulb for pressure level arrays with surface values sfc_ta_unit = units.units.degC * sfc_ta sfc_dp_unit = units.units.degC * sfc_dp sfc_p_unit = units.units.hectopascals * sfc_p_3d hur_unit = mpcalc.relative_humidity_from_dewpoint(ta_t*units.units.degC, dp*units.units.degC)*\ 100*units.units.percent q_unit = mpcalc.mixing_ratio_from_relative_humidity(hur_unit,\ ta_t*units.units.degC,np.array(p_3d)*units.units.hectopascals) sfc_hur_unit = mpcalc.relative_humidity_from_dewpoint(sfc_ta_unit, sfc_dp_unit)*\ 100*units.units.percent sfc_q_unit = mpcalc.mixing_ratio_from_relative_humidity(sfc_hur_unit,\ sfc_ta_unit,sfc_p_unit) sfc_theta_unit = mpcalc.potential_temperature(sfc_p_unit, sfc_ta_unit) sfc_thetae_unit = mpcalc.equivalent_potential_temperature( sfc_p_unit, sfc_ta_unit, sfc_dp_unit) sfc_thetae = np.array(mpcalc.equivalent_potential_temperature(ps_t*units.units.hectopascals,tas_t*units.units.degC,\ ta2d_t*units.units.degC)) sfc_q = np.array(sfc_q_unit) sfc_hur = np.array(sfc_hur_unit) #sfc_wb = np.array(wrf.wetbulb( sfc_p_3d*100, sfc_ta+273.15, sfc_q, units="degC")) #Use getcape.f90 #cape_gb_mu1, cape_gb_mu4 = getcape_driver(sfc_p_3d, sfc_ta, sfc_dp, ps_t) #Now get most-unstable CAPE (max CAPE in vertical, ensuring parcels used are AGL) cape3d = wrf.cape_3d(sfc_p_3d,sfc_ta+273.15,\ sfc_q,sfc_hgt,\ terrain,ps_t,\ True,meta=False, missing=0) cape = cape3d.data[0] cin = cape3d.data[1] lfc = cape3d.data[2] lcl = cape3d.data[3] el = cape3d.data[4] #Mask values which are below the surface and above 350 hPa AGL cape[(sfc_p_3d > ps_t) | (sfc_p_3d < (ps_t - 350))] = np.nan cin[(sfc_p_3d > ps_t) | (sfc_p_3d < (ps_t - 350))] = np.nan lfc[(sfc_p_3d > ps_t) | (sfc_p_3d < (ps_t - 350))] = np.nan lcl[(sfc_p_3d > ps_t) | (sfc_p_3d < (ps_t - 350))] = np.nan el[(sfc_p_3d > ps_t) | (sfc_p_3d < (ps_t - 350))] = np.nan #Get maximum (in the vertical), and get cin, lfc, lcl for the same parcel mu_cape_inds = np.tile(np.nanargmax(cape, axis=0), (cape.shape[0], 1, 1)) mu_cape = np.take_along_axis(cape, mu_cape_inds, 0)[0] mu_cin = np.take_along_axis(cin, mu_cape_inds, 0)[0] mu_lfc = np.take_along_axis(lfc, mu_cape_inds, 0)[0] mu_lcl = np.take_along_axis(lcl, mu_cape_inds, 0)[0] mu_el = np.take_along_axis(el, mu_cape_inds, 0)[0] muq = np.take_along_axis(sfc_q, mu_cape_inds, 0)[0] * 1000 #Calculate other parameters #Thermo thermo_start = dt.datetime.now() lr700_500 = get_lr_p(ta_t, p_3d, hgt_t, 700, 500) melting_hgt = get_t_hgt(sfc_ta, np.copy(sfc_hgt), 0, terrain) melting_hgt = np.where((melting_hgt < 0) | (np.isnan(melting_hgt)), 0, melting_hgt) ta500 = get_var_p_lvl(np.copy(sfc_ta), sfc_p_3d, 500) ta925 = get_var_p_lvl(np.copy(sfc_ta), sfc_p_3d, 925) ta850 = get_var_p_lvl(np.copy(sfc_ta), sfc_p_3d, 850) ta700 = get_var_p_lvl(np.copy(sfc_ta), sfc_p_3d, 700) rho = mpcalc.density( np.array(sfc_p_3d) * (units.units.hectopascal), sfc_ta * units.units.degC, sfc_q_unit) rho925 = np.array(get_var_p_lvl(np.array(rho), sfc_p_3d, 925)) rho850 = np.array(get_var_p_lvl(np.array(rho), sfc_p_3d, 850)) rho700 = np.array(get_var_p_lvl(np.array(rho), sfc_p_3d, 700)) #Winds winds_start = dt.datetime.now() s06 = get_shear_hgt(sfc_ua, sfc_va, np.copy(sfc_hgt), 0, 6000, terrain) s0500 = get_shear_p(ua_t, va_t, p_3d, "sfc", np.array([500]), p_3d, uas=uas_t, vas=vas_t)[0] #WAP if model in ["erai", "era5"]: sfc_w = mpcalc.vertical_velocity( wap_t * (units.units.pascal / units.units.second),\ np.array(p_3d) * (units.units.hectopascal), \ ta_t * units.units.degC, q_unit) w925 = np.array(get_var_p_lvl(np.array(sfc_w), p_3d, 925)) w850 = np.array(get_var_p_lvl(np.array(sfc_w), p_3d, 850)) w700 = np.array(get_var_p_lvl(np.array(sfc_w), p_3d, 700)) #Convergence if era5_interp: x, y = np.meshgrid(era5_lon, era5_lat) else: x, y = np.meshgrid(lon, lat) dx, dy = mpcalc.lat_lon_grid_deltas(x, y) u925 = np.array(get_var_p_lvl(np.copy(sfc_ua), sfc_p_3d, 925)) u850 = np.array(get_var_p_lvl(np.copy(sfc_ua), sfc_p_3d, 850)) u700 = np.array(get_var_p_lvl(np.copy(sfc_ua), sfc_p_3d, 700)) v925 = np.array(get_var_p_lvl(np.copy(sfc_va), sfc_p_3d, 925)) v850 = np.array(get_var_p_lvl(np.copy(sfc_va), sfc_p_3d, 850)) v700 = np.array(get_var_p_lvl(np.copy(sfc_va), sfc_p_3d, 700)) conv925 = -1e5 * np.array( mpcalc.divergence(u925 * (units.units.meter / units.units.second), v925 * (units.units.meter / units.units.second), dx, dy)) conv850 = -1e5 * np.array( mpcalc.divergence(u850 * (units.units.meter / units.units.second), v850 * (units.units.meter / units.units.second), dx, dy)) conv700 = -1e5 * np.array( mpcalc.divergence(u700 * (units.units.meter / units.units.second), v700 * (units.units.meter / units.units.second), dx, dy)) #CS6 mucs6 = mu_cape * np.power(s06, 1.67) #Fill output output = fill_output(output, t, param, ps, "mu_cape", mu_cape) output = fill_output(output, t, param, ps, "mu_cin", mu_cin) output = fill_output(output, t, param, ps, "muq", muq) output = fill_output(output, t, param, ps, "s06", s06) output = fill_output(output, t, param, ps, "s0500", s0500) output = fill_output(output, t, param, ps, "lr700_500", lr700_500) output = fill_output(output, t, param, ps, "ta500", ta500) output = fill_output(output, t, param, ps, "mhgt", melting_hgt) output = fill_output(output, t, param, ps, "tp", tp_t) if (model == "erai") | (model == "era5"): output = fill_output(output, t, param, ps, "mod_cape", mod_cape_t) output_data[t] = output print("SAVING DATA...") param_out = [] for param_name in param: temp_data = output_data[:, :, :, np.where(param == param_name)[0][0]] param_out.append(temp_data) #If the mhgt variable is zero everywhere, then it is likely that data has not been read. #In this case, all values are missing, set to zero. for t in np.arange(param_out[0].shape[0]): if param_out[np.where(param == "mhgt")[0][0]][t].max() == 0: for p in np.arange(len(param_out)): param_out[p][t] = np.nan if issave: if era5_interp: save_netcdf(region, model, out_name, date_list, era5_lat, era5_lon, param, param_out, \ out_dtype = "f4", compress=True) else: save_netcdf(region, model, out_name, date_list, lat, lon, param, param_out, \ out_dtype = "f4", compress=True) print(dt.datetime.now() - tot_start)
def test_potential_temperature(): """Test potential_temperature calculation.""" temp = np.array([278., 283., 291., 298.]) * units.kelvin pres = np.array([900., 500., 300., 100.]) * units.mbar real_th = np.array([286.493, 344.961, 410.4335, 575.236]) * units.kelvin assert_array_almost_equal(potential_temperature(pres, temp), real_th, 3)
def test_pot_temp_inhg(): """Test that potential_temperature can handle pressure not in mb (issue #165).""" assert_almost_equal(potential_temperature(29.92 * units.inHg, 29 * units.degC), 301.019735 * units.kelvin, 4)
# p) for all radiosonde variables including, Temperature, Dewpoint, # u-component of the wind, and v-component of the wind. # xsect = radisonde_cross_section(stn_list, df) ###################################################################### # Calculate Variables for Plotting # -------------------------------- # # Use MetPy to calculate common variables for plotting a cross section, # specifically potential temperature and mixing ratio # potemp = mpcalc.potential_temperature( xsect['p_grid'] * units('hPa'), xsect['grid_data']['temperature'] * units('degC')) relhum = mpcalc.relative_humidity_from_dewpoint( xsect['grid_data']['temperature'] * units('degC'), xsect['grid_data']['dewpoint'] * units('degC')) mixrat = mpcalc.mixing_ratio_from_relative_humidity( relhum, xsect['grid_data']['temperature'] * units('degC'), xsect['p_grid'] * units('hPa')) ###################################################################### # Plot Cross Section # ------------------ # # Use standard Matplotlib to plot the now 2D cross section grid using the
PHIS = PHIS / 9.81 # Force PHIS to have same dimensions as Z3 PHISnew1 = np.repeat(PHIS[np.newaxis, :, :], np.shape(Z3)[1], axis=0) PHISnew = np.repeat(PHISnew1[np.newaxis, :, :, :], np.shape(Z3)[0], axis=0) print('Shape of Z3: ', np.shape(Z3)) print('Shape of PHIS: ', np.shape(PHISnew)) # Height agl is then just Z3 - PHISnew z_agl = (Z3 - PHISnew) * units.meters # Get potential temperature P = (pressDS.PRESSURE.values * landMask) * units('Pa') T = (varsDS.T.values * landMask) * units('K') potTemp = mpc.potential_temperature(P, T) # Clear variables from memory that aren't needed anymore del PHISnew del PHIS del Z3 del P del T del pressDS del z3_ds del topo_ds del testDF # --------- Compute gradient richardson number ------ # Compute gradient richardson number U = (varsDS.U.values) * units('m/s')
############################## # Get the cross section, and convert lat/lon to supplementary coordinates: cross = cross_section(data, start, end) cross.set_coords(('lat', 'lon'), True) print(cross) ############################## # For this example, we will be plotting potential temperature, relative humidity, and # tangential/normal winds. And so, we need to calculate those, and add them to the dataset: temperature, pressure, specific_humidity = xr.broadcast(cross['Temperature'], cross['isobaric'], cross['Specific_humidity']) theta = mpcalc.potential_temperature(pressure, temperature) rh = mpcalc.relative_humidity_from_specific_humidity(specific_humidity, temperature, pressure) # These calculations return unit arrays, so put those back into DataArrays in our Dataset cross['Potential_temperature'] = xr.DataArray(theta, coords=temperature.coords, dims=temperature.dims, attrs={'units': theta.units}) cross['Relative_humidity'] = xr.DataArray(rh, coords=specific_humidity.coords, dims=specific_humidity.dims, attrs={'units': rh.units}) cross['u_wind'].metpy.convert_units('knots') cross['v_wind'].metpy.convert_units('knots') cross['t_wind'], cross['n_wind'] = mpcalc.cross_section_components(cross['u_wind'],
def f(fullname, selected_time): fullname_el = fullname.split('/') #fullname_el = fullname.split('\\') filename = fullname_el[-1] filename_el = filename.split('_') save_base_dir_name = '../1data/' save_dir_name = '{0}{1}/'.format(save_base_dir_name + dir_name, obs_year) print('site : {0}'.format(dir_name)) if os.path.isfile('{0}{1}_{2}_student.csv'\ .format(save_dir_name, filename_el[-5], selected_time[:13]))\ and os.path.isfile('{0}{1}_{2}_solution.csv'\ .format(save_dir_name, filename_el[-5], selected_time[:13])): write_log(log_file, '{3} ::: {0}{1}_{2} files are already exist'\ .format(save_dir_name, filename_el[-5], selected_time[:13], datetime.now())) else: try: f = lambda s: selected_time in s ids = df['time'].apply(f) df_selected_time = df[ids] df_selected_time = df_selected_time.sort_values('pressure', ascending=False) print('filename : {0}'.format(fullname)) print('df_selected_time.\n{0}'.format(df_selected_time)) df_selected_time.to_csv(r'{0}{1}_{2}_student.csv'\ .format(save_dir_name, filename_el[-5], selected_time[:13])) ################################################################################# ### We will pull the data out of the example dataset into individual variables and ### assign units. ################################################################################# p = df_selected_time['pressure'].values * units.hPa T = df_selected_time['temperature'].values * units.degC Td = df_selected_time['dewpoint'].values * units.degC wind_speed = df_selected_time['speed'].values * units.knots wind_dir = df_selected_time['direction'].values * units.degrees u, v = mpcalc.wind_components(wind_speed, wind_dir) # Calculate web bulb temperature df_selected_time['wet_bulb_T'] = mpcalc.wet_bulb_temperature( p, T, Td) # Calculate potential temperature df_selected_time['potential_T'] = mpcalc.potential_temperature( p, T) df_selected_time['potential_T_C'] = df_selected_time[ 'potential_T'].values - 273.15 # Calculate saturation vaper pressure df_selected_time[ 'saturation_vaper_pressure'] = mpcalc.saturation_vapor_pressure( T) df_selected_time[ 'vaper_pressure'] = mpcalc.saturation_vapor_pressure(Td) SVP = df_selected_time[ 'saturation_vaper_pressure'].values * units.hPa VP = df_selected_time['vaper_pressure'].values * units.hPa # Calculate mixing ratio df_selected_time['saturation_mixing_ratio'] = mpcalc.mixing_ratio( SVP, p) df_selected_time['mixing_ratio'] = mpcalc.mixing_ratio(VP, p) SMR = df_selected_time['saturation_mixing_ratio'].values * units( 'g/kg') MR = df_selected_time['mixing_ratio'].values * units('g/kg') # Calculate relative humidity df_selected_time['relative_humidity_from_dewpoint'] \ = mpcalc.relative_humidity_from_dewpoint(T, Td) df_selected_time['relative_humidity_from_mixing_ratio'] \ = mpcalc.relative_humidity_from_mixing_ratio(MR, T, p) # Calculate virtual temperature df_selected_time['virtual_temperature'] \ = mpcalc.virtual_temperature(T, MR) # Calculate virtual potential temperature df_selected_time['virtual_potential_temperature'] \ = mpcalc.virtual_potential_temperature(p, T, MR) print('df_selected_time after drop nan.\n{0}'.format( df_selected_time)) df_selected_time.to_csv(r'{0}{1}_{2}_solution.csv'\ .format(save_dir_name, filename_el[-5], selected_time[:13])) except Exception as err: write_log(err_log_file, '{4} ::: {0} with {1}{2} on {3}'\ .format(err, dir_name, filename, selected_time[:13], datetime.now())) print('Thread {0} is finished'.format(selected_time)) return 0 # Return a dummy value
# skew.plot(profP, parcel_prof, 'k', linewidth=2) # noL = list(launch.keys())[-8:] noL = list(launch.keys())[-12:] # colorL = ['r','o','y','g','b','p','k',''] cmap = cm.get_cmap('rainbow', 10) colorL = cmap(range(10)) i = 0 for no in noL: time = dtmdtm.strptime(launch[f"{no}"], "%Y/%m/%d %H:%M:%S") print(no, time) st = STreader(no, launch[f"{no}"], Path('../../data/ST')) try: P, T, Td, U, V = st.read() Theta = mcalc.potential_temperature(P, T).to('K') print(Theta) Thetae = mcalc.equivalent_potential_temperature(P, T, Td).to('K') ## UTC UTC = max((time + dtmdt(minutes=25)).hour, (time - dtmdt(minutes=25)).hour) - 8 LST = max((time + dtmdt(minutes=25)).hour, (time - dtmdt(minutes=25)).hour) if (UTC < 0): UTC += 24 title = (time - dtmdt(days=1)).strftime('%m%d') else: title = time.strftime('%m%d')
TArr = np.array([t1, t2, t3, t4]) RHArr = np.array([rh1, rh2, rh3, rh4]) Tmean = np.nanmean(TArr, 0) RHmean = np.nanmean(RHArr, 0) if np.isnan(RHmean).all(): isRH = 0 else: isRH = 1 ###################################################### ## Calculate thermodymanic and convective variables ## ###################################################### theta = np.array( mcalc.potential_temperature(pres * units.mbar, (Tmean + 273.15) * units.kelvin)) Td = np.array(mcalc.dewpoint_rh(Tmean * units.degC, RHmean / 100.)) ws = np.array( mcalc.saturation_mixing_ratio(pres * units.mbar, (Tmean + 273.15) * units.kelvin)) w = np.multiply(RHmean / 100., ws * 1000.) # check for RH if isRH: lclpres, lcltemp = mcalc.lcl(pres[0] * units.mbar, Tmean[0] * units.degC, Td[0] * units.degC) print 'LCL Pressure: {}'.format(lclpres) print 'LCL Temperature: {}'.format(lcltemp) # parcel profile # determine if there are points sampled above lcl
########################################### # We will pull the data out of the example dataset into individual variables and # assign units. p = df_selected_time['pressure'].values * units.hPa T = df_selected_time['temperature'].values * units.degC Td = df_selected_time['dewpoint'].values * units.degC wind_speed = df_selected_time['speed'].values * units.knots wind_dir = df_selected_time[ 'direction'].values * units.degrees u, v = mpcalc.wind_components(wind_speed, wind_dir) # Calculate potential temperature #potential_T = mpcalc.potential_temperature(p[1], T[10]) df_selected_time[ 'potential_T'] = mpcalc.potential_temperature(p, T) df_selected_time['potential_T_C'] = df_selected_time[ 'potential_T'].values - 273.15 df_selected_time[ 'saturation_vaper_pressure'] = mpcalc.saturation_vapor_pressure( T) df_selected_time[ 'vaper_pressure'] = mpcalc.saturation_vapor_pressure( Td) VPS = df_selected_time[ 'saturation_vaper_pressure'].values * units.hPa VP = df_selected_time['vaper_pressure'].values * units.hPa df_selected_time[ 'saturation_mixing_ratio'] = mpcalc.mixing_ratio(
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 # ============================================================================= H850 = HGT_DATA.variables['hgt'][TIME_INDEX, 2, :, :] T850 = AIR_DATA.variables['air'][TIME_INDEX, 2, :, :] * units('kelvin') U850 = UWND_DATA.variables['uwnd'][TIME_INDEX, 2, :, :] * units('m/s') V850 = VWND_DATA.variables['vwnd'][TIME_INDEX, 2, :, :] * units('m/s') T_ADV850 = mpcalc.advection(T850 * units.kelvin, [U850, V850], (DX, DY), dim_order='yx') * units('K/sec') PT850 = mpcalc.potential_temperature(850 * units.mbar, T850) FRONT_850 = mpcalc.frontogenesis(PT850, U850, V850, DX, DY, dim_order='YX') # ============================================================================= # FIG #5: 850: GEOPOTENTIAL HEIGHT, EQUIV. POT. TEMP, WINDS, LAPSE RATES # ============================================================================= H500 = HGT_DATA.variables['hgt'][TIME_INDEX, 5, :, :] H700 = HGT_DATA.variables['hgt'][TIME_INDEX, 3, :, :] T500 = AIR_DATA.variables['air'][TIME_INDEX, 5, :, :] * units('degC') T700 = AIR_DATA.variables['air'][TIME_INDEX, 3, :, :] * units('degC') LR = -1000 * (T500 - T700) / (H500 - H700) H850 = HGT_DATA.variables['hgt'][TIME_INDEX, 2, :, :] T850 = AIR_DATA.variables['air'][TIME_INDEX, 2, :, :] * units('kelvin') SH850 = SHUM_DATA.variables['shum'][TIME_INDEX, 2, :, :] DP850 = mpcalc.dewpoint_from_specific_humidity(SH850, T850, 850 * units.mbar) EPT850 = mpcalc.equivalent_potential_temperature(850 * units.mbar, T850, DP850) # =============================================================================
def cross_section(isentlev, num, left_lat, left_lon, right_lat, right_lon): """Plot an isentropic cross-section.""" # get the coordinates of the endpoints for the cross-section left_coord = np.array((float(left_lat), float(left_lon))) right_coord = np.array((float(right_lat), float(right_lon))) # Calculate data for the inset isentropic map isent_anal = mcalc.isentropic_interpolation(float(isentlev) * units.kelvin, lev, tmp, spech, tmpk_out=True) isentprs = isent_anal[0] isenttmp = isent_anal[1] isentspech = isent_anal[2] isentrh = mcalc.relative_humidity_from_specific_humidity(isentspech, isenttmp, isentprs) # Find index values for the cross section slice iright = lat_lon_2d_index(lat, lon, right_coord[0], right_coord[1]) ileft = lat_lon_2d_index(lat, lon, left_coord[0], left_coord[1]) # Get the cross-section slice data cross_data = mcalc.extract_cross_section(ileft, iright, lat, lon, tmp, uwnd, vwnd, spech, num=num) cross_lat = cross_data[0] cross_lon = cross_data[1] cross_t = cross_data[2] cross_u = cross_data[3] cross_v = cross_data[4] cross_spech = cross_data[5] # Calculate theta and RH on the cross-section cross_theta = mcalc.potential_temperature(lev[:, np.newaxis], cross_t) cross_rh = mcalc.relative_humidity_from_specific_humidity(cross_spech, cross_t, lev[:, np.newaxis]) # Create figure for ploting fig = plt.figure(1, figsize=(17., 12.)) # Plot the cross section ax1 = plt.axes() ax1.set_yscale('symlog') ax1.grid() cint = np.arange(250, 450, 5) # Determine whether to label x-axis with lat or lon values if np.abs(left_lon - right_lon) > np.abs(left_lat - right_lat): cs = ax1.contour(cross_lon, lev[::-1], cross_theta[::-1, :], cint, colors='tab:red') cf = ax1.contourf(cross_lon, lev[::-1], cross_rh[::-1, :], range(10, 106, 5), cmap=plt.cm.gist_earth_r) ax1.barbs(cross_lon[4::4], lev, cross_u[:, 4::4], cross_v[:, 4::4], length=6) plt.xlabel('Longitude (Degrees East)') else: cs = ax1.contour(cross_lat[::-1], lev[::-1], cross_theta[::-1, ::-1], cint, colors='tab:red') cf = ax1.contourf(cross_lat[::-1], lev[::-1], cross_rh[::-1, ::-1], range(10, 106, 5), cmap=plt.cm.gist_earth_r) ax1.barbs(cross_lat[::-4], lev, cross_u[:, ::-4], cross_v[:, ::-4], length=6) plt.xlim(cross_lat[0], cross_lat[-1]) plt.xlabel('Latitude (Degrees North)') # Label the cross section axes plt.clabel(cs, fontsize=10, inline=1, inline_spacing=7, fmt='%i', rightside_up=True, use_clabeltext=True) cb = plt.colorbar(cf, orientation='horizontal', extend=max, aspect=65, shrink=0.75, pad=0.06, extendrect='True') cb.set_label('Relative Humidity', size='x-large') plt.ylabel('Pressure (hPa)') ax1.set_yticklabels(np.arange(1000, 50, -50)) plt.ylim(lev[0], lev[-1]) plt.yticks(np.arange(1000, 50, -50)) # Add a title plt.title(('NARR Isentropic Cross-Section: ' + str(left_coord[0]) + ' N, ' + str(left_coord[1]) + ' E to ' + str(right_coord[0]) + ' N, ' + str(right_coord[1]) + ' E'), loc='left') plt.title('VALID: {:s}'.format(str(vtimes[0])), loc='right') # Add Inset Map ax2 = fig.add_axes([0.125, 0.643, 0.25, 0.25], projection=crs) # Coordinates to limit map area bounds = [(-122., -75., 25., 50.)] # Limit extent of inset map ax2.set_extent(*bounds, crs=ccrs.PlateCarree()) ax2.coastlines('50m', edgecolor='black', linewidth=0.75) ax2.add_feature(states_provinces, edgecolor='black', linewidth=0.5) # Plot the surface clevisent = np.arange(0, 1000, 25) cs = ax2.contour(tlons, tlats, isentprs[0, :, :], clevisent, colors='k', linewidths=1.0, linestyles='solid') plt.clabel(cs, fontsize=10, inline=1, inline_spacing=7, fmt='%i', rightside_up=True, use_clabeltext=True) # Plot RH cf = ax2.contourf(tlons, tlats, isentrh[0, :, :], range(10, 106, 5), cmap=plt.cm.gist_earth_r) # Convert endpoints of cross-section line left = crs.transform_point(left_coord[1], left_coord[0], ccrs.PlateCarree()) right = crs.transform_point(right_coord[1], right_coord[0], ccrs.PlateCarree()) # Plot the cross section line plt.plot([left[0], right[0]], [left[1], right[1]], color='r') plt.show()
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)
def calc_param_wrf_par(it): #Have copied this function here from calc_param_wrf_par, to use global arrays t, param = it wg = False p_3d = np.moveaxis(np.tile(p, [ta.shape[0], ta.shape[2], ta.shape[3], 1]), [0, 1, 2, 3], [0, 2, 3, 1]) param = np.array(param) param_out = [0] * (len(param)) for i in np.arange(0, len(param)): param_out[i] = np.empty((len(lat), len(lon))) if len(param) != len(np.unique(param)): ValueError("Each parameter can only appear once in parameter list") print(date_list[t]) start = dt.datetime.now() hur_unit = units.percent * hur[t, :, :, :] ta_unit = units.degC * ta[t, :, :, :] dp_unit = units.degC * dp[t, :, :, :] p_unit = units.hectopascals * p_3d[t, :, :, :] q_unit = mpcalc.mixing_ratio_from_relative_humidity(hur_unit,\ ta_unit,p_unit) theta_unit = mpcalc.potential_temperature(p_unit, ta_unit) q = np.array(q_unit) ml_inds = ((p_3d[t] <= ps[t]) & (p_3d[t] >= (ps[t] - 100))) ml_ta_avg = np.ma.masked_where(~ml_inds, ta[t]).mean(axis=0).data ml_q_avg = np.ma.masked_where(~ml_inds, q).mean(axis=0).data ml_hgt_avg = np.ma.masked_where(~ml_inds, hgt[t]).mean(axis=0).data ml_p3d_avg = np.ma.masked_where(~ml_inds, p_3d[t]).mean(axis=0).data ml_ta_arr = np.insert(ta[t], 0, ml_ta_avg, axis=0) ml_q_arr = np.insert(q, 0, ml_q_avg, axis=0) ml_hgt_arr = np.insert(hgt[t], 0, ml_hgt_avg, axis=0) ml_p3d_arr = np.insert(p_3d[t], 0, ml_p3d_avg, axis=0) a,temp1,temp2 = np.meshgrid(np.arange(ml_p3d_arr.shape[0]) ,\ np.arange(ml_p3d_arr.shape[1]), np.arange(ml_p3d_arr.shape[2])) sort_inds = np.flipud( np.lexsort([np.swapaxes(a, 1, 0), ml_p3d_arr], axis=0)) ml_ta_arr = np.take_along_axis(ml_ta_arr, sort_inds, axis=0) ml_p3d_arr = np.take_along_axis(ml_p3d_arr, sort_inds, axis=0) ml_hgt_arr = np.take_along_axis(ml_hgt_arr, sort_inds, axis=0) ml_q_arr = np.take_along_axis(ml_q_arr, sort_inds, axis=0) cape3d_mlavg = wrf.cape_3d(ml_p3d_arr,ml_ta_arr + 273.15,\ ml_q_arr,ml_hgt_arr,terrain,ps[t,:,:],False,meta=False,missing=0) ml_cape = np.ma.masked_where(~((ml_ta_arr==ml_ta_avg) & (ml_p3d_arr==ml_p3d_avg)),\ cape3d_mlavg.data[0]).max(axis=0).filled(0) ml_cin = np.ma.masked_where(~((ml_ta_arr==ml_ta_avg) & (ml_p3d_arr==ml_p3d_avg)),\ cape3d_mlavg.data[1]).max(axis=0).filled(0) cape3d = wrf.cape_3d(p_3d[t,:,:,:],ta[t,:,:,:]+273.15,q,hgt[t,:,:,:],terrain,ps[t,:,:],\ True,meta=False,missing=0) cape = cape3d.data[0] cin = cape3d.data[1] cape[p_3d[t] > ps[t] - 25] = np.nan cin[p_3d[t] > ps[t] - 25] = np.nan mu_cape_inds = np.nanargmax(cape, axis=0) mu_cape = mu_cape_inds.choose(cape) mu_cin = mu_cape_inds.choose(cin) cape_2d = wrf.cape_2d(p_3d[t,:,:,:],ta[t,:,:,:]+273.15,q\ ,hgt[t,:,:,:],terrain,ps[t,:,:],True,meta=False,missing=0) lcl = cape_2d[2].data lfc = cape_2d[3].data del hur_unit, dp_unit, theta_unit, ml_inds, ml_ta_avg, ml_q_avg, \ ml_hgt_avg, ml_p3d_avg, ml_ta_arr, ml_q_arr, ml_hgt_arr, ml_p3d_arr, a, temp1, temp2,\ sort_inds, cape3d_mlavg, cape3d, cape, cin, cape_2d if "relhum850-500" in param: param_ind = np.where(param == "relhum850-500")[0][0] param_out[param_ind] = get_mean_var_p(hur[t], p, 850, 500) if "relhum1000-700" in param: param_ind = np.where(param == "relhum1000-700")[0][0] param_out[param_ind] = get_mean_var_p(hur[t], p, 1000, 700) if "mu_cape" in param: param_ind = np.where(param == "mu_cape")[0][0] param_out[param_ind] = mu_cape if "ml_cape" in param: param_ind = np.where(param == "ml_cape")[0][0] param_out[param_ind] = ml_cape if "s06" in param: param_ind = np.where(param == "s06")[0][0] s06 = get_shear_hgt(ua[t],va[t],hgt[t],0,6000,\ uas[t],vas[t]) param_out[param_ind] = s06 if "s03" in param: param_ind = np.where(param == "s03")[0][0] s03 = get_shear_hgt(ua[t],va[t],hgt[t],0,3000,\ uas[t],vas[t]) param_out[param_ind] = s03 if "s01" in param: param_ind = np.where(param == "s01")[0][0] s01 = get_shear_hgt(ua[t],va[t],hgt[t],0,1000,\ uas[t],vas[t]) param_out[param_ind] = s01 if "s0500" in param: param_ind = np.where(param == "s0500")[0][0] param_out[param_ind] = get_shear_hgt(ua[t],va[t],hgt[t],0,500,\ uas[t],vas[t]) if "lr1000" in param: param_ind = np.where(param == "lr1000")[0][0] lr1000 = get_lr_hgt(ta[t], hgt[t], 0, 1000) param_out[param_ind] = lr1000 if "mu_cin" in param: param_ind = np.where(param == "mu_cin")[0][0] param_out[param_ind] = mu_cin if "lcl" in param: param_ind = np.where(param == "lcl")[0][0] temp_lcl = np.copy(lcl) temp_lcl[temp_lcl <= 0] = np.nan param_out[param_ind] = temp_lcl if "ml_cin" in param: param_ind = np.where(param == "ml_cin")[0][0] param_out[param_ind] = ml_cin if "srh01" in param: param_ind = np.where(param == "srh01")[0][0] srh01 = get_srh(ua[t], va[t], hgt[t], 1000, True, 850, 700, p) param_out[param_ind] = srh01 if "srh03" in param: srh03 = get_srh(ua[t], va[t], hgt[t], 3000, True, 850, 700, p) param_ind = np.where(param == "srh03")[0][0] param_out[param_ind] = srh03 if "srh06" in param: param_ind = np.where(param == "srh06")[0][0] srh06 = get_srh(ua[t], va[t], hgt[t], 6000, True, 850, 700, p) param_out[param_ind] = srh06 if "ship" in param: if "s06" not in param: raise NameError("To calculate ship, s06 must be included") param_ind = np.where(param == "ship")[0][0] muq = mu_cape_inds.choose(q) ship = get_ship(mu_cape, np.copy(muq), ta[t], ua[t], va[t], hgt[t], p, np.copy(s06)) param_out[param_ind] = ship if "mmp" in param: param_ind = np.where(param == "mmp")[0][0] param_out[param_ind] = get_mmp(ua[t],va[t],uas[t],vas[t],\ mu_cape,ta[t],hgt[t]) if "scp" in param: if "srh03" not in param: raise NameError("To calculate ship, srh03 must be included") param_ind = np.where(param == "scp")[0][0] scell_pot = get_supercell_pot(mu_cape,ua[t],va[t],hgt[t],ta_unit,p_unit,\ q_unit,srh03) param_out[param_ind] = scell_pot if "stp" in param: if "srh01" not in param: raise NameError("To calculate stp, srh01 must be included") param_ind = np.where(param == "stp")[0][0] stp = get_tornado_pot(ml_cape,np.copy(lcl),np.copy(ml_cin),ua[t],va[t],p_3d[t],hgt[t],p,\ np.copy(srh01)) param_out[param_ind] = stp if "vo10" in param: param_ind = np.where(param == "vo10")[0][0] x, y = np.meshgrid(lon, lat) dx, dy = mpcalc.lat_lon_grid_deltas(x, y) vo10 = get_vo(uas[t], vas[t], dx, dy) param_out[param_ind] = vo10 if "conv10" in param: param_ind = np.where(param == "conv10")[0][0] x, y = np.meshgrid(lon, lat) dx, dy = mpcalc.lat_lon_grid_deltas(x, y) param_out[param_ind] = get_conv(uas[t], vas[t], dx, dy) if "conv1000-850" in param: levs = np.where((p <= 1001) & (p >= 849))[0] param_ind = np.where(param == "conv1000-850")[0][0] x, y = np.meshgrid(lon, lat) dx, dy = mpcalc.lat_lon_grid_deltas(x, y) param_out[param_ind] = \ np.mean(np.stack([get_conv(ua[t,i],va[t,i],dx,dy) for i in levs]),axis=0) if "conv800-600" in param: levs = np.where((p <= 801) & (p >= 599))[0] param_ind = np.where(param == "conv800-600")[0][0] x, y = np.meshgrid(lon, lat) dx, dy = mpcalc.lat_lon_grid_deltas(x, y) param_out[param_ind] = \ np.mean(np.stack([get_conv(ua[t,i],va[t,i],dx,dy) for i in levs]),axis=0) if "non_sc_stp" in param: if "vo10" not in param: raise NameError("To calculate non_sc_stp, vo must be included") if "lr1000" not in param: raise NameError("To calculate non_sc_stp, lr1000 must be included") param_ind = np.where(param == "non_sc_stp")[0][0] non_sc_stp = get_non_sc_tornado_pot(ml_cape,ml_cin,np.copy(lcl),ua[t],va[t],\ uas[t],vas[t],p_3d[t],ta[t],hgt[t],p,vo10,lr1000) param_out[param_ind] = non_sc_stp if "cape*s06" in param: param_ind = np.where(param == "cape*s06")[0][0] cs6 = ml_cape * np.power(s06, 1.67) param_out[param_ind] = cs6 if "td850" in param: param_ind = np.where(param == "td850")[0][0] td850 = get_td_diff(ta[t], dp[t], p_3d[t], 850) param_out[param_ind] = td850 if "td800" in param: param_ind = np.where(param == "td800")[0][0] param_out[param_ind] = get_td_diff(ta[t], dp[t], p_3d[t], 800) if "td950" in param: param_ind = np.where(param == "td950")[0][0] param_out[param_ind] = get_td_diff(ta[t], dp[t], p_3d[t], 950) if "wg" in param: try: param_ind = np.where(param == "wg")[0][0] param_out[param_ind] = wg[t] except ValueError: print("wg field expected, but not parsed") if "dcape" in param: param_ind = np.where(param == "dcape")[0][0] dcape = np.nanmax(get_dcape(p_3d[t], ta[t], hgt[t], p, ps[t]), axis=0) param_out[param_ind] = dcape if "mlm" in param: param_ind = np.where(param == "mlm")[0][0] mlm_u, mlm_v = get_mean_wind(ua[t], va[t], hgt[t], 800, 600, False, None, "plevels", p) mlm = np.sqrt(np.square(mlm_u) + np.square(mlm_v)) param_out[param_ind] = mlm if "dlm" in param: param_ind = np.where(param == "dlm")[0][0] dlm_u, dlm_v = get_mean_wind(ua[t], va[t], hgt[t], 1000, 500, False, None, "plevels", p) dlm = np.sqrt(np.square(dlm_u) + np.square(dlm_v)) param_out[param_ind] = dlm if "dlm+dcape" in param: param_ind = np.where(param == "dlm+dcape")[0][0] dlm_dcape = dlm + np.sqrt(2 * dcape) param_out[param_ind] = dlm_dcape if "mlm+dcape" in param: param_ind = np.where(param == "mlm+dcape")[0][0] mlm_dcape = mlm + np.sqrt(2 * dcape) param_out[param_ind] = mlm_dcape if "dcape*cs6" in param: param_ind = np.where(param == "dcape*cs6")[0][0] param_out[param_ind] = (dcape / 980.) * (cs6 / 20000) if "dlm*dcape*cs6" in param: param_ind = np.where(param == "dlm*dcape*cs6")[0][0] param_out[param_ind] = (dlm_dcape / 30.) * (cs6 / 20000) if "mlm*dcape*cs6" in param: param_ind = np.where(param == "mlm*dcape*cs6")[0][0] param_out[param_ind] = (mlm_dcape / 30.) * (cs6 / 20000) if "dcp" in param: param_ind = np.where(param == "dcp")[0][0] param_out[param_ind] = (dcape / 980) * (mu_cape / 2000) * (s06 / 10) * (dlm / 8) if "mf" in param: param_ind = np.where(param == "mf")[0][0] mf = ((ml_cape > 120) & (dcape > 350) & (mlm < 26)) mf = mf * 1.0 param_out[param_ind] = mf if "sf" in param: param_ind = np.where(param == "sf")[0][0] sf = ((s06 >= 30) & (dcape < 500) & (mlm >= 26)) sf = sf * 1.0 param_out[param_ind] = sf if "cond" in param: param_ind = np.where(param == "cond")[0][0] cond = (sf == 1.0) | (mf == 1.0) cond = cond * 1.0 param_out[param_ind] = cond return param_out
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)