def test_log_interpolate_no_extrap(): """Test interpolating with log x-scale setting out of bounds value error.""" x_log = np.array([1e3, 1e4, 1e5, 1e6]) y_log = np.log(x_log) * 2 + 3 x_interp = np.array([1e7]) with pytest.raises(ValueError): log_interpolate_1d(x_interp, x_log, y_log, fill_value=None)
def test_log_interpolate_3d(): """Test interpolating with log x-scale 3 dimensions along second axis.""" x_log = np.ones((3, 4, 3)) * np.array([1e3, 1e4, 1e5, 1e6]).reshape(-1, 1) y_log = np.log(x_log) * 2 + 3 x_interp = np.array([5e3, 5e4, 5e5]) y_interp_truth = np.array([20.0343863828, 24.6395565688, 29.2447267548]) y_interp = log_interpolate_1d(x_interp, x_log, y_log, axis=1) assert_array_almost_equal(y_interp[0, :, 0], y_interp_truth, 7)
def test_log_interpolate_2d(): """Test interpolating with log x-scale in 2 dimensions.""" x_log = np.array([[1e3, 1e4, 1e5, 1e6], [1e3, 1e4, 1e5, 1e6]]) y_log = np.log(x_log) * 2 + 3 x_interp = np.array([5e3, 5e4, 5e5]) y_interp_truth = np.array([20.0343863828, 24.6395565688, 29.2447267548]) y_interp = log_interpolate_1d(x_interp, x_log, y_log, axis=1) assert_array_almost_equal(y_interp[1], y_interp_truth, 7)
def test_log_interpolate_1d_units(): """Test interpolating with log x-scale with units.""" x_log = np.array([1e3, 1e4, 1e5, 1e6]) * units.hPa y_log = (np.log(x_log.m) * 2 + 3) * units.degC x_interp = np.array([5e5, 5e6, 5e7]) * units.Pa y_interp_truth = np.array([20.0343863828, 24.6395565688, 29.2447267548]) * units.degC y_interp = log_interpolate_1d(x_interp, x_log, y_log) assert_array_almost_equal(y_interp, y_interp_truth, 7)
def test_log_interpolate_4d(): """Test interpolating with log x-scale 4 dimensions.""" x_log = np.ones((2, 2, 3, 4)) * np.array([1e3, 1e4, 1e5, 1e6]) y_log = np.log(x_log) * 2 + 3 x_interp = np.array([5e3, 5e4, 5e5]) y_interp_truth = np.array([20.0343863828, 24.6395565688, 29.2447267548]) y_interp = log_interpolate_1d(x_interp, x_log, y_log, axis=3) assert_array_almost_equal(y_interp[0, 0, 0, :], y_interp_truth, 7)
def test_log_interpolate_set_nan_below(): """Test interpolating with log x-scale setting out of bounds below data to nan.""" x_log = np.array([1e3, 1e4, 1e5, 1e6]) y_log = np.log(x_log) * 2 + 3 x_interp = 1e2 y_interp_truth = np.nan with pytest.warns(Warning): y_interp = log_interpolate_1d(x_interp, x_log, y_log) assert_array_almost_equal(y_interp, y_interp_truth, 7)
def calcgw_wrf(f, lat, lon, levels, tidx=0): # MFDataset removes the time dimension from XLAT, XLONG xlat = f.variables['XLAT'] xlslice = (0, ) * (len(xlat.shape) - 2) + (slice(None), slice(None)) xlat = xlat[xlslice] xlong = f.variables['XLONG'][xlslice] (iy, ix), area, (iby, ibx) = get_wrf_dims(f, lat, lon, xlat, xlong) areat = (tidx, ) + area areatz = (tidx, slice(None)) + area #print('wrf coords', lat, lon, xlat[iy,ix], xlong[iy,ix]) #print(xlat[area][iby,ibx], xlong[area][iby,ibx], areat) # load area hgt = (f.variables['PH'][areatz] + f.variables['PHB'][areatz]) / 9.81 hgtu = (hgt[:-1] + hgt[1:]) * .5 pres = f.variables['P'][areatz] + f.variables['PB'][areatz] terrain = f.variables['HGT'][areat] # find suitable pressure levels yminpres, xminpres = np.unravel_index(pres[0].argmin(), pres[0].shape) pres1 = pres[0, yminpres, xminpres] - 1. aglpt = hgtu[:, iby, ibx] - terrain[iby, ibx] pres0 = pres[np.searchsorted(aglpt, levels[-1]), iby, ibx] # plevels = np.arange(pres1, min(pres0, pres1)-1, -1000.) plevels = np.arange(pres1, min(pres0, pres1) - 1000, -1000.) # !!!! # interpolate wrf into pressure levels phgt = log_interpolate_1d(plevels, pres, hgtu, axis=0) # Set up some constants based on our projection, including the Coriolis parameter and # grid spacing, converting lon/lat spacing to Cartesian coriol = mpcalc.coriolis_parameter(np.deg2rad(xlat[area])).to('1/s') # lat_lon_grid_deltas doesn't work under py2, but for WRF grid it is still # not very accurate, better use direct values. #dx, dy = mpcalc.lat_lon_grid_deltas(xlong[area], xlat[area]) dx = f.DX * units.m dy = f.DY * units.m # Smooth height data. Sigma=1.5 for gfs 0.5deg res_km = f.DX / 1000. ug = np.zeros(plevels.shape, 'f8') vg = np.zeros(plevels.shape, 'f8') for i in range(len(plevels)): sh = ndimage.gaussian_filter(phgt[i, :, :], sigma=1.5 * 50 / res_km, order=0) # ugl, vgl = mpcalc.geostrophic_wind(sh * units.m, coriol, dx, dy) # bug1 ugl, vgl = mpcalc.geostrophic_wind(sh * units.m, dx, dy, np.deg2rad(xlat[area])) ug[i] = ugl[iby, ibx].magnitude vg[i] = vgl[iby, ibx].magnitude return phgt[:, iby, ibx], ug, vg
def test_log_interpolate_2args(): """Test interpolating with log x-scale with 2 arguments.""" x_log = np.array([1e3, 1e4, 1e5, 1e6]) y_log = np.log(x_log) * 2 + 3 y_log2 = np.log(x_log) * 2 + 3 x_interp = np.array([5e3, 5e4, 5e5]) y_interp_truth = np.array([20.0343863828, 24.6395565688, 29.2447267548]) y_interp = log_interpolate_1d(x_interp, x_log, y_log, y_log2) assert_array_almost_equal(y_interp[1], y_interp_truth, 7) assert_array_almost_equal(y_interp[0], y_interp_truth, 7)
def interpolate(self, plevs): for name, (d_arr, conf) in list(self.var_conf.items()): d_arr_interp = log_interpolate_1d(plevs, self.__press_inter, d_arr) # Back to DataArray: d_arr_interp = xr.DataArray(data=d_arr_interp, dims=['plevs', 'lat', 'lon'], coords={'plevs': ('plevs', plevs), 'lat': ('lat', d_arr['lat']), 'lon': ('lon', d_arr['lon'])}, attrs=d_arr.attrs) # Change dict entry for interpolated values self.var_conf[name] = (d_arr_interp, conf)
def interpolate_csec(self, plevs, start, end, steps=100): start = (start['lat'], start['lon']) end = (end['lat'], end['lon']) xp_interp = cross_section(self.__press_inter, start, end, steps=steps) for name, (d_arr, conf) in list(self.var_conf.items()): d_arr = cross_section(d_arr, start, end, steps=steps) d_arr_interp = log_interpolate_1d(plevs, xp_interp, d_arr) # Back to DataArray: d_arr_interp = xr.DataArray(data=d_arr_interp, dims=['plevs', 'index'], coords={'lat': ('index', d_arr['lat']), 'lon': ('index', d_arr['lon']), 'plevs': ('plevs', plevs), 'index': ('index', d_arr['index'])}, attrs=d_arr.attrs) # Anpassen, nicht identisch # Change dict entry for interpolated values self.var_conf[name] = (d_arr_interp, conf)
def get_isobaric_variables(data, var_list, plevs, outfile, dtype, compression, complevel): """Gets isobaric variables from a list""" # use wrf-python to get data for each of the variables var_def = get_variables() # get pressure array and attach units p = getvar(data, 'p', ALL_TIMES) p_np = np.array(p.data) * units(p.units) for i in range(len(var_list)): name = var_list[i] var_data = getvar(data, var_def[name][2], ALL_TIMES) iso_data = log_interpolate_1d(plevs, p_np, var_data.data, axis=1) # write each of the variables to the output file pres_data = outfile.createVariable( var_list[i], dtype, ('time', 'pressure_levels', 'lat', 'lon'), zlib=compression, complevel=complevel) pres_data.units = var_data.units if var_list[i] == 'height': pres_data.decription = 'height [MSL] of isobaric surfaces' elif var_list[i] == 'uwnd': pres_data.description = 'u-wind component on isobaric surfaces' elif var_list[i] == 'vwnd': pres_data.description = 'v-wind component on isobaric surfaces' elif var_list[i] == 'wwnd': pres_data.description = 'w-wind component on isobaric surfaces' elif var_list[i] == 'temp': pres_data.description = 'temperature on isobaric surfaces' elif var_list[i] == 'dewpt': pres_data.description = 'dewpoint temperature on isobaric surfaces' elif var_list[i] == 'avor': pres_data.description = 'absolute vorticity on isobaric surfaces' else: pres_data.description = var_data.description pres_data[:] = iso_data
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
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
def pressure_interpolation(pressures, altitudes, output_altitudes, convergence_error=0.05): """ Interpolates pressure on altitude grid The pressure is interpolated logarithmically. Input ----- pressure : array pressures in hPa altitudes : array altitudes in m belonging to pressure values output_altitudes : array altitudes (m) on which the pressure should be interpolated to convergence_error : float Error that needs to be reached to stop convergence iteration Output ------- pressure_interpolated : array array of interpolated pressure values on altitudes """ pressure_interpolated = np.empty(len(output_altitudes)) pressure_interpolated[:] = np.nan # Exclude heights outside of the intersection of measurements heights # and output_altitudes altitudes_above_measurements = output_altitudes > max(altitudes) range_of_alt_max = (np.min( np.where(altitudes_above_measurements | (output_altitudes == output_altitudes[-1]))) - 1) altitudes_below_measurements = output_altitudes < min(altitudes) range_of_alt_min = (np.max( np.where(altitudes_below_measurements | (output_altitudes == output_altitudes[0]))) + 1) for i in range(range_of_alt_min, range_of_alt_max): target_h = output_altitudes[i] lower_idx = np.nanmax(np.where(altitudes < target_h)) upper_idx = np.nanmin(np.where(altitudes > target_h)) p1 = pressures[lower_idx] # pressure at lower altitude p2 = pressures[upper_idx] # pressure at higher altitude a1 = altitudes[lower_idx] # lower altitude a2 = altitudes[upper_idx] # higher altitude xp = np.array([p1, p2]) arr = np.array([a1, a2]) err = 10 if a2 - a1 < 100: while err > convergence_error: x = np.mean([p1, p2]) ah = mpinterp.log_interpolate_1d(x, xp, arr, fill_value=np.nan) if ah > target_h: p2 = x else: p1 = x err = abs(ah - target_h) pressure_interpolated[i] = x return pressure_interpolated
#################################### # Array of desired pressure levels plevs = [700.] * units.hPa ##################################### # **Interpolate The Data** # # Now that the data is ready, we can interpolate to the new isobaric levels. The data is # interpolated from the irregular pressure values for each sigma level to the new input # mandatory isobaric levels. `mpcalc.log_interp` will interpolate over a specified dimension # with the `axis` argument. In this case, `axis=1` will correspond to interpolation on the # vertical axis. The interpolated data is output in a list, so we will pull out each # variable for plotting. height, temp = log_interpolate_1d(plevs, pres, hgt, temperature, axis=1) #################################### # **Plotting the Data for 700 hPa.** # Set up our projection crs = ccrs.LambertConformal(central_longitude=-100.0, central_latitude=45.0) # Set the forecast hour FH = 1 # Create the figure and grid for subplots fig = plt.figure(figsize=(17, 12)) add_metpy_logo(fig, 470, 320, size='large') # Plot 700 hPa
def significant_tornado(self): u, v = self.bulk_shear() return mpcalc.significant_tornado( self.cape_cin(0)[0], mpint.log_interpolate_1d(self.lcl(0)[0], self.p, self.z), self.storm_relative_helicity()[2], (u**2 + v**2)**0.5)