def test_cube_metadata(self): """Check metadata of returned cube.""" result = WetBulbTemperature().create_wet_bulb_temperature_cube( self.temperature, self.relative_humidity, self.pressure) self.assertIsInstance(result, Cube) self.assertEqual(result.units, Unit('K')) self.assertEqual(result.name(), 'wet_bulb_temperature')
def test_basic(self, warning_list=None): """Basic test that a warning is raised if temperatures fall outside the allowed range.""" WetBulbTemperature.check_range(self.temperature, 270., 360.) assert len(warning_list) == 1 assert issubclass(warning_list[0].category, UserWarning) assert "Wet bulb temperatures are" in str(warning_list[0])
def test_basic(self, warning_list=None): """Basic test that a warning is raised if temperatures fall outside the allowed range.""" WetBulbTemperature.check_range(self.temperature.data, 270., 360.) warning_msg = "Wet bulb temperatures are" self.assertTrue( any(item.category == UserWarning for item in warning_list)) self.assertTrue(any(warning_msg in str(item) for item in warning_list))
def test_basic(self): """Basic test that a warning is raised if temperatures fall outside the allowed range.""" with warnings.catch_warnings(record=True) as w_messages: WetBulbTemperature.check_range(self.temperature, 270., 360.) assert len(w_messages) == 1 assert issubclass(w_messages[0].category, UserWarning) assert "Wet bulb temperatures are" in str(w_messages[0])
def test_cube_multi_level(self): """Check the cube is returned with expected coordinate order after the data has been sliced and reconstructed.""" temperature = self._make_multi_level(self.temperature, time_promote=True) relative_humidity = self._make_multi_level(self.relative_humidity, time_promote=True) pressure = self._make_multi_level(self.pressure, time_promote=True) result = WetBulbTemperature().process( CubeList([temperature, relative_humidity, pressure])) self.assertEqual(result.coord_dims('time')[0], 0) self.assertEqual(result.coord_dims('height')[0], 1)
def test_values_multi_level(self): """Basic wet bulb temperature calculation using multi-level data.""" temperature = self._make_multi_level(self.temperature) relative_humidity = self._make_multi_level(self.relative_humidity) pressure = self._make_multi_level(self.pressure) result = WetBulbTemperature().process( CubeList([temperature, relative_humidity, pressure]) ) self.assertArrayAlmostEqual(result.data[0], self.expected_wbt_data, decimal=3) self.assertArrayAlmostEqual(result.data[1], self.expected_wbt_data, decimal=3) self.assertEqual(result.units, Unit("K")) self.assertArrayEqual(result.coord("height").points, [10, 20])
def test_calculate_mixing_ratio(self): """Test mixing ratio calculation""" pressure = np.array([1.E5, 9.9E4, 9.8E4], dtype=np.float32) expected = [6.06744631e-08, 1.31079322e-03, 1.77063149e-01] result = WetBulbTemperature()._calculate_mixing_ratio( self.temperature, pressure) self.assertArrayAlmostEqual(result, expected, decimal=7)
def test_values(self): """Basic wet bulb temperature calculation.""" result = WetBulbTemperature().create_wet_bulb_temperature_cube( self.temperature, self.relative_humidity, self.pressure) self.assertArrayAlmostEqual(result.data, self.expected_wbt_data, decimal=3)
def test_values(self): """Basic extraction of some SVP values from the lookup table.""" self.temperature.data[1] = 260.5683203 expected = [9.664590e-03, 206., 2.501530e+04] result = WetBulbTemperature().lookup_svp(self.temperature) self.assertArrayAlmostEqual(result.data, expected) self.assertEqual(result.units, Unit('Pa'))
def process(*cubes: cli.inputcube, convergence_condition=0.05): """Module to generate wet-bulb temperatures. Call the calculate_wet_bulb_temperature function to calculate wet-bulb temperatures. This process function splits input cubes over vertical levels to mitigate memory issues when trying to operate on multi-level data. Args: cubes (iris.cube.CubeList or list or iris.cube.Cube): containing: temperature (iris.cube.Cube): Cube of air temperatures, where these may be on multiple height levels. relative_humidity (iris.cube.Cube): Cube of relative humidities, where these may be on multiple height levels. pressure (iris.cube.Cube): Cube of air pressure, where these may be on multiple height levels. convergence_condition (float): The precision in Kelvin to which the Newton iterator must converge before returning wet-bulb temperatures. Returns: iris.cube.Cube: Cube of wet-bulb temperature (K). """ from improver.psychrometric_calculations.psychrometric_calculations \ import WetBulbTemperature return WetBulbTemperature(precision=convergence_condition)(cubes)
def test_values_multi_level(self): """Basic wet bulb temperature calculation using multi-level data.""" temperature = self._make_multi_level(self.temperature) relative_humidity = self._make_multi_level(self.relative_humidity) pressure = self._make_multi_level(self.pressure) expected = [183.15, 259.883055, 333.960651] result = WetBulbTemperature().process( temperature, relative_humidity, pressure) self.assertArrayAlmostEqual(result.data[0], expected) self.assertArrayAlmostEqual(result.data[1], expected) self.assertEqual(result.units, Unit('K')) self.assertArrayEqual(result.coord('height').points, [10, 20])
def process(temperature, relative_humidity, pressure, convergence_condition=0.05): """Module to generate wet-bulb temperatures. Call the calculate_wet_bulb_temperature function to calculate wet-bulb temperatures. This process function splits input cubes over vertical levels to mitigate memory issues when trying to operate on multi-level data. Args: temperature (iris.cube.Cube): Cube of air temperatures. relative_humidity (iris.cube.Cube): Cube of relative humidities. pressure (iris.cube.Cube): Cube of air pressure. convergence_condition (float): The precision to which the Newton iterator must converge before returning wet-bulb temperatures. Default is 0.05. Returns: iris.cube.Cube: Cube of wet-bulb temperature (K). """ result = (WetBulbTemperature(precision=convergence_condition).process( temperature, relative_humidity, pressure)) return result
def test_values(self): """Basic extraction of some SVP values from the lookup table.""" self.temperature.data[0, 1] = 260.56833 expected = [[1.350531e-02, 2.06000274e+02, 2.501530e+04]] result = WetBulbTemperature().lookup_svp(self.temperature) self.assertArrayAlmostEqual(result.data, expected) self.assertEqual(result.units, Unit('Pa'))
def test_values(self): """Basic mixing ratio calculation.""" expected = [[6.06744631e-08, 1.31079322e-03, 1.77063149e-01]] result = WetBulbTemperature()._calculate_mixing_ratio( self.temperature.data, self.pressure.data) self.assertArrayAlmostEqual(result, expected)
def test_too_many_cubes(self): """Tests that an error is raised if there are too many cubes.""" temp = self.temperature humid = self.relative_humidity pressure = self.pressure msg = "Expected 3" with self.assertRaisesRegex(ValueError, msg): WetBulbTemperature().process(CubeList([temp, humid, pressure, temp]))
def test_calculate_enthalpy_gradient(self): """Test calculation of enthalpy gradient with temperature. Comparison adjusted for 32-bit precision.""" expected = [41662.730, 41300.594, 36356.254] result = WetBulbTemperature()._calculate_enthalpy_gradient( self.mixing_ratio, self.specific_heat, self.latent_heat, self.temperature ) self.assertArrayAlmostEqual(result.data, expected, decimal=3)
def test_values_single_level_reorder_cubes(self): """Same test as test_values_single_level but the cubes are in a different order.""" result = WetBulbTemperature().process( CubeList([self.relative_humidity, self.temperature, self.pressure]) ) self.assertArrayAlmostEqual(result.data, self.expected_wbt_data, decimal=3) self.assertEqual(result.units, Unit("K"))
def test_calculate_enthalpy(self): """Basic calculation of some enthalpies. Comparison adjusted for 32-bit precision.""" expected = [454734.6, 807677.3, 1171053.1] result = WetBulbTemperature()._calculate_enthalpy( self.mixing_ratio, self.specific_heat, self.latent_heat, self.temperature ) self.assertArrayAlmostEqual(result, expected, decimal=1)
def test_values(self): """Basic wet bulb temperature calculation.""" expected = [183.15, 259.883055, 333.960651] result = WetBulbTemperature().calculate_wet_bulb_temperature( self.temperature, self.relative_humidity, self.pressure) self.assertArrayAlmostEqual(result.data, expected) self.assertEqual(result.units, Unit('K'))
def test_values_single_level(self): """Basic wet bulb temperature calculation as if calling the create_wet_bulb_temperature_cube function directly with single level data.""" result = WetBulbTemperature().process( CubeList([self.temperature, self.relative_humidity, self.pressure]) ) self.assertArrayAlmostEqual(result.data, self.expected_wbt_data, decimal=3) self.assertEqual(result.units, Unit("K"))
def test_values(self): """Basic wet bulb temperature calculation.""" expected = np.array([[185.0, 259.88306, 333.96063]], dtype=np.float32) result = WetBulbTemperature().calculate_wet_bulb_temperature( self.temperature, self.relative_humidity, self.pressure) self.assertArrayAlmostEqual(result.data, expected) self.assertEqual(result.units, Unit('K'))
def test_values(self): """Basic pressure correction of water vapour SVPs to give SVPs in air.""" svp = self.pressure.copy(data=[[197.41815, 474.1368, 999.5001]]) expected = [[199.226956, 476.293096, 1006.391004]] result = WetBulbTemperature().pressure_correct_svp( svp, self.temperature.data, self.pressure.data) self.assertArrayAlmostEqual(result.data, expected)
def test_values(self): """Basic mixing ratio calculation.""" expected = [6.067447e-08, 1.310793e-03, 0.1770631] result = WetBulbTemperature()._calculate_mixing_ratio( self.temperature, self.pressure) self.assertArrayAlmostEqual(result.data, expected) self.assertEqual(result.units, Unit('1'))
def test_different_units(self): """Wet bulb temperature calculation with unit conversion.""" self.temperature.convert_units("celsius") self.relative_humidity.convert_units("1") self.pressure.convert_units("kPa") result = WetBulbTemperature().create_wet_bulb_temperature_cube( self.temperature, self.relative_humidity, self.pressure ) self.assertArrayAlmostEqual(result.data, self.expected_wbt_data, decimal=3) self.assertEqual(result.units, Unit("K"))
def test_values(self): """Basic pressure correction of water vapour SVPs to give SVPs in air.""" svp = self.pressure.copy(data=[197.41815, 474.1368, 999.5001]) expected = [199.265984, 476.293085, 1006.390954] result = WetBulbTemperature().pressure_correct_svp( svp, self.temperature, self.pressure) self.assertArrayAlmostEqual(result.data, expected) self.assertEqual(result.units, Unit('Pa'))
def test_different_level_types(self): """Check an exception is raised if trying to work with data on a mix of height and pressure levels.""" temperature = self._make_multi_level(self.temperature) relative_humidity = self._make_multi_level(self.relative_humidity) pressure = self._make_multi_level(self.pressure) temperature.coord('height').rename('pressure') msg = 'WetBulbTemperature: Cubes have differing' with self.assertRaisesRegex(ValueError, msg): WetBulbTemperature().process( CubeList([temperature, relative_humidity, pressure]))
def test_values_single_level(self): """Basic wet bulb temperature calculation as if calling the calculate_wet_bulb_temperature function directly with single level data.""" expected = [183.15, 259.883055, 333.960651] result = WetBulbTemperature().process( self.temperature, self.relative_humidity, self.pressure) self.assertArrayAlmostEqual(result.data, expected) self.assertEqual(result.units, Unit('K'))
def test_beyond_table_bounds(self, warning_list=None): """Extracting SVP values from the lookup table with temperatures beyond its valid range. Should return the nearest end of the table.""" self.temperature.data[1] = 150. self.temperature.data[2] = 400. expected = [9.664590e-03, 9.664590e-03, 2.501530e+04] result = WetBulbTemperature()._lookup_svp(self.temperature) assert len(warning_list) == 1 assert issubclass(warning_list[0].category, UserWarning) assert "Wet bulb temperatures are" in str(warning_list[0]) self.assertArrayAlmostEqual(result.data, expected) self.assertEqual(result.units, Unit('Pa'))
def test_beyond_table_bounds(self, warning_list=None): """Extracting SVP values from the lookup table with temperatures beyond its valid range. Should return the nearest end of the table.""" self.temperature.data[0, 0] = 150. self.temperature.data[0, 2] = 400. expected = [[9.664590e-03, 2.075279e+02, 2.501530e+04]] result = WetBulbTemperature().lookup_svp(self.temperature.data) warning_msg = "Wet bulb temperatures are" self.assertTrue( any(item.category == UserWarning for item in warning_list)) self.assertTrue(any(warning_msg in str(item) for item in warning_list)) self.assertArrayAlmostEqual(result, expected)
def test_different_units(self): """Basic wet bulb temperature calculation with a unit conversion required.""" self.temperature.convert_units('celsius') self.relative_humidity.convert_units('1') self.pressure.convert_units('kPa') expected = [183.15, 259.883055, 333.960651] result = WetBulbTemperature().calculate_wet_bulb_temperature( self.temperature, self.relative_humidity, self.pressure) self.assertArrayAlmostEqual(result.data, expected) self.assertEqual(result.units, Unit('K'))