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

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. 

14 

15"""Load spatial difference field recipes.""" 

16 

17import itertools 

18 

19from CSET.recipes import Config, RawRecipe, get_models 

20 

21 

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. 

27 

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 ) 

49 

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 ) 

76 

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 ) 

103 

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 ) 

121 

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 ) 

139 

140 # Create a list of case aggregation types. 

141 AGGREGATION_TYPES = ["lead_time", "hour_of_day", "validity_time", "all"] 

142 

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 ) 

165 

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 ) 

190 

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 )