def test_basic(self):
     """Test that the method returns the expected cube type
     and that the metadata are as expected.
     We expect a new name, the threshold coord to be removed and
     cell methods to be discarded."""
     result = self.plugin._update_metadata(self.cube)
     self.assertIsInstance(result, Cube)
     self.assertEqual(result.name(),
                      "probability_of_rate_of_lightning_above_threshold")
     msg = "No threshold coord found"
     with self.assertRaisesRegex(CoordinateNotFoundError, msg):
         find_threshold_coordinate(result)
     self.assertEqual(result.cell_methods, ())
Exemple #2
0
    def _update_metadata(cube):
        """
        Modify the meta data of input cube to resemble a Nowcast of lightning
        probability.

        1. Rename to "probability_of_rate_of_lightning_above_threshold"

        2. Remove "threshold" coord
        (or causes iris.exceptions.CoordinateNotFoundError)

        3. Discard all cell_methods

        Args:
            cube (iris.cube.Cube):
                An input cube

        Returns:
            new_cube (iris.cube.Cube):
                Output cube - a copy of input cube with meta-data relating to
                a Nowcast of lightning probability.
                The data array will be a copy of the input cube.data
        """
        new_cube = cube.copy()
        new_cube.rename("probability_of_rate_of_lightning_above_threshold")
        threshold_coord = find_threshold_coordinate(new_cube)
        new_cube.remove_coord(threshold_coord)
        new_cube.cell_methods = None
        return new_cube
 def setUp(self):
     """Create a cube with threshold coord is not first coord."""
     self.cube1 = create_cube_with_threshold()
     self.cube2 = add_coordinate(
         self.cube1, np.arange(2).astype(np.float32),
         "realization", dtype=np.float32)
     self.coord_name = find_threshold_coordinate(self.cube1).name()
    def process(self, cube):
        """
        Calculate probabilities between thresholds for the input cube

        Args:
            cube (iris.cube.Cube):
                Probability cube containing thresholded data (above or below)

        Returns:
            output_cube (iris.cube.Cube):
                Cube containing probability of occurrence between thresholds
        """
        # if cube has no threshold-type coordinate, raise an error
        try:
            self.thresh_coord = find_threshold_coordinate(cube)
        except CoordinateNotFoundError:
            raise ValueError('Input is not a probability cube '
                             '(has no threshold-type coordinate)')
        self.cube = cube.copy()

        # check input cube units and convert if needed
        original_units = self.thresh_coord.units
        if original_units != self.threshold_units:
            self.cube.coord(self.thresh_coord).convert_units(
                self.threshold_units)

        # extract suitable cube slices
        self.cube_slices = self._slice_cube()

        # generate "between thresholds" probabilities
        output_cube = self._calculate_probabilities()
        self._update_metadata(output_cube, original_units)

        return output_cube
 def setUp(self):
     """Set up current_temperature_forecast_cube for testing."""
     self.current_temperature_forecast_cube = (
         add_forecast_reference_time_and_forecast_period(
             set_up_probability_above_threshold_temperature_cube()))
     self.threshold_points = find_threshold_coordinate(
         self.current_temperature_forecast_cube).points
Exemple #6
0
    def iterate_over_threshold(self, cubelist, threshold):
        """
        Iterate over the application of thresholding to multiple cubes.

        Args:
            cubelist (iris.cube.CubeList):
                Cubelist containing cubes to be thresholded.
            threshold (float):
                The threshold that will be applied.

        Returns:
            cubes (iris.cube.CubeList):
                Cubelist after thresholding each cube.
        """
        cubes = iris.cube.CubeList([])
        for cube in cubelist:
            threshold_cube = (BasicThreshold(
                threshold,
                fuzzy_factor=self.fuzzy_factor,
                below_thresh_ok=self.below_thresh_ok).process(cube.copy()))
            # Will only ever contain one slice on threshold
            for cube_slice in threshold_cube.slices_over(
                    find_threshold_coordinate(threshold_cube)):
                threshold_cube = cube_slice

            cubes.append(threshold_cube)
        return cubes
