def test_works_one_thresh(self):
        """Test that the plugin retains the single threshold from the input
           cube."""

        # Creates a cube containing the expected outputs.
        fill_value = 1 + 1 / 3.0
        data = np.full((2, 2), fill_value)

        # Take a slice of the time coordinate.
        expected_cube = self.cube[0].copy(data.astype(np.float32))

        # Add threshold axis to expected output cube.
        changes = {'points': [0.5], 'units': '1', 'var_name': 'threshold'}
        expected_cube = add_coord(expected_cube, 'precipitation_amount',
                                  changes)

        # Add threshold axis to standard input cube.
        cube_with_thresh = add_coord(self.cube.copy(), 'precipitation_amount',
                                     changes)

        width = 2.0
        plugin = TriangularWeightedBlendAcrossAdjacentPoints(
            'forecast_period', self.forecast_period, 'hours', width)
        result = plugin.process(cube_with_thresh)

        # Test that the result cube retains threshold co-ordinates
        # from original cube.
        self.assertEqual(expected_cube.coord('precipitation_amount'),
                         result.coord('precipitation_amount'))
        self.assertArrayEqual(expected_cube.data, result.data)
        self.assertEqual(expected_cube, result)
Exemplo n.º 2
0
    def test_works_two_thresh(self):
        """Test that the plugin works with a cube that contains multiple
           thresholds."""
        width = 2.0

        changes = {'points': [0.25], 'units': '1'}
        cube_with_thresh1 = add_coord(self.cube.copy(), 'threshold', changes)

        changes = {'points': [0.5], 'units': '1'}
        cube_with_thresh2 = add_coord(self.cube.copy(), 'threshold', changes)

        changes = {'points': [0.75], 'units': '1'}
        cube_with_thresh3 = add_coord(self.cube.copy(), 'threshold', changes)

        cubelist = iris.cube.CubeList([cube_with_thresh1, cube_with_thresh2,
                                       cube_with_thresh3])
        thresh_cubes = concatenate_cubes(cubelist,
                                         coords_to_slice_over='threshold')

        plugin = TriangularWeightedBlendAcrossAdjacentPoints(
            'forecast_period', self.forecast_period, 'hours', width,
            'weighted_mean')
        result = plugin.process(thresh_cubes)

        # Test that the result cube retains threshold co-ordinates
        # from origonal cube.
        self.assertEqual(thresh_cubes.coord('threshold'),
                         result.coord('threshold'))
Exemplo n.º 3
0
 def test_central_point_not_available(self):
     """Test that the central point is not available within the
        input cube."""
     forecast_period = 2
     plugin = TriangularWeightedBlendAcrossAdjacentPoints(
         "forecast_period", forecast_period, "hours", self.width)
     msg = "The central point 2 in units of hours"
     with self.assertRaisesRegex(ValueError, msg):
         plugin._find_central_point(self.cube)
