def test_first_derivative_2d(deriv_2d_data): """Test first_derivative with a full 2D array.""" df_dx = first_derivative(deriv_2d_data.f, x=deriv_2d_data.x, axis=1) df_dx_analytic = np.tile(2 * deriv_2d_data.a * (deriv_2d_data.x - deriv_2d_data.x0), (deriv_2d_data.f.shape[0], 1)) assert_array_almost_equal(df_dx, df_dx_analytic, 5) df_dy = first_derivative(deriv_2d_data.f, x=deriv_2d_data.y, axis=0) # Repeat each row, then flip to get variation along rows df_dy_analytic = np.tile(2 * deriv_2d_data.b * (deriv_2d_data.y - deriv_2d_data.y0), (deriv_2d_data.f.shape[1], 1)).T assert_array_almost_equal(df_dy, df_dy_analytic, 5)
def test_first_derivative(deriv_1d_data): """Test first_derivative with a simple 1D array.""" dv_dx = first_derivative(deriv_1d_data.values, x=deriv_1d_data.x) # Worked by hand and taken from Chapra and Canale 23.2 truth = np.array([-1.333333, -1.06666667, -0.5333333]) * units('delta_degC / cm') assert_array_almost_equal(dv_dx, truth, 5)
def test_first_derivative_xarray_pint_conversion(test_da_lonlat): """Test first derivative with implicit xarray to pint quantity conversion.""" dx, _ = grid_deltas_from_dataarray(test_da_lonlat) deriv = first_derivative(test_da_lonlat, delta=dx, axis=-1) truth = np.array([[[-3.30782978e-06] * 4, [-3.42816074e-06] * 4, [-3.57012948e-06] * 4, [-3.73759364e-06] * 4]] * 3) * units('kelvin / meter') assert_array_almost_equal(deriv, truth, 12)
def test_first_derivative_xarray_time_and_default_axis(test_da_xy): """Test first derivative with an xarray.DataArray over time as default first dimension.""" deriv = first_derivative(test_da_xy) truth = xr.full_like(test_da_xy, -0.000777000777) truth.attrs['units'] = 'kelvin / second' xr.testing.assert_allclose(deriv, truth) assert deriv.metpy.units == truth.metpy.units
def kinematics(u, v, thetae, dx, dy, lats, smooth=False, sigma=1): ''' Use metpy functions to calculate various kinematics, given 2d numpy arrays as inputs. X and y grid spacing, as well as a 2d array of latitudes is also required. Option to smooth the thetae field before calculating front diagnostics (recommended), with addition "sigma" parameter controlling the smoothness (see scipy docs) ''' if smooth: thetae = gaussian_filter(thetae, sigma) #Kinematics ddy_thetae = mpcalc.first_derivative(thetae, delta=dy, axis=0) ddx_thetae = mpcalc.first_derivative(thetae, delta=dx, axis=1) mag_thetae = np.sqrt(ddx_thetae**2 + ddy_thetae**2) div = mpcalc.divergence(u, v, dx, dy) strch_def = mpcalc.stretching_deformation(u, v, dx, dy) shear_def = mpcalc.shearing_deformation(u, v, dx, dy) tot_def = mpcalc.total_deformation(u, v, dx, dy) psi = 0.5 * np.arctan2(shear_def, strch_def) beta = np.arcsin( (-ddx_thetae * np.cos(psi) - ddy_thetae * np.sin(psi)) / mag_thetae) vo = mpcalc.vorticity(u, v, dx, dy) conv = -div * 1e5 F = np.array(0.5 * mag_thetae * (tot_def * np.cos(2 * beta) - div) * 1.08e4 * 1e5) Fn = np.array(0.5 * mag_thetae * (div - tot_def * np.cos(2 * beta)) * 1.08e4 * 1e5) Fs = np.array(0.5 * mag_thetae * (vo + tot_def * np.sin(2 * beta)) * 1.08e4 * 1e5) icon = np.array(0.5 * (tot_def - div) * 1e5) vgt = np.array(np.sqrt(div**2 + vo**2 + tot_def**2) * 1e5) #TFP ddx_thetae_scaled = ddx_thetae / mag_thetae ddy_thetae_scaled = ddy_thetae / mag_thetae ddy_mag_thetae = -1 * mpcalc.first_derivative(mag_thetae, delta=dy, axis=0) ddx_mag_thetae = -1 * mpcalc.first_derivative(mag_thetae, delta=dx, axis=1) tfp = ddx_mag_thetae * ddx_thetae_scaled + ddy_mag_thetae * ddy_thetae_scaled ddy_tfp = mpcalc.first_derivative(tfp, delta=dy, axis=0) ddx_tfp = mpcalc.first_derivative(tfp, delta=dx, axis=1) mag_tfp = np.sqrt(ddx_tfp**2 + ddy_tfp**2) v_f = (u * units.units("m/s")) * (ddx_tfp / mag_tfp) + ( v * units.units("m/s")) * (ddy_tfp / mag_tfp) #Extra condition ddy_ddy_mag_te = mpcalc.first_derivative(-1 * ddy_mag_thetae, delta=dy, axis=0) ddx_ddx_mag_te = mpcalc.first_derivative(-1 * ddx_mag_thetae, delta=dx, axis=1) cond = ddy_ddy_mag_te + ddx_ddx_mag_te return [F, Fn, Fs, icon, vgt, conv, vo*1e5, \ np.array(tfp.to("km^-2")*(100*100)), np.array(mag_thetae.to("km^-1"))*100, np.array(v_f), thetae, cond]
def test_first_derivative_masked(): """Test that first_derivative properly propagates masks.""" data = np.ma.arange(7) data[3] = np.ma.masked df_dx = first_derivative(data, delta=1) truth = np.ma.array([1., 1., 1., 1., 1., 1., 1.], mask=[False, False, True, True, True, False, False]) assert_array_almost_equal(df_dx, truth) assert_array_equal(df_dx.mask, truth.mask)
def test_first_derivative_xarray_lonlat(test_da_lonlat): """Test first derivative with an xarray.DataArray on a lonlat grid in each axis usage.""" deriv = first_derivative(test_da_lonlat, axis='lon') # dimension coordinate name deriv_alt1 = first_derivative(test_da_lonlat, axis='x') # axis type deriv_alt2 = first_derivative(test_da_lonlat, axis=-1) # axis number # Build the xarray of the desired values partial = xr.DataArray(np.array( [-3.30782978e-06, -3.42816074e-06, -3.57012948e-06, -3.73759364e-06]), coords=(('lat', test_da_lonlat['lat']), )) _, truth = xr.broadcast(test_da_lonlat, partial) truth.coords['crs'] = test_da_lonlat['crs'] truth.attrs['units'] = 'kelvin / meter' # Assert result matches expectation xr.testing.assert_allclose(deriv, truth) assert deriv.metpy.units == truth.metpy.units # Assert alternative specifications give same result xr.testing.assert_identical(deriv_alt1, deriv) xr.testing.assert_identical(deriv_alt2, deriv)
def test_first_derivative_xarray_lonlat(test_da_lonlat): """Test first derivative with an xarray.DataArray on a lonlat grid in each axis usage.""" deriv = first_derivative(test_da_lonlat, axis='lon') # dimension coordinate name deriv_alt1 = first_derivative(test_da_lonlat, axis='x') # axis type deriv_alt2 = first_derivative(test_da_lonlat, axis=-1) # axis number # Build the xarray of the desired values partial = xr.DataArray( np.array([-3.30782978e-06, -3.42816074e-06, -3.57012948e-06, -3.73759364e-06]), coords=(('lat', test_da_lonlat['lat']),) ) _, truth = xr.broadcast(test_da_lonlat, partial) truth.coords['crs'] = test_da_lonlat['crs'] truth.attrs['units'] = 'kelvin / meter' # Assert result matches expectation xr.testing.assert_allclose(deriv, truth) assert deriv.metpy.units == truth.metpy.units # Assert alternative specifications give same result xr.testing.assert_identical(deriv_alt1, deriv) xr.testing.assert_identical(deriv_alt2, deriv)
def test_first_derivative_xarray_time_subsecond_precision(): """Test time derivative with an xarray.DataArray where subsecond precision is needed.""" test_da = xr.DataArray([299.5, 300, 300.5], dims='time', coords={'time': np.array(['2019-01-01T00:00:00.0', '2019-01-01T00:00:00.1', '2019-01-01T00:00:00.2'], dtype='datetime64[ms]')}, attrs={'units': 'kelvin'}) deriv = first_derivative(test_da) truth = xr.full_like(test_da, 5.) truth.attrs['units'] = 'kelvin / second' xr.testing.assert_allclose(deriv, truth) assert deriv.metpy.units == truth.metpy.units
lon, lat = np.meshgrid(lons, lats) # Calculate Geostrophic Wind from Analytic Heights f = mpcalc.coriolis_parameter(lat * units('degrees')) dx, dy = mpcalc.lat_lon_grid_deltas(lons, lats) ugeo, vgeo = mpcalc.geostrophic_wind(Z * units.meter, f, dx, dy, dim_order='yx') # Get the wind direction for each point wdir = mpcalc.wind_direction(ugeo, vgeo) # Compute the Gradient Wind via an approximation dydx = mpcalc.first_derivative(Z, delta=dx, axis=1) d2ydx2 = mpcalc.first_derivative(dydx, delta=dx, axis=1) R = ((1 + dydx.m**2)**(3. / 2.)) / d2ydx2.m geo_mag = mpcalc.wind_speed(ugeo, vgeo) grad_mag = geo_mag.m - (geo_mag.m**2) / (f.magnitude * R) 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)
def test_first_derivative_scalar_delta(): """Test first_derivative with a scalar passed for a delta.""" df_dx = first_derivative(np.arange(3), delta=1) assert_array_almost_equal(df_dx, np.array([1., 1., 1.]), 6)
def test_first_derivative_too_small(deriv_1d_data): """Test first_derivative with too small an array.""" with pytest.raises(ValueError): first_derivative(deriv_1d_data.values[None, :].T, x=deriv_1d_data.x, axis=1)