예제 #1
0
 def test_inverse_order_false(self):
     """ Test setting of inverse_order flag using percentiles_cube. In this
     case the flag should be false as the values associated with the
     percentiles increase in the same direction as the percentiles."""
     plugin_instance = ProbabilitiesFromPercentiles2D(
         self.test_cube, 'new_name')
     self.assertFalse(plugin_instance.inverse_ordering)
예제 #2
0
 def setUp(self):
     """ Set up class instance and orography cube """
     percentiles_cube = set_up_percentiles_cube()
     self.plugin_instance = ProbabilitiesFromPercentiles2D(
         percentiles_cube, 'new_name')
     self.reference_cube = percentiles_cube[0]
     self.orography_cube = set_up_threshold_cube()
def process(percentiles_cube, threshold_cube, output_diagnostic_name):
    """Calculates probability from a percentiled field.

    Plugin generates probabilities at a fixed threshold (height) from a set
    of (height) percentiles.

    Args:
        percentiles_cube (iris.cube.Cube):
            The percentiled field from which probabilities will be obtained
            using the input cube.
            This cube should contain a percentiles dimension, with fields of
            values that correspond to these percentiles. The cube passed to
            the process method will contain values of the same diagnostic.
        threshold_cube (iris.cube.Cube):
            A cube of values that effectively behave as thresholds, for which
            it is desired to obtain probability values from a percentiled
            reference cube.
        output_diagnostic_name (str):
            The name of the cube being created, e.g
            'probability_of_snow_falling_level_below_ground_level'

    Returns:
        iris.cube.Cube:
            A cube of probabilities obtained by interpolating between
            percentile values at the "threshold" level.
    """
    result = ProbabilitiesFromPercentiles2D(percentiles_cube,
                                            output_diagnostic_name)
    probability_cube = result.process(threshold_cube)
    return probability_cube
예제 #4
0
    def test_preservation_of_dimensions(self):
        """Test that if the pecentiles_cube has other dimension coordinates
        over which slicing is performed, that these dimensions are properly
        restored in the resulting probability cube."""
        percentiles_cube = set_up_percentiles_cube()
        test_data = np.array([percentiles_cube.data, percentiles_cube.data])
        percentiles = percentiles_cube.coord('percentiles')
        grid_x = percentiles_cube.coord('projection_x_coordinate')
        grid_y = percentiles_cube.coord('projection_y_coordinate')

        new_model_coord = build_coordinate([0, 1],
                                           long_name='leading_coord',
                                           coord_type=DimCoord,
                                           data_type=int)
        input_cube = iris.cube.Cube(
            test_data, long_name="snow_level", units="m",
            dim_coords_and_dims=[(new_model_coord, 0),
                                 (percentiles, 1),
                                 (grid_y, 2), (grid_x, 3)])

        plugin_instance = ProbabilitiesFromPercentiles2D(
            input_cube, 'new_name')
        probability_cube = plugin_instance.process(self.orography_cube)
        self.assertEqual(input_cube.coords(dim_coords=True)[0],
                         probability_cube.coords(dim_coords=True)[0])
 def test_inverse_order_true(self):
     """ Test setting of inverse_order flag using percentiles_cube. In this
     case the flag should be true as the values associated with the
     percentiles increase in the opposite direction to the percentiles."""
     percentiles_cube = self.test_cube.copy(data=np.flipud(self.test_cube.data))
     plugin_instance = ProbabilitiesFromPercentiles2D(percentiles_cube, "new_name")
     self.assertTrue(plugin_instance.inverse_ordering)
예제 #6
0
 def test_single_percentile(self):
     """Test for sensible behaviour when a percentiles_cube containing a
     single percentile is passed into the plugin."""
     percentiles_cube = set_up_percentiles_cube()
     percentiles_cube = percentiles_cube[0]
     msg = "Percentile coordinate has only one value. Interpolation"
     with self.assertRaisesRegex(ValueError, msg):
         ProbabilitiesFromPercentiles2D(percentiles_cube, 'new_name')
예제 #7
0
    def test_values(self):
        """Test that interpolated probabilities at given topography heights are
        sensible.  Includes out-of-range values (P=0 and P=1)."""
        expected = set_reference_probabilities()

        probability_cube = ProbabilitiesFromPercentiles2D(
            self.percentiles_cube, 'new_name').percentile_interpolation(
                self.orography_cube, self.percentiles_cube)
        self.assertArrayAlmostEqual(probability_cube.data, expected)
예제 #8
0
 def test_attributes_inverse_ordering(self):
     """Test relative_to_threshold attribute is suitable for the
     inverse_ordering case, when it should be 'above'."""
     self.percentiles_cube.data = np.flipud(self.percentiles_cube.data)
     plugin_instance = ProbabilitiesFromPercentiles2D(self.percentiles_cube,
                                                      self.new_name)
     result = plugin_instance.create_probability_cube(self.percentiles_cube,
                                                      self.orography_cube)
     self.assertEqual(result.attributes['relative_to_threshold'], 'above')