Exemple #7
0
 def test_old_convention(self):
     """Test function recognises threshold coordinate with name "threshold"
     """
     threshold_coord = find_threshold_coordinate(self.cube_old)
     self.assertEqual(threshold_coord.name(), "threshold")
     self.assertArrayAlmostEqual(threshold_coord.points,
                                 self.threshold_points)
    def test_check_single_threshold(self):
        """
        Test that the plugin returns an Iris.cube.Cube with the expected
        data values for the percentiles, if a single threshold is used for
        constructing the percentiles.
        """
        data = np.array([[[[12.2, 8., 12.2],
                           [-16., 8., -30.4],
                           [-30.4, -34., -35.2]]],
                         [[[29., 26.66666667, 29.],
                           [23.75, 26.66666667, 8.],
                           [8., -10., -16.]]],
                         [[[45.8, 45.33333333, 45.8],
                           [44.75, 45.33333333, 41.6],
                           [41.6, 29., 3.2]]]], dtype=np.float32)

        threshold_coord = find_threshold_coordinate(
            self.current_temperature_forecast_cube)
        for acube in self.current_temperature_forecast_cube.slices_over(
                threshold_coord):
            cube = acube
            break
        percentiles = [10, 50, 90]
        bounds_pairing = (-40, 50)
        plugin = Plugin()
        result = plugin._probabilities_to_percentiles(
            cube, percentiles, bounds_pairing)
        self.assertArrayAlmostEqual(result.data, data, decimal=5)
    def _check_unit_compatibility(mean_values, variance_values,
                                  probability_cube_template):
        """
        The mean, variance, and threshold values come from three different
        cubes. They should all be in the same units, but this is a sanity check
        to ensure this is the case, converting units of the means and variances
        if possible. This has been written specifically for this plugin as we
        are comparing squared units in the case of the variance.

        Args:
            mean_values (iris.cube.Cube):
                Cube of mean values.
            variance_values (iris.cube.Cube):
                Cube of variance values.
            probability_cube_template (iris.cube.Cube):
                Cube containing threshold values.
        Raises:
            ValueError: If units of input cubes are not compatible.
        """
        threshold_units = (
            find_threshold_coordinate(probability_cube_template).units)

        try:
            mean_values.convert_units(threshold_units)
            variance_values.convert_units(threshold_units**2)
        except ValueError as err:
            msg = ('Error: {} This is likely because the mean '
                   'variance and template cube threshold units are '
                   'not equivalent/compatible.'.format(err))
            raise ValueError(msg)
    def _check_template_cube(cube):
        """
        The template cube is expected to contain a leading threshold dimension
        followed by spatial (y/x) dimensions. This check raises an error if
        this is not the case. If the cube contains the expected dimensions,
        a threshold leading order is enforced.

        Args:
            cube (iris.cube.Cube):
                A cube whose dimensions are checked to ensure they match what
                is expected.
        Raises:
            ValueError: If cube is not of the expected dimensions.
        """
        check_for_x_and_y_axes(cube, require_dim_coords=True)
        dim_coords = [coord.name() for coord in cube.coords(dim_coords=True)]
        msg = ('GenerateProbabilitiesFromMeanAndVariance expects a cube with '
               'only a leading threshold dimension, followed by spatial (y/x) '
               'dimensions. Got dimensions: {}'.format(dim_coords))

        try:
            threshold_coord = find_threshold_coordinate(cube)
        except CoordinateNotFoundError:
            raise ValueError(msg)

        if len(dim_coords) < 4:
            enforce_coordinate_ordering(cube, threshold_coord.name())
            return

        raise ValueError(msg)
 def test_missing_threshold_coord(self):
     """Test that the method raises an error in Iris if the cube doesn't
     have a threshold coordinate to remove."""
     self.cube.remove_coord(find_threshold_coordinate(self.cube))
     msg = "No threshold coord found"
     with self.assertRaisesRegex(CoordinateNotFoundError, msg):
         self.plugin._update_metadata(self.cube)
Exemple #12
0
 def test_new_convention(self):
     """Test function recognises threshold coordinate with standard
     diagnostic name and "threshold" as var_name"""
     threshold_coord = find_threshold_coordinate(self.cube_new)
     self.assertEqual(threshold_coord.name(), "air_temperature")
     self.assertEqual(threshold_coord.var_name, "threshold")
     self.assertArrayAlmostEqual(threshold_coord.points,
                                 self.threshold_points)
