Example #1
0
 def test_below_threshold_without_fuzzy_factor(self):
     """Test if the fixed threshold is above the value in the data."""
     plugin = Threshold(0.6)
     result = plugin.process(self.cube)
     expected_result_array = np.zeros_like(self.cube.data).reshape(
         1, 1, 5, 5)
     self.assertArrayAlmostEqual(result.data, expected_result_array)
Example #2
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:
            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,
                comparison_operator=self.comparison_operator,
            )(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
Example #3
0
 def test_threshold_fuzzy_miss_high_threshold(self):
     """Test when a point is not within the fuzzy high threshold area."""
     plugin = Threshold(3.0, fuzzy_factor=self.fuzzy_factor)
     result = plugin.process(self.cube)
     expected_result_array = np.zeros_like(self.cube.data).reshape(
         1, 1, 5, 5)
     self.assertArrayAlmostEqual(result.data, expected_result_array)
class Test__add_threshold_coord(IrisTest):
    """Test the _add_threshold_coord method"""

    def setUp(self):
        """Set up a cube and plugin for testing."""
        self.cube = set_up_variable_cube(np.ones((3, 3), dtype=np.float32))
        self.plugin = Threshold([1])
        self.plugin.threshold_coord_name = self.cube.name()

    def test_basic(self):
        """Test a scalar threshold coordinate is created"""
        result = self.plugin._add_threshold_coord(self.cube, 1)
        self.assertEqual(result.ndim, 3)
        self.assertIn("air_temperature", [coord.standard_name for coord in
                                          result.coords(dim_coords=True)])
        threshold_coord = result.coord("air_temperature")
        self.assertEqual(threshold_coord.var_name, "threshold")
        self.assertEqual(threshold_coord.attributes,
                         {"spp__relative_to_threshold": "above"})
        self.assertAlmostEqual(threshold_coord.points[0], 1)
        self.assertEqual(threshold_coord.units, self.cube.units)

    def test_long_name(self):
        """Test coordinate is created with non-standard diagnostic name"""
        self.cube.rename("sky_temperature")
        self.plugin.threshold_coord_name = self.cube.name()
        result = self.plugin._add_threshold_coord(self.cube, 1)
        self.assertIn("sky_temperature", [coord.long_name for coord in
                                          result.coords(dim_coords=True)])

    def test_value_error(self):
        """Test method catches ValueErrors unrelated to name, by passing it a
        list of values where a scalar is required"""
        with self.assertRaises(ValueError):
            self.plugin._add_threshold_coord(self.cube, [1, 1])
Example #5
0
 def test_basic(self):
     """Test that the plugin returns an iris.cube.Cube."""
     fuzzy_factor = 0.95
     threshold = 0.1
     plugin = Threshold(threshold, fuzzy_factor=fuzzy_factor)
     result = plugin.process(self.cube)
     self.assertIsInstance(result, Cube)
Example #6
0
 def test_threshold_dimension_added(self):
     """Test that a threshold dimension coordinate is added."""
     plugin = Threshold(0.1)
     result = plugin.process(self.cube)
     expected_coord = DimCoord([0.1], long_name='threshold',
                               units=self.cube.units)
     self.assertEqual(result.coord('threshold'), expected_coord)
Example #7
0
 def test_threshold_below_fuzzy_miss(self):
     """Test not meeting the threshold in fuzzy below-threshold-mode."""
     plugin = Threshold(
         2.0, fuzzy_factor=self.fuzzy_factor, below_thresh_ok=True)
     result = plugin.process(self.cube)
     expected_result_array = np.ones_like(self.cube.data).reshape(
         1, 1, 5, 5)
     self.assertArrayAlmostEqual(result.data, expected_result_array)
Example #8
0
 def test_threshold_fuzzy(self):
     """Test when a point is in the fuzzy threshold area."""
     plugin = Threshold(0.6, fuzzy_factor=self.fuzzy_factor)
     result = plugin.process(self.cube)
     expected_result_array = np.zeros_like(self.cube.data).reshape(
         1, 1, 5, 5)
     expected_result_array[0][0][2][2] = 1.0/3.0
     self.assertArrayAlmostEqual(result.data, expected_result_array)
Example #9
0
 def test_threshold_asymmetric_bounds_below(self):
     """Test when a point is below asymmetric fuzzy threshold area."""
     bounds = (0.51, 0.9)
     plugin = Threshold(0.6, fuzzy_bounds=bounds)
     result = plugin.process(self.cube)
     expected_result_array = np.zeros_like(self.cube.data).reshape(
         1, 1, 5, 5)
     self.assertArrayAlmostEqual(result.data, expected_result_array)
Example #10
0
    def correct_where_input_true(self, selector_val):
        """
        Replace points in the output_cube where output_land matches the
        selector_val and the input_land does not match, but has matching
        points in the vicinity, with the nearest matching point in the
        vicinity in the original nearest_cube.

        Updates self.output_cube.data

        Args:
            selector_val (int):
                Value of mask to replace if needed.
                Intended to be 1 for filling land points near the coast
                and 0 for filling sea points near the coast.
        """
        # Find all points on output grid matching selector_val
        use_points = np.where(self.input_land.data == selector_val)

        # If there are no matching points on the input grid, no alteration can
        # be made. This tests the size of the y-coordinate of use_points.
        if use_points[0].size is 0:
            return

        # Get shape of output grid
        ynum, xnum = self.output_land.shape

        # Using only these points, extrapolate to fill domain using nearest
        # neighbour. This will generate a grid where the non-selector_val
        # points are filled with the nearest value in the same mask
        # classification.
        (y_points, x_points) = np.mgrid[0:ynum, 0:xnum]
        selector_data = griddata(
            use_points,
            self.nearest_cube.data[use_points],
            (y_points, x_points),
            method="nearest",
        )

        # Identify nearby points on regridded input_land that match the
        # selector_value
        if selector_val > 0.5:
            thresholder = BasicThreshold(0.5)
        else:
            thresholder = BasicThreshold(0.5, comparison_operator="<=")
        in_vicinity = self.vicinity(thresholder(self.input_land))

        # Identify those points sourced from the opposite mask that are
        # close to a source point of the correct mask
        mismatch_points = np.logical_and(
            np.logical_and(
                self.output_land.data == selector_val,
                self.input_land.data != selector_val,
            ),
            in_vicinity.data > 0.5,
        )

        # Replace these points with the filled-domain data
        self.output_cube.data[mismatch_points] = selector_data[mismatch_points]
Example #11
0
 def test_threshold_asymmetric_bounds_above(self):
     """Test when a point is above asymmetric fuzzy threshold area."""
     bounds = (0.0, 0.45)
     plugin = Threshold(0.4, fuzzy_bounds=bounds)
     result = plugin.process(self.cube)
     expected_result_array = np.zeros_like(self.cube.data).reshape(
         1, 1, 5, 5)
     expected_result_array[0][0][2][2] = 1.
     self.assertArrayAlmostEqual(result.data, expected_result_array)
Example #12
0
 def test_threshold_boundingbelowzero(self):
     """Test fuzzy threshold of below-zero."""
     bounds = (-1.0, 1.0)
     plugin = Threshold(0.0, fuzzy_bounds=bounds, below_thresh_ok=True)
     result = plugin.process(self.cube)
     expected_result_array = np.full_like(
         self.cube.data, fill_value=0.5).reshape(1, 1, 5, 5)
     expected_result_array[0][0][2][2] = 0.25
     self.assertArrayAlmostEqual(result.data, expected_result_array)
Example #13
0
 def test_threshold_boundingzero_above(self):
     """Test fuzzy threshold of zero where data are above upper-bound."""
     bounds = (-0.1, 0.1)
     plugin = Threshold(0.0, fuzzy_bounds=bounds)
     result = plugin.process(self.cube)
     expected_result_array = np.full_like(
         self.cube.data, fill_value=0.5).reshape(1, 1, 5, 5)
     expected_result_array[0][0][2][2] = 1.
     self.assertArrayAlmostEqual(result.data, expected_result_array)
Example #14
0
 def test_threshold_negative(self):
     """Test a point when the threshold is negative."""
     plugin = Threshold(-1.0,
                        fuzzy_factor=self.fuzzy_factor,
                        below_thresh_ok=True)
     result = plugin.process(self.cube)
     expected_result_array = np.ones_like(self.cube.data).reshape(
         1, 1, 5, 5)
     self.assertArrayAlmostEqual(result.data, expected_result_array)
Example #15
0
 def test_threshold_below_fuzzy(self):
     """Test a point in fuzzy threshold in below-threshold-mode."""
     plugin = Threshold(
         0.6, fuzzy_factor=self.fuzzy_factor, below_thresh_ok=True)
     result = plugin.process(self.cube)
     expected_result_array = np.ones_like(self.cube.data).reshape(
         1, 1, 5, 5)
     expected_result_array[0][0][2][2] = 2.0/3.0
     self.assertArrayAlmostEqual(result.data, expected_result_array)
Example #16
0
 def test_above_threshold_without_fuzzy_factor(self):
     """Test if the fixed threshold is below the value in the data."""
     # Copy the cube as the cube.data is used as the basis for comparison.
     cube = self.cube.copy()
     plugin = Threshold(0.1)
     result = plugin.process(cube)
     expected_result_array = self.cube.data.reshape(1, 1, 5, 5)
     expected_result_array[0][0][2][2] = 1.0
     self.assertArrayAlmostEqual(result.data, expected_result_array)
Example #17
0
 def test_threshold_point_nan(self):
     """Test behaviour for a single NaN grid cell."""
     # Need to copy the cube as we're adjusting the data.
     self.cube.data[0][2][2] = np.NAN
     msg = "NaN detected in input cube data"
     plugin = Threshold(
         2.0, fuzzy_factor=self.fuzzy_factor, below_thresh_ok=True)
     with self.assertRaisesRegex(ValueError, msg):
         plugin.process(self.cube)
Example #18
0
 def test_threshold_asymmetric_bounds_upper_below(self):
     """Test when a point is in upper asymmetric fuzzy threshold area
     and below-threshold is requested."""
     bounds = (0.0, 0.6)
     plugin = Threshold(0.4, fuzzy_bounds=bounds, below_thresh_ok=True)
     result = plugin.process(self.cube)
     expected_result_array = np.ones_like(self.cube.data).reshape(
         1, 1, 5, 5)
     expected_result_array[0][0][2][2] = 0.25
     self.assertArrayAlmostEqual(result.data, expected_result_array)
Example #19
0
 def test_threshold_asymmetric_bounds_middle(self):
     """Test when a point is on the threshold with asymmetric fuzzy
     bounds."""
     bounds = (0.4, 0.9)
     plugin = Threshold(0.5, fuzzy_bounds=bounds)
     result = plugin.process(self.cube)
     expected_result_array = np.zeros_like(self.cube.data).reshape(
         1, 1, 5, 5)
     expected_result_array[0][0][2][2] = 0.5
     self.assertArrayAlmostEqual(result.data, expected_result_array)
Example #20
0
 def test_threshold(self):
     """Test the basic threshold functionality."""
     # Copy the cube as the cube.data is used as the basis for comparison.
     cube = self.cube.copy()
     fuzzy_factor = 0.95
     plugin = Threshold(0.1, fuzzy_factor=fuzzy_factor)
     result = plugin.process(cube)
     # The single 0.5-valued point => 1.0, so cheat by * 2.0 vs orig data.
     expected_result_array = (self.cube.data * 2.0).reshape(1, 1, 5, 5)
     self.assertArrayAlmostEqual(result.data, expected_result_array)
Example #21
0
 def test_threshold_unit_conversion(self):
     """Test data are correctly thresholded when the threshold is given in
     units different from that of the input cube.  In this test two
     thresholds (of 4 and 6 mm/h) are used on a 5x5 cube where the
     central data point value is 1.39e-6 m/s (~ 5 mm/h)."""
     expected_result_array = np.zeros((2, 5, 5))
     expected_result_array[0][2][2] = 1.
     plugin = Threshold([4.0, 6.0], threshold_units='mm h-1')
     result = plugin.process(self.rate_cube)
     self.assertArrayAlmostEqual(result.data, expected_result_array)
Example #22
0
 def test_masked_array_fuzzybounds(self):
     """Test masked array are handled correctly when using fuzzy bounds.
     Masked values are preserved following thresholding."""
     bounds = (0.6 * self.fuzzy_factor, 0.6 * (2. - self.fuzzy_factor))
     plugin = Threshold(0.6, fuzzy_bounds=bounds)
     result = plugin.process(self.masked_cube)
     expected_result_array = self.masked_cube.data.reshape((1, 1, 5, 5))
     expected_result_array[0][0][2][2] = 1.0/3.0
     self.assertArrayAlmostEqual(result.data.data, expected_result_array)
     self.assertArrayEqual(
         result.data.mask, self.masked_cube.data.mask.reshape((1, 1, 5, 5)))
Example #23
0
 def test_data_precision_preservation(self):
     """Test that the plugin returns an iris.cube.Cube of the same float
     precision as the input cube."""
     threshold = 0.1
     plugin = Threshold(threshold, fuzzy_factor=self.fuzzy_factor)
     f64cube = self.cube.copy(data=self.cube.data.astype(np.float64))
     f32cube = self.cube.copy(data=self.cube.data.astype(np.float32))
     f64result = plugin.process(f64cube)
     f32result = plugin.process(f32cube)
     self.assertEqual(f64cube.dtype, f64result.dtype)
     self.assertEqual(f32cube.dtype, f32result.dtype)
Example #24
0
 def test_threshold_negative(self):
     """Test a point when the threshold is negative."""
     self.cube.data[0][2][2] = -0.75
     plugin = Threshold(-1.0,
                        fuzzy_factor=self.fuzzy_factor,
                        comparison_operator='<')
     result = plugin.process(self.cube)
     expected_result_array = np.zeros_like(self.cube.data).reshape(
         1, 1, 5, 5)
     expected_result_array[0][0][2][2] = 0.25
     self.assertArrayAlmostEqual(result.data, expected_result_array)
Example #25
0
 def test_threshold_unit_conversion_fuzzy_factor(self):
     """Test for sensible fuzzy factor behaviour when units of threshold
     are different from input cube.  A fuzzy factor of 0.75 is equivalent
     to bounds +/- 25% around the threshold in the given units.  So for a
     threshold of 4 (6) mm/h, the thresholded exceedance probabilities
     increase linearly from 0 at 3 (4.5) mm/h to 1 at 5 (7.5) mm/h."""
     expected_result_array = np.zeros((2, 5, 5))
     expected_result_array[0][2][2] = 1.
     expected_result_array[1][2][2] = 0.168
     plugin = Threshold([4.0, 6.0], threshold_units='mm h-1',
                        fuzzy_factor=0.75)
     result = plugin.process(self.rate_cube)
     self.assertArrayAlmostEqual(result.data, expected_result_array)
Example #26
0
 def test_multiple_thresholds(self):
     """Test multiple thresholds applied to the cube return a single cube
     with multiple arrays corresponding to each threshold."""
     thresholds = [0.2, 0.4, 0.6]
     plugin = Threshold(thresholds)
     result = plugin.process(self.cube)
     expected_array12 = np.zeros_like(self.cube.data).reshape(1, 1, 5, 5)
     expected_array12[0][0][2][2] = 1.
     expected_array3 = expected_array12 * 0.
     expected_result_array = np.vstack(
         [expected_array12, expected_array12, expected_array3])
     self.assertIsInstance(result, Cube)
     self.assertArrayAlmostEqual(result.data, expected_result_array)
Example #27
0
 def test_data_type_change_for_ints(self):
     """Test that the plugin returns an iris.cube.Cube of float32 type
     if the input cube is of int type. This allows fuzzy bounds to be used
     which return fractional values."""
     fuzzy_factor = 5./6.
     threshold = 12
     self.cube.data = np.arange(25).reshape(1, 5, 5)
     plugin = Threshold(threshold, fuzzy_factor=fuzzy_factor)
     result = plugin.process(self.cube)
     expected = np.round(np.arange(0, 1, 1./25.)).reshape(1, 1, 5, 5)
     expected[0, 0, 2, 1:4] = [0.25, 0.5, 0.75]
     self.assertEqual(result.dtype, 'float32')
     self.assertArrayEqual(result.data, expected)
Example #28
0
 def test_multiple_thresholds(self):
     """Test multiple thresholds applied to the cube return a single cube
     with multiple arrays corresponding to each threshold."""
     thresholds = [0.2, 0.4, 0.6]
     plugin = Threshold(thresholds)
     result = plugin.process(self.cube)
     all_zeroes = np.zeros_like(self.cube.data).reshape(1, 1, 5, 5)
     one_exceed_point = all_zeroes.copy()
     one_exceed_point[0][0][2][2] = 1.
     expected_result_array = np.vstack(
         [one_exceed_point, one_exceed_point, all_zeroes])
     # transpose array to reflect realization coordinate re-ordering
     expected_result_array = np.transpose(expected_result_array,
                                          [1, 0, 2, 3])
     self.assertIsInstance(result, Cube)
     self.assertArrayAlmostEqual(result.data, expected_result_array)
Example #29
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('threshold'):
                threshold_cube = cube_slice

            cubes.append(threshold_cube)
        return cubes
Example #30
0
 def test_threshold_le(self):
     """Test a point when we are in le threshold mode."""
     plugin = Threshold(0.5, comparison_operator='<=')
     name = "probability_of_{}_below_threshold"
     expected_name = name.format(self.cube.name())
     expected_attribute = "below"
     result = plugin.process(self.cube)
     expected_result_array = np.ones_like(self.cube.data).reshape(
         1, 1, 5, 5)
     expected_result_array[0][0][2][2] = 1
     self.assertEqual(result.name(), expected_name)
     self.assertEqual(
         result.coord(
             var_name="threshold").attributes['spp__relative_to_threshold'],
         expected_attribute)
     self.assertArrayAlmostEqual(result.data, expected_result_array)