def test_updated_metadata(self):
     """Test that the metadata is set as expected """
     plugin = WindGustDiagnostic(50.0, 80.0)
     result = plugin.update_metadata_after_max(self.cube, self.perc_coord)
     msg = 'Expected to find exactly 1 .* coordinate, but found none.'
     with self.assertRaisesRegex(CoordinateNotFoundError, msg):
         result.coord(self.perc_coord)
def process(gust_cube, speed_cube, percentile_gust, percentile_speed):
    """Create a cube containing the wind_gust diagnostic.

    Calculate revised wind-gust data using a specified percentiles of
    wind-gust data and a specified percentile of wind-speed data through the
    WindGustDiagnostic plugin. The wind-gust diagnostic will be the max of the
    specified percentile data.

    Args:
        gust_cube (iris.cube.Cube):
            Cube containing one or more percentiles of wind_gust data.
        speed_cube (iris.cube.Cube):
            Cube containing one or more percentiles of wind_speed data.
        percentile_gust (float):
            Percentile value required from wind-gust cube.
        percentile_speed (float):
            Percentile value required from wind-speed cube.

    Returns:
        result (iris.cube.Cube):
            Cube containing the wind-gust diagnostic data.
    """
    result = (WindGustDiagnostic(percentile_gust, percentile_speed).process(
        gust_cube, speed_cube))
    return result
Example #3
0
 def test_metadata(self):
     """Test that the metadata is set as expected """
     plugin = WindGustDiagnostic(50.0, 80.0)
     result = plugin.add_metadata(self.cube_wg)
     self.assertEqual(result.standard_name, "wind_speed_of_gust")
     msg = "<WindGustDiagnostic: wind-gust perc=50.0, " "wind-speed perc=80.0>"
     self.assertEqual(result.attributes["wind_gust_diagnostic"], msg)
 def test_returns_correct_cube_and_coord(self):
     """Test it returns the correct Cube and Coord."""
     plugin = WindGustDiagnostic(self.wg_perc, self.ws_perc)
     result, perc_coord = (plugin.extract_percentile_data(
         self.cube_wg, self.wg_perc, "wind_speed_of_gust"))
     self.assertEqual(perc_coord.name(), "percentile")
     self.assertEqual(result.coord("percentile").points, [self.wg_perc])
Example #5
0
def process(
    wind_gust: cli.inputcube,
    wind_speed: cli.inputcube,
    *,
    wind_gust_percentile: float = 50.0,
    wind_speed_percentile: float = 95.0,
):
    """Create a cube containing the wind_gust diagnostic.

    Calculate revised wind-gust data using a specified percentile of
    wind-gust data and a specified percentile of wind-speed data through the
    WindGustDiagnostic plugin. The wind-gust diagnostic will be the max of the
    specified percentile data.

    Args:
        wind_gust (iris.cube.Cube):
            Cube containing one or more percentiles of wind_gust data.
        wind_speed (iris.cube.Cube):
            Cube containing one or more percentiles of wind_speed data.
        wind_gust_percentile (float):
            Percentile value required from wind-gust cube.
        wind_speed_percentile (float):
            Percentile value required from wind-speed cube.

    Returns:
        iris.cube.Cube:
            Cube containing the wind-gust diagnostic data.
    """
    from improver.wind_calculations.wind_gust_diagnostic import WindGustDiagnostic

    result = WindGustDiagnostic(wind_gust_percentile,
                                wind_speed_percentile)(wind_gust, wind_speed)
    return result
 def test_fails_if_req_percentile_not_in_cube(self):
     """Test it raises a Value Error if req_perc not in cube."""
     plugin = WindGustDiagnostic(self.wg_perc, self.ws_perc)
     msg = ('Could not find required percentile')
     with self.assertRaisesRegex(ValueError, msg):
         plugin.extract_percentile_data(self.cube_wg, 20.0,
                                        "wind_speed_of_gust")
 def test_basic(self):
     """Test that the function returns a Cube and Coord."""
     plugin = WindGustDiagnostic(self.wg_perc, self.ws_perc)
     result, perc_coord = (plugin.extract_percentile_data(
         self.cube_wg, self.wg_perc, "wind_speed_of_gust"))
     self.assertIsInstance(result, Cube)
     self.assertIsInstance(perc_coord, iris.coords.Coord)