Exemple #13
0
    def process(self, cubelist):
        """
        Produce Nowcast of lightning probability.

        Args:
            cubelist (iris.cube.CubeList):
                Where thresholds are listed, only these threshold values will
                    be used.
                Contains cubes of
                    * First-guess lightning probability
                    * Nowcast precipitation probability
                        (required thresholds: > 0.5, 7., 35. mm hr-1)
                    * Nowcast lightning rate
                    * (optional) Analysis of vertically integrated ice (VII)
                      from radar thresholded into probability slices
                      at self.ice_thresholds.

        Returns:
            new_cube (iris.cube.Cube):
                Output cube containing Nowcast lightning probability.
                This cube will have the same dimensions as the input
                Nowcast precipitation probability after the threshold coord
                has been removed.

        Raises:
            iris.exceptions.ConstraintMismatchError:
                If cubelist does not contain the expected cubes.
        """
        first_guess_lightning_cube = cubelist.extract(
            "probability_of_rate_of_lightning_above_threshold", strict=True)
        lightning_rate_cube = cubelist.extract(
            "rate_of_lightning", strict=True)
        lightning_rate_cube.convert_units("min^-1")  # Ensure units are correct
        prob_precip_cube = cubelist.extract(
            "probability_of_lwe_precipitation_rate_above_threshold",
            strict=True)
        # Now find prob_vii_cube. Can't use strict=True here as cube may not be
        # present, so will use a normal extract and then merge_cube if needed.
        prob_vii_cube = cubelist.extract(
            "probability_of_vertical_integral_of_ice_above_threshold")
        if prob_vii_cube:
            prob_vii_cube = prob_vii_cube.merge_cube()
        precip_threshold_coord = find_threshold_coordinate(prob_precip_cube)
        precip_threshold_coord.convert_units('mm hr-1')
        precip_slice = prob_precip_cube.extract(
            iris.Constraint(coord_values={
                precip_threshold_coord: lambda t: isclose(t.point, 0.5)}))
        if not isinstance(precip_slice, iris.cube.Cube):
            raise ConstraintMismatchError(
                "Cannot find prob(precip > 0.5 mm hr-1) cube in cubelist.")
        template_cube = self._update_metadata(precip_slice)
        new_cube = self._modify_first_guess(
            template_cube, first_guess_lightning_cube, lightning_rate_cube,
            prob_precip_cube, prob_vii_cube)
        # Adjust data so that lightning probability does not decrease too
        # rapidly with distance.
        self.neighbourhood.process(new_cube)
        return new_cube
