-
Notifications
You must be signed in to change notification settings - Fork 89
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add CLIs to support rescaling of the forecast based on altitude diffe…
…rence (#1917) * Add CLIs and acceptance tests. Make minor update to correct dtype. * Corrections to estimate-dz-rescaling CLI docstrings. * Updates to docstrings following review comments. * Updates to docstrings within the estimate-dz-rescaling CLI.
- Loading branch information
1 parent
57a1003
commit 8b218e0
Showing
7 changed files
with
320 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
#!/usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||
# ----------------------------------------------------------------------------- | ||
# (C) British Crown copyright. The Met Office. | ||
# All rights reserved. | ||
# | ||
# Redistribution and use in source and binary forms, with or without | ||
# modification, are permitted provided that the following conditions are met: | ||
# | ||
# * Redistributions of source code must retain the above copyright notice, this | ||
# list of conditions and the following disclaimer. | ||
# | ||
# * Redistributions in binary form must reproduce the above copyright notice, | ||
# this list of conditions and the following disclaimer in the documentation | ||
# and/or other materials provided with the distribution. | ||
# | ||
# * Neither the name of the copyright holder nor the names of its | ||
# contributors may be used to endorse or promote products derived from | ||
# this software without specific prior written permission. | ||
# | ||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | ||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
# POSSIBILITY OF SUCH DAMAGE. | ||
"""CLI to apply a scaling factor to account for a correction linked to the | ||
difference in altitude between the grid point and the site location.""" | ||
|
||
from improver import cli | ||
|
||
|
||
@cli.clizefy | ||
@cli.with_output | ||
def process( | ||
forecast: cli.inputcube, | ||
scaling_factor: cli.inputcube, | ||
*, | ||
site_id_coord: str = "wmo_id", | ||
): | ||
"""Apply a scaling factor to account for a correction linked to the difference | ||
in altitude between the grid point and the site location. | ||
Args: | ||
forecast (iris.cube.Cube): | ||
Percentile forecasts. | ||
rescaling_cube (iris.cube.Cube): | ||
Multiplicative scaling factor to adjust the percentile forecasts. | ||
This cube is expected to contain multiple values for the forecast_period | ||
and forecast_reference_time_hour coordinates. The most appropriate | ||
forecast period and forecast reference_time_hour pair within the | ||
rescaling cube are chosen using the forecast reference time hour from | ||
the forecast and the nearest forecast period that is greater than or | ||
equal to the forecast period of the forecast. This cube is generated | ||
using the estimate_dz_rescaling CLI. | ||
site_id_coord (str): | ||
The name of the site ID coordinate. This defaults to 'wmo_id'. | ||
Returns: | ||
iris.cube.Cube: | ||
Percentile forecasts that have been rescaled to account for a difference | ||
in altitude between the grid point and the site location. | ||
""" | ||
|
||
from improver.calibration.dz_rescaling import ApplyDzRescaling | ||
|
||
return ApplyDzRescaling(site_id_coord=site_id_coord)(forecast, scaling_factor) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
#!/usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||
# ----------------------------------------------------------------------------- | ||
# (C) British Crown copyright. The Met Office. | ||
# All rights reserved. | ||
# | ||
# Redistribution and use in source and binary forms, with or without | ||
# modification, are permitted provided that the following conditions are met: | ||
# | ||
# * Redistributions of source code must retain the above copyright notice, this | ||
# list of conditions and the following disclaimer. | ||
# | ||
# * Redistributions in binary form must reproduce the above copyright notice, | ||
# this list of conditions and the following disclaimer in the documentation | ||
# and/or other materials provided with the distribution. | ||
# | ||
# * Neither the name of the copyright holder nor the names of its | ||
# contributors may be used to endorse or promote products derived from | ||
# this software without specific prior written permission. | ||
# | ||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | ||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
# POSSIBILITY OF SUCH DAMAGE. | ||
"""CLI to estimate a scaling factor to account for a correction linked to the | ||
difference in altitude between the grid point and the site location.""" | ||
|
||
from improver import cli | ||
|
||
|
||
@cli.clizefy | ||
@cli.with_output | ||
def process( | ||
forecast: cli.inputcube, | ||
truth: cli.inputcube, | ||
neighbour_cube: cli.inputcube, | ||
*, | ||
forecast_period: int, | ||
dz_lower_bound: float = None, | ||
dz_upper_bound: float = None, | ||
land_constraint: bool = False, | ||
similar_altitude: bool = False, | ||
site_id_coord: str = "wmo_id", | ||
): | ||
"""Estimate a scaling factor to account for a correction linked to the difference | ||
in altitude between the grid point and the site location. | ||
Args: | ||
forecast (iris.cube.Cube): | ||
Historical percentile forecasts. A 50th percentile forecast is required. | ||
truth (iris.cube.Cube): | ||
Truths that are expected to match the validity times of the forecasts. | ||
neighbour_cube (iris.cube.Cube): | ||
The neighbour cube is a cube of spot-data neighbours and | ||
the spot site information. | ||
forecast_period (int): | ||
The forecast period that is considered representative of | ||
the input forecasts. This is required as the input forecasts could | ||
contain multiple forecast periods. | ||
dz_lower_bound (float): | ||
The lowest acceptable value for the difference in altitude | ||
between the grid point and the site. Sites with a lower | ||
(or more negative) difference in altitude will be excluded. | ||
If the altitude difference is calculated as site altitude minus the | ||
grid point altitude, the lower bound therefore indicates how far below | ||
the orographic surface (i.e. within unresolved valleys) the correction | ||
should be applied. Defaults to None. | ||
dz_upper_bound (float): | ||
The highest acceptable value for the difference in altitude | ||
between the grid point and the site. Sites with a larger | ||
positive difference in altitude will be excluded. | ||
If the altitude difference is calculated as site altitude minus the | ||
grid point altitude, the upper bound therefore indicates how far above | ||
the orographic surface (i.e. on unresolved hills or mountains) the | ||
correction should be applied. Defaults to None. | ||
land_constraint (bool): | ||
Use to select the nearest-with-land-constraint neighbour-selection | ||
method from the neighbour_cube. This means that the grid points | ||
should be land points except for sites where none were found within | ||
the search radius when the neighbour cube was created. May be used | ||
with similar_altitude. | ||
similar_altitude (bool): | ||
Use to select the nearest-with-height-constraint neighbour-selection | ||
method from the neighbour_cube. These are grid points that were found | ||
to be the closest in altitude to the spot site within the search radius | ||
defined when the neighbour cube was created. May be used with | ||
land_constraint. | ||
site_id_coord (str): | ||
The name of the site ID coordinate. This defaults to 'wmo_id'. | ||
Returns: | ||
iris.cube.Cube: | ||
Cube containing a scaling factor computed using the difference | ||
in altitude between the grid point and the site location. | ||
""" | ||
|
||
from improver.calibration.dz_rescaling import EstimateDzRescaling | ||
|
||
plugin = EstimateDzRescaling( | ||
forecast_period=forecast_period, | ||
dz_lower_bound=dz_lower_bound, | ||
dz_upper_bound=dz_upper_bound, | ||
land_constraint=land_constraint, | ||
similar_altitude=similar_altitude, | ||
site_id_coord=site_id_coord, | ||
) | ||
return plugin(forecast, truth, neighbour_cube) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
# -*- coding: utf-8 -*- | ||
# ----------------------------------------------------------------------------- | ||
# (C) British Crown copyright. The Met Office. | ||
# All rights reserved. | ||
# | ||
# Redistribution and use in source and binary forms, with or without | ||
# modification, are permitted provided that the following conditions are met: | ||
# | ||
# * Redistributions of source code must retain the above copyright notice, this | ||
# list of conditions and the following disclaimer. | ||
# | ||
# * Redistributions in binary form must reproduce the above copyright notice, | ||
# this list of conditions and the following disclaimer in the documentation | ||
# and/or other materials provided with the distribution. | ||
# | ||
# * Neither the name of the copyright holder nor the names of its | ||
# contributors may be used to endorse or promote products derived from | ||
# this software without specific prior written permission. | ||
# | ||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | ||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
# POSSIBILITY OF SUCH DAMAGE. | ||
""" | ||
Tests for the apply-dz-rescaling CLI | ||
""" | ||
|
||
import pytest | ||
|
||
from . import acceptance as acc | ||
|
||
pytestmark = [pytest.mark.acc, acc.skip_if_kgo_missing] | ||
CLI = acc.cli_name_with_dashes(__file__) | ||
run_cli = acc.run_cli(CLI) | ||
|
||
|
||
def test_apply_dz_rescaling(tmp_path): | ||
"""Test apply_dz_rescaling CLI.""" | ||
kgo_dir = acc.kgo_root() / "apply-dz-rescaling/" | ||
kgo_path = kgo_dir / "kgo.nc" | ||
forecast_path = kgo_dir / "20230220T1200Z-PT0006H00M-wind_speed_at_10m.nc" | ||
scaled_dz_path = kgo_dir / "scaled_dz.nc" | ||
output_path = tmp_path / "output.nc" | ||
args = [ | ||
forecast_path, | ||
scaled_dz_path, | ||
"--output", | ||
output_path, | ||
] | ||
run_cli(args) | ||
acc.compare(output_path, kgo_path) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
# -*- coding: utf-8 -*- | ||
# ----------------------------------------------------------------------------- | ||
# (C) British Crown copyright. The Met Office. | ||
# All rights reserved. | ||
# | ||
# Redistribution and use in source and binary forms, with or without | ||
# modification, are permitted provided that the following conditions are met: | ||
# | ||
# * Redistributions of source code must retain the above copyright notice, this | ||
# list of conditions and the following disclaimer. | ||
# | ||
# * Redistributions in binary form must reproduce the above copyright notice, | ||
# this list of conditions and the following disclaimer in the documentation | ||
# and/or other materials provided with the distribution. | ||
# | ||
# * Neither the name of the copyright holder nor the names of its | ||
# contributors may be used to endorse or promote products derived from | ||
# this software without specific prior written permission. | ||
# | ||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | ||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
# POSSIBILITY OF SUCH DAMAGE. | ||
""" | ||
Tests for the estimate-dz-rescaling CLI | ||
""" | ||
|
||
import pytest | ||
|
||
from . import acceptance as acc | ||
|
||
pytestmark = [pytest.mark.acc, acc.skip_if_kgo_missing] | ||
CLI = acc.cli_name_with_dashes(__file__) | ||
run_cli = acc.run_cli(CLI) | ||
|
||
|
||
def test_estimate_dz_rescaling(tmp_path): | ||
"""Test estimate_dz_rescaling CLI.""" | ||
kgo_dir = acc.kgo_root() / "estimate-dz-rescaling/" | ||
kgo_path = kgo_dir / "kgo.nc" | ||
forecast_path = kgo_dir / "T1200Z-PT0006H00M-wind_speed_at_10m.nc" | ||
truth_path = kgo_dir / "T1200Z-srfc_wind_sped_spot_truths.nc" | ||
neighbour_path = kgo_dir / "neighbour.nc" | ||
output_path = tmp_path / "output.nc" | ||
args = [ | ||
forecast_path, | ||
truth_path, | ||
neighbour_path, | ||
"--forecast-period", | ||
"6", | ||
"--dz-lower-bound", | ||
"-550", | ||
"--dz-upper-bound", | ||
"550", | ||
"--land-constraint", | ||
"--output", | ||
output_path, | ||
] | ||
run_cli(args) | ||
acc.compare(output_path, kgo_path) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters