class Test_process(IrisTest):

    """Test the process method."""

    def setUp(self):
        """Set up the cube."""
        cube = _set_up_height_cube(np.array([5.0, 10.0, 20.0]))
        self.coord_name = "height"
        data = np.zeros(cube.shape)
        data[0] = np.ones(cube[0].shape, dtype=np.int32)
        data[1] = np.full(cube[1].shape, 2, dtype=np.int32)
        data[2] = np.full(cube[2].shape, 3, dtype=np.int32)
        data[0, 0, 0] = 6
        cube.data = data
        self.cube = cube
        self.plugin = Integration("height")

    def test_basic(self):
        """Test that a cube with the points on the chosen coordinate are
        in the expected order."""
        result = self.plugin.process(self.cube)
        self.assertIsInstance(result, iris.cube.Cube)
        self.assertArrayAlmostEqual(
            result.coord("height").points, np.array([10.0, 5.0])
        )
        self.assertArrayAlmostEqual(
            result.coord("height").bounds, np.array([[10.0, 20.0], [5.0, 10.0]])
        )

    def test_metadata(self):
        """Test that the metadata on the resulting cube is as expected"""
        expected_attributes = generate_mandatory_attributes([self.cube])
        result = self.plugin.process(self.cube)
        self.assertEqual(result.name(), self.cube.name() + "_integral")
        self.assertEqual(result.units, "{} m".format(self.cube.units))
        self.assertDictEqual(result.attributes, expected_attributes)

    def test_data(self):
        """Test that the resulting cube contains the expected data following
        vertical integration."""
        expected = np.array(
            [
                [[25.00, 25.00, 25.00], [25.00, 25.00, 25.00], [25.00, 25.00, 25.00]],
                [[45.00, 32.50, 32.50], [32.50, 32.50, 32.50], [32.50, 32.50, 32.50]],
            ]
        )
        result = self.plugin.process(self.cube)
        self.assertArrayAlmostEqual(
            result.coord("height").points, np.array([10.0, 5.0])
        )
        self.assertArrayAlmostEqual(result.data, expected)

    def test_dimension_preservation(self):
        """Test the result preserves input dimension order when the coordinate
        to integrate is not the first dimension (eg there's a leading
        realization coordinate)
        """
        cube = set_up_variable_cube(280 * np.ones((3, 3, 3), dtype=np.float32))
        cube = add_coordinate(
            cube, np.array([5.0, 10.0, 20.0]), "height", coord_units="m"
        )
        cube.transpose([1, 0, 2, 3])
        expected_coord_order = [coord.name() for coord in cube.coords(dim_coords=True)]
        result = self.plugin.process(cube)
        self.assertEqual(result.coord_dims("height"), (1,))
        result_coord_order = [coord.name() for coord in result.coords(dim_coords=True)]
        self.assertListEqual(result_coord_order, expected_coord_order)