Exemplo n.º 4
0
 def test_central_point_not_available(self):
     """Test that the central point is not available within the
        input cube."""
     forecast_period = 2
     plugin = TriangularWeightedBlendAcrossAdjacentPoints(
         'forecast_period', forecast_period, 'hours', self.width,
         'weighted_mean')
     msg = 'The central point of'
     with self.assertRaisesRegex(ValueError, msg):
         plugin._find_central_point(self.cube)
 def test_central_point_available(self):
     """Test that the central point is available within the input cube."""
     plugin = TriangularWeightedBlendAcrossAdjacentPoints(
         'forecast_period', self.forecast_period, 'hours', self.width)
     central_cube = plugin._find_central_point(self.cube)
     self.assertEqual(self.central_cube.coord('forecast_period'),
                      central_cube.coord('forecast_period'))
     self.assertEqual(self.central_cube.coord('time'),
                      central_cube.coord('time'))
     self.assertArrayEqual(self.central_cube.data, central_cube.data)
 def test_central_point_not_in_allowed_range(self):
     """Test that an exception is generated when the central cube is not
        within the allowed range."""
     width = 1.0
     forecast_period = 2
     plugin = TriangularWeightedBlendAcrossAdjacentPoints(
         'forecast_period', forecast_period, 'hours', width)
     msg = "The central point 2 in units of hours"
     with self.assertRaisesRegex(ValueError, msg):
         plugin.process(self.cube)
 def test_basic_triangle_width_1(self):
     """Test that the plugin produces sensible results when the width
        of the triangle is 1. This is equivalent to no blending."""
     width = 1.0
     plugin = TriangularWeightedBlendAcrossAdjacentPoints(
         'forecast_period', self.forecast_period, 'hours', width)
     result = plugin.process(self.cube)
     self.assertEqual(self.central_cube.coord('forecast_period'),
                      result.coord('forecast_period'))
     self.assertEqual(self.central_cube.coord('time'), result.coord('time'))
     self.assertArrayEqual(self.central_cube.data, result.data)
 def test_basic_triangle_width_2(self):
     """Test that the plugin produces sensible results when the width
        of the triangle is 2 and there is some blending."""
     width = 2.0
     plugin = TriangularWeightedBlendAcrossAdjacentPoints(
         'forecast_period', self.forecast_period, 'hours', width)
     result = plugin.process(self.cube)
     expected_data = np.array([[1.333333, 1.333333], [1.333333, 1.333333]])
     self.assertEqual(self.central_cube.coord('forecast_period'),
                      result.coord('forecast_period'))
     self.assertEqual(self.central_cube.coord('time'), result.coord('time'))
     self.assertArrayAlmostEqual(expected_data, result.data)
 def test_alternative_parameter_units(self):
     """Test that the plugin produces sensible results when the width
        of the triangle is 7200 seconds. """
     forecast_period = 0
     width = 7200.0
     plugin = TriangularWeightedBlendAcrossAdjacentPoints(
         'forecast_period', forecast_period, 'seconds', width)
     result = plugin.process(self.cube)
     expected_data = np.array([[1.333333, 1.333333], [1.333333, 1.333333]])
     self.assertEqual(self.central_cube.coord('forecast_period'),
                      result.coord('forecast_period'))
     self.assertEqual(self.central_cube.coord('time'), result.coord('time'))
     self.assertArrayAlmostEqual(expected_data, result.data)
Exemplo n.º 10
0
 def setUp(self):
     """Set up a test orig_cube, new_cube and plugin instance."""
     self.orig_cube = set_up_cube()
     new_cube = set_up_cube()
     new_cube.remove_coord('longitude')
     new_cube.add_dim_coord(DimCoord(np.linspace(100, 160, 2), 'longitude',
                                     units='degrees'), 2)
     new_cube.remove_coord('forecast_period')
     new_cube.add_aux_coord(DimCoord([5, 6],
                                     "forecast_period", units="hours"), 0)
     self.new_cube = new_cube
     self.plugin = TriangularWeightedBlendAcrossAdjacentPoints(
         'time', 1.0, 'hours', 'weighted_mean')
Exemplo n.º 11
0
    def test_extra_dimension(self):
        """Test that the plugin retains the single height point from the input
           cube."""

        # Creates a cube containing the expected outputs.
        fill_value = 1 + 1 / 3.0
        data = np.full((2, 2), fill_value)

        # Take a slice of the time coordinate.
        expected_cube = self.cube[0].copy(data.astype(np.float32))

        # Add height axis to expected output cube.
        expected_cube = add_coordinate(expected_cube, [0.5],
                                       "height",
                                       coord_units="m")

        # Add height axis to standard input cube.
        cube = add_coordinate(self.cube.copy(), [0.5],
                              "height",
                              coord_units="m")
        width = 2.0
        plugin = TriangularWeightedBlendAcrossAdjacentPoints(
            "forecast_period", self.forecast_period, "hours", width)
        result = plugin(cube)

        # Test that the result cube retains height co-ordinates
        # from original cube.
        self.assertEqual(expected_cube.coord("height"), result.coord("height"))
        self.assertArrayEqual(expected_cube.data, result.data)
        self.assertEqual(expected_cube, result)