Exemple #14
0
    def apply_ice(self, prob_lightning_cube, ice_cube):
        """
        Modify Nowcast of lightning probability with ice data from a radar
        composite (VII; Vertically Integrated Ice)

        Args:
            prob_lightning_cube (iris.cube.Cube):
                First-guess lightning probability.
                The forecast_period coord is modified in-place to "minutes".
            ice_cube (iris.cube.Cube):
                Analysis of vertically integrated ice (VII) from radar
                thresholded at self.ice_thresholds.
                Units of threshold coord modified in-place to kg m^-2

        Returns:
            new_cube (iris.cube.Cube):
                Output cube containing updated nowcast lightning probability.
                This cube will have the same dimensions and meta-data as
                prob_lightning_cube.
                The influence of the data in ice_cube reduces linearly to zero
                as forecast_period increases to 2H30M.

        Raises:
            iris.exceptions.ConstraintMismatchError:
                If ice_cube does not contain the expected thresholds.
        """
        prob_lightning_cube.coord('forecast_period').convert_units('minutes')
        # check prob-ice threshold units are as expected
        ice_threshold_coord = find_threshold_coordinate(ice_cube)
        ice_threshold_coord.convert_units('kg m^-2')
        new_cube_list = iris.cube.CubeList([])
        err_string = "No matching prob(Ice) cube for threshold {}"
        for cube_slice in prob_lightning_cube.slices_over('time'):
            fcmins = cube_slice.coord('forecast_period').points[0]
            for threshold, prob_max in zip(self.ice_thresholds,
                                           self.ice_scaling):
                ice_slice = ice_cube.extract(
                    iris.Constraint(coord_values={
                        ice_threshold_coord: lambda t: isclose(
                            t.point, threshold)}))
                if not isinstance(ice_slice, iris.cube.Cube):
                    raise ConstraintMismatchError(err_string.format(threshold))
                # Linearly reduce impact of ice as fcmins increases to 2H30M.
                ice_scaling = [0., (prob_max * (1. - (fcmins / 150.)))]
                if ice_scaling[1] > 0:
                    cube_slice.data = np.maximum(
                        rescale(ice_slice.data,
                                data_range=(0., 1.),
                                scale_range=ice_scaling,
                                clip=True),
                        cube_slice.data)
            new_cube_list.append(cube_slice)

        new_cube = new_cube_list.merge_cube()
        new_cube = check_cube_coordinates(
            prob_lightning_cube, new_cube)
        return new_cube
 def test_precip_has_no_thresholds(self):
     """Test that the method raises an error if the threshold coord is
     omitted from the precip_cube"""
     threshold_coord = find_threshold_coordinate(self.precip_cube)
     self.precip_cube.remove_coord(threshold_coord)
     msg = "No threshold coord found"
     with self.assertRaisesRegex(CoordinateNotFoundError, msg):
         self.plugin.process(
             CubeList([self.fg_cube, self.ltng_cube, self.precip_cube]))
 def test_varying_mask_fail(self):
     """Test error is raised when mask varies along collapsing dim"""
     # Check fails when blending along threshold coordinate, as mask
     # varies along this coordinate.
     threshold_coord = find_threshold_coordinate(self.cube_to_collapse)
     message = (
         "The mask on the input cube can only vary along the blend_coord")
     with self.assertRaisesRegex(ValueError, message):
         self.plugin.create_template_slice(self.cube_to_collapse,
                                           threshold_coord.name())
    def _mean_and_variance_to_probabilities(mean_values, variance_values,
                                            probability_cube_template):
        """
        Function returning probabilities relative to provided thresholds based
        on the supplied mean and variance. A Gaussian distribution is assumed.

        Args:
            mean_values (iris.cube.Cube):
                Predictor for the calibrated forecast i.e. the mean.
            variance_values (iris.cube.Cube):
                Variance for the calibrated forecast.
            probability_cube_template (iris.cube.Cube):
                A probability cube that has a threshold coordinate, where the
                probabilities are defined as above or below the threshold by
                the spp__relative_to_threshold attribute. This cube matches
                the desired output cube format.

        Returns:
            probability_cube (iris.cube.Cube):
                Cube containing the data expressed as probabilities relative to
                the provided thresholds in the way described by
                spp__relative_to_threshold.
        """
        thresholds = (
            find_threshold_coordinate(probability_cube_template).points)
        relative_to_threshold = find_threshold_coordinate(
            probability_cube_template).attributes['spp__relative_to_threshold']

        # Loop over thresholds, and use a normal distribution with the mean
        # and variance to calculate the probabilities relative to each
        # threshold.
        probabilities = np.empty_like(probability_cube_template.data)
        distribution = norm(loc=mean_values.data,
                            scale=np.sqrt(variance_values.data))
        probability_method = distribution.cdf
        if relative_to_threshold == 'above':
            probability_method = distribution.sf

        for index, threshold in enumerate(thresholds):
            probabilities[index, ...] = probability_method(threshold)

        probability_cube = probability_cube_template.copy(data=probabilities)
        return probability_cube