예제 #9
0
 def setUp(self):
     """ Set up a percentiles cube, plugin instance and orography cube """
     self.percentiles_cube = set_up_percentiles_cube()
     self.percentile_coordinate = find_percentile_coordinate(
         self.percentiles_cube)
     self.new_name = "probability"
     self.plugin_instance = ProbabilitiesFromPercentiles2D(
         self.percentiles_cube, self.new_name)
     self.orography_cube = set_up_threshold_cube()
예제 #10
0
 def test_basic(self):
     """ Compare __repr__ string with expectation """
     new_name = "probability_of_snowfall"
     test_cube = set_up_percentiles_cube()
     inverse_ordering = False
     expected = ("<ProbabilitiesFromPercentiles2D: percentiles_"
                 "cube: {}, output_name: {}, inverse_ordering: {}".format(
                     test_cube, new_name, inverse_ordering))
     result = str(ProbabilitiesFromPercentiles2D(test_cube, new_name))
     self.assertEqual(result, expected)
def process(
    percentiles_cube: cli.inputcube,
    threshold_cube: cli.inputcube,
    *,
    output_diagnostic_name,
):
    r"""Probability from a percentiled field at a 2D threshold level.

    Probabilities are generated at a fixed threshold (height) from a set of
    (height) percentiles. E.g. for 2D percentile levels at different heights,
    calculate probability that height is at ground level, where the threshold
    cube contains a 2D topography field.

    Example::

        Snow-fall level:

            Reference field: Percentiled snow fall level (m ASL)
            Other field: Orography (m ASL)

            300m ----------------- 30th Percentile snow fall level
            200m ----_------------ 20th Percentile snow fall level
            100m ---/-\----------- 10th Percentile snow fall level
            000m --/---\----------  0th Percentile snow fall level
            ______/     \_________ Orogaphy

    The orography heights are compared against the heights that correspond with
    percentile values to find the band in which they fall, then interpolated
    linearly to obtain a probability at / below the ground surface.

    Args:
        percentiles_cube (iris.cube.Cube):
            The percentiled field from which probabilities will be obtained
            using the input cube.
            This cube should contain a percentiles dimension, with fields of
            values that correspond to these percentiles. The cube passed to
            the process method will contain values of the same diagnostic.
        threshold_cube (iris.cube.Cube):
            A cube of values that effectively behave as thresholds, for which
            it is desired to obtain probability values from a percentiled
            reference cube.
        output_diagnostic_name (str):
            The name of the cube being created, e.g
            'probability_of_snow_falling_level_below_ground_level'

    Returns:
        iris.cube.Cube:
            A cube of probabilities obtained by interpolating between
            percentile values at the "threshold" level.
    """
    from improver.utilities.statistical_operations import ProbabilitiesFromPercentiles2D

    probability_cube = ProbabilitiesFromPercentiles2D(
        percentiles_cube, output_diagnostic_name)(threshold_cube)
    return probability_cube
예제 #12
0
    def test_equal_percentiles(self):
        """Test for sensible behaviour when some percentile levels are
        equal."""
        self.percentiles_cube.data[0, :, :].fill(300.)
        expected = set_reference_probabilities()
        expected[np.where(expected < 0.25)] = 0.
        probability_cube = ProbabilitiesFromPercentiles2D(
            self.percentiles_cube, 'new_name').percentile_interpolation(
                self.orography_cube, self.percentiles_cube)

        self.assertArrayAlmostEqual(probability_cube.data, expected)
예제 #13
0
def main(argv=None):
    r"""
    Load arguments and run ProbabilitiesFromPercentiles plugin.

    Plugin generates probabilities at a fixed threshold (height) from a set of
    (height) percentiles.

    Example:

        Snow-fall level::

            Reference field: Percentiled snow fall level (m ASL)
            Other field: Orography (m ASL)

            300m ----------------- 30th Percentile snow fall level
            200m ----_------------ 20th Percentile snow fall level
            100m ---/-\----------- 10th Percentile snow fall level
            000m --/---\----------  0th Percentile snow fall level
            ______/     \_________ Orogaphy

        The orography heights are compared against the heights that correspond
        with percentile values to find the band in which they fall, then
        interpolated linearly to obtain a probability of snow level at / below
        the ground surface.
    """
    parser = ArgParser(
        description="Calculate probability from a percentiled field at a "
        "2D threshold level.  Eg for 2D percentile levels at different "
        "heights, calculate probability that height is at ground level, where"
        " the threshold file contains a 2D topography field.")
    parser.add_argument("percentiles_filepath", metavar="PERCENTILES_FILE",
                        help="A path to an input NetCDF file containing a "
                        "percentiled field")
    parser.add_argument("threshold_filepath", metavar="THRESHOLD_FILE",
                        help="A path to an input NetCDF file containing a "
                        "threshold value at which probabilities should be "
                        "calculated.")
    parser.add_argument("output_filepath", metavar="OUTPUT_FILE",
                        help="The output path for the processed NetCDF")
    parser.add_argument("output_diagnostic_name",
                        metavar="OUTPUT_DIAGNOSTIC_NAME", type=str,
                        help="Name for data in output file e.g. "
                        "probability_of_snow_falling_level_below_ground_level")
    args = parser.parse_args(args=argv)

    threshold_cube = load_cube(args.threshold_filepath)
    percentiles_cube = load_cube(args.percentiles_filepath)

    result = ProbabilitiesFromPercentiles2D(percentiles_cube,
                                            args.output_diagnostic_name)
    probability_cube = result.process(threshold_cube)

    save_netcdf(probability_cube, args.output_filepath)
예제 #14
0
    def test_all_equal_percentiles(self):
        """Test for sensible behaviour when all percentile levels are
        equal at some points."""
        self.percentiles_cube.data[:, :, 0:2].fill(300.)
        expected = set_reference_probabilities()
        expected[0:2, 0:2] = 0
        expected[2:, 0:2] = 1
        probability_cube = ProbabilitiesFromPercentiles2D(
            self.percentiles_cube, 'new_name').percentile_interpolation(
                self.orography_cube, self.percentiles_cube)

        self.assertArrayAlmostEqual(probability_cube.data, expected)
예제 #15
0
 def test_equal_percentiles_inverse_ordering(self):
     """Test for sensible behaviour when some percentile levels are equal
     in the case of inverse ordering (as described above)."""
     self.percentiles_cube.data[0, :, :].fill(300.)
     # Invert the values associated with the percentiles.
     self.percentiles_cube.data = np.flipud(self.percentiles_cube.data)
     expected = set_reference_probabilities()
     expected[np.where(expected <= 0.25)] = 0.
     expected = 1.0 - expected
     probability_cube = ProbabilitiesFromPercentiles2D(
         self.percentiles_cube, 'new_name').percentile_interpolation(
             self.orography_cube, self.percentiles_cube)
     self.assertArrayAlmostEqual(probability_cube.data, expected)
예제 #16
0
 def test_preservation_of_single_valued_dimension(self):
     """Test that if the pecentiles_cube has a single value dimension
     coordinate over which slicing is performed, that this coordinate is
     restored as a dimension coordinate in the resulting probability
     cube."""
     percentiles_cube = set_up_percentiles_cube()
     new_model_coord = DimCoord([0], units="1", long_name="leading_coord")
     percentiles_cube.add_aux_coord(new_model_coord)
     percentiles_cube = iris.util.new_axis(percentiles_cube,
                                           scalar_coord="leading_coord")
     plugin_instance = ProbabilitiesFromPercentiles2D(
         percentiles_cube, "new_name")
     probability_cube = plugin_instance.process(self.orography_cube)
     self.assertEqual(
         percentiles_cube.coords(dim_coords=True)[0],
         probability_cube.coords(dim_coords=True)[0],
     )
예제 #17
0
    def test_values_inverse_ordering(self):
        """Test that interpolated probabilities at given topography heights are
        sensible when we use the inverse_ordering set to True. This is for
        situations in which the values associated with the percentiles increase
        in the opposite direction, e.g. 0 % = 100m, 20% = 50m, etc.
        In this situation we expect the lowest points to have a probability of
        1, and the highest points to have probabilities of 0. The probabilities
        between should be the inverse of what is found in the usual case."""
        # Invert the values associated with the percentiles.
        self.percentiles_cube.data = np.flipud(self.percentiles_cube.data)
        expected = set_reference_probabilities()
        expected = 1.0 - expected

        probability_cube = ProbabilitiesFromPercentiles2D(
            self.percentiles_cube, 'new_name').percentile_interpolation(
                self.orography_cube, self.percentiles_cube)
        self.assertArrayAlmostEqual(probability_cube.data, expected)
예제 #18
0
 def test_basic(self):
     """ Test setting of a custom name """
     plugin_instance = ProbabilitiesFromPercentiles2D(self.test_cube,
                                                      self.new_name)
     self.assertEqual(plugin_instance.output_name, self.new_name)
예제 #19
0
 def test_naming(self):
     """ Test default naming """
     plugin_instance = ProbabilitiesFromPercentiles2D(self.test_cube)
     self.assertEqual(plugin_instance.output_name,
                      "probability_of_{}".format(self.test_cube.name()))