diff --git a/src/CSET/loaders/spatial_difference_field.py b/src/CSET/loaders/spatial_difference_field.py index d90fa1702..525c59ea6 100644 --- a/src/CSET/loaders/spatial_difference_field.py +++ b/src/CSET/loaders/spatial_difference_field.py @@ -217,7 +217,7 @@ def load(conf: Config): ]: base_model = models[0] yield RawRecipe( - recipe=f"mlevel_spatial_difference_case_aggregation_mean_{atype}.yaml", + recipe=f"level_spatial_difference_case_aggregation_mean_{atype}.yaml", variables={ "VARNAME": field, "LEVELTYPE": "model_level_number", diff --git a/src/CSET/operators/filters.py b/src/CSET/operators/filters.py index 465292366..4485a95ac 100644 --- a/src/CSET/operators/filters.py +++ b/src/CSET/operators/filters.py @@ -15,6 +15,7 @@ """Operators to perform various kind of filtering.""" import logging +from typing import Literal import iris import iris.cube @@ -70,8 +71,9 @@ def apply_mask( def filter_cubes( cube: iris.cube.Cube | iris.cube.CubeList, constraint: iris.Constraint, + per_model: Literal[True] | Literal[False] = False, **kwargs, -) -> iris.cube.Cube: +) -> iris.cube.Cube | iris.cube.CubeList: """Filter a CubeList down to a single Cube based on a constraint. Arguments @@ -80,28 +82,54 @@ def filter_cubes( Cube(s) to filter constraint: iris.Constraint Constraint to extract + per_model: bool + If True, the filter is expected to return a CubeList with + one cube per model, otherwise a single cube is expected. Returns ------- - iris.cube.Cube + iris.cube.Cube | iris.cube.CubeList Raises ------ ValueError If the constraint doesn't produce a single cube. """ + model_names = set() + + if per_model: + for c in iter_maybe(cube): + model_names.add(c.attributes.get("model_name", None)) + if None in model_names: + raise ValueError( + "per_model mode can only be used if all cubes have a model_name attribute." + ) + filtered_cubes = cube.extract(constraint) - # Return directly if already a cube. - if isinstance(filtered_cubes, iris.cube.Cube): - return filtered_cubes - # Check filtered cubes is a CubeList containing one cube. - if isinstance(filtered_cubes, iris.cube.CubeList) and len(filtered_cubes) == 1: - return filtered_cubes[0] - else: + + if per_model: + if isinstance(filtered_cubes, iris.cube.Cube) and len(model_names) == 1: + return iris.cube.CubeList((filtered_cubes,)) + if isinstance(filtered_cubes, iris.cube.CubeList) and len( + filtered_cubes + ) == len(model_names): + return filtered_cubes raise ValueError( - f"Constraint doesn't produce single cube. Constraint: {constraint}" + f"Constraint doesn't produce one cube per model. Constraint: {constraint}" f"\nSource: {cube}\nResult: {filtered_cubes}" ) + else: + # Return directly if already a cube. + if isinstance(filtered_cubes, iris.cube.Cube): + return filtered_cubes + # Check filtered cubes is a CubeList containing one cube. + if isinstance(filtered_cubes, iris.cube.CubeList) and len(filtered_cubes) == 1: + return filtered_cubes[0] + else: + raise ValueError( + f"Constraint doesn't produce single cube. Constraint: {constraint}" + f"\nSource: {cube}\nResult: {filtered_cubes}" + ) def filter_multiple_cubes( diff --git a/src/CSET/recipes/level_fields/generic_level_domain_mean_time_series.yaml b/src/CSET/recipes/level_fields/generic_level_domain_mean_time_series.yaml index aea234d54..a69670e5d 100644 --- a/src/CSET/recipes/level_fields/generic_level_domain_mean_time_series.yaml +++ b/src/CSET/recipes/level_fields/generic_level_domain_mean_time_series.yaml @@ -6,6 +6,12 @@ steps: - operator: read.read_cubes file_paths: $INPUT_PATHS model_names: $MODEL_NAME + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints varname_constraint: @@ -15,8 +21,6 @@ steps: operator: constraints.generate_level_constraint coordinate: $LEVELTYPE levels: $LEVEL - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: collapse.collapse coordinate: [grid_latitude, grid_longitude] diff --git a/src/CSET/recipes/level_fields/generic_level_domain_mean_time_series_case_aggregation_all.yaml b/src/CSET/recipes/level_fields/generic_level_domain_mean_time_series_case_aggregation_all.yaml index e09a51bb8..06ed0ffe0 100644 --- a/src/CSET/recipes/level_fields/generic_level_domain_mean_time_series_case_aggregation_all.yaml +++ b/src/CSET/recipes/level_fields/generic_level_domain_mean_time_series_case_aggregation_all.yaml @@ -6,6 +6,10 @@ steps: - operator: read.read_cubes file_paths: $INPUT_PATHS model_names: $MODEL_NAME + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints varname_constraint: diff --git a/src/CSET/recipes/level_fields/generic_level_domain_mean_time_series_case_aggregation_hour_of_day.yaml b/src/CSET/recipes/level_fields/generic_level_domain_mean_time_series_case_aggregation_hour_of_day.yaml index 222735f22..63d43a21d 100644 --- a/src/CSET/recipes/level_fields/generic_level_domain_mean_time_series_case_aggregation_hour_of_day.yaml +++ b/src/CSET/recipes/level_fields/generic_level_domain_mean_time_series_case_aggregation_hour_of_day.yaml @@ -10,6 +10,10 @@ steps: - operator: read.read_cubes file_paths: $INPUT_PATHS model_names: $MODEL_NAME + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints varname_constraint: diff --git a/src/CSET/recipes/level_fields/generic_level_domain_mean_time_series_case_aggregation_lead_time.yaml b/src/CSET/recipes/level_fields/generic_level_domain_mean_time_series_case_aggregation_lead_time.yaml index 321277b89..7df64f02b 100644 --- a/src/CSET/recipes/level_fields/generic_level_domain_mean_time_series_case_aggregation_lead_time.yaml +++ b/src/CSET/recipes/level_fields/generic_level_domain_mean_time_series_case_aggregation_lead_time.yaml @@ -10,6 +10,10 @@ steps: - operator: read.read_cubes file_paths: $INPUT_PATHS model_names: $MODEL_NAME + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints varname_constraint: diff --git a/src/CSET/recipes/level_fields/generic_level_domain_mean_time_series_case_aggregation_validity_time.yaml b/src/CSET/recipes/level_fields/generic_level_domain_mean_time_series_case_aggregation_validity_time.yaml index cbbadefb0..0d635ab1d 100644 --- a/src/CSET/recipes/level_fields/generic_level_domain_mean_time_series_case_aggregation_validity_time.yaml +++ b/src/CSET/recipes/level_fields/generic_level_domain_mean_time_series_case_aggregation_validity_time.yaml @@ -10,6 +10,10 @@ steps: - operator: read.read_cubes file_paths: $INPUT_PATHS model_names: $MODEL_NAME + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints varname_constraint: diff --git a/src/CSET/recipes/level_fields/generic_level_domain_mean_vertical_profile_series.yaml b/src/CSET/recipes/level_fields/generic_level_domain_mean_vertical_profile_series.yaml index 0f530ce6a..73fc08329 100644 --- a/src/CSET/recipes/level_fields/generic_level_domain_mean_vertical_profile_series.yaml +++ b/src/CSET/recipes/level_fields/generic_level_domain_mean_vertical_profile_series.yaml @@ -9,6 +9,12 @@ steps: - operator: read.read_cubes file_paths: $INPUT_PATHS model_names: $MODEL_NAME + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints variable_constraint: @@ -18,8 +24,6 @@ steps: operator: constraints.generate_level_constraint coordinate: $LEVELTYPE levels: "*" - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: collapse.collapse coordinate: [grid_latitude, grid_longitude] diff --git a/src/CSET/recipes/level_fields/generic_level_domain_mean_vertical_profile_series_case_aggregation_all.yaml b/src/CSET/recipes/level_fields/generic_level_domain_mean_vertical_profile_series_case_aggregation_all.yaml index c3e8cdbf1..727186d86 100644 --- a/src/CSET/recipes/level_fields/generic_level_domain_mean_vertical_profile_series_case_aggregation_all.yaml +++ b/src/CSET/recipes/level_fields/generic_level_domain_mean_vertical_profile_series_case_aggregation_all.yaml @@ -10,6 +10,10 @@ steps: - operator: read.read_cubes file_paths: $INPUT_PATHS model_names: $MODEL_NAME + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints variable_constraint: diff --git a/src/CSET/recipes/level_fields/generic_level_domain_mean_vertical_profile_series_case_aggregation_hour_of_day.yaml b/src/CSET/recipes/level_fields/generic_level_domain_mean_vertical_profile_series_case_aggregation_hour_of_day.yaml index abb010022..fbbffd10e 100644 --- a/src/CSET/recipes/level_fields/generic_level_domain_mean_vertical_profile_series_case_aggregation_hour_of_day.yaml +++ b/src/CSET/recipes/level_fields/generic_level_domain_mean_vertical_profile_series_case_aggregation_hour_of_day.yaml @@ -11,6 +11,12 @@ steps: - operator: read.read_cubes file_paths: $INPUT_PATHS model_names: $MODEL_NAME + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints variable_constraint: @@ -20,8 +26,6 @@ steps: operator: constraints.generate_level_constraint coordinate: $LEVELTYPE levels: "*" - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: aggregate.ensure_aggregatable_across_cases diff --git a/src/CSET/recipes/level_fields/generic_level_domain_mean_vertical_profile_series_case_aggregation_lead_time.yaml b/src/CSET/recipes/level_fields/generic_level_domain_mean_vertical_profile_series_case_aggregation_lead_time.yaml index fe87c060d..58969b96a 100644 --- a/src/CSET/recipes/level_fields/generic_level_domain_mean_vertical_profile_series_case_aggregation_lead_time.yaml +++ b/src/CSET/recipes/level_fields/generic_level_domain_mean_vertical_profile_series_case_aggregation_lead_time.yaml @@ -11,6 +11,12 @@ steps: - operator: read.read_cubes file_paths: $INPUT_PATHS model_names: $MODEL_NAME + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints variable_constraint: @@ -20,8 +26,6 @@ steps: operator: constraints.generate_level_constraint coordinate: $LEVELTYPE levels: "*" - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: aggregate.ensure_aggregatable_across_cases diff --git a/src/CSET/recipes/level_fields/generic_level_domain_mean_vertical_profile_series_case_aggregation_validity_time.yaml b/src/CSET/recipes/level_fields/generic_level_domain_mean_vertical_profile_series_case_aggregation_validity_time.yaml index 873466054..283f1c0ac 100644 --- a/src/CSET/recipes/level_fields/generic_level_domain_mean_vertical_profile_series_case_aggregation_validity_time.yaml +++ b/src/CSET/recipes/level_fields/generic_level_domain_mean_vertical_profile_series_case_aggregation_validity_time.yaml @@ -11,6 +11,12 @@ steps: - operator: read.read_cubes file_paths: $INPUT_PATHS model_names: $MODEL_NAME + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints variable_constraint: @@ -20,8 +26,6 @@ steps: operator: constraints.generate_level_constraint coordinate: $LEVELTYPE levels: "*" - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: aggregate.ensure_aggregatable_across_cases diff --git a/src/CSET/recipes/level_fields/generic_level_histogram_series.yaml b/src/CSET/recipes/level_fields/generic_level_histogram_series.yaml index c6275b07d..a1ec00487 100644 --- a/src/CSET/recipes/level_fields/generic_level_histogram_series.yaml +++ b/src/CSET/recipes/level_fields/generic_level_histogram_series.yaml @@ -13,6 +13,12 @@ steps: - operator: read.read_cubes model_names: $MODEL_NAME file_paths: $INPUT_PATHS + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints variable_constraint: @@ -26,8 +32,6 @@ steps: operator: constraints.generate_level_constraint coordinate: $LEVELTYPE levels: $LEVEL - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: plot.plot_histogram_series sequence_coordinate: $SEQUENCE diff --git a/src/CSET/recipes/level_fields/generic_level_histogram_series_case_aggregation_all.yaml b/src/CSET/recipes/level_fields/generic_level_histogram_series_case_aggregation_all.yaml index a82b5c0d9..a799fe2fb 100644 --- a/src/CSET/recipes/level_fields/generic_level_histogram_series_case_aggregation_all.yaml +++ b/src/CSET/recipes/level_fields/generic_level_histogram_series_case_aggregation_all.yaml @@ -15,6 +15,12 @@ steps: - operator: read.read_cubes model_names: $MODEL_NAME file_paths: $INPUT_PATHS + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints variable_constraint: @@ -28,8 +34,6 @@ steps: operator: constraints.generate_level_constraint coordinate: $LEVELTYPE levels: $LEVEL - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: aggregate.ensure_aggregatable_across_cases diff --git a/src/CSET/recipes/level_fields/generic_level_histogram_series_case_aggregation_hour_of_day.yaml b/src/CSET/recipes/level_fields/generic_level_histogram_series_case_aggregation_hour_of_day.yaml index 23dc7a59b..028673ab7 100644 --- a/src/CSET/recipes/level_fields/generic_level_histogram_series_case_aggregation_hour_of_day.yaml +++ b/src/CSET/recipes/level_fields/generic_level_histogram_series_case_aggregation_hour_of_day.yaml @@ -15,6 +15,12 @@ steps: - operator: read.read_cubes file_paths: $INPUT_PATHS model_names: $MODEL_NAME + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints variable_constraint: @@ -28,8 +34,6 @@ steps: operator: constraints.generate_level_constraint coordinate: $LEVELTYPE levels: $LEVEL - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: aggregate.ensure_aggregatable_across_cases diff --git a/src/CSET/recipes/level_fields/generic_level_histogram_series_case_aggregation_lead_time.yaml b/src/CSET/recipes/level_fields/generic_level_histogram_series_case_aggregation_lead_time.yaml index 93cd960bf..da4fc8def 100644 --- a/src/CSET/recipes/level_fields/generic_level_histogram_series_case_aggregation_lead_time.yaml +++ b/src/CSET/recipes/level_fields/generic_level_histogram_series_case_aggregation_lead_time.yaml @@ -15,6 +15,12 @@ steps: - operator: read.read_cubes model_names: $MODEL_NAME file_paths: $INPUT_PATHS + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints variable_constraint: @@ -28,8 +34,6 @@ steps: operator: constraints.generate_level_constraint coordinate: $LEVELTYPE levels: $LEVEL - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: aggregate.ensure_aggregatable_across_cases diff --git a/src/CSET/recipes/level_fields/generic_level_histogram_series_case_aggregation_validity_time.yaml b/src/CSET/recipes/level_fields/generic_level_histogram_series_case_aggregation_validity_time.yaml index 611e929c2..c3a21f4f5 100644 --- a/src/CSET/recipes/level_fields/generic_level_histogram_series_case_aggregation_validity_time.yaml +++ b/src/CSET/recipes/level_fields/generic_level_histogram_series_case_aggregation_validity_time.yaml @@ -15,6 +15,12 @@ steps: - operator: read.read_cubes file_paths: $INPUT_PATHS model_names: $MODEL_NAME + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints variable_constraint: @@ -28,8 +34,6 @@ steps: operator: constraints.generate_level_constraint coordinate: $LEVELTYPE levels: $LEVEL - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: aggregate.ensure_aggregatable_across_cases diff --git a/src/CSET/recipes/level_fields/generic_level_spatial_plot_sequence.yaml b/src/CSET/recipes/level_fields/generic_level_spatial_plot_sequence.yaml index 587f04a55..e8ca5c3cb 100644 --- a/src/CSET/recipes/level_fields/generic_level_spatial_plot_sequence.yaml +++ b/src/CSET/recipes/level_fields/generic_level_spatial_plot_sequence.yaml @@ -6,6 +6,12 @@ description: | steps: - operator: read.read_cube file_paths: $INPUT_PATHS + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints variable_constraint: @@ -15,8 +21,6 @@ steps: operator: constraints.generate_level_constraint coordinate: $LEVELTYPE levels: $LEVEL - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: collapse.collapse coordinate: [time] diff --git a/src/CSET/recipes/level_fields/generic_level_spatial_plot_sequence_case_aggregation_mean_all.yaml b/src/CSET/recipes/level_fields/generic_level_spatial_plot_sequence_case_aggregation_mean_all.yaml index 7d81d6537..31fcb5450 100644 --- a/src/CSET/recipes/level_fields/generic_level_spatial_plot_sequence_case_aggregation_mean_all.yaml +++ b/src/CSET/recipes/level_fields/generic_level_spatial_plot_sequence_case_aggregation_mean_all.yaml @@ -7,6 +7,10 @@ description: | steps: - operator: read.read_cubes file_paths: $INPUT_PATHS + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints variable_constraint: diff --git a/src/CSET/recipes/level_fields/generic_level_spatial_plot_sequence_case_aggregation_mean_hour_of_day.yaml b/src/CSET/recipes/level_fields/generic_level_spatial_plot_sequence_case_aggregation_mean_hour_of_day.yaml index c6f873ea2..32c0a3e66 100644 --- a/src/CSET/recipes/level_fields/generic_level_spatial_plot_sequence_case_aggregation_mean_hour_of_day.yaml +++ b/src/CSET/recipes/level_fields/generic_level_spatial_plot_sequence_case_aggregation_mean_hour_of_day.yaml @@ -7,6 +7,12 @@ description: | steps: - operator: read.read_cubes file_paths: $INPUT_PATHS + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints variable_constraint: @@ -16,8 +22,6 @@ steps: operator: constraints.generate_level_constraint coordinate: $LEVELTYPE levels: $LEVEL - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: aggregate.ensure_aggregatable_across_cases diff --git a/src/CSET/recipes/level_fields/generic_level_spatial_plot_sequence_case_aggregation_mean_lead_time.yaml b/src/CSET/recipes/level_fields/generic_level_spatial_plot_sequence_case_aggregation_mean_lead_time.yaml index f7d3b11bb..be54f293d 100644 --- a/src/CSET/recipes/level_fields/generic_level_spatial_plot_sequence_case_aggregation_mean_lead_time.yaml +++ b/src/CSET/recipes/level_fields/generic_level_spatial_plot_sequence_case_aggregation_mean_lead_time.yaml @@ -7,6 +7,12 @@ description: | steps: - operator: read.read_cubes file_paths: $INPUT_PATHS + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints variable_constraint: @@ -16,8 +22,6 @@ steps: operator: constraints.generate_level_constraint coordinate: $LEVELTYPE levels: $LEVEL - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: aggregate.ensure_aggregatable_across_cases diff --git a/src/CSET/recipes/level_fields/generic_level_spatial_plot_sequence_case_aggregation_mean_validity_time.yaml b/src/CSET/recipes/level_fields/generic_level_spatial_plot_sequence_case_aggregation_mean_validity_time.yaml index 9e58615ec..dc550ced7 100644 --- a/src/CSET/recipes/level_fields/generic_level_spatial_plot_sequence_case_aggregation_mean_validity_time.yaml +++ b/src/CSET/recipes/level_fields/generic_level_spatial_plot_sequence_case_aggregation_mean_validity_time.yaml @@ -7,6 +7,12 @@ description: | steps: - operator: read.read_cubes file_paths: $INPUT_PATHS + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints variable_constraint: @@ -16,8 +22,6 @@ steps: operator: constraints.generate_level_constraint coordinate: $LEVELTYPE levels: $LEVEL - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: aggregate.ensure_aggregatable_across_cases diff --git a/src/CSET/recipes/level_fields/level_spatial_difference.yaml b/src/CSET/recipes/level_fields/level_spatial_difference.yaml index 5d50945c8..7e1f219f1 100644 --- a/src/CSET/recipes/level_fields/level_spatial_difference.yaml +++ b/src/CSET/recipes/level_fields/level_spatial_difference.yaml @@ -6,6 +6,12 @@ steps: - operator: read.read_cubes file_paths: $INPUT_PATHS model_names: [$BASE_MODEL, $OTHER_MODEL] + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints varname_constraint: @@ -19,8 +25,6 @@ steps: operator: constraints.generate_level_constraint coordinate: $LEVELTYPE levels: $LEVEL - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: collapse.collapse coordinate: [time] diff --git a/src/CSET/recipes/level_fields/level_spatial_difference_case_aggregation_mean_all.yaml b/src/CSET/recipes/level_fields/level_spatial_difference_case_aggregation_mean_all.yaml index cbc9b92ea..1d7c96174 100644 --- a/src/CSET/recipes/level_fields/level_spatial_difference_case_aggregation_mean_all.yaml +++ b/src/CSET/recipes/level_fields/level_spatial_difference_case_aggregation_mean_all.yaml @@ -7,6 +7,10 @@ description: | steps: - operator: read.read_cubes file_paths: $INPUT_PATHS + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints varname_constraint: diff --git a/src/CSET/recipes/level_fields/level_spatial_difference_case_aggregation_mean_hour_of_day.yaml b/src/CSET/recipes/level_fields/level_spatial_difference_case_aggregation_mean_hour_of_day.yaml index 2b71fe22e..8e593f4f6 100644 --- a/src/CSET/recipes/level_fields/level_spatial_difference_case_aggregation_mean_hour_of_day.yaml +++ b/src/CSET/recipes/level_fields/level_spatial_difference_case_aggregation_mean_hour_of_day.yaml @@ -8,6 +8,10 @@ steps: - operator: read.read_cubes file_paths: $INPUT_PATHS model_names: [$BASE_MODEL, $OTHER_MODEL] + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints varname_constraint: diff --git a/src/CSET/recipes/level_fields/level_spatial_difference_case_aggregation_mean_lead_time.yaml b/src/CSET/recipes/level_fields/level_spatial_difference_case_aggregation_mean_lead_time.yaml index 2bacc8ce2..fedcf5a11 100644 --- a/src/CSET/recipes/level_fields/level_spatial_difference_case_aggregation_mean_lead_time.yaml +++ b/src/CSET/recipes/level_fields/level_spatial_difference_case_aggregation_mean_lead_time.yaml @@ -8,6 +8,10 @@ steps: - operator: read.read_cubes file_paths: $INPUT_PATHS model_names: [$BASE_MODEL, $OTHER_MODEL] + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints varname_constraint: diff --git a/src/CSET/recipes/level_fields/level_spatial_difference_case_aggregation_mean_validity_time.yaml b/src/CSET/recipes/level_fields/level_spatial_difference_case_aggregation_mean_validity_time.yaml index e4d8c6e98..020366122 100644 --- a/src/CSET/recipes/level_fields/level_spatial_difference_case_aggregation_mean_validity_time.yaml +++ b/src/CSET/recipes/level_fields/level_spatial_difference_case_aggregation_mean_validity_time.yaml @@ -8,6 +8,10 @@ steps: - operator: read.read_cubes file_paths: $INPUT_PATHS model_names: [$BASE_MODEL, $OTHER_MODEL] + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints varname_constraint: diff --git a/src/CSET/recipes/level_fields/transect.yaml b/src/CSET/recipes/level_fields/transect.yaml index 0da565aa2..a0c072736 100644 --- a/src/CSET/recipes/level_fields/transect.yaml +++ b/src/CSET/recipes/level_fields/transect.yaml @@ -10,6 +10,10 @@ description: | steps: - operator: read.read_cube file_paths: $INPUT_PATHS + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints cell_method_constraint: diff --git a/src/CSET/recipes/surface_fields/generic_surface_domain_mean_time_series.yaml b/src/CSET/recipes/surface_fields/generic_surface_domain_mean_time_series.yaml index a6334c6c1..bc80a39e4 100644 --- a/src/CSET/recipes/surface_fields/generic_surface_domain_mean_time_series.yaml +++ b/src/CSET/recipes/surface_fields/generic_surface_domain_mean_time_series.yaml @@ -6,6 +6,12 @@ steps: - operator: read.read_cubes file_paths: $INPUT_PATHS model_names: $MODEL_NAME + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints varname_constraint: @@ -19,8 +25,6 @@ steps: operator: constraints.generate_level_constraint coordinate: "pressure" levels: [] - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: collapse.collapse coordinate: [grid_latitude, grid_longitude] diff --git a/src/CSET/recipes/surface_fields/generic_surface_domain_mean_time_series_case_aggregation_all.yaml b/src/CSET/recipes/surface_fields/generic_surface_domain_mean_time_series_case_aggregation_all.yaml index 54afe80c6..03c32b219 100644 --- a/src/CSET/recipes/surface_fields/generic_surface_domain_mean_time_series_case_aggregation_all.yaml +++ b/src/CSET/recipes/surface_fields/generic_surface_domain_mean_time_series_case_aggregation_all.yaml @@ -10,6 +10,10 @@ steps: - operator: read.read_cubes file_paths: $INPUT_PATHS model_names: $MODEL_NAME + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints varname_constraint: diff --git a/src/CSET/recipes/surface_fields/generic_surface_domain_mean_time_series_case_aggregation_hour_of_day.yaml b/src/CSET/recipes/surface_fields/generic_surface_domain_mean_time_series_case_aggregation_hour_of_day.yaml index 7e06a90b3..d1c7be7d4 100644 --- a/src/CSET/recipes/surface_fields/generic_surface_domain_mean_time_series_case_aggregation_hour_of_day.yaml +++ b/src/CSET/recipes/surface_fields/generic_surface_domain_mean_time_series_case_aggregation_hour_of_day.yaml @@ -10,6 +10,12 @@ steps: - operator: read.read_cubes file_paths: $INPUT_PATHS model_names: $MODEL_NAME + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints varname_constraint: @@ -23,8 +29,6 @@ steps: operator: constraints.generate_level_constraint coordinate: "pressure" levels: [] - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: aggregate.ensure_aggregatable_across_cases diff --git a/src/CSET/recipes/surface_fields/generic_surface_domain_mean_time_series_case_aggregation_lead_time.yaml b/src/CSET/recipes/surface_fields/generic_surface_domain_mean_time_series_case_aggregation_lead_time.yaml index d81b30fc6..03cd68f74 100644 --- a/src/CSET/recipes/surface_fields/generic_surface_domain_mean_time_series_case_aggregation_lead_time.yaml +++ b/src/CSET/recipes/surface_fields/generic_surface_domain_mean_time_series_case_aggregation_lead_time.yaml @@ -10,6 +10,12 @@ steps: - operator: read.read_cubes file_paths: $INPUT_PATHS model_names: $MODEL_NAME + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints varname_constraint: @@ -23,8 +29,6 @@ steps: operator: constraints.generate_level_constraint coordinate: "pressure" levels: [] - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: aggregate.ensure_aggregatable_across_cases diff --git a/src/CSET/recipes/surface_fields/generic_surface_domain_mean_time_series_case_aggregation_validity_time.yaml b/src/CSET/recipes/surface_fields/generic_surface_domain_mean_time_series_case_aggregation_validity_time.yaml index 9aed477d9..a67c72851 100644 --- a/src/CSET/recipes/surface_fields/generic_surface_domain_mean_time_series_case_aggregation_validity_time.yaml +++ b/src/CSET/recipes/surface_fields/generic_surface_domain_mean_time_series_case_aggregation_validity_time.yaml @@ -10,6 +10,12 @@ steps: - operator: read.read_cubes file_paths: $INPUT_PATHS model_names: $MODEL_NAME + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints varname_constraint: @@ -23,8 +29,6 @@ steps: operator: constraints.generate_level_constraint coordinate: "pressure" levels: [] - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: aggregate.ensure_aggregatable_across_cases diff --git a/src/CSET/recipes/surface_fields/generic_surface_histogram_series.yaml b/src/CSET/recipes/surface_fields/generic_surface_histogram_series.yaml index 0ded153ca..eb13f2c4f 100644 --- a/src/CSET/recipes/surface_fields/generic_surface_histogram_series.yaml +++ b/src/CSET/recipes/surface_fields/generic_surface_histogram_series.yaml @@ -16,6 +16,12 @@ steps: - operator: read.read_cubes file_paths: $INPUT_PATHS model_names: $MODEL_NAME + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints variable_constraint: @@ -29,8 +35,6 @@ steps: operator: constraints.generate_level_constraint coordinate: pressure levels: [] - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: write.write_cube_to_nc overwrite: True diff --git a/src/CSET/recipes/surface_fields/generic_surface_histogram_series_case_aggregation_all.yaml b/src/CSET/recipes/surface_fields/generic_surface_histogram_series_case_aggregation_all.yaml index 801a8e620..8e753cee3 100644 --- a/src/CSET/recipes/surface_fields/generic_surface_histogram_series_case_aggregation_all.yaml +++ b/src/CSET/recipes/surface_fields/generic_surface_histogram_series_case_aggregation_all.yaml @@ -16,6 +16,12 @@ steps: - operator: read.read_cubes file_paths: $INPUT_PATHS model_names: $MODEL_NAME + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints variable_constraint: @@ -29,8 +35,6 @@ steps: operator: constraints.generate_level_constraint coordinate: pressure levels: [] - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: aggregate.ensure_aggregatable_across_cases diff --git a/src/CSET/recipes/surface_fields/generic_surface_histogram_series_case_aggregation_hour_of_day.yaml b/src/CSET/recipes/surface_fields/generic_surface_histogram_series_case_aggregation_hour_of_day.yaml index 1685dd932..d5d1240e9 100644 --- a/src/CSET/recipes/surface_fields/generic_surface_histogram_series_case_aggregation_hour_of_day.yaml +++ b/src/CSET/recipes/surface_fields/generic_surface_histogram_series_case_aggregation_hour_of_day.yaml @@ -16,6 +16,12 @@ steps: - operator: read.read_cubes file_paths: $INPUT_PATHS model_names: $MODEL_NAME + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints variable_constraint: @@ -29,8 +35,6 @@ steps: operator: constraints.generate_level_constraint coordinate: pressure levels: [] - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: aggregate.ensure_aggregatable_across_cases diff --git a/src/CSET/recipes/surface_fields/generic_surface_histogram_series_case_aggregation_lead_time.yaml b/src/CSET/recipes/surface_fields/generic_surface_histogram_series_case_aggregation_lead_time.yaml index 7bb0e2d4d..e0b97c3bc 100644 --- a/src/CSET/recipes/surface_fields/generic_surface_histogram_series_case_aggregation_lead_time.yaml +++ b/src/CSET/recipes/surface_fields/generic_surface_histogram_series_case_aggregation_lead_time.yaml @@ -16,6 +16,12 @@ steps: - operator: read.read_cubes file_paths: $INPUT_PATHS model_names: $MODEL_NAME + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints variable_constraint: @@ -29,8 +35,6 @@ steps: operator: constraints.generate_level_constraint coordinate: pressure levels: [] - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: aggregate.ensure_aggregatable_across_cases diff --git a/src/CSET/recipes/surface_fields/generic_surface_histogram_series_case_aggregation_validity_time.yaml b/src/CSET/recipes/surface_fields/generic_surface_histogram_series_case_aggregation_validity_time.yaml index bcfed7647..d0ca2e75d 100644 --- a/src/CSET/recipes/surface_fields/generic_surface_histogram_series_case_aggregation_validity_time.yaml +++ b/src/CSET/recipes/surface_fields/generic_surface_histogram_series_case_aggregation_validity_time.yaml @@ -16,6 +16,12 @@ steps: - operator: read.read_cubes file_paths: $INPUT_PATHS model_names: $MODEL_NAME + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints variable_constraint: @@ -29,8 +35,6 @@ steps: operator: constraints.generate_level_constraint coordinate: pressure levels: [] - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: aggregate.ensure_aggregatable_across_cases diff --git a/src/CSET/recipes/surface_fields/generic_surface_single_point_time_series.yaml b/src/CSET/recipes/surface_fields/generic_surface_single_point_time_series.yaml index 722fe7e69..7dd97fce9 100644 --- a/src/CSET/recipes/surface_fields/generic_surface_single_point_time_series.yaml +++ b/src/CSET/recipes/surface_fields/generic_surface_single_point_time_series.yaml @@ -6,6 +6,10 @@ steps: - operator: read.read_cubes file_paths: $INPUT_PATHS model_names: $MODEL_NAME + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints varname_constraint: diff --git a/src/CSET/recipes/surface_fields/generic_surface_spatial_plot_sequence.yaml b/src/CSET/recipes/surface_fields/generic_surface_spatial_plot_sequence.yaml index 48c1d7b3e..eeca75f6e 100644 --- a/src/CSET/recipes/surface_fields/generic_surface_spatial_plot_sequence.yaml +++ b/src/CSET/recipes/surface_fields/generic_surface_spatial_plot_sequence.yaml @@ -5,7 +5,12 @@ description: Extracts and plots the $METHOD of $VARNAME from all times in $MODEL steps: - operator: read.read_cube file_paths: $INPUT_PATHS - + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints varname_constraint: @@ -19,8 +24,6 @@ steps: operator: constraints.generate_level_constraint coordinate: "pressure" levels: [] - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: collapse.collapse coordinate: [time] diff --git a/src/CSET/recipes/surface_fields/generic_surface_spatial_plot_sequence_case_aggregation_mean_all.yaml b/src/CSET/recipes/surface_fields/generic_surface_spatial_plot_sequence_case_aggregation_mean_all.yaml index 03cc3ba88..5c08c6afa 100644 --- a/src/CSET/recipes/surface_fields/generic_surface_spatial_plot_sequence_case_aggregation_mean_all.yaml +++ b/src/CSET/recipes/surface_fields/generic_surface_spatial_plot_sequence_case_aggregation_mean_all.yaml @@ -7,6 +7,12 @@ description: | steps: - operator: read.read_cubes file_paths: $INPUT_PATHS + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints varname_constraint: @@ -20,8 +26,6 @@ steps: operator: constraints.generate_level_constraint coordinate: "pressure" levels: [] - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: aggregate.ensure_aggregatable_across_cases diff --git a/src/CSET/recipes/surface_fields/generic_surface_spatial_plot_sequence_case_aggregation_mean_hour_of_day.yaml b/src/CSET/recipes/surface_fields/generic_surface_spatial_plot_sequence_case_aggregation_mean_hour_of_day.yaml index 61b25676e..76f17b627 100644 --- a/src/CSET/recipes/surface_fields/generic_surface_spatial_plot_sequence_case_aggregation_mean_hour_of_day.yaml +++ b/src/CSET/recipes/surface_fields/generic_surface_spatial_plot_sequence_case_aggregation_mean_hour_of_day.yaml @@ -7,6 +7,12 @@ description: | steps: - operator: read.read_cubes file_paths: $INPUT_PATHS + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints varname_constraint: @@ -20,8 +26,6 @@ steps: operator: constraints.generate_level_constraint coordinate: "pressure" levels: [] - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: aggregate.ensure_aggregatable_across_cases diff --git a/src/CSET/recipes/surface_fields/generic_surface_spatial_plot_sequence_case_aggregation_mean_lead_time.yaml b/src/CSET/recipes/surface_fields/generic_surface_spatial_plot_sequence_case_aggregation_mean_lead_time.yaml index e9af8cd79..6fe8c3436 100644 --- a/src/CSET/recipes/surface_fields/generic_surface_spatial_plot_sequence_case_aggregation_mean_lead_time.yaml +++ b/src/CSET/recipes/surface_fields/generic_surface_spatial_plot_sequence_case_aggregation_mean_lead_time.yaml @@ -7,6 +7,12 @@ description: | steps: - operator: read.read_cubes file_paths: $INPUT_PATHS + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints varname_constraint: @@ -20,8 +26,6 @@ steps: operator: constraints.generate_level_constraint coordinate: "pressure" levels: [] - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: aggregate.ensure_aggregatable_across_cases diff --git a/src/CSET/recipes/surface_fields/generic_surface_spatial_plot_sequence_case_aggregation_mean_validity_time.yaml b/src/CSET/recipes/surface_fields/generic_surface_spatial_plot_sequence_case_aggregation_mean_validity_time.yaml index b2738a7a5..fb8ca6c05 100644 --- a/src/CSET/recipes/surface_fields/generic_surface_spatial_plot_sequence_case_aggregation_mean_validity_time.yaml +++ b/src/CSET/recipes/surface_fields/generic_surface_spatial_plot_sequence_case_aggregation_mean_validity_time.yaml @@ -7,6 +7,12 @@ description: | steps: - operator: read.read_cubes file_paths: $INPUT_PATHS + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints varname_constraint: @@ -20,8 +26,6 @@ steps: operator: constraints.generate_level_constraint coordinate: "pressure" levels: [] - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: aggregate.ensure_aggregatable_across_cases diff --git a/src/CSET/recipes/surface_fields/generic_surface_spatial_plot_sequence_regrid.yaml b/src/CSET/recipes/surface_fields/generic_surface_spatial_plot_sequence_regrid.yaml index a68880131..11a89cc05 100644 --- a/src/CSET/recipes/surface_fields/generic_surface_spatial_plot_sequence_regrid.yaml +++ b/src/CSET/recipes/surface_fields/generic_surface_spatial_plot_sequence_regrid.yaml @@ -5,6 +5,10 @@ description: Extracts and plots the surface $VARNAME for all times in $MODEL_NAM steps: - operator: read.read_cube file_paths: $INPUT_PATHS + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints varname_constraint: diff --git a/src/CSET/recipes/surface_fields/surface_spatial_difference.yaml b/src/CSET/recipes/surface_fields/surface_spatial_difference.yaml index bfae548e9..faece6312 100644 --- a/src/CSET/recipes/surface_fields/surface_spatial_difference.yaml +++ b/src/CSET/recipes/surface_fields/surface_spatial_difference.yaml @@ -6,6 +6,12 @@ steps: - operator: read.read_cubes file_paths: $INPUT_PATHS model_names: [$BASE_MODEL, $OTHER_MODEL] + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints varname_constraint: @@ -19,8 +25,6 @@ steps: operator: constraints.generate_level_constraint coordinate: "pressure" levels: [] - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: misc.difference diff --git a/src/CSET/recipes/surface_fields/surface_spatial_difference_case_aggregation_mean_all.yaml b/src/CSET/recipes/surface_fields/surface_spatial_difference_case_aggregation_mean_all.yaml index 57d7f892f..54838c8ad 100644 --- a/src/CSET/recipes/surface_fields/surface_spatial_difference_case_aggregation_mean_all.yaml +++ b/src/CSET/recipes/surface_fields/surface_spatial_difference_case_aggregation_mean_all.yaml @@ -8,6 +8,12 @@ steps: - operator: read.read_cubes file_paths: $INPUT_PATHS model_names: [$BASE_MODEL, $OTHER_MODEL] + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints varname_constraint: @@ -21,8 +27,6 @@ steps: operator: constraints.generate_level_constraint coordinate: "pressure" levels: [] - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: aggregate.ensure_aggregatable_across_cases diff --git a/src/CSET/recipes/surface_fields/surface_spatial_difference_case_aggregation_mean_hour_of_day.yaml b/src/CSET/recipes/surface_fields/surface_spatial_difference_case_aggregation_mean_hour_of_day.yaml index 45153ddef..aa0c69236 100644 --- a/src/CSET/recipes/surface_fields/surface_spatial_difference_case_aggregation_mean_hour_of_day.yaml +++ b/src/CSET/recipes/surface_fields/surface_spatial_difference_case_aggregation_mean_hour_of_day.yaml @@ -8,6 +8,12 @@ steps: - operator: read.read_cubes file_paths: $INPUT_PATHS model_names: [$BASE_MODEL, $OTHER_MODEL] + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints varname_constraint: @@ -21,8 +27,6 @@ steps: operator: constraints.generate_level_constraint coordinate: "pressure" levels: [] - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: aggregate.ensure_aggregatable_across_cases diff --git a/src/CSET/recipes/surface_fields/surface_spatial_difference_case_aggregation_mean_lead_time.yaml b/src/CSET/recipes/surface_fields/surface_spatial_difference_case_aggregation_mean_lead_time.yaml index f4a732a61..1e0dfcf6e 100644 --- a/src/CSET/recipes/surface_fields/surface_spatial_difference_case_aggregation_mean_lead_time.yaml +++ b/src/CSET/recipes/surface_fields/surface_spatial_difference_case_aggregation_mean_lead_time.yaml @@ -8,6 +8,12 @@ steps: - operator: read.read_cubes file_paths: $INPUT_PATHS model_names: [$BASE_MODEL, $OTHER_MODEL] + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints varname_constraint: @@ -21,8 +27,6 @@ steps: operator: constraints.generate_level_constraint coordinate: "pressure" levels: [] - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: aggregate.ensure_aggregatable_across_cases diff --git a/src/CSET/recipes/surface_fields/surface_spatial_difference_case_aggregation_mean_validity_time.yaml b/src/CSET/recipes/surface_fields/surface_spatial_difference_case_aggregation_mean_validity_time.yaml index beea9e6e4..318551473 100644 --- a/src/CSET/recipes/surface_fields/surface_spatial_difference_case_aggregation_mean_validity_time.yaml +++ b/src/CSET/recipes/surface_fields/surface_spatial_difference_case_aggregation_mean_validity_time.yaml @@ -8,6 +8,12 @@ steps: - operator: read.read_cubes file_paths: $INPUT_PATHS model_names: [$BASE_MODEL, $OTHER_MODEL] + constraint: + operator: constraints.generate_var_constraint + varname: $VARNAME + subarea_type: $SUBAREA_TYPE + subarea_extent: $SUBAREA_EXTENT + - operator: filters.filter_cubes constraint: operator: constraints.combine_constraints varname_constraint: @@ -21,8 +27,6 @@ steps: operator: constraints.generate_level_constraint coordinate: "pressure" levels: [] - subarea_type: $SUBAREA_TYPE - subarea_extent: $SUBAREA_EXTENT - operator: aggregate.ensure_aggregatable_across_cases diff --git a/tests/operators/test_filters.py b/tests/operators/test_filters.py index 8c2e8b86d..6fc0359b0 100644 --- a/tests/operators/test_filters.py +++ b/tests/operators/test_filters.py @@ -36,6 +36,28 @@ def test_filter_cubes_cubelist(cubes): assert repr(cube) == expected_cube +def test_filter_cubes_cubelist_per_model(cube): + """Test filtering a CubeList with multiple models.""" + constraint = constraints.generate_cell_methods_constraint([]) + model1 = cube.copy() + model1.attributes["model_name"] = "model_1" + model2 = cube.copy() + model2.attributes["model_name"] = "model_2" + + cube = filters.filter_cubes( + iris.cube.CubeList([model1, model2]), constraint, per_model=True + ) + + expected_cube = "" + assert [repr(c) for c in cube] == [expected_cube, expected_cube] + + model1.attributes.pop("model_name") + with pytest.raises(ValueError): + filters.filter_cubes( + iris.cube.CubeList([model1, model2]), constraint, per_model=True + ) + + def test_filter_cubes_cube(cube): """Test filtering a Cube.""" constraint = constraints.generate_cell_methods_constraint([]) @@ -43,6 +65,30 @@ def test_filter_cubes_cube(cube): assert repr(cube) == repr(single_cube) +def test_filter_cubes_single_cube_per_model(cube): + """Test filtering a single Cube in per_model mode.""" + constraint = constraints.generate_cell_methods_constraint([]) + cube = cube.copy() + cube.attributes["model_name"] = "model_1" + returned_cubes = filters.filter_cubes(cube, constraint, per_model=True) + assert isinstance(returned_cubes, iris.cube.CubeList) + assert len(returned_cubes) == 1 + assert repr(cube) == repr(returned_cubes[0]) + + +def test_filter_cubes_single_entry_cubelist_per_model(cube): + """Test filtering a CubeList with one entry in per_model mode.""" + constraint = constraints.generate_cell_methods_constraint([]) + cube = cube.copy() + cube.attributes["model_name"] = "model_1" + returned_cubes = filters.filter_cubes( + iris.cube.CubeList((cube,)), constraint, per_model=True + ) + assert isinstance(returned_cubes, iris.cube.CubeList) + assert len(returned_cubes) == 1 + assert repr(cube) == repr(returned_cubes[0]) + + def test_filter_cubes_multiple_returned_exception(cubes): """Test for exception when multiple cubes returned.""" constraint = constraints.generate_stash_constraint("m01s03i236")