Exemplo n.º 12
0
 def test_basic_triangle_width_2_max_mode(self):
     """Test that the plugin produces sensible results when the width
        of the triangle is 2 and there is some blending. This time
        use the weighted_maximum mode"""
     width = 2.0
     plugin = TriangularWeightedBlendAcrossAdjacentPoints(
         'forecast_period', width, 'hours', 'weighted_maximum')
     result = plugin.process(self.cube)
     expected_data = np.array([[[0.6666666, 0.6666666],
                                [0.6666666, 0.6666666]],
                               [[1.3333333, 1.3333333],
                                [1.3333333, 1.3333333]]])
     self.assertEqual(self.cube.coord('forecast_period'),
                      result.coord('forecast_period'))
     self.assertEqual(self.cube.coord('time'), result.coord('time'))
     self.assertArrayAlmostEqual(expected_data, result.data)
Exemplo n.º 13
0
    def test_input_cube_no_change(self):
        """Test that the plugin does not change the origonal input cube."""

        # Add threshold axis to standard input cube.
        changes = {'points': [0.5], 'units': '1'}
        cube_with_thresh = add_coord(self.cube.copy(), 'threshold', changes)
        original_cube = cube_with_thresh.copy()

        width = 2.0
        plugin = TriangularWeightedBlendAcrossAdjacentPoints(
            'forecast_period', self.forecast_period, 'hours', width,
            'weighted_mean')
        _ = plugin.process(cube_with_thresh)

        # Test that the input cube is unchanged by the function.
        self.assertEqual(cube_with_thresh, original_cube)
Exemplo n.º 14
0
 def test_raises_expression(self):
     """Test that the __init__ raises the right error"""
     message = ("weighting_mode: no_mode is not recognised, "
                "must be either weighted_maximum or weighted_mean")
     with self.assertRaisesRegex(ValueError, message):
         TriangularWeightedBlendAcrossAdjacentPoints(
             'time', 1, 'hours', 3.0, 'no_mode')
    def test_works_two_thresh(self):
        """Test that the plugin works with a cube that contains multiple
           thresholds."""
        width = 2.0

        thresh_cube = self.cube.copy()
        thresh_cube.remove_coord("forecast_reference_time")

        changes = {'points': [0.25], 'units': '1', 'var_name': 'threshold'}
        cube_with_thresh1 = add_coord(thresh_cube.copy(),
                                      'precipitation_amount', changes)

        changes = {'points': [0.5], 'units': '1', 'var_name': 'threshold'}
        cube_with_thresh2 = add_coord(thresh_cube.copy(),
                                      'precipitation_amount', changes)

        changes = {'points': [0.75], 'units': '1', 'var_name': 'threshold'}
        cube_with_thresh3 = add_coord(thresh_cube.copy(),
                                      'precipitation_amount', changes)

        cubelist = iris.cube.CubeList(
            [cube_with_thresh1, cube_with_thresh2, cube_with_thresh3])

        thresh_cubes = concatenate_cubes(
            cubelist, coords_to_slice_over='precipitation_amount')

        plugin = TriangularWeightedBlendAcrossAdjacentPoints(
            'forecast_period', self.forecast_period, 'hours', width)
        result = plugin(thresh_cubes)

        # Test that the result cube retains threshold co-ordinates
        # from original cube.
        self.assertEqual(thresh_cubes.coord('precipitation_amount'),
                         result.coord('precipitation_amount'))
