Source code for improver.utilities.deterministic_realization_selector
# (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.
"""Module containing a deterministic realization selector."""
import json
import iris
from iris.cube import Cube, CubeList
from improver import PostProcessingPlugin
[docs]
class DeterministicRealizationSelector(PostProcessingPlugin):
"""Plugin to extract a deterministic realization from a set of realizations that
have been clustered using the improver.clustering.realization_clustering plugin.
"""
[docs]
def __init__(
self,
target_realization_number: int = 0,
attribute: str = "primary_input_realizations_to_clusters",
) -> None:
"""Initialise the plugin.
Args:
target_realization_number:
The number of the realization of interest. Default value = 0.
attribute:
The attribute of the cluster cube, used to identify target realization,
and it's associated cluster.
Default value = "primary_input_realizations_to_clusters".
"""
self.target_realization_number = target_realization_number
self.attribute = attribute
[docs]
def find_target_key(self, cluster_cube: Cube) -> int | None:
"""Find the key (cluster) of the cluster cube, that contains the target
realization. This cluster will become the deterministic realization.
Args:
cluster_cube:
Clustered cube with the attribute :
"primary_input_realizations_to_clusters", as a dictionary,
to be searched through for the target realization.
Returns:
- Key (cluster) that contains the target realization.
"""
# Extract the attribute and convert it into a dictionary
try:
cube_attribute = cluster_cube.attributes[self.attribute]
cube_attribute_dict = json.loads(cube_attribute)
except KeyError:
# Return None as this case is handled in the process method.
return None
# Search through dictionary, to find target realization's key
target_key = None
for key, value in cube_attribute_dict.items():
if self.target_realization_number in value:
target_key = key
break
else:
target_key = None
return target_key
[docs]
def process(self, cubes: CubeList) -> Cube:
"""Extracts the target deterministic realization from the forecast cubes.
Identifies the cluster cube, (containing the attribute:
"primary_input_realizations_to_clusters") and the
forecast cube from the input cubelist. Determines the target realization,
and its cluster, extracts this from the forecast cube and
returns the deterministic_realization_cube.
Args:
cubes:
A list of two cubes containing a forecast and a cluster cube.
The cluster cube will contain the attribute:
"primary_input_realizations_to_clusters".
This will be used to split the forecasts and cluster cube and
determine which realizations to extract from the forecast cube.
Returns:
- Forecast cube containing only the cluster with the target realization.
This cluster becomes our deterministic realization.
Raises:
AttributeError:
- If the target realization, does not exist or cannot be extracted.
"""
cluster_cube, forecast_cube = self.split_input_cubelist(cubes)
target_key = self.find_target_key(cluster_cube)
if target_key is None:
raise AttributeError(
f"Target realization not found in the {self.attribute} attribute."
)
deterministic_realization_cube = self.extract_cluster_from_cube(
target_key, forecast_cube
)
return deterministic_realization_cube