Example #8
0
 def test_raises_error_points_mismatch_and_no_bounds(self):
     """Test raises Value Error if points mismatch and no bounds """
     # offset times by half an hour (in seconds)
     self.cube_wg.coord("time").points = self.cube_wg.coord("time").points + 30 * 60
     plugin = WindGustDiagnostic(self.wg_perc, self.ws_perc)
     msg = "Could not match time coordinate"
     with self.assertRaisesRegex(ValueError, msg):
         plugin(self.cube_wg, self.cube_ws)
 def test_raises_error_points_mismatch_and_no_bounds(self):
     """Test raises Value Error if points mismatch and no bounds """
     cube_wg = self.cube_wg
     cube_wg.coord('time').points = [402192.5, 402194.5]
     plugin = WindGustDiagnostic(self.wg_perc, self.ws_perc)
     msg = ('Could not match time coordinate')
     with self.assertRaisesRegex(ValueError, msg):
         plugin.process(cube_wg, self.cube_ws)
Example #10
0
 def test_raises_error_for_mismatching_perc_coords(self):
     """Test raises an error for mismatching perc coords. """
     plugin = WindGustDiagnostic(self.wg_perc, self.ws_perc)
     self.cube_wg.coord("percentile").rename("percentile_dummy")
     msg = ("Percentile coord of wind-gust data"
            "does not match coord of wind-speed data")
     with self.assertRaisesRegex(ValueError, msg):
         plugin(self.cube_wg, self.cube_ws)
Example #11
0
 def test_fails_if_data_is_not_cube(self):
     """Test it raises a Type Error if cube is not a cube."""
     plugin = WindGustDiagnostic(self.wg_perc, self.ws_perc)
     msg = ('Expecting wind_speed_of_gust data to be an instance of '
            'iris.cube.Cube but is'
            ' {0}.'.format(type(self.wg_perc)))
     with self.assertRaisesRegex(TypeError, msg):
         plugin.extract_percentile_data(self.wg_perc, self.wg_perc,
                                        "wind_speed_of_gust")
Example #12
0
 def test_returns_wind_gust_diagnostic(self):
     """Test that the plugin returns a Cube. """
     plugin = WindGustDiagnostic(self.wg_perc, self.ws_perc)
     result = plugin(self.cube_wg, self.cube_ws)
     expected_data = np.zeros((2, 2, 2), dtype=np.float32)
     expected_data[0, :, :] = 3.0
     expected_data[1, :, :] = 2.0
     self.assertArrayAlmostEqual(result.data, expected_data)
     self.assertEqual(result.attributes["wind_gust_diagnostic"], "Typical gusts")
Example #13
0
 def test_raises_error_for_no_time_coord(self):
     """Test raises Value Error if cubes have no time coordinate """
     cube_wg = self.cube_wg[:, 0, ::]
     cube_ws = self.cube_ws[:, 0, ::]
     cube_wg.remove_coord('time')
     cube_wg = iris.util.squeeze(cube_wg)
     plugin = WindGustDiagnostic(self.wg_perc, self.ws_perc)
     msg = ('Could not match time coordinate')
     with self.assertRaisesRegex(ValueError, msg):
         plugin.process(cube_wg, cube_ws)
Example #14
0
 def test_raises_error_points_mismatch_and_bounds(self):
     """Test raises Value Error if both points and bounds mismatch """
     cube_wg = self.cube_wg
     cube_wg.coord('time').points = [402192.0, 402193.0]
     cube_wg.coord('time').bounds = [[402191.0, 402192.0],
                                     [402192.0, 402193.0]]
     plugin = WindGustDiagnostic(self.wg_perc, self.ws_perc)
     msg = ('Could not match time coordinate')
     with self.assertRaisesRegex(ValueError, msg):
         plugin.process(cube_wg, self.cube_ws)