Exemplo n.º 16
0
 def test_basic(self):
     """Test that the __repr__ returns the expected string."""
     width = 3.0
     result = str(TriangularWeightedBlendAcrossAdjacentPoints(
         'time', width, 'hours', 'weighted_mean'))
     msg = ('<TriangularWeightedBlendAcrossAdjacentPoints:'
            ' coord = time, width = 3.00,'
            ' parameter_units = hours, mode = weighted_mean>')
     self.assertEqual(result, msg)
Exemplo n.º 17
0
 def test_basic(self):
     """Test that the __repr__ returns the expected string."""
     width = 3.0
     forecast_period = 1
     result = str(
         TriangularWeightedBlendAcrossAdjacentPoints(
             "time", forecast_period, "hours", width))
     msg = ("<TriangularWeightedBlendAcrossAdjacentPoints:"
            " coord = time, central_point = 1.00, "
            "parameter_units = hours, width = 3.00")
     self.assertEqual(result, msg)
Exemplo n.º 18
0
 def test_basic(self):
     """Test that the __repr__ returns the expected string."""
     width = 3.0
     plugin = TriangularWeightedBlendAcrossAdjacentPoints(
         'time', width, 'hours', 'weighted_mean')
     expected_coord = "time"
     expected_width = 3.0
     expected_parameter_units = "hours"
     self.assertEqual(plugin.coord, expected_coord)
     self.assertEqual(plugin.width, expected_width)
     self.assertEqual(plugin.parameter_units, expected_parameter_units)
Exemplo n.º 19
0
    def test_works_one_thresh(self):
        """Test that the plugin retains the single threshold from the input
           cube."""

        # Creates a cube containing the expected outputs.
        fill_value = 1 + 1/3.0
        data = np.full((2, 2), fill_value)

        expected_cube = (Cube(data, units='m',
                         standard_name='lwe_thickness_of_precipitation_amount')
                         )
        expected_cube.add_dim_coord(DimCoord(np.linspace(-45.0, 45.0, 2),
                                    'latitude', units='degrees'), 0)
        expected_cube.add_dim_coord(DimCoord(np.linspace(120, 180, 2),
                                    'longitude', units='degrees'), 1)

        time_origin = 'hours since 1970-01-01 00:00:00'
        calendar = 'gregorian'
        tunit = Unit(time_origin, calendar)
        expected_cube.add_aux_coord(DimCoord([402192.5], 'time', units=tunit))
        expected_cube.add_aux_coord(DimCoord([0], 'forecast_period',
                                             units='hours'))
        # Add threshold axis to expected output cube.
        changes = {'points': [0.5], 'units': '1'}
        expected_cube = add_coord(expected_cube, 'threshold', changes)

        # Add threshold axis to standard input cube.
        cube_with_thresh = add_coord(self.cube.copy(), 'threshold', changes)

        width = 2.0
        plugin = TriangularWeightedBlendAcrossAdjacentPoints(
            'forecast_period', self.forecast_period, 'hours', width,
            'weighted_mean')
        result = plugin.process(cube_with_thresh)

        # Test that the result cube retains threshold co-ordinates
        # from origonal cube.
        self.assertEqual(expected_cube.coord('threshold'),
                         result.coord('threshold'))
        self.assertArrayEqual(expected_cube.data, result.data)
        self.assertEqual(expected_cube, result)
Exemplo n.º 20
0
 def test_basic(self):
     """Test that the __repr__ returns the expected string."""
     width = 3.0
     forecast_period = 1
     plugin = TriangularWeightedBlendAcrossAdjacentPoints(
         "time", forecast_period, "hours", width)
     expected_coord = "time"
     expected_width = 3.0
     expected_parameter_units = "hours"
     self.assertEqual(plugin.coord, expected_coord)
     self.assertEqual(plugin.width, expected_width)
     self.assertEqual(plugin.parameter_units, expected_parameter_units)