Exemple #18
0
    def test_incorrect_units(self):
        """Test that check_input_cubes method raises an error if the units are
        incompatible between the input cube and the decision tree."""
        plugin = WeatherSymbols()

        msg = "Unable to convert from"
        threshold_coord = find_threshold_coordinate(self.cubes[0])
        self.cubes[0].coord(threshold_coord).units = Unit('mm kg-1')
        with self.assertRaisesRegex(ValueError, msg):
            plugin.check_input_cubes(self.cubes)
 def setUp(self):
     """
     Set up a basic cube and linear weights cube for the process
     method. Input cube has 2 thresholds on and 3
     forecast_reference_times
     """
     thresholds = [10, 20]
     data = np.ones((2, 2, 3), dtype=np.float32)
     cycle1 = set_up_probability_cube(
         data,
         thresholds,
         spatial_grid="equalarea",
         time=datetime(2017, 11, 10, 4, 0),
         frt=datetime(2017, 11, 10, 0, 0),
     )
     cycle2 = set_up_probability_cube(
         data,
         thresholds,
         spatial_grid="equalarea",
         time=datetime(2017, 11, 10, 4, 0),
         frt=datetime(2017, 11, 10, 1, 0),
     )
     cycle3 = set_up_probability_cube(
         data,
         thresholds,
         spatial_grid="equalarea",
         time=datetime(2017, 11, 10, 4, 0),
         frt=datetime(2017, 11, 10, 2, 0),
     )
     self.cube_to_collapse = CubeList([cycle1, cycle2, cycle3]).merge_cube()
     self.cube_to_collapse = squeeze(self.cube_to_collapse)
     self.cube_to_collapse.rename("weights")
     # This input array has 3 forecast reference times and 2 thresholds.
     # The two thresholds have the same weights.
     self.cube_to_collapse.data = np.array(
         [[[[1, 0, 1], [1, 1, 1]], [[1, 0, 1], [1, 1, 1]]],
          [[[0, 0, 1], [0, 1, 1]], [[0, 0, 1], [0, 1, 1]]],
          [[[1, 1, 1], [1, 1, 1]], [[1, 1, 1], [1, 1, 1]]]],
         dtype=np.float32)
     self.cube_to_collapse.data = np.ma.masked_equal(
         self.cube_to_collapse.data, 0)
     # Create a one_dimensional weights cube by slicing the larger
     # weights cube.
     # The resulting cube only has a forecast_reference_time coordinate.
     self.one_dimensional_weights_cube = self.cube_to_collapse[:, 0, 0, 0]
     self.one_dimensional_weights_cube.remove_coord(
         "projection_x_coordinate")
     self.one_dimensional_weights_cube.remove_coord(
         "projection_y_coordinate")
     self.one_dimensional_weights_cube.remove_coord(
         find_threshold_coordinate(self.one_dimensional_weights_cube))
     self.one_dimensional_weights_cube.data = np.array([0.2, 0.5, 0.3],
                                                       dtype=np.float32)
     self.plugin = SpatiallyVaryingWeightsFromMask(fuzzy_length=4)
 def setUp(self):
     """Set up information for testing."""
     self.changes = {
         'points': [2.0],
         'bounds': [0.1, 2.0],
         'units': 'mm',
         'var_name': 'threshold'
         }
     cube = create_cube_with_threshold()
     self.coord_name = find_threshold_coordinate(cube).name()
     cube.remove_coord(self.coord_name)
     self.cube = iris.util.squeeze(cube)
 def setUp(self):
     """
     Set up a basic weights cube with 2 thresholds to multiple with
     a cube with one_dimensional weights.
     """
     thresholds = [10, 20]
     data = np.ones((2, 2, 3), dtype=np.float32)
     cycle1 = set_up_probability_cube(
         data,
         thresholds,
         spatial_grid="equalarea",
         time=datetime(2017, 11, 10, 4, 0),
         frt=datetime(2017, 11, 10, 0, 0),
     )
     cycle2 = set_up_probability_cube(
         data,
         thresholds,
         spatial_grid="equalarea",
         time=datetime(2017, 11, 10, 4, 0),
         frt=datetime(2017, 11, 10, 1, 0),
     )
     cycle3 = set_up_probability_cube(
         data,
         thresholds,
         spatial_grid="equalarea",
         time=datetime(2017, 11, 10, 4, 0),
         frt=datetime(2017, 11, 10, 2, 0),
     )
     self.spatial_weights_cube = CubeList([cycle1, cycle2,
                                           cycle3]).merge_cube()
     self.spatial_weights_cube = squeeze(self.spatial_weights_cube)
     self.spatial_weights_cube.rename("weights")
     # This input array has 3 forecast reference times and 2 thresholds.
     # The two thresholds have the same weights.
     self.spatial_weights_cube.data = np.array(
         [[[[1, 0, 1], [1, 0, 1]], [[1, 0, 1], [1, 0, 1]]],
          [[[0, 0, 1], [0, 0, 1]], [[0, 0, 1], [0, 0, 1]]],
          [[[1, 1, 1], [1, 1, 1]], [[1, 1, 1], [1, 1, 1]]]],
         dtype=np.float32)
     # Create a one_dimensional weights cube by slicing the
     # larger weights cube.
     # The resulting cube only has a forecast_reference_time coordinate.
     self.one_dimensional_weights_cube = (self.spatial_weights_cube[:, 0, 0,
                                                                    0])
     self.one_dimensional_weights_cube.remove_coord(
         "projection_x_coordinate")
     self.one_dimensional_weights_cube.remove_coord(
         "projection_y_coordinate")
     self.one_dimensional_weights_cube.remove_coord(
         find_threshold_coordinate(self.one_dimensional_weights_cube))
     self.one_dimensional_weights_cube.data = np.array([0.2, 0.5, 0.3],
                                                       dtype=np.float32)
     self.plugin = SpatiallyVaryingWeightsFromMask()