Example #15
0
    def test_no_raises_error_if_ws_point_in_bounds(self):
        """Test raises no Value Error if wind-speed point in bounds """
        cube_wg = self.cube_wg
        cube_wg.coord('time').points = [402192.0, 402193.0]
        cube_wg.coord('time').bounds = [[402191.5, 402192.5],
                                        [402192.5, 402193.5]]

        plugin = WindGustDiagnostic(self.wg_perc, self.ws_perc)
        result = plugin.process(cube_wg, self.cube_ws)
        self.assertIsInstance(result, Cube)
Example #16
0
def main(argv=None):
    """Load in arguments for wind-gust diagnostic.
    Wind-gust and Wind-speed data should be supplied along with the required
    percentile value. The wind-gust diagnostic will be the Max of the specified
    percentile data.
    Currently
        * Typical gusts is
          MAX(wind-gust(50th percentile),wind-speed(95th percentile))
        * Extreme gust is
          MAX(wind-gust(95th percentile),wind-speed(100th percentile))
    If no percentile values are supplied the code defaults
    to values for Typical gusts.
    """
    parser = ArgParser(
        description="Calculate revised wind-gust data using a specified "
        "percentile of wind-gust data and a specified percentile "
        "of wind-speed data through the WindGustDiagnostic plugin. "
        "The wind-gust diagnostic will be the Max of the specified "
        "percentile data."
        "Currently Typical gusts is "
        "MAX(wind-gust(50th percentile),wind-speed(95th percentile))"
        "and Extreme gust is "
        "MAX(wind-gust(95th percentile),wind-speed(100th percentile)). "
        "If no percentile values are supplied the code defaults "
        "to values for Typical gusts.")
    parser.add_argument("input_filegust",
                        metavar="INPUT_FILE_GUST",
                        help="A path to an input Wind Gust Percentile"
                        " NetCDF file")
    parser.add_argument("input_filews",
                        metavar="INPUT_FILE_WINDSPEED",
                        help="A path to an input Wind Speed Percentile"
                        " NetCDF file")
    parser.add_argument("output_filepath",
                        metavar="OUTPUT_FILE",
                        help="The output path for the processed NetCDF")
    parser.add_argument("--percentile_gust",
                        metavar="PERCENTILE_GUST",
                        default="50.0",
                        help="Percentile of wind-gust required."
                        " Default=50.0",
                        type=float)
    parser.add_argument("--percentile_ws",
                        metavar="PERCENTILE_WIND_SPEED",
                        default="95.0",
                        help="Percentile of wind-speed required."
                        " Default=95.0",
                        type=float)

    args = parser.parse_args(args=argv)
    cube_wg = load_cube(args.input_filegust)
    cube_ws = load_cube(args.input_filews)
    result = (WindGustDiagnostic(args.percentile_gust,
                                 args.percentile_ws).process(cube_wg, cube_ws))
    save_netcdf(result, args.output_filepath)
Example #17
0
 def test_warning_if_standard_names_do_not_match(self, warning_list=None):
     """Test it raises a warning if standard names do not match."""
     plugin = WindGustDiagnostic(self.wg_perc, self.ws_perc)
     warning_msg = ('Warning mismatching name for data expecting')
     result, perc_coord = (plugin.extract_percentile_data(
         self.cube_wg, self.wg_perc, "wind_speed"))
     self.assertTrue(
         any(item.category == UserWarning for item in warning_list))
     self.assertTrue(any(warning_msg in str(item) for item in warning_list))
     self.assertIsInstance(result, Cube)
     self.assertIsInstance(perc_coord, iris.coords.Coord)
Example #18
0
 def test_no_error_if_ws_point_in_bounds(self):
     """Test raises no Value Error if wind-speed point in bounds """
     self.cube_wg.coord("time").points = self.cube_wg.coord("time").points + 30 * 60
     times = self.cube_wg.coord("time").points
     self.cube_wg.coord("time").bounds = [
         [times[0] - 3600, times[0]],
         [times[1] - 3600, times[1]],
     ]
     plugin = WindGustDiagnostic(self.wg_perc, self.ws_perc)
     result = plugin(self.cube_wg, self.cube_ws)
     self.assertIsInstance(result, Cube)
Example #19
0
 def test_raises_error_points_mismatch_and_bounds(self):
     """Test raises Value Error if both points and bounds mismatch """
     # offset by 4 hours (in seconds)
     self.cube_wg.coord("time").points = (
         self.cube_wg.coord("time").points + 4 * 60 * 60)
     times = self.cube_wg.coord("time").points
     self.cube_wg.coord("time").bounds = [
         [times[0] - 3600, times[0]],
         [times[1] - 3600, times[1]],
     ]
     plugin = WindGustDiagnostic(self.wg_perc, self.ws_perc)
     msg = "Could not match time coordinate"
     with self.assertRaisesRegex(ValueError, msg):
         plugin(self.cube_wg, self.cube_ws)
Example #20
0
 def test_raises_error_for_mismatching_perc_coords(self):
     """Test raises an error for mismatching perc coords. """
     plugin = WindGustDiagnostic(self.wg_perc, self.ws_perc)
     data_wg = np.zeros((1, 2, 2, 2))
     data_wg[0, 0, :, :] = 3.0
     data_wg[0, 1, :, :] = 1.5
     gust = "wind_speed_of_gust"
     cube_wg = (create_cube_with_percentile_coord(
         data=data_wg,
         perc_values=[self.wg_perc],
         standard_name=gust,
         perc_name='percentile_dummy'))
     msg = ('Percentile coord of wind-gust data'
            'does not match coord of wind-speed data')
     with self.assertRaisesRegex(ValueError, msg):
         plugin.process(cube_wg, self.cube_ws)
Example #21
0
 def test_basic(self):
     """Test that the __repr__ returns the expected string."""
     result = str(WindGustDiagnostic(50.0, 95.0))
     msg = ('<WindGustDiagnostic: wind-gust perc=50.0, '
            'wind-speed perc=95.0>')
     self.assertEqual(result, msg)
Example #22
0
 def test_basic(self):
     """Test that the __init__ sets things up correctly"""
     plugin = (WindGustDiagnostic(50.0, 95.0))
     self.assertEqual(plugin.percentile_gust, 50.0)
     self.assertEqual(plugin.percentile_windspeed, 95.0)
Example #23
0
 def test_basic(self):
     """Test that the function returns a Cube. """
     plugin = WindGustDiagnostic(50.0, 95.0)
     result = plugin.add_metadata(self.cube_wg)
     self.assertIsInstance(result, Cube)
Example #24
0
 def test_diagnostic_typical_txt(self):
     """Test that the attribute is set as expected for typical gusts"""
     plugin = WindGustDiagnostic(50.0, 95.0)
     result = plugin.add_metadata(self.cube_wg)
     msg = 'Typical gusts'
     self.assertEqual(result.attributes['wind_gust_diagnostic'], msg)
Example #25
0
 def test_diagnostic_extreme_txt(self):
     """Test that the attribute is set as expected for extreme gusts"""
     plugin = WindGustDiagnostic(95.0, 100.0)
     result = plugin.add_metadata(self.cube_wg)
     msg = 'Extreme gusts'
     self.assertEqual(result.attributes['wind_gust_diagnostic'], msg)
Example #26
0
 def test_basic(self):
     """Test that the plugin returns a Cube. """
     plugin = WindGustDiagnostic(self.wg_perc, self.ws_perc)
     result = plugin.process(self.cube_wg, self.cube_ws)
     self.assertIsInstance(result, Cube)
Example #27
0
 def test_basic(self):
     """Test that the function returns a Cube. """
     plugin = WindGustDiagnostic(50.0, 95.0)
     result = plugin.update_metadata_after_max(self.cube, self.perc_coord)
     self.assertIsInstance(result, Cube)