Exemplo n.º 21
0
    def test_input_cube_no_change(self):
        """Test that the plugin does not change the original input cube."""

        # Add height axis to standard input cube.
        cube = add_coordinate(self.cube.copy(), [0], "height", coord_units="m")
        original_cube = cube.copy()

        width = 2.0
        plugin = TriangularWeightedBlendAcrossAdjacentPoints(
            "forecast_period", self.forecast_period, "hours", width)
        _ = plugin(cube)

        # Test that the input cube is unchanged by the function.
        self.assertEqual(cube, original_cube)
Exemplo n.º 22
0
    def test_works_two_thresh(self):
        """Test that the plugin works with a cube that contains multiple
           thresholds."""
        width = 2.0
        thresh_cube = self.cube.copy()
        thresh_cubes = add_coordinate(thresh_cube, [0.25, 0.5, 0.75],
                                      "precipitation_amount",
                                      coord_units="mm")
        thresh_cubes.coord("precipitation_amount").var_name = "threshold"
        plugin = TriangularWeightedBlendAcrossAdjacentPoints(
            "forecast_period", self.forecast_period, "hours", width)
        result = plugin(thresh_cubes)

        # Test that the result cube retains threshold co-ordinates
        # from original cube.
        self.assertEqual(
            thresh_cubes.coord("precipitation_amount"),
            result.coord("precipitation_amount"),
        )
def main(argv=None):
    """Load in arguments and ensure they are set correctly.
       Then run Triangular weighted blending across the given coordinate."""
    parser = ArgParser(
        description='Use the TriangularWeightedBlendAcrossAdjacentPoints to '
                    'blend across a particular coordinate. It does not '
                    'collapse the coordinate, but instead blends across '
                    'adjacent points and puts the blended values back in the '
                    'original coordinate, with adjusted bounds.')
    parser.add_argument('coordinate', type=str,
                        metavar='COORDINATE_TO_BLEND_OVER',
                        help='The coordinate over which the blending '
                             'will be applied.')
    parser.add_argument('central_point', metavar='CENTRAL_POINT', type=float,
                        help='Central point at which the output from the '
                             'triangular weighted blending will be '
                             'calculated. This should be in the units of the '
                             'units argument that is passed in. '
                             'This value should be a point on the '
                             'coordinate for blending over.')
    parser.add_argument('--units', metavar='UNIT_STRING', required=True,
                        help='Units of the the central_point and width.')
    parser.add_argument('--calendar', metavar='CALENDAR',
                        default='gregorian',
                        help='Calendar for parameter_unit if required. '
                             'Default=gregorian')
    parser.add_argument('--width', metavar='TRIANGLE_WIDTH', type=float,
                        required=True,
                        help='Width of the triangular weighting function used '
                             'in the blending, in the units of the '
                             'units argument passed in.')
    parser.add_argument('--blend_time_using_forecast_period',
                        default=False, action='store_true', help='Flag that '
                        'we are blending over time but using the forecast '
                        'period coordinate as a proxy.  Note this should only '
                        'be used when time and forecast_period share a '
                        'dimension: ie when all files provided are from the '
                        'same forecast cycle.')
    parser.add_argument('input_filepaths', metavar='INPUT_FILES', nargs="+",
                        help='Paths to input NetCDF files including and '
                             'surrounding the central_point.')
    parser.add_argument('output_filepath', metavar='OUTPUT_FILE',
                        help='The output path for the processed NetCDF.')

    args = parser.parse_args(args=argv)

    # TriangularWeightedBlendAcrossAdjacentPoints can't currently handle
    # blending over times where iris reads the coordinate points as datetime
    # objects.  Fail here to avoid unhelpful errors downstream.
    if "time" in args.coordinate:
        msg = ("Cannot blend over {} coordinate (points encoded as datetime "
               "objects)".format(args.coordinate))
        raise ValueError(msg)

    # This is left as a placeholder for when we have this capability
    if args.coordinate == 'time':
        units = Unit(args.units, args.calendar)
    else:
        units = args.units

    cubelist = load_cubelist(args.input_filepaths)

    if (args.blend_time_using_forecast_period and
            args.coordinate == 'forecast_period'):
        cube = MergeCubes().process(cubelist, check_time_bounds_ranges=True)
    elif args.blend_time_using_forecast_period:
        msg = ('"--blend_time_using_forecast_period" can only be used with '
               '"forecast_period" coordinate')
        raise ValueError(msg)
    else:
        cube = MergeCubes().process(cubelist)

    BlendingPlugin = TriangularWeightedBlendAcrossAdjacentPoints(
        args.coordinate, args.central_point, units, args.width)
    result = BlendingPlugin.process(cube)
    save_netcdf(result, args.output_filepath)
Exemplo n.º 24
0
def process(*cubes: cli.inputcube,
            coordinate,
            central_point: float,
            units=None,
            width: float = None,
            calendar='gregorian',
            blend_time_using_forecast_period=False):
    """Runs weighted blending across adjacent points.

    Uses the TriangularWeightedBlendAcrossAdjacentPoints to blend across
    a particular coordinate. It does not collapse the coordinate, but
    instead blends across adjacent points and puts the blended values back
    in the original coordinate, with adjusted bounds.

    Args:
        cubes (list of iris.cube.Cube):
            A list of cubes including and surrounding the central point.
        coordinate (str):
            The coordinate over which the blending will be applied.
        central_point (float):
            Central point at which the output from the triangular weighted
            blending will be calculated. This should be in the units of the
            units argument that is passed in. This value should be a point
            on the coordinate for blending over.
        units (str):
            Units of the central_point and width
        width (float):
            Width of the triangular weighting function used in the blending,
            in the units of the units argument.
        calendar (str)
            Calendar for parameter_unit if required.
        blend_time_using_forecast_period (bool):
            If True, we are blending over time but using the forecast
            period coordinate as a proxy. Note, this should only be used when
            time and forecast_period share a dimension: i.e when all cubes
            provided are from the same forecast cycle.

    Returns:
        iris.cube.Cube:
            A processed Cube

    Raises:
        ValueError:
            If coordinate has "time" in it.
        ValueError:
            If blend_time_forecast_period is not used with forecast_period
            coordinate.

    """
    from cf_units import Unit
    from iris.cube import CubeList

    from improver.blending.blend_across_adjacent_points import \
        TriangularWeightedBlendAcrossAdjacentPoints
    from improver.utilities.cube_manipulation import MergeCubes

    # TriangularWeightedBlendAcrossAdjacentPoints can't currently handle
    # blending over times where iris reads the coordinate points as datetime
    # objects. Fail here to avoid unhelpful errors downstream.
    if "time" in coordinate:
        msg = ("Cannot blend over {} coordinate (points encoded as datetime "
               "objects)".format(coordinate))
        raise ValueError(msg)

    # This is left as a placeholder for when we have this capability
    if coordinate == 'time':
        units = Unit(units, calendar)

    cubes = CubeList(cubes)

    if blend_time_using_forecast_period and coordinate == 'forecast_period':
        cube = MergeCubes().process(cubes, check_time_bounds_ranges=True)
    elif blend_time_using_forecast_period:
        msg = ('"--blend-time-using-forecast-period" can only be used with '
               '"forecast_period" coordinate')
        raise ValueError(msg)
    else:
        cube = MergeCubes().process(cubes)

    blending_plugin = TriangularWeightedBlendAcrossAdjacentPoints(
        coordinate, central_point, units, width)
    result = blending_plugin.process(cube)
    return result