Пример #2
0
class WetBulbTemperatureIntegral(object):
    """Calculate  a wet-bulb temperature integral."""
    def __init__(self,
                 precision=0.005,
                 coord_name_to_integrate="height",
                 start_point=None,
                 end_point=None,
                 direction_of_integration="negative"):
        """
        Initialise class.

        Keyword Args:
            precision (float):
                The precision to which the Newton iterator must converge
                before returning wet bulb temperatures.
            coord_name_to_integrate (string):
                Name of the coordinate to be integrated.
            start_point (float or None):
                Point at which to start the integration.
                Default is None. If start_point is None, integration starts
                from the first available point.
            end_point (float or None):
                Point at which to end the integration.
                Default is None. If end_point is None, integration will
                continue until the last available point.
            direction_of_integration (string):
                Description of the direction in which to integrate.
                Options are 'positive' or 'negative'.
                'positive' corresponds to the values within the array
                increasing as the array index increases.
                'negative' corresponds to the values within the array
                decreasing as the array index increases.
        """
        self.wet_bulb_temperature_plugin = (WetBulbTemperature(
            precision=precision))
        self.integration_plugin = Integration(
            coord_name_to_integrate,
            start_point=start_point,
            end_point=end_point,
            direction_of_integration=direction_of_integration)
        self.coord_name_to_integrate = coord_name_to_integrate

    def __repr__(self):
        """Represent the configured plugin instance as a string."""
        result = ('<WetBulbTemperatureIntegral: {}, {}>'.format(
            self.wet_bulb_temperature_plugin, self.integration_plugin))
        return result

    def process(self, temperature, relative_humidity, pressure):
        """
        Calculate the wet bulb temperature integral by firstly calculating
        the wet bulb temperature from the inputs provided, and then
        calculating the vertical integral of the wet bulb temperature.

        Args:
            temperature (iris.cube.Cube):
                Cube of air temperatures (K).
            relative_humidity (iris.cube.Cube):
                Cube of relative humidities (%, converted to fractional).
            pressure (iris.cube.Cube):
                Cube of air pressures (Pa).

        Returns:
            wet_bulb_temperature_integral (iris.cube.Cube):
                Cube of wet bulb temperature integral (Kelvin-metres).
        """
        # Calculate wet-bulb temperature.
        wet_bulb_temperature = (self.wet_bulb_temperature_plugin.process(
            temperature, relative_humidity, pressure))
        # Convert to Celsius
        wet_bulb_temperature.convert_units('celsius')
        # Integrate.
        wet_bulb_temperature_integral = (
            self.integration_plugin.process(wet_bulb_temperature))
        wet_bulb_temperature_integral.rename("wet_bulb_temperature_integral")
        units_string = "K {}".format(
            wet_bulb_temperature.coord(self.coord_name_to_integrate).units)
        wet_bulb_temperature_integral.units = Unit(units_string)
        return wet_bulb_temperature_integral
Пример #3
0
class WetBulbTemperatureIntegral(BasePlugin):
    """Calculate a wet-bulb temperature integral."""
    def __init__(self,
                 coord_name_to_integrate="height",
                 start_point=None,
                 end_point=None,
                 direction_of_integration="negative"):
        """
        Initialise class.

        Args:
            coord_name_to_integrate (str):
                Name of the coordinate to be integrated.
            start_point (float or None):
                Point at which to start the integration.
                Default is None. If start_point is None, integration starts
                from the first available point.
            end_point (float or None):
                Point at which to end the integration.
                Default is None. If end_point is None, integration will
                continue until the last available point.
            direction_of_integration (str):
                Description of the direction in which to integrate.
                Options are 'positive' or 'negative'.
                'positive' corresponds to the values within the array
                increasing as the array index increases.
                'negative' corresponds to the values within the array
                decreasing as the array index increases.
        """
        self.integration_plugin = Integration(
            coord_name_to_integrate,
            start_point=start_point,
            end_point=end_point,
            direction_of_integration=direction_of_integration)
        self.coord_name_to_integrate = coord_name_to_integrate

    def __repr__(self):
        """Represent the configured plugin instance as a string."""
        result = ('<WetBulbTemperatureIntegral: {}>'.format(
            self.integration_plugin))
        return result

    def process(self, wet_bulb_temperature):
        """
        Calculate the vertical integal of wet bulb temperature from the input
        wet bulb temperatures on height levels.

        Args:
            wet_bulb_temperature (iris.cube.Cube):
                Cube of wet bulb temperatures of height levels.

        Returns:
            wet_bulb_temperature_integral (iris.cube.Cube):
                Cube of wet bulb temperature integral (Kelvin-metres).
        """
        # Touch the data to ensure it is not lazy
        # otherwise vertical interpolation is slow
        # pylint: disable=pointless-statement
        wet_bulb_temperature.data
        # Convert to Celsius
        wet_bulb_temperature.convert_units('celsius')
        # Integrate.
        wet_bulb_temperature_integral = (
            self.integration_plugin.process(wet_bulb_temperature))
        wet_bulb_temperature_integral.rename("wet_bulb_temperature_integral")
        units_string = "K {}".format(
            wet_bulb_temperature.coord(self.coord_name_to_integrate).units)
        wet_bulb_temperature_integral.units = Unit(units_string)
        return wet_bulb_temperature_integral