def test_heat_index_units(): """Test units coming out of heat index.""" temp = units.Quantity([35., 20.], units.degC) rh = 70 * units.percent hi = heat_index(temp, rh) assert_almost_equal(hi.to('degC'), units.Quantity([50.3405, np.nan], units.degC), 4)
def test_height_to_geopotential(): """Test conversion from height to geopotential.""" height = units.Quantity([0, 1000, 2000, 3000], units.m) geopot = height_to_geopotential(height) assert_array_almost_equal( geopot, units.Quantity([0., 9817, 19632, 29443], units('m**2 / second**2')), 0)
def test_heat_index_ratio(): """Test giving humidity as number [0, 1] to heat index.""" temp = units.Quantity([35., 20.], units.degC) rh = 0.7 hi = heat_index(temp, rh) assert_almost_equal(hi.to('degC'), units.Quantity([50.3405, np.nan], units.degC), 4)
def test_precipitable_water_descriptive_bound_error(): """Test that error is raised when bound is outside profile after nan have been removed.""" pressure = np.array([ 1001, 1000, 997, 977.9, 977, 957, 937.8, 925, 906, 899.3, 887, 862.5, 854, 850, 800, 793.9, 785, 777, 771, 762, 731.8, 726, 703, 700, 655, 630, 621.2, 602, 570.7, 548, 546.8, 539, 513, 511, 485, 481, 468, 448, 439, 424, 420, 412 ]) * units.hPa dewpoint = np.array([ np.nan, np.nan, -26.8, np.nan, -27.3, -28.2, np.nan, -27.2, -26.6, np.nan, -27.4, np.nan, -23.5, -23.5, -25.1, np.nan, -22.9, -17.8, -16.6, np.nan, np.nan, -16.4, np.nan, -18.5, -21., -23.7, np.nan, -28.3, np.nan, -32.6, np.nan, -33.8, -35., -35.1, -38.1, -40., -43.3, -44.6, -46.4, np.nan, np.nan, np.nan ]) * units.degC # Top bound is above highest pressure in profile with pytest.raises(ValueError, match='The pressure and dewpoint profile ranges from'): precipitable_water(pressure, dewpoint, top=units.Quantity(415, 'hPa')) # Bottom bound is below lowest pressure in profile with pytest.raises(ValueError, match='The pressure and dewpoint profile ranges from'): precipitable_water(pressure, dewpoint, bottom=units.Quantity(999, 'hPa'))
def test_heat_index_undefined_flag(): """Test whether masking values can be disabled for heat index.""" temp = units.Quantity(np.ma.array([80, 88, 92, 79, 30, 81]), units.degF) rh = units.Quantity(np.ma.array([40, 39, 2, 70, 50, 39]), units.percent) hi = heat_index(temp, rh, mask_undefined=False) mask = np.array([False] * 6) assert_array_equal(hi.mask, mask)
def test_heat_index_vs_nws(): """Test heat_index against online calculated HI from NWS Website.""" # https://www.wpc.ncep.noaa.gov/html/heatindex.shtml, visited 2019-Jul-17 temp = units.Quantity(np.array([86, 111, 40, 96]), units.degF) rh = np.ma.array([45, 27, 99, 60]) * units.percent hi = heat_index(temp, rh) truth = units.Quantity(np.ma.array([87, 121, 40, 116]), units.degF) assert_array_almost_equal(hi, truth, 0)
def test_windchill_undefined_flag(): """Test whether masking values for windchill can be disabled.""" temp = units.Quantity(np.ma.array([49, 50, 49, 60, 80, 81]), units.degF) speed = units.Quantity(([4, 4, 3, 1, 10, 39]), units.mph) wc = windchill(temp, speed, mask_undefined=False) mask = np.array([False] * 6) assert_array_equal(wc.mask, mask)
def test_interpolate_masked_units(): """Test interpolating with masked arrays with units.""" x = units.Quantity(np.ma.array([1., 2., 3., 4.]), units.m) y = units.Quantity(np.ma.array([50., 60., 70., 80.]), units.degC) x_interp = np.array([250., 350.]) * units.cm y_interp_truth = np.array([65., 75.]) * units.degC y_interp = interpolate_1d(x_interp, x, y) assert_array_almost_equal(y_interp, y_interp_truth, 7)
def test_geopotential_to_height(): """Test conversion from geopotential to height.""" geopotential = units.Quantity( [0, 9817.70342881, 19632.32592389, 29443.86893527], units('m**2 / second**2')) height = geopotential_to_height(geopotential) assert_array_almost_equal(height, units.Quantity([0, 1000, 2000, 3000], units.m), 0)
def test_geopotential_to_height(): """Test conversion from geopotential to height.""" geopotential = units.Quantity( [0., 9805.11102602, 19607.14506998, 29406.10358006], units('m**2 / second**2')) height = geopotential_to_height(geopotential) assert_array_almost_equal(height, units.Quantity([0, 1000, 2000, 3000], units.m), 0)
def test_concatenate_masked(): """Test concatenate preserves masks.""" d1 = units.Quantity(np.ma.array([1, 2, 3], mask=[False, True, False]), 'degC') result = concatenate((d1, 32 * units.degF)) truth = np.ma.array([1, np.inf, 3, 0]) truth[1] = np.ma.masked assert_array_almost_equal(result, units.Quantity(truth, 'degC'), 6) assert_array_equal(result.mask, np.array([False, True, False, False]))
def _gradient(f, *args, **kwargs): """Wrap :func:`numpy.gradient` to handle units.""" if len(args) < f.ndim: args = list(args) args.extend([units.Quantity(1., 'dimensionless')] * (f.ndim - len(args))) grad = np.gradient(f, *(a.magnitude for a in args), **kwargs) if f.ndim == 1: return units.Quantity(grad, f.units / args[0].units) return [units.Quantity(g, f.units / dx.units) for dx, g in zip(args, grad)]
def test_direction_masked(): """Test calculating wind direction from masked wind components.""" mask = np.array([True, False, True, False]) u = np.array([4., 2., 0., 0.]) v = np.array([0., 2., 4., 0.]) u_masked = units.Quantity(np.ma.array(u, mask=mask), units('m/s')) v_masked = units.Quantity(np.ma.array(v, mask=mask), units('m/s')) direc = wind_direction(u_masked, v_masked) true_dir = np.array([270., 225., 180., 0.]) true_dir_masked = units.Quantity(np.ma.array(true_dir, mask=mask), units.deg) assert_array_almost_equal(true_dir_masked, direc, 4)
def test_dequantify(): """Test dequantify method for converting data away from Quantity.""" original = xr.DataArray(units.Quantity([280, 290, 300], 'K')) result = original.metpy.dequantify() assert isinstance(result.data, np.ndarray) assert result.attrs['units'] == 'kelvin' np.testing.assert_array_almost_equal(result.data, original.data.magnitude)
def test_hodograph_masked_array(): """Basic test of Hodograph API.""" fig = plt.figure(figsize=(9, 9)) ax = fig.add_subplot(1, 1, 1) hodo = Hodograph(ax, component_range=20) u = np.ma.array([1, 3, 5, 10]) v = np.ma.array([2, 4, 6, 11]) h = units.Quantity(np.array([0.1, 3.5, 5.5, 10.9]), 'km') intervals = units.Quantity(np.array([0.0, 3.0, 6.0, 9.0, 12.0, 15.0]), 'km') colors = ['red', 'green', 'yellow', 'blue', 'purple'] # Check that we're not triggering interpolation warnings with warnings.catch_warnings(record=True) as record: hodo.plot_colormapped(u, v, h, intervals=intervals, colors=colors) assert len(record) == 0 return fig
def temp_advection_setup(filepaths, time, predictor): r""" """ pred = predictor.copy() pred.change_property('Temp') temp = fetch(filepaths, time, **pred.search_metadata) pred.change_property('Uwind') u_wind = fetch(filepaths, time, **pred.search_metadata) pred.change_property('Vwind') v_wind = fetch(filepaths, time, **pred.search_metadata) # source : 'GFS13' property : 'Lat_grid' pred.change_property('Lat_grid') lat = fetch(filepaths, time, **pred.search_metadata) pred.change_property('Lon_grid') lon = fetch(filepaths, time, **pred.search_metadata) #pdb.set_trace() la, lo = geo_direct(lat, lon) q_t = units.Quantity(temp.data, temp.units) q_u = units.Quantity(u_wind.data, u_wind.units) q_v = units.Quantity(v_wind.data, v_wind.units).to(u_wind.units) q_x = q_u*lo[:,:,1] + q_v*la[:,:,1] q_y = q_u*lo[:,:,0] + q_v*la[:,:,0] x = temp.get_x() y = temp.get_y() q_dx = units.Quantity(x.data[1:]-x.data[:-1], x.units) q_dy = units.Quantity(y.data[1:]-y.data[:-1], y.units) q_ta = temperature_advection(q_t, [q_y,q_x], [q_dy, q_dx]) temp_adv = Camps_data('temperature_advection') temp_adv.time = temp.time temp_adv.location = temp.location temp_adv.dimensions = temp.dimensions temp_adv.processes = temp.processes temp_adv.add_coord(temp.get_coordinate()) temp_adv.data = np.array(q_ta) for k,v in temp.metadata.iteritems(): if not 'name' in k \ and not 'Property' in k: temp_adv.metadata[k] = v return temp_advect
def rel_hum(p, t, q): """Compute relative humidity in [%] from pressure, temperature, and specific humidity. Arguments: p -- pressure in [Pa] t -- temperature in [K] q -- specific humidity in [kg/kg] Returns: Relative humidity in [%]. Same dimension as input fields. """ p = units.Quantity(p, "Pa") t = units.Quantity(t, "K") rel_humidity = mpcalc.relative_humidity_from_specific_humidity(p, t, q) # Return specific humidity in [%]. return rel_humidity * 100
def test_dataset_quantify(test_ds_generic): """Test quantify method for converting data to Quantity on Datasets.""" result = test_ds_generic.metpy.quantify() assert isinstance(result['test'].data, units.Quantity) assert result['test'].data.units == units.dimensionless assert 'units' not in result['test'].attrs np.testing.assert_array_almost_equal( result['test'].data, units.Quantity(test_ds_generic['test'].data))
def test_inverse_distance_to_points(method, assume_units, test_data, test_points): r"""Test inverse distance interpolation to points function.""" xp, yp, z = test_data obs_points = np.vstack([xp, yp]).transpose() extra_kw, test_file = {'cressman': ({'r': 20, 'min_neighbors': 1}, 'cressman_r20_mn1.npz'), 'barnes': ({'r': 40, 'kappa': 100}, 'barnes_r40_k100.npz')}[method] with get_test_data(test_file) as fobj: truth = np.load(fobj)['img'].reshape(-1) if assume_units: z = units.Quantity(z, assume_units) truth = units.Quantity(truth, assume_units) img = inverse_distance_to_points(obs_points, z, test_points, kind=method, **extra_kw) assert_array_almost_equal(truth, img)
def test_quantify(test_ds_generic): """Test quantify method for converting data to Quantity.""" original = test_ds_generic['test'].values result = test_ds_generic['test'].metpy.quantify() assert isinstance(result.data, units.Quantity) assert result.data.units == units.dimensionless assert 'units' not in result.attrs np.testing.assert_array_almost_equal(result.data, units.Quantity(original))
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 test_undefined_flag(self): 'Tests whether masking values can be disabled.' temp = units.Quantity(np.ma.array([80, 88, 92, 79, 30, 81]), units.degF) rh = np.ma.array([40, 39, 2, 70, 50, 39]) hi = heat_index(temp, rh, mask_undefined=False) mask = np.array([False] * 6) assert_array_equal(hi.mask, mask)
def omega_to_w(omega, p, t): """ Convert pressure vertical velocity to geometric vertical velocity. Arguments: omega -- vertical velocity in pressure coordinates, in [Pa/s] p -- pressure in [Pa] t -- temperature in [K] All inputs can be scalars or NumPy arrays. Returns the vertical velocity in geometric coordinates, [m/s]. """ omega = units.Quantity(omega, "Pa/s") p = units.Quantity(p, "Pa") t = units.Quantity(t, "K") om_w = mpcalc.vertical_velocity(omega, p, t) return om_w
def test_windchill_invalid(): """Test windchill for values that should be masked.""" temp = np.array([10, 51, 49, 60, 80, 81]) * units.degF speed = np.array([4, 4, 3, 1, 10, 39]) * units.mph wc = windchill(temp, speed) # We don't care about the masked values truth = units.Quantity(np.ma.array([2.6230789, np.nan, np.nan, np.nan, np.nan, np.nan], mask=[False, True, True, True, True, True]), units.degF) assert_array_almost_equal(truth, wc)
def test_dataset_dequantify(): """Test dequantify method for converting data away from Quantity on Datasets.""" original = xr.Dataset({ 'test': ('x', units.Quantity([280, 290, 300], 'K')), 'x': np.arange(3) }) result = original.metpy.dequantify() assert isinstance(result['test'].data, np.ndarray) assert result['test'].attrs['units'] == 'kelvin' np.testing.assert_array_almost_equal(result['test'].data, original['test'].data.magnitude)
def eqpt_approx(p, t, q): """ Computes equivalent potential temperature in [K] from pressure, temperature and specific humidity. Arguments: p -- pressure in [Pa] t -- temperature in [K] q -- specific humidity in [kg/kg] p, t and q can be scalars or NumPy arrays. Returns: equivalent potential temperature in [K]. Same dimensions as the inputs. """ p = units.Quantity(p, "Pa") t = units.Quantity(t, "K") dew_temp = mpcalc.dewpoint_from_specific_humidity(p, t, q) eqpt_temp = mpcalc.equivalent_potential_temperature(p, t, dew_temp) return eqpt_temp.to('K').magnitude
def test_apparent_temperature(): """Test the apparent temperature calculation.""" temperature = np.array([[90, 90, 70], [20, 20, 60]]) * units.degF rel_humidity = np.array([[60, 20, 60], [10, 10, 10]]) * units.percent wind = np.array([[5, 3, 3], [10, 1, 10]]) * units.mph truth = units.Quantity( np.ma.array([[99.6777178, 86.3357671, 70], [8.8140662, 20, 60]], mask=[[False, False, True], [False, True, True]]), units.degF) res = apparent_temperature(temperature, rel_humidity, wind) assert_array_almost_equal(res, truth, 6)
def convert_to(value, from_unit, to_unit, default=1.): try: value_unit = units.Quantity(value, from_unit) result = value_unit.to(to_unit).magnitude except pint.UndefinedUnitError: logging.error("Error in unit conversion (undefined) '%s'/'%s'", from_unit, to_unit) result = value * default except pint.DimensionalityError: if units(to_unit).to_base_units().units == units.m: try: result = (value_unit / units.Quantity(9.81, "m s^-2")).to(to_unit).magnitude except pint.DimensionalityError: logging.error( "Error in unit conversion (dimensionality) %s/%s", from_unit, to_unit) result = value * default else: logging.error("Error in unit conversion (dimensionality) %s/%s", from_unit, to_unit) result = value * default return result
def test_interpolate_to_grid(method, assume_units, test_coords, boundary_coords): r"""Test main grid interpolation function.""" xp, yp = test_coords xp *= 10 yp *= 10 z = np.array( [0.064, 4.489, 6.241, 0.1, 2.704, 2.809, 9.604, 1.156, 0.225, 3.364]) extra_kw = {} if method == 'cressman': extra_kw['search_radius'] = 200 extra_kw['minimum_neighbors'] = 1 elif method == 'barnes': extra_kw['search_radius'] = 400 extra_kw['minimum_neighbors'] = 1 extra_kw['gamma'] = 1 if boundary_coords is not None: extra_kw['boundary_coords'] = boundary_coords with get_test_data(f'{method}_test.npz') as fobj: truth = np.load(fobj)['img'] if assume_units: z = units.Quantity(z, assume_units) truth = units.Quantity(truth, assume_units) _, _, img = interpolate_to_grid(xp, yp, z, hres=10, interp_type=method, **extra_kw) assert_array_almost_equal(truth, img)
def test_sensitive_sounding(): """Test quantities for a sensitive sounding (#902).""" # This sounding has a very small positive area in the low level. It's only captured # properly if the parcel profile includes the LCL, otherwise it breaks LFC and CAPE p = units.Quantity([ 1004., 1000., 943., 928., 925., 850., 839., 749., 700., 699., 603., 500., 404., 400., 363., 306., 300., 250., 213., 200., 176., 150. ], 'hectopascal') t = units.Quantity([ 24.2, 24., 20.2, 21.6, 21.4, 20.4, 20.2, 14.4, 13.2, 13., 6.8, -3.3, -13.1, -13.7, -17.9, -25.5, -26.9, -37.9, -46.7, -48.7, -52.1, -58.9 ], 'degC') td = units.Quantity([ 21.9, 22.1, 19.2, 20.5, 20.4, 18.4, 17.4, 8.4, -2.8, -3.0, -15.2, -20.3, -29.1, -27.7, -24.9, -39.5, -41.9, -51.9, -60.7, -62.7, -65.1, -71.9 ], 'degC') lfc_pressure, lfc_temp = lfc(p, t, td) assert_almost_equal(lfc_pressure, 947.476 * units.mbar, 2) assert_almost_equal(lfc_temp, 20.498 * units.degC, 2) pos, neg = surface_based_cape_cin(p, t, td) assert_almost_equal(pos, 0.112 * units('J/kg'), 3) assert_almost_equal(neg, -6.075 * units('J/kg'), 3)