Exemple #22
0
 def test_ordering_for_threshold_coordinate(self):
     """Test that the cube has been reordered, if it is originally in an
     undesirable order and the cube contains a "threshold" coordinate."""
     cube = set_up_probability_cube(
         np.zeros((3, 4, 5), dtype=np.float32),
         np.array([273., 274., 275.], dtype=np.float32))
     cube.transpose([2, 1, 0])
     save_netcdf(cube, self.filepath)
     result = load_cube(self.filepath)
     threshold_coord = find_threshold_coordinate(result)
     self.assertEqual(result.coord_dims(threshold_coord)[0], 0)
     self.assertArrayAlmostEqual(result.coord_dims("latitude")[0], 1)
     self.assertArrayAlmostEqual(result.coord_dims("longitude")[0], 2)
 def test_basic(self):
     """Test that the method returns the expected cube type with coords"""
     result = self.plugin.process(
         CubeList([self.fg_cube, self.ltng_cube, self.precip_cube]))
     self.assertIsInstance(result, Cube)
     # We expect the threshold coordinate to have been removed.
     threshold_coord = find_threshold_coordinate(self.precip_cube).name()
     self.assertCountEqual(
         find_dimension_coordinate_mismatch(result, self.precip_cube),
         [threshold_coord])
     self.assertEqual(result.name(),
                      'probability_of_rate_of_lightning_above_threshold')
     self.assertEqual(result.units, '1')
    def setUp(self):
        """Set up temperature cube."""
        self.template_cube = (
            set_up_probability_above_threshold_temperature_cube())
        self.template_cube = iris.util.squeeze(self.template_cube)

        threshold_coord = find_threshold_coordinate(self.template_cube)
        threshold_coord.points = [8.65105, 10., 11.34895]
        mean_values = np.ones((3, 3)) * 10
        variance_values = np.ones((3, 3)) * 4
        self.means = self.template_cube[0, :, :].copy(data=mean_values)
        self.means.units = 'Celsius'
        self.variances = self.template_cube[0, :, :].copy(data=variance_values)
        self.variances.units = 'Celsius2'
Exemple #25
0
 def test_defaults(self):
     """Test default arguments produce cube with expected dimensions
     and metadata"""
     result = set_up_probability_cube(self.data, self.thresholds)
     thresh_coord = find_threshold_coordinate(result)
     self.assertEqual(result.name(),
                      'probability_of_air_temperature_above_threshold')
     self.assertEqual(result.units, '1')
     self.assertArrayEqual(thresh_coord.points, self.thresholds)
     self.assertEqual(thresh_coord.name(), 'air_temperature')
     self.assertEqual(thresh_coord.var_name, 'threshold')
     self.assertEqual(thresh_coord.units, 'K')
     self.assertEqual(len(result.attributes), 1)
     self.assertEqual(result.attributes['relative_to_threshold'], 'above')