Exemplo n.º 25
0
class Test_correct_collapsed_coordinates(IrisTest):

    """Test the correct_collapsed_coordinates method"""

    def setUp(self):
        """Set up a test orig_cube, new_cube and plugin instance."""
        self.orig_cube = set_up_cube()
        new_cube = set_up_cube()
        new_cube.remove_coord('longitude')
        new_cube.add_dim_coord(DimCoord(np.linspace(100, 160, 2), 'longitude',
                                        units='degrees'), 2)
        new_cube.remove_coord('forecast_period')
        new_cube.add_aux_coord(DimCoord([5, 6],
                                        "forecast_period", units="hours"), 0)
        self.new_cube = new_cube
        self.plugin = TriangularWeightedBlendAcrossAdjacentPoints(
            'time', 1.0, 'hours', 'weighted_mean')

    def test_no_change_to_new_cube(self):
        """Test it does nothing when nothing to correct"""
        input_new_cube = self.new_cube.copy()
        self.plugin.correct_collapsed_coordinates(self.orig_cube,
                                                  input_new_cube, ['latitude'])
        self.assertEqual(input_new_cube, self.new_cube)

    def test_change_one_coord(self):
        """Test it changes only one coordinate"""
        input_new_cube = self.new_cube.copy()
        self.plugin.correct_collapsed_coordinates(self.orig_cube,
                                                  input_new_cube,
                                                  ['longitude'])
        self.assertEqual(input_new_cube.coord('longitude'),
                         self.orig_cube.coord('longitude'))
        self.assertEqual(input_new_cube.coord('latitude'),
                         self.new_cube.coord('latitude'))
        self.assertEqual(input_new_cube.coord('forecast_period'),
                         self.new_cube.coord('forecast_period'))

    def test_change_two_coord(self):
        """Test it corrects multiple coordinate"""
        input_new_cube = self.new_cube.copy()
        self.plugin.correct_collapsed_coordinates(
            self.orig_cube, input_new_cube, ['longitude', 'forecast_period'])
        self.assertEqual(input_new_cube.coord('longitude'),
                         self.orig_cube.coord('longitude'))
        self.assertEqual(input_new_cube.coord('latitude'),
                         self.new_cube.coord('latitude'))
        self.assertEqual(input_new_cube.coord('forecast_period'),
                         self.orig_cube.coord('forecast_period'))

    def test_bounds_corrected(self):
        """Test it corrects bounds"""
        input_new_cube = self.new_cube.copy()
        input_orig_cube = self.orig_cube.copy()
        input_orig_cube.remove_coord('forecast_period')
        input_orig_cube.add_aux_coord(DimCoord(
            [5, 6], "forecast_period", bounds=[[4.5, 5.5], [5.5, 6.5]],
            units="hours"), 0)
        self.plugin.correct_collapsed_coordinates(
            input_orig_cube, input_new_cube, ['forecast_period'])
        self.assertEqual(input_new_cube.coord('forecast_period'),
                         input_orig_cube.coord('forecast_period'))

    def test_wrong_size_coords(self):
        """Test it raises an error when new_cube and old_cube have
           different length coordinates"""
        data = np.zeros((2, 2, 2))
        orig_cube = Cube(data, units="m",
                         standard_name="lwe_thickness_of_precipitation_amount")
        orig_cube.add_dim_coord(DimCoord([0, 1], "forecast_period",
                                         units="hours"), 0)
        data = np.zeros((3, 2, 2))
        new_cube = Cube(data, units="m",
                        standard_name="lwe_thickness_of_precipitation_amount")
        new_cube.add_dim_coord(DimCoord([0, 1, 2], "forecast_period",
                                        units="hours"), 0)
        message = "New points shape must match existing points shape."
        with self.assertRaisesRegexp(ValueError, message):
            self.plugin.correct_collapsed_coordinates(orig_cube, new_cube,
                                                      ['forecast_period'])

    def test_exception_when_coord_not_found(self):
        """Test that an exception is raised by Iris when we try to correct
           a coordinate that doesn't exist."""
        self.new_cube.remove_coord('forecast_period')
        message = "Expected to find exactly 1  coordinate, but found none."
        with self.assertRaisesRegexp(CoordinateNotFoundError, message):
            self.plugin.correct_collapsed_coordinates(self.orig_cube,
                                                      self.new_cube,
                                                      ['forecast_period'])