def test_ice_large_with_fc(self):
     """Test that large VII probs do increase zero lightning risk when
     forecast lead time is non-zero (three forecast_period points)"""
     self.ice_cube.data[:, 1, 1] = 1.0
     self.fg_cube.data[1, 1] = 0.0
     frt_point = self.fg_cube.coord("forecast_reference_time").points[0]
     fg_cube_input = CubeList([])
     for fc_time in np.array([1, 2.5, 3]) * 3600:  # seconds
         fg_cube_next = self.fg_cube.copy()
         fg_cube_next.coord("time").points = [frt_point + fc_time]
         fg_cube_next.coord("forecast_period").points = [fc_time]
         fg_cube_input.append(squeeze(fg_cube_next))
     fg_cube_input = fg_cube_input.merge_cube()
     expected = fg_cube_input.copy()
     # expected.data contains all ones except:
     expected.data[0, 1, 1] = 0.54
     expected.data[1, 1, 1] = 0.0
     expected.data[2, 1, 1] = 0.0
     result = self.plugin.apply_ice(fg_cube_input, self.ice_cube)
     self.assertArrayAlmostEqual(result.data, expected.data)
Exemple #2
0
class Test__create_template_slice(IrisTest):
    """Test create_template_slice method"""
    def setUp(self):
        """
        Set up a basic input cube. 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)
        self.plugin = SpatiallyVaryingWeightsFromMask(
            "forecast_reference_time")

    def test_multi_dim_blend_coord_fail(self):
        """Test error is raised when we have a multi-dimensional blend_coord"""
        # Add a surface altitude coordinate which covers x and y dimensions.
        altitudes = np.array([[10, 20, 30], [20, 30, 10]])
        altitudes_coord = AuxCoord(altitudes,
                                   standard_name="surface_altitude",
                                   units="m")
        self.cube_to_collapse.add_aux_coord(altitudes_coord, data_dims=(2, 3))
        message = "Blend coordinate must only be across one dimension."
        plugin = SpatiallyVaryingWeightsFromMask("surface_altitude")
        with self.assertRaisesRegex(ValueError, message):
            plugin._create_template_slice(self.cube_to_collapse)

    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"
        plugin = SpatiallyVaryingWeightsFromMask(threshold_coord.name())
        with self.assertRaisesRegex(ValueError, message):
            plugin._create_template_slice(self.cube_to_collapse)

    def test_scalar_blend_coord_fail(self):
        """Test error is raised when blend_coord is scalar"""
        message = "Blend coordinate must only be across one dimension."
        with self.assertRaisesRegex(ValueError, message):
            self.plugin._create_template_slice(self.cube_to_collapse[0])

    def test_basic(self):
        """Test a correct template slice is returned for simple case"""
        expected = self.cube_to_collapse.copy()[:, 0, :, :]
        result = self.plugin._create_template_slice(self.cube_to_collapse)
        self.assertEqual(expected.metadata, result.metadata)
        self.assertArrayAlmostEqual(expected.data, result.data)

    def test_basic_no_change(self):
        """Test a correct template slice is returned for a case where
           no slicing is needed"""
        input_cube = self.cube_to_collapse.copy()[:, 0, :, :]
        expected = input_cube.copy()
        result = self.plugin._create_template_slice(input_cube)
        self.assertEqual(expected.metadata, result.metadata)
        self.assertArrayAlmostEqual(expected.data, result.data)

    def test_aux_blending_coord(self):
        """Test a correct template slice is returned when blending_coord is
           an AuxCoord"""
        expected = self.cube_to_collapse.copy()[:, 0, :, :]
        plugin = SpatiallyVaryingWeightsFromMask("forecast_period")
        result = self.plugin._create_template_slice(self.cube_to_collapse)
        self.assertEqual(expected.metadata, result.metadata)
        self.assertArrayAlmostEqual(expected.data, result.data)
Exemple #3
0
class Test_apply_ice(IrisTest):
    """Test the apply_ice method."""
    def setUp(self):
        """Create cubes with a single zero prob(precip) point.
        The cubes look like this:
        precipitation_amount / (kg m^-2)
        Dimension coordinates:
            time: 1;
            projection_y_coordinate: 3;
            projection_x_coordinate: 3;
        Auxiliary coordinates:
            forecast_period (on time coord): 0.0 hours (simulates nowcast data)
        Scalar coordinates:
            forecast_reference_time: 2015-11-23 03:00:00
        Data:
        self.fg_cube:
            All points contain float(1.)
            Cube name is "probability_of_lightning".
        self.ice_cube:
            With extra coordinate of length(3) "threshold" containing
            points [0.5, 1., 2.] kg m^-2.
            Time and forecast_period dimensions "sqeezed" to be Scalar coords.
            All points contain float(0.)
            Cube name is "probability_of_vertical_integral_of_ice".
        """
        self.fg_cube = add_forecast_reference_time_and_forecast_period(
            set_up_cube_with_no_realizations(zero_point_indices=[],
                                             num_grid_points=3),
            fp_point=0.0)
        self.fg_cube.rename("probability_of_lightning")
        self.ice_cube = squeeze(
            add_forecast_reference_time_and_forecast_period(set_up_cube(
                num_realization_points=3,
                zero_point_indices=[],
                num_grid_points=3),
                                                            fp_point=0.0))
        threshold_coord = self.ice_cube.coord('realization')
        threshold_coord.points = [0.5, 1.0, 2.0]
        threshold_coord.rename('threshold')
        threshold_coord.units = cf_units.Unit('kg m^-2')
        self.ice_cube.data = np.zeros_like(self.ice_cube.data)
        self.ice_cube.rename("probability_of_vertical_integral_of_ice")
        self.plugin = Plugin()

    def test_basic(self):
        """Test that the method returns the expected cube type"""
        result = self.plugin.apply_ice(self.fg_cube, self.ice_cube)
        self.assertIsInstance(result, Cube)

    def test_input(self):
        """Test that the method does not modify the input cubes."""
        cube_a = self.fg_cube.copy()
        cube_b = self.ice_cube.copy()
        self.plugin.apply_ice(cube_a, cube_b)
        self.assertArrayAlmostEqual(cube_a.data, self.fg_cube.data)
        self.assertArrayAlmostEqual(cube_b.data, self.ice_cube.data)

    def test_missing_threshold_low(self):
        """Test that the method raises an error if the ice_cube doesn't
        have a threshold coordinate for 0.5."""
        self.ice_cube.coord('threshold').points = [0.4, 1., 2.]
        msg = (r"No matching prob\(Ice\) cube for threshold 0.5")
        with self.assertRaisesRegex(ConstraintMismatchError, msg):
            self.plugin.apply_ice(self.fg_cube, self.ice_cube)

    def test_missing_threshold_mid(self):
        """Test that the method raises an error if the ice_cube doesn't
        have a threshold coordinate for 1.0."""
        self.ice_cube.coord('threshold').points = [0.5, 0.9, 2.]
        msg = (r"No matching prob\(Ice\) cube for threshold 1.")
        with self.assertRaisesRegex(ConstraintMismatchError, msg):
            self.plugin.apply_ice(self.fg_cube, self.ice_cube)

    def test_missing_threshold_high(self):
        """Test that the method raises an error if the ice_cube doesn't
        have a threshold coordinate for 2.0."""
        self.ice_cube.coord('threshold').points = [0.5, 1., 4.]
        msg = (r"No matching prob\(Ice\) cube for threshold 2.")
        with self.assertRaisesRegex(ConstraintMismatchError, msg):
            self.plugin.apply_ice(self.fg_cube, self.ice_cube)

    def test_ice_null(self):
        """Test that small VII probs do not increase moderate lightning risk"""
        self.ice_cube.data[:, 1, 1] = 0.
        self.ice_cube.data[0, 1, 1] = 0.5
        self.fg_cube.data[0, 1, 1] = 0.25
        expected = self.fg_cube.copy()
        # expected.data contains all ones except:
        expected.data[0, 1, 1] = 0.25
        result = self.plugin.apply_ice(self.fg_cube, self.ice_cube)
        self.assertArrayAlmostEqual(result.data, expected.data)

    def test_ice_zero(self):
        """Test that zero VII probs do not increase zero lightning risk"""
        self.ice_cube.data[:, 1, 1] = 0.
        self.fg_cube.data[0, 1, 1] = 0.
        expected = self.fg_cube.copy()
        # expected.data contains all ones except:
        expected.data[0, 1, 1] = 0.
        result = self.plugin.apply_ice(self.fg_cube, self.ice_cube)
        self.assertArrayAlmostEqual(result.data, expected.data)

    def test_ice_small(self):
        """Test that small VII probs do increase zero lightning risk"""
        self.ice_cube.data[:, 1, 1] = 0.
        self.ice_cube.data[0, 1, 1] = 0.5
        self.fg_cube.data[0, 1, 1] = 0.
        expected = self.fg_cube.copy()
        # expected.data contains all ones except:
        expected.data[0, 1, 1] = 0.05
        result = self.plugin.apply_ice(self.fg_cube, self.ice_cube)
        self.assertArrayAlmostEqual(result.data, expected.data)

    def test_ice_large(self):
        """Test that large VII probs do increase zero lightning risk"""
        self.ice_cube.data[:, 1, 1] = 1.
        self.fg_cube.data[0, 1, 1] = 0.
        expected = self.fg_cube.copy()
        # expected.data contains all ones except:
        expected.data[0, 1, 1] = 0.9
        result = self.plugin.apply_ice(self.fg_cube, self.ice_cube)
        self.assertArrayAlmostEqual(result.data, expected.data)

    def test_ice_large_with_fc(self):
        """Test that large VII probs do increase zero lightning risk when
        forecast lead time is non-zero (two forecast_period points)"""
        self.ice_cube.data[:, 1, 1] = 1.
        self.fg_cube.data[0, 1, 1] = 0.
        self.fg_cube.coord('forecast_period').points = [1.]  # hours
        fg_cube_next = self.fg_cube.copy()
        time_pt, = self.fg_cube.coord('time').points
        fg_cube_next.coord('time').points = [time_pt + 2.]  # hours
        fg_cube_next.coord('forecast_period').points = [3.]  # hours
        self.fg_cube = CubeList([squeeze(self.fg_cube),
                                 squeeze(fg_cube_next)]).merge_cube()
        expected = self.fg_cube.copy()
        # expected.data contains all ones except:
        expected.data[0, 1, 1] = 0.54
        expected.data[1, 1, 1] = 0.0
        result = self.plugin.apply_ice(self.fg_cube, self.ice_cube)
        self.assertArrayAlmostEqual(result.data, expected.data)
Exemple #4
0
class Test_apply_ice(IrisTest):
    """Test the apply_ice method."""
    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)

    def test_basic(self):
        """Test that the method returns the expected cube type"""
        result = self.plugin.apply_ice(self.fg_cube, self.ice_cube)
        self.assertIsInstance(result, Cube)

    def test_input(self):
        """Test that the method does not modify the input cubes."""
        cube_a = self.fg_cube.copy()
        cube_b = self.ice_cube.copy()
        self.plugin.apply_ice(cube_a, cube_b)
        self.assertArrayAlmostEqual(cube_a.data, self.fg_cube.data)
        self.assertArrayAlmostEqual(cube_b.data, self.ice_cube.data)

    def test_missing_threshold_low(self):
        """Test that the method raises an error if the ice_cube doesn't
        have a threshold coordinate for 0.5."""
        self.ice_threshold_coord.points = [0.4, 1., 2.]
        msg = (r"No matching prob\(Ice\) cube for threshold 0.5")
        with self.assertRaisesRegex(ConstraintMismatchError, msg):
            self.plugin.apply_ice(self.fg_cube, self.ice_cube)

    def test_missing_threshold_mid(self):
        """Test that the method raises an error if the ice_cube doesn't
        have a threshold coordinate for 1.0."""
        self.ice_threshold_coord.points = [0.5, 0.9, 2.]
        msg = (r"No matching prob\(Ice\) cube for threshold 1.")
        with self.assertRaisesRegex(ConstraintMismatchError, msg):
            self.plugin.apply_ice(self.fg_cube, self.ice_cube)

    def test_missing_threshold_high(self):
        """Test that the method raises an error if the ice_cube doesn't
        have a threshold coordinate for 2.0."""
        self.ice_threshold_coord.points = [0.5, 1., 4.]
        msg = (r"No matching prob\(Ice\) cube for threshold 2.")
        with self.assertRaisesRegex(ConstraintMismatchError, msg):
            self.plugin.apply_ice(self.fg_cube, self.ice_cube)

    def test_ice_null(self):
        """Test that small VII probs do not increase moderate lightning risk"""
        self.ice_cube.data[:, 1, 1] = 0.
        self.ice_cube.data[0, 1, 1] = 0.5
        self.fg_cube.data[1, 1] = 0.25
        expected = self.fg_cube.copy()
        # expected.data contains all ones except:
        expected.data[1, 1] = 0.25
        result = self.plugin.apply_ice(self.fg_cube, self.ice_cube)
        self.assertArrayAlmostEqual(result.data, expected.data)

    def test_ice_zero(self):
        """Test that zero VII probs do not increase zero lightning risk"""
        self.ice_cube.data[:, 1, 1] = 0.
        self.fg_cube.data[1, 1] = 0.
        expected = self.fg_cube.copy()
        # expected.data contains all ones except:
        expected.data[1, 1] = 0.
        result = self.plugin.apply_ice(self.fg_cube, self.ice_cube)
        self.assertArrayAlmostEqual(result.data, expected.data)

    def test_ice_small(self):
        """Test that small VII probs do increase zero lightning risk"""
        self.ice_cube.data[:, 1, 1] = 0.
        self.ice_cube.data[0, 1, 1] = 0.5
        self.fg_cube.data[1, 1] = 0.
        expected = self.fg_cube.copy()
        # expected.data contains all ones except:
        expected.data[1, 1] = 0.05
        result = self.plugin.apply_ice(self.fg_cube, self.ice_cube)
        self.assertArrayAlmostEqual(result.data, expected.data)

    def test_ice_large(self):
        """Test that large VII probs do increase zero lightning risk"""
        self.ice_cube.data[:, 1, 1] = 1.
        self.fg_cube.data[1, 1] = 0.
        expected = self.fg_cube.copy()
        # expected.data contains all ones except:
        expected.data[1, 1] = 0.9
        result = self.plugin.apply_ice(self.fg_cube, self.ice_cube)
        self.assertArrayAlmostEqual(result.data, expected.data)

    def test_ice_large_with_fc(self):
        """Test that large VII probs do increase zero lightning risk when
        forecast lead time is non-zero (two forecast_period points)"""
        self.ice_cube.data[:, 1, 1] = 1.
        self.fg_cube.data[1, 1] = 0.
        self.fg_cube.coord('forecast_period').points = [3600]  # 1 hour
        fg_cube_next = self.fg_cube.copy()
        time_pt, = self.fg_cube.coord('time').points
        fg_cube_next.coord('time').points = [time_pt + 7200]  # 2 hours
        fg_cube_next.coord('forecast_period').points = [10800]  # 3 hours
        self.fg_cube = CubeList([squeeze(self.fg_cube),
                                 squeeze(fg_cube_next)]).merge_cube()
        expected = self.fg_cube.copy()
        # expected.data contains all ones except:
        expected.data[0, 1, 1] = 0.54
        expected.data[1, 1, 1] = 0.0
        result = self.plugin.apply_ice(self.fg_cube, self.ice_cube)
        self.assertArrayAlmostEqual(result.data, expected.data)