Exemple #26
0
 def test_range_constraint(self):
     """ Test that a constraint passed in as a range is parsed correctly """
     # create input cube
     precip_cube = set_up_precip_probability_cube()
     threshold_coord = find_threshold_coordinate(precip_cube).name()
     precip_cube.coord(threshold_coord).convert_units("mm h-1")
     # generate constraints
     constraints = ["{}=[0.03:0.1]".format(threshold_coord)]
     result, _ = parse_constraint_list(constraints)
     self.assertIsInstance(result, iris._constraints.ConstraintCombination)
     cdict = result.rhs._coord_values
     self.assertEqual(list(cdict.keys()), [threshold_coord])
     # extract from input cube
     result_cube = precip_cube.extract(result)
     self.assertArrayAlmostEqual(
         result_cube.coord(threshold_coord).points, np.array([0.03, 0.1]))
    def setUp(self):
        """Set up temperature cube."""
        self.template_cube = (
            set_up_probability_above_threshold_temperature_cube())
        self.template_cube = iris.util.squeeze(self.template_cube)

        # Thresholds such that we obtain probabilities of 75%, 50%, and 25% for
        # the mean and variance values set here.
        threshold_coord = find_threshold_coordinate(self.template_cube)
        threshold_coord.points = [8.65105, 10., 11.34895]
        mean_values = np.ones((3, 3)) * 10
        variance_values = np.ones((3, 3)) * 4
        self.means = self.template_cube[0, :, :].copy(data=mean_values)
        self.means.units = 'Celsius'
        self.variances = self.template_cube[0, :, :].copy(data=variance_values)
        self.variances.units = 'Celsius2'
Exemple #28
0
    def test_weights_scalar_coord(self):
        """Test building a cube of weights where the blending coordinate is a
        scalar."""

        weights = [1.0]
        blending_coord = find_threshold_coordinate(self.cube).name()
        cube = iris.util.squeeze(self.cube)

        plugin = WeightsUtilities.build_weights_cube
        result = plugin(cube, weights, blending_coord)

        self.assertIsInstance(result, iris.cube.Cube)
        self.assertEqual(result.name(), 'weights')
        self.assertFalse(result.attributes)
        self.assertArrayEqual(result.data, weights)
        self.assertEqual(result.coords(dim_coords=True)[0].name(),
                         blending_coord)
    def setUp(self):
        """Create test cubes and plugin instance.
        The cube coordinates look like this:
        Dimension coordinates:
            projection_y_coordinate: 3;
            projection_x_coordinate: 3;
        Scalar coordinates:
            time: 2015-11-23 07:00:00
            forecast_reference_time: 2015-11-23 07:00:00
            forecast_period: 0 seconds

        self.vii_cube:
            Has extra coordinate of length(3) "threshold" containing
            points [0.5, 1., 2.] kg m-2.
        """
        (_, self.fg_cube, _, _, self.ice_cube) = (set_up_lightning_test_cubes(
            validity_time=dt(2015, 11, 23, 7), fg_frt=dt(2015, 11, 23, 7)))
        self.plugin = Plugin()
        self.ice_threshold_coord = find_threshold_coordinate(self.ice_cube)
Exemple #30
0
 def test_ordering_for_realization_threshold_percentile_over_coordinate(
         self):
     """Test that the cube has been reordered, if it is originally in an
     undesirable order and the cube contains a "threshold" coordinate,
     a "realization" coordinate and a "percentile_over" coordinate."""
     cube = set_up_probability_cube(
         np.zeros((3, 4, 5), dtype=np.float32),
         np.array([273., 274., 275.], dtype=np.float32))
     cube = add_coordinate(cube, [0, 1, 2], "realization")
     cube = add_coordinate(cube, [10, 50, 90],
                           "percentile_over_neighbourhood")
     cube.transpose([4, 3, 2, 1, 0])
     save_netcdf(cube, self.filepath)
     result = load_cube(self.filepath)
     threshold_coord = find_threshold_coordinate(result)
     self.assertEqual(result.coord_dims("realization")[0], 0)
     self.assertEqual(
         result.coord_dims("percentile_over_neighbourhood")[0], 1)
     self.assertEqual(result.coord_dims(threshold_coord)[0], 2)
     self.assertArrayAlmostEqual(result.coord_dims("latitude")[0], 3)
     self.assertArrayAlmostEqual(result.coord_dims("longitude")[0], 4)