-
Notifications
You must be signed in to change notification settings - Fork 100
Support use of Google Film for temporal interpolation #2270
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
906090c
2b63e38
8c43de8
17fc967
6a7b352
0c009eb
b1da7dd
d7af663
706ad8c
e0fa0b5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| #!/usr/bin/env python | ||
| # (C) Crown Copyright, Met Office. All rights reserved. | ||
| # | ||
| # This file is part of 'IMPROVER' and is released under the BSD 3-Clause license. | ||
| # See LICENSE in the root of the repository for full licensing details. | ||
| """CLI to fill gaps in forecast period sequences using temporal interpolation.""" | ||
|
|
||
| from improver import cli | ||
|
|
||
|
|
||
| @cli.clizefy | ||
| @cli.with_output | ||
| def process( | ||
| *cubes: cli.inputcube, | ||
| interval_in_mins: int = None, | ||
| interpolation_method: str = "linear", | ||
| cluster_sources_attribute: str = None, | ||
| interpolation_window_in_hours: int = None, | ||
| model_path: str = None, | ||
| scaling: str = "minmax", | ||
| clipping_bounds: cli.comma_separated_list = (0.0, 1.0), | ||
| ): | ||
| """Fill gaps in forecast period sequences using temporal interpolation. | ||
| Identifies missing forecast periods in a sequence and fills them using | ||
| temporal interpolation. Can optionally regenerate periods at forecast | ||
| source transitions when cluster_sources configuration is provided. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Your comments here and below talk about forecast periods but that's potentially misleading. For the cube shown below, where the data is all valid at the same time I have a set of forecast periods due to differing forecast reference times: It is not appropriate to use this tool to try and fill in a missing forecast initialisation time but that's what would happen in this case. The IMPROVER conventions are to have a single validity time in a cube, which this example adheres to, it simply isn't structured in the way we normally do it. All of this is to simply say that I think it is important to make clear here that the intention is to fill in missing validity times in a sequence of validity times, providing a more complete forecast evolution through time. |
||
| Args: | ||
| cubes (iris.cube.CubeList or iris.cube.Cube): | ||
| A cube or cubelist containing cubes with potentially missing | ||
| forecast periods. Can be a single Cube with forecast_period as | ||
| a dimension coordinate (will be sliced automatically), or multiple | ||
| individual cubes representing different forecast periods. All cubes | ||
| should have forecast_period coordinates and represent the same | ||
| diagnostic at different forecast periods. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See comment above as to why this is potentially misleading. |
||
| interval_in_mins (int): | ||
| The expected interval between forecast periods in minutes. | ||
| Used to identify gaps in the sequence. If not provided, gaps | ||
| will not be filled, but periods can still be regenerated if | ||
| cluster_sources_attribute is set. | ||
| interpolation_method (str): | ||
| ["linear", "solar", "daynight", "google_film"] | ||
| Method of interpolation to use. Default is "linear". | ||
| - "linear": Standard linear interpolation | ||
| - "solar": Interpolation scaled by solar elevation angle | ||
| - "daynight": Linear interpolation with night-time values set to zero | ||
| - "google_film": Deep learning model for frame interpolation | ||
| cluster_sources_attribute (str): | ||
| Name of cube attribute containing cluster sources dictionary. | ||
| This dictionary maps realization indices to their forecast sources | ||
| and periods. When provided with interpolation_window_in_hours, | ||
| enables identification and regeneration of forecast periods at | ||
| source transitions. Format: {realization_index: {source_name: [periods]}} | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sufficiently au fait with the clustering stuff yet to understand how the forecast period / validity time / forecast reference time coordinates are used across models and whether that's guided you towards all the discussion of forecast periods here. |
||
| interpolation_window_in_hours (int): | ||
| Time window (in hours) to use as a +/- range around forecast | ||
| source transition points. Used with cluster_sources_attribute | ||
| to identify which periods should be regenerated. For example, | ||
| if set to 3 hours and a transition occurs at T+24, periods | ||
| T+21, T+24, and T+27 will be regenerated if they fall within | ||
| the sequence. | ||
| model_path (str): | ||
| Path to the TensorFlow Hub module for the Google FILM model. | ||
| Required when interpolation_method is "google_film". Can be a | ||
| local path or a TensorFlow Hub URL. | ||
| scaling (str): | ||
| Scaling method to apply to the data before interpolation when | ||
| using "google_film" method. Options are "log10" or "minmax". | ||
| Default is "minmax". | ||
| clipping_bounds (str): | ||
| Comma-separated lower and upper bounds for clipping interpolated | ||
| values when using "google_film" method. E.g. "0.0,1.0". | ||
| Default is "0.0,1.0". | ||
| Returns: | ||
| iris.cube.Cube: | ||
| A single merged cube with all forecast periods filled. The cube | ||
| will have time as a dimension coordinate and will include: | ||
| - All original time slices (except those regenerated at transitions) | ||
| - Interpolated slices filling identified gaps | ||
| - Regenerated slices at source transitions (if configured) | ||
| """ | ||
| from improver.utilities.temporal_interpolation import ForecastPeriodGapFiller | ||
|
|
||
| plugin = ForecastPeriodGapFiller( | ||
| interval_in_minutes=interval_in_mins, | ||
| interpolation_method=interpolation_method, | ||
| cluster_sources_attribute=cluster_sources_attribute, | ||
| interpolation_window_in_hours=interpolation_window_in_hours, | ||
| model_path=model_path, | ||
| scaling=scaling, | ||
| clipping_bounds=clipping_bounds, | ||
| ) | ||
|
|
||
| result = plugin.process(*cubes) | ||
|
|
||
| return result | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,6 +20,9 @@ def process( | |
| accumulation: bool = False, | ||
| max: bool = False, | ||
| min: bool = False, | ||
| model_path: str = None, | ||
| scaling: str = "minmax", | ||
| clipping_bounds: cli.comma_separated_list = None, | ||
| ): | ||
| """Interpolate data between validity times. | ||
|
|
||
|
|
@@ -47,11 +50,12 @@ def process( | |
| by a comma. | ||
| If times are set, interval_in_mins can not be used. | ||
| interpolation_method (str): | ||
| ["linear", "solar", "daynight"] | ||
| ["linear", "solar", "daynight", "google_film"] | ||
| Specifies the interpolation method; | ||
| solar interpolates using the solar elevation, | ||
| daynight uses linear interpolation but sets night time points to | ||
| 0.0 linear is linear interpolation. | ||
| 0.0, linear is linear interpolation, google_film uses a deep | ||
| learning model for frame interpolation. | ||
| accumulation: | ||
| Set True if the diagnostic being temporally interpolated is a | ||
| period accumulation. The output will be renormalised to ensure | ||
|
|
@@ -69,6 +73,18 @@ def process( | |
| period minimum. Trends between adjacent input periods will be used | ||
| to provide variation across the interpolated periods where these | ||
| are consistent with the inputs. | ||
| model_path (str): | ||
| Path to the TensorFlow model for google_film interpolation. | ||
| Required when interpolation_method is "google_film". Can be a | ||
| local path or a TensorFlow Hub URL. | ||
| scaling (str): | ||
| Scaling method to apply to the data before interpolation when | ||
| using google_film method. Options are "log10" or "minmax". | ||
| Default is "minmax". | ||
| clipping_bounds (str): | ||
| Comma-separated lower and upper bounds for clipping interpolated | ||
| values when using google_film method. E.g. "0.0,1.0". | ||
| Default is "0.0,1.0". | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should make clear that the clipping is applied to the scaled values prior to rescaling and so the returned values may not be within these bounds. |
||
| Returns: | ||
| iris.cube.CubeList: | ||
| A list of cubes interpolated to the desired times. The | ||
|
|
@@ -88,12 +104,21 @@ def process( | |
| if times is not None: | ||
| times = [cycletime_to_datetime(timestr) for timestr in times] | ||
|
|
||
| # Convert clipping_bounds from comma-separated list to tuple | ||
| if clipping_bounds is not None: | ||
| clipping_bounds = tuple(float(x) for x in clipping_bounds) | ||
| else: | ||
| clipping_bounds = (0.0, 1.0) | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why can you not handle clipping bounds in the same way as the other CLI to avoid adding things here that Carwyn will have to later move to a meta plugin? |
||
| result = TemporalInterpolation( | ||
| interval_in_minutes=interval_in_mins, | ||
| times=times, | ||
| interpolation_method=interpolation_method, | ||
| accumulation=accumulation, | ||
| max=max, | ||
| min=min, | ||
| model_path=model_path, | ||
| scaling=scaling, | ||
| clipping_bounds=clipping_bounds, | ||
| )(start_cube, end_cube) | ||
| return MergeCubes()(result) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please update the list of exclusions in environment_b to indicate that the temporal interpolation / gap filling CLIs are unsupported by that environment:
improver/envs/environment_b.yml
Line 2 in e0fa0b5