Coverage for src/CSET/loaders/spatial_difference_field.py: 30%
37 statements
« prev ^ index » next coverage.py v7.10.6, created at 2025-09-05 21:08 +0000
« prev ^ index » next coverage.py v7.10.6, created at 2025-09-05 21:08 +0000
1# © Crown copyright, Met Office (2022-2025) and CSET contributors.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
15"""Load spatial difference field recipes."""
17import itertools
19from CSET.recipes import Config, RawRecipe, get_models
22def load(conf: Config):
23 """Yield recipes from the given workflow configuration."""
24 # Load a list of model detail dictionaries.
25 models = get_models(conf.asdict())
26 # Models are listed in order, so model 1 is the first element.
28 # Surface (2D) fields.
29 if conf.SPATIAL_DIFFERENCE_SURFACE_FIELD: 29 ↛ 30line 29 didn't jump to line 30 because the condition on line 29 was never true
30 base_model = models[0]
31 for model, field, method in itertools.product(
32 models[1:], conf.SURFACE_FIELDS, conf.SPATIAL_SURFACE_FIELD_METHOD
33 ):
34 yield RawRecipe(
35 recipe="surface_spatial_difference.yaml",
36 variables={
37 "VARNAME": field,
38 "BASE_MODEL": base_model["name"],
39 "OTHER_MODEL": model["name"],
40 "METHOD": method,
41 "SUBAREA_TYPE": conf.SUBAREA_TYPE if conf.SELECT_SUBAREA else None,
42 "SUBAREA_EXTENT": conf.SUBAREA_EXTENT
43 if conf.SELECT_SUBAREA
44 else None,
45 },
46 model_ids=[base_model["id"], model["id"]],
47 aggregation=False,
48 )
50 # Pressure level fields.
51 if conf.SPATIAL_DIFFERENCE_PLEVEL_FIELD: 51 ↛ 52line 51 didn't jump to line 52 because the condition on line 51 was never true
52 base_model = models[0]
53 for model, field, plevel, method in itertools.product(
54 models[1:],
55 conf.PRESSURE_LEVEL_FIELDS,
56 conf.PRESSURE_LEVELS,
57 conf.SPATIAL_PLEVEL_FIELD_METHOD,
58 ):
59 yield RawRecipe(
60 recipe="level_spatial_difference.yaml",
61 variables={
62 "VARNAME": field,
63 "LEVELTYPE": "pressure",
64 "LEVEL": plevel,
65 "BASE_MODEL": base_model["name"],
66 "OTHER_MODEL": model["name"],
67 "METHOD": method,
68 "SUBAREA_TYPE": conf.SUBAREA_TYPE if conf.SELECT_SUBAREA else None,
69 "SUBAREA_EXTENT": conf.SUBAREA_EXTENT
70 if conf.SELECT_SUBAREA
71 else None,
72 },
73 model_ids=[base_model["id"], model["id"]],
74 aggregation=False,
75 )
77 # Model level fields
78 if conf.SPATIAL_MLEVEL_DIFFERENCE: 78 ↛ 79line 78 didn't jump to line 79 because the condition on line 78 was never true
79 base_model = models[0]
80 for model, field, mlevel, method in itertools.product(
81 models[1:],
82 conf.MODEL_LEVEL_FIELDS,
83 conf.MODEL_LEVELS,
84 conf.SPATIAL_MLEVEL_FIELD_METHOD,
85 ):
86 yield RawRecipe(
87 recipe="level_spatial_difference.yaml",
88 variables={
89 "VARNAME": field,
90 "LEVELTYPE": "model_level_number",
91 "LEVEL": mlevel,
92 "BASE_MODEL": base_model["name"],
93 "OTHER_MODEL": model["name"],
94 "METHOD": method,
95 "SUBAREA_TYPE": conf.SUBAREA_TYPE if conf.SELECT_SUBAREA else None,
96 "SUBAREA_EXTENT": conf.SUBAREA_EXTENT
97 if conf.SELECT_SUBAREA
98 else None,
99 },
100 model_ids=[base_model["id"], model["id"]],
101 aggregation=False,
102 )
104 # Rain presence
105 if conf.RAIN_PRESENCE_SPATIAL_DIFFERENCE: 105 ↛ 106line 105 didn't jump to line 106 because the condition on line 105 was never true
106 base_model = models[0]
107 for model in models[1:]:
108 yield RawRecipe(
109 recipe="rain_presence_spatial_difference.yaml",
110 variables={
111 "BASE_MODEL": base_model["name"],
112 "OTHER_MODEL": model["name"],
113 "SUBAREA_TYPE": conf.SUBAREA_TYPE if conf.SELECT_SUBAREA else None,
114 "SUBAREA_EXTENT": conf.SUBAREA_EXTENT
115 if conf.SELECT_SUBAREA
116 else None,
117 },
118 model_ids=[base_model["id"], model["id"]],
119 aggregation=False,
120 )
122 # Surface winds on Beaufort Scale
123 if conf.SFC_WIND_BEAUFORT_SCALE_SPATIAL_DIFFERENCE: 123 ↛ 124line 123 didn't jump to line 124 because the condition on line 123 was never true
124 base_model = models[0]
125 for model in models[1:]:
126 yield RawRecipe(
127 recipe="surface_wind_speed_on_beaufort_scale_spatial_difference.yaml",
128 variables={
129 "BASE_MODEL": base_model["name"],
130 "OTHER_MODEL": model["name"],
131 "SUBAREA_TYPE": conf.SUBAREA_TYPE if conf.SELECT_SUBAREA else None,
132 "SUBAREA_EXTENT": conf.SUBAREA_EXTENT
133 if conf.SELECT_SUBAREA
134 else None,
135 },
136 model_ids=[base_model["id"], model["id"]],
137 aggregation=False,
138 )
140 # Create a list of case aggregation types.
141 AGGREGATION_TYPES = ["lead_time", "hour_of_day", "validity_time", "all"]
143 # Surface (2D) fields.
144 for model, atype, field in itertools.product( 144 ↛ 147line 144 didn't jump to line 147 because the loop on line 144 never started
145 models[1:], AGGREGATION_TYPES, conf.SURFACE_FIELDS
146 ):
147 if conf.SPATIAL_DIFFERENCE_SURFACE_FIELD_AGGREGATION[
148 AGGREGATION_TYPES.index(atype)
149 ]:
150 base_model = models[0]
151 yield RawRecipe(
152 recipe=f"surface_spatial_difference_case_aggregation_mean_{atype}.yaml",
153 variables={
154 "VARNAME": field,
155 "BASE_MODEL": base_model["name"],
156 "OTHER_MODEL": model["name"],
157 "SUBAREA_TYPE": conf.SUBAREA_TYPE if conf.SELECT_SUBAREA else None,
158 "SUBAREA_EXTENT": conf.SUBAREA_EXTENT
159 if conf.SELECT_SUBAREA
160 else None,
161 },
162 model_ids=[base_model["id"], model["id"]],
163 aggregation=True,
164 )
166 # Pressure level fields.
167 for model, atype, field, plevel in itertools.product( 167 ↛ 170line 167 didn't jump to line 170 because the loop on line 167 never started
168 models[1:], AGGREGATION_TYPES, conf.PRESSURE_LEVEL_FIELDS, conf.PRESSURE_LEVELS
169 ):
170 if conf.SPATIAL_DIFFERENCE_PLEVEL_FIELD_AGGREGATION[
171 AGGREGATION_TYPES.index(atype)
172 ]:
173 base_model = models[0]
174 yield RawRecipe(
175 recipe=f"level_spatial_difference_case_aggregation_mean_{atype}.yaml",
176 variables={
177 "VARNAME": field,
178 "LEVELTYPE": "pressure",
179 "LEVEL": plevel,
180 "BASE_MODEL": base_model["name"],
181 "OTHER_MODEL": model["name"],
182 "SUBAREA_TYPE": conf.SUBAREA_TYPE if conf.SELECT_SUBAREA else None,
183 "SUBAREA_EXTENT": conf.SUBAREA_EXTENT
184 if conf.SELECT_SUBAREA
185 else None,
186 },
187 model_ids=[base_model["id"], model["id"]],
188 aggregation=True,
189 )
191 # Model level fields.
192 for model, atype, field, mlevel in itertools.product( 192 ↛ 195line 192 didn't jump to line 195 because the loop on line 192 never started
193 models[1:], AGGREGATION_TYPES, conf.MODEL_LEVEL_FIELDS, conf.MODEL_LEVELS
194 ):
195 if conf.SPATIAL_DIFFERENCE_MLEVEL_FIELD_AGGREGATION[
196 AGGREGATION_TYPES.index(atype)
197 ]:
198 base_model = models[0]
199 yield RawRecipe(
200 recipe=f"mlevel_spatial_difference_case_aggregation_mean_{atype}.yaml",
201 variables={
202 "VARNAME": field,
203 "LEVELTYPE": "model_level_number",
204 "LEVEL": mlevel,
205 "BASE_MODEL": base_model["name"],
206 "OTHER_MODEL": model["name"],
207 "SUBAREA_TYPE": conf.SUBAREA_TYPE if conf.SELECT_SUBAREA else None,
208 "SUBAREA_EXTENT": conf.SUBAREA_EXTENT
209 if conf.SELECT_SUBAREA
210 else None,
211 },
212 model_ids=[base_model["id"], model["id"]],
213 aggregation=True,
214 )