示例#1
0
 def test_exception_using_allowed_dt_difference(self):
     """Test that an exception is raised, if the time point is outside of
     the allowed difference specified in seconds."""
     time_point = datetime(2017, 11, 23, 6, 0)
     msg = "is not available within the input cube"
     with self.assertRaisesRegex(ValueError, msg):
         extract_nearest_time_point(self.cube, time_point,
                                    allowed_dt_difference=3600)
示例#2
0
 def test_time_name_exception(self):
     """Test that an exception is raised, if an invalid time name
     is specified."""
     time_point = datetime(2017, 11, 23, 6, 0)
     msg = "The time_name must be either " "'time' or 'forecast_reference_time'"
     with self.assertRaisesRegex(ValueError, msg):
         extract_nearest_time_point(self.cube,
                                    time_point,
                                    time_name="forecast_period")
示例#3
0
    def _select_orographic_enhancement_cube(
            precip_cube: Cube,
            oe_cube: Cube,
            allowed_time_diff: int = 1800) -> Cube:
        """Select the orographic enhancement cube with the required time
        coordinate.

        Args:
            precip_cube:
                Cube containing the input precipitation fields.
            oe_cube:
                Cube containing orographic enhancement fields at one or
                more times.
            allowed_time_diff:
                The maximum permitted difference, in integer seconds,
                between the datetime of the precipitation cube and the time
                points available within the orographic enhancement cube.
                If this limit is exceeded, then an error is raised.


        Returns:
            Cube containing the orographic enhancement field at the
            required time.

        Raises:
            ValueError: If required time step is not available within tolerance
                (in theory.  In practise, the tolerance is left as the default
                None, which matches ANY available field regardless of time
                offset.  So this error will never be thrown.)
        """
        (time_point, ) = iris_time_to_datetime(
            precip_cube.coord("time").copy())
        oe_cube_slice = extract_nearest_time_point(
            oe_cube, time_point, allowed_dt_difference=allowed_time_diff)
        return oe_cube_slice
示例#4
0
    def _select_orographic_enhancement_cube(precip_cube,
                                            oe_cube,
                                            allowed_time_diff=1800):
        """Select the orographic enhancement cube with the required time
        coordinate.

        Args:
            precip_cube (iris.cube.Cube):
                Cube containing the input precipitation fields.
            oe_cube (iris.cube.Cube):
                Cube containing orographic enhancement fields at one or
                more times.
            allowed_time_diff (int):
                The maximum permitted difference, in integer seconds,
                between the datetime of the precipitation cube and the time
                points available within the orographic enhancement cube.
                If this limit is exceeded, then an error is raised.


        Returns:
            iris.cube.Cube:
                Cube containing the orographic enhancement field at the
                required time.

        """
        (time_point, ) = iris_time_to_datetime(
            precip_cube.coord("time").copy())
        oe_cube_slice = extract_nearest_time_point(
            oe_cube, time_point, allowed_dt_difference=allowed_time_diff)
        return oe_cube_slice
示例#5
0
 def test_time_coord_upper_case(self):
     """Test that the nearest time point within the time coordinate is
     extracted, when a time of 07:31 is requested."""
     expected = self.cube[:, 1, :, :]
     time_point = datetime.datetime(2015, 11, 23, 7, 31)
     result = extract_nearest_time_point(self.cube, time_point)
     self.assertEqual(result, expected)
示例#6
0
 def test_time_coord(self):
     """Test that the nearest time point within the time coordinate is
     extracted."""
     expected = self.cube[:, 0, :, :]
     time_point = datetime.datetime(2015, 11, 23, 6, 0)
     result = extract_nearest_time_point(self.cube, time_point)
     self.assertEqual(result, expected)
示例#7
0
    def _select_orographic_enhancement_cube(precip_cube,
                                            oe_cubes,
                                            allowed_time_diff=1800):
        """Select the orographic enhancement cube with the required time
        coordinate.

        Args:
            precip_cube (iris.cube.Cube):
                Cube containing the input precipitation fields.
            oe_cubes (iris.cube.Cube or iris.cube.CubeList):
                Cube or CubeList containing the orographic enhancement fields.
            allowed_time_diff (int):
                An int in seconds to define a limit to the maximum difference
                between the datetime of the precipitation cube and the time
                points available within the orographic enhancement cube.
                If this limit is exceeded, then an error is raised.


        Returns:
            iris.cube.Cube:
                Cube containing the orographic enhancement fields at the
                required time.

        """
        time_point, = iris_time_to_datetime(precip_cube.coord("time").copy())
        oe_cube = extract_nearest_time_point(
            oe_cubes, time_point, allowed_dt_difference=allowed_time_diff)
        return oe_cube
示例#8
0
 def test_time_coord_lower_case(self):
     """Test that the nearest time point within the time coordinate is
     extracted, when a time of 07:30 is requested."""
     expected = self.cube[:, 0, :, :]
     time_point = datetime(2015, 11, 23, 7, 30)
     result = extract_nearest_time_point(self.cube, time_point,
                                         allowed_dt_difference=1800)
     self.assertEqual(result, expected)
示例#9
0
 def test_time_coord(self):
     """Test that the nearest time point within the time coordinate is
     extracted."""
     expected = self.cube[:, 0, :, :]
     time_point = datetime(2015, 11, 23, 6, 31)
     result = extract_nearest_time_point(self.cube, time_point,
                                         allowed_dt_difference=1800)
     self.assertEqual(result, expected)
示例#10
0
 def test_forecast_reference_time_coord(self):
     """Test that the nearest time point within the forecast_reference_time
     coordinate is extracted."""
     expected = self.cube
     time_point = datetime.datetime(2015, 11, 23, 6, 0)
     result = extract_nearest_time_point(
         self.cube, time_point, time_name="forecast_reference_time")
     self.assertEqual(result, expected)
示例#11
0
 def test_forecast_reference_time_coord(self):
     """Test that the nearest time point within the forecast_reference_time
     coordinate is extracted."""
     later_frt = self.cube.copy()
     later_frt.coord('forecast_reference_time').points = (
         later_frt.coord('forecast_reference_time').points + 3600)
     cubes = iris.cube.CubeList([self.cube, later_frt])
     cube = cubes.merge_cube()
     expected = self.cube
     time_point = datetime(2015, 11, 23, 3, 29)
     result = extract_nearest_time_point(
         cube, time_point, time_name="forecast_reference_time",
         allowed_dt_difference=1800)
     self.assertEqual(result, expected)
示例#12
0
    def _select_orographic_enhancement_cube(precip_cube, oe_cubes):
        """Select the orographic enhancement cube with the required time
        coordinate.

        Args:
            precip_cube (iris.cube.Cube):
                Cube containing the input precipitation fields.
            oe_cubes (iris.cube.Cube or iris.cube.CubeList):
                Cube or CubeList containing the orographic enhancement fields.

        Returns:
            oe_cube (iris.cube.Cube):
                Cube containing the orographic enhancement fields at the
                required time.

        """
        time_point, = iris_time_to_datetime(precip_cube.coord("time").copy())
        oe_cube = extract_nearest_time_point(oe_cubes, time_point)
        return oe_cube
示例#13
0
    def _modify_first_guess(
        self,
        cube: Cube,
        first_guess_lightning_cube: Cube,
        lightning_rate_cube: Cube,
        prob_precip_cube: Cube,
        prob_vii_cube: Optional[Cube] = None,
    ) -> Cube:
        """
        Modify first-guess lightning probability with nowcast data.

        Args:
            cube:
                Provides the meta-data for the Nowcast lightning probability
                output cube.
            first_guess_lightning_cube:
                First-guess lightning probability.
                Must have same x & y dimensions as cube.
                Time dimension should overlap that of cube (closest slice in
                time is used with a maximum time mismatch of 2 hours).
                This is included to allow this cube to come from a different
                modelling system, such as the UM.
            lightning_rate_cube:
                Nowcast lightning rate.
                Must have same dimensions as cube.
            prob_precip_cube:
                Nowcast precipitation probability (threshold > 0.5, 7, 35).
                Must have same other dimensions as cube.
            prob_vii_cube:
                Radar-derived vertically integrated ice content (VII).
                Must have same x and y dimensions as cube.
                Time should be a scalar coordinate.
                Must have a threshold coordinate with points matching.
                self.vii_thresholds.
                Can be <No cube> or None or anything that evaluates to False.

        Returns:
            Output cube containing Nowcast lightning probability.

        Raises:
            iris.exceptions.ConstraintMismatchError:
                If lightning_rate_cube or first_guess_lightning_cube do not
                contain the expected times.
        """
        new_cube_list = iris.cube.CubeList([])
        # Loop over required forecast validity times
        for cube_slice in cube.slices_over("time"):
            this_time = iris_time_to_datetime(
                cube_slice.coord("time").copy())[0]
            lightning_rate_slice = lightning_rate_cube.extract(
                iris.Constraint(time=this_time))
            err_string = "No matching {} cube for {}"
            if not isinstance(lightning_rate_slice, iris.cube.Cube):
                raise ConstraintMismatchError(
                    err_string.format("lightning", this_time))
            first_guess_slice = extract_nearest_time_point(
                first_guess_lightning_cube,
                this_time,
                allowed_dt_difference=7201)
            first_guess_slice = cube_slice.copy(data=first_guess_slice.data)
            first_guess_slice.coord("forecast_period").convert_units("minutes")
            fcmins = first_guess_slice.coord("forecast_period").points[0]

            # Increase prob(lightning) to Risk 2 (pl_dict[2]) when
            #   lightning nearby (lrt_lev2)
            # (and leave unchanged when condition is not met):
            first_guess_slice.data = np.where(
                (lightning_rate_slice.data >= self.lrt_lev2)
                & (first_guess_slice.data < self.pl_dict[2]),
                self.pl_dict[2],
                first_guess_slice.data,
            )

            # Increase prob(lightning) to Risk 1 (pl_dict[1]) when within
            #   lightning storm (lrt_lev1):
            # (and leave unchanged when condition is not met):
            lratethresh = self.lrt_lev1(fcmins)
            first_guess_slice.data = np.where(
                (lightning_rate_slice.data >= lratethresh)
                & (first_guess_slice.data < self.pl_dict[1]),
                self.pl_dict[1],
                first_guess_slice.data,
            )

            new_cube_list.append(first_guess_slice)

        new_prob_lightning_cube = new_cube_list.merge_cube()
        new_prob_lightning_cube = check_cube_coordinates(
            cube, new_prob_lightning_cube)

        # Apply precipitation adjustments.
        new_prob_lightning_cube = self.apply_precip(new_prob_lightning_cube,
                                                    prob_precip_cube)

        # If we have VII data, increase prob(lightning) accordingly.
        if prob_vii_cube:
            new_prob_lightning_cube = self.apply_ice(new_prob_lightning_cube,
                                                     prob_vii_cube)
        return new_prob_lightning_cube