Skip to content

Commit 2c4ba36

Browse files
committed
Testcase for multiple hybrid coordinates.
1 parent db13546 commit 2c4ba36

File tree

2 files changed

+75
-10
lines changed

2 files changed

+75
-10
lines changed

lib/iris/fileformats/_nc_load_rules/actions.py

+9-4
Original file line numberDiff line numberDiff line change
@@ -459,12 +459,17 @@ def action_formula_type(engine, formula_root_fact):
459459
# Check we don't already have one.
460460
existing_type = engine.requires.get("formula_type")
461461
if existing_type:
462+
# NOTE: in this case, for now, we will accept the last appearing,
463+
# which matches the older behaviour.
464+
# TODO: this needs resolving, somehow.
462465
succeed = False
463-
rule_name += (
464-
f"(FAILED - new formula type ={formula_type!r} "
465-
f"collided with existing one ={existing_type!r}.)"
466+
msg = (
467+
"Omitting factories for some hybrid coordinates, as multiple "
468+
"hybrid coordinates on a single variable are not supported: "
469+
f"Formula of type ={formula_type!r} "
470+
f"overrides another of type ={existing_type!r}.)"
466471
)
467-
if succeed:
472+
warnings.warn(msg)
468473
rule_name += f"_{formula_type}"
469474
# Set 'requires' info for iris.fileformats.netcdf._load_aux_factory.
470475
engine.requires["formula_type"] = formula_type

lib/iris/tests/unit/fileformats/netcdf/load_cube/load_cube__activate/test__hybrid_formulae.py

+66-6
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919

2020

2121
class Mixin__formulae_tests(Mixin__nc_load_actions):
22-
def _make_testcase_cdl(self, formula_root_name=None, term_names=None):
22+
def _make_testcase_cdl(
23+
self, formula_root_name=None, term_names=None, extra_formula_type=None
24+
):
2325
"""Construct a testcase CDL for data with hybrid vertical coords."""
2426
if formula_root_name is None:
2527
formula_root_name = "atmosphere_hybrid_height_coordinate"
@@ -29,22 +31,54 @@ def _make_testcase_cdl(self, formula_root_name=None, term_names=None):
2931
# unsupported type : just make something up
3032
term_names = ["term1"]
3133

32-
terms_string = ""
33-
phenom_coord_names = ["vert"] # always include the root variable
34+
# Arrange to create additional term variables for an 'extra' hybrid
35+
# formula, if requested.
36+
if extra_formula_type is None:
37+
term_names_extra = []
38+
phenom_coord_names = ["vert"] # always include the root variable
39+
else:
40+
phenom_coord_names = ["vert", "vert_2"] # two formula coords
41+
term_names_extra = hh.CF_COORD_VERTICAL.get(extra_formula_type)
42+
43+
# Build strings to define term variables.
3444
formula_term_strings = []
35-
for term_name in term_names:
45+
extra_formula_term_strings = []
46+
terms_string = ""
47+
for term_name in term_names + term_names_extra:
3648
term_varname = "v_" + term_name
49+
# Include in the phenom coordinates list.
3750
phenom_coord_names.append(term_varname)
38-
formula_term_strings.append(f"{term_name}: {term_varname}")
51+
term_string = f"{term_name}: {term_varname}"
52+
if term_name in term_names:
53+
# Include in the 'main' terms list.
54+
formula_term_strings.append(term_string)
55+
else:
56+
# Include in the 'extra' terms list.
57+
extra_formula_term_strings.append(term_string)
3958
terms_string += f"""
4059
double {term_varname}(h) ;
4160
{term_varname}:long_name = "{term_name}_long_name" ;
4261
{term_varname}:units = "m" ;
4362
"""
4463

45-
# remove the extra initial space from the formula terms string
64+
# Construct the reference strings.
4665
phenom_coords_string = " ".join(phenom_coord_names)
4766
formula_terms_string = " ".join(formula_term_strings)
67+
extra_formula_terms_string = " ".join(extra_formula_term_strings)
68+
69+
# Construct the 'extra' hybrid coord if requested.
70+
if extra_formula_type is None:
71+
extra_formula_string = ""
72+
else:
73+
# Create the lines to add an 'extra' formula.
74+
# For now, put this on the same dim : makes no difference.
75+
extra_formula_string = f"""
76+
double vert_2(h) ;
77+
vert_2:standard_name = "{extra_formula_type}" ;
78+
vert_2:units = "m" ;
79+
vert_2:formula_terms = "{extra_formula_terms_string}" ;
80+
"""
81+
4882
# Create the main result string.
4983
cdl_str = f"""
5084
netcdf test {{
@@ -61,6 +95,7 @@ def _make_testcase_cdl(self, formula_root_name=None, term_names=None):
6195
vert:units = "m" ;
6296
vert:formula_terms = "{formula_terms_string}" ;
6397
{terms_string}
98+
{extra_formula_string}
6499
}}
65100
"""
66101
return cdl_str
@@ -171,6 +206,31 @@ def test_unrecognised_verticaltype(self):
171206
# which is simply discarded.
172207
self.check_result(result, factory_type=None, formula_terms=["a", "b"])
173208

209+
def test_two_formulae(self):
210+
# Construct an example with TWO hybrid coords.
211+
# This is not errored, but we don't correctly support it.
212+
#
213+
# NOTE: the original Pyke implementation does not detect this problem
214+
# By design, the new mechanism does + will raise a warning.
215+
warning = (
216+
"Omitting factories for some hybrid coordinates.*"
217+
"multiple hybrid coordinates.* not supported"
218+
)
219+
220+
extra_type = "ocean_sigma_coordinate"
221+
result = self.run_testcase(
222+
extra_formula_type=extra_type, warning=warning
223+
)
224+
# NOTE: FOR NOW, check expected behaviour : only one factory will be
225+
# built, but there are coordinates (terms) for both types.
226+
# TODO: this is a bug and needs fixing : translation should handle
227+
# multiple hybrid coordinates in a sensible way.
228+
self.check_result(
229+
result,
230+
factory_type=extra_type,
231+
formula_terms=["a", "b", "depth", "eta", "orog", "sigma"],
232+
)
233+
174234

175235
# Add in tests methods to exercise each (supported) vertical coordinate type
176236
# individually.

0 commit comments

Comments
 (0)