Skip to content

Commit f2da52f

Browse files
committed
dev
1 parent 79698f7 commit f2da52f

File tree

2 files changed

+99
-66
lines changed

2 files changed

+99
-66
lines changed

cf/cellmethod.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -486,8 +486,7 @@ def expand_intervals(self, inplace=False, i=False):
486486
@_deprecated_kwarg_check("i", version="3.0.0", removed_at="4.0.0")
487487
@_inplace_enabled(default=False)
488488
def change_axes(self, axis_map, inplace=False, i=False):
489-
"""Change the axes of the cell method according to a given
490-
mapping.
489+
"""Replace the axes of the cell method.
491490
492491
:Parameters:
493492

cf/field.py

Lines changed: 98 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@
191191
)
192192

193193
_xxx = namedtuple(
194-
"data_dimension", ["size", "axis", "key", "coord", "coord_type", "scalar"]
194+
"data_dimension", ["size", "axis", "keys", "coords", "coord_type", "scalar"]
195195
)
196196

197197
# _empty_set = set()
@@ -1006,35 +1006,63 @@ def _binary_operation(self, other, method):
10061006

10071007
if identity is None and relaxed_identities:
10081008
identity = coord.identity(relaxed=True, default=None)
1009+
1010+
keys = (key,)
1011+
coords = (coord,)
10091012
else:
1010-
key, coord = f.auxiliary_coordinate(
1011-
item=True,
1012-
default=(None, None),
1013-
filter_by_axis=(axis,),
1014-
axis_mode="exact",
1015-
)
1016-
if coord is not None:
1017-
# This axis of the domain does not have a
1018-
# dimension coordinate but it does have
1019-
# exactly one 1-d auxiliary coordinate, so
1020-
# that will do.
1021-
identity = coord.identity(strict=True, default=None)
1022-
1023-
if identity is None and relaxed_identities:
1024-
identity = coord.identity(
1025-
relaxed=True, default=None
1026-
)
1013+
discrete_axis = f.has_property('featureType') or f.domain_topologies(todict=True)
1014+
if discrete_axis:
1015+
x = {}
1016+
for key, coord in f.auxiliary_coordinates(
1017+
filter_by_axis=(axis,),
1018+
axis_mode="exact", todict=True
1019+
).items():
1020+
identity = coord.identity(strict=True, default=None)
1021+
if identity is None and relaxed_identities:
1022+
identity = coord.identity(
1023+
relaxed=True, default=None
1024+
)
1025+
if identity is not None:
1026+
x[identity] = key
1027+
1028+
if x:
1029+
# E.g. {2:3, 4:6, 1:7} -> (1, 2, 4), (7, 3, 6)
1030+
identity, keys = tuple(zip(*sorted(x.items())))
1031+
coords = tuple(f.auxiliary_coordinate(key) for key in keys)
1032+
else:
1033+
identity = None
1034+
keys = None
1035+
coords = None
1036+
else:
1037+
key, coord = f.auxiliary_coordinate(
1038+
item=True,
1039+
default=(None, None),
1040+
filter_by_axis=(axis,),
1041+
axis_mode="exact",
1042+
)
1043+
if coord is not None:
1044+
# This axis of the domain does not have a
1045+
# dimension coordinate but it does have
1046+
# exactly one 1-d auxiliary coordinate, so
1047+
# that will do.
1048+
coords = (coord,)
1049+
identity = coord.identity(strict=True, default=None)
1050+
if identity is None and relaxed_identities:
1051+
identity = coord.identity(
1052+
relaxed=True, default=None
1053+
)
1054+
10271055

10281056
if identity is None:
10291057
identity = i
10301058
else:
1031-
coord_type = coord.construct_type
1059+
coord_type = coords[0].construct_type
10321060

10331061
out[identity] = _xxx(
10341062
size=f.domain_axis(axis).get_size(),
10351063
axis=axis,
1036-
key=key,
1037-
coord=coord,
1064+
keys=keys,
1065+
coords=coords,
10381066
coord_type=coord_type,
10391067
scalar=(axis not in data_axes),
10401068
)
@@ -1178,48 +1206,49 @@ def _binary_operation(self, other, method):
11781206
f"{a.size} {identity!r} axis"
11791207
)
11801208

1181-
# Ensure matching axis directions
1182-
if y.coord.direction() != a.coord.direction():
1183-
other.flip(y.axis, inplace=True)
1184-
1185-
# Check for matching coordinate values
1186-
if not y.coord._equivalent_data(a.coord):
1187-
raise ValueError(
1188-
f"Can't combine size {y.size} {identity!r} axes with "
1189-
f"non-matching coordinate values"
1190-
)
1191-
1192-
# Check coord refs
1193-
refs1 = field1.get_coordinate_reference(construct=y.key, key=True)
1194-
refs0 = field0.get_coordinate_reference(construct=a.key, key=True)
1195-
1196-
n_refs = len(refs1)
1197-
n0_refs = len(refs0)
1198-
1199-
if n_refs != n0_refs:
1200-
raise ValueError(
1201-
f"Can't combine {self.__class__.__name__!r} with "
1202-
f"{other.__class__.__name__!r} because the coordinate "
1203-
f"references have different lengths: {n_refs} and "
1204-
f"{n0_refs}."
1205-
)
1206-
1207-
n_equivalent_refs = 0
1208-
for ref1 in refs1:
1209-
for ref0 in refs0[:]:
1210-
if field1._equivalent_coordinate_references(
1211-
field0, key0=ref1, key1=ref0, axis_map=axis_map
1212-
):
1213-
n_equivalent_refs += 1
1214-
refs0.remove(ref0)
1215-
break
1216-
1217-
if n_equivalent_refs != n_refs:
1218-
raise ValueError(
1219-
f"Can't combine {self.__class__.__name__!r} with "
1220-
f"{other.__class__.__name__!r} because the fields have "
1221-
"incompatible coordinate references."
1222-
)
1209+
for a_key, a_coord, y_key, y_coord in zip(a.keys, a.coords, y.keys, y.coords):
1210+
# Ensure matching axis directions
1211+
if y_coord.direction() != a_coord.direction():
1212+
other.flip(y.axis, inplace=True)
1213+
1214+
# Check for matching coordinate values
1215+
if not y_coord._equivalent_data(a_coord):
1216+
raise ValueError(
1217+
f"Can't combine size {y.size} {identity!r} axes with "
1218+
f"non-matching coordinate values"
1219+
)
1220+
1221+
# Check coord refs
1222+
refs1 = field1.get_coordinate_reference(construct=y_key, key=True)
1223+
refs0 = field0.get_coordinate_reference(construct=a_key, key=True)
1224+
1225+
n_refs = len(refs1)
1226+
n0_refs = len(refs0)
1227+
1228+
if n_refs != n0_refs:
1229+
raise ValueError(
1230+
f"Can't combine {self.__class__.__name__!r} with "
1231+
f"{other.__class__.__name__!r} because the coordinate "
1232+
f"references have different lengths: {n_refs} and "
1233+
f"{n0_refs}."
1234+
)
1235+
1236+
n_equivalent_refs = 0
1237+
for ref1 in refs1:
1238+
for ref0 in refs0[:]:
1239+
if field1._equivalent_coordinate_references(
1240+
field0, key0=ref1, key1=ref0, axis_map=axis_map
1241+
):
1242+
n_equivalent_refs += 1
1243+
refs0.remove(ref0)
1244+
break
1245+
1246+
if n_equivalent_refs != n_refs:
1247+
raise ValueError(
1248+
f"Can't combine {self.__class__.__name__!r} with "
1249+
f"{other.__class__.__name__!r} because the fields have "
1250+
"incompatible coordinate references."
1251+
)
12231252

12241253
# Change the domain axis sizes in field0 so that they match
12251254
# the broadcasted result data
@@ -1425,7 +1454,12 @@ def _conform_cell_methods(self):
14251454
axis_map = {}
14261455

14271456
for cm in self.cell_methods(todict=True).values():
1428-
for axis in cm.get_axes(()):
1457+
1458+
axes = cm.get_axis_identities(None)
1459+
if axes is None:
1460+
axes = cm.get_axes(None)
1461+
1462+
for axis in axes:
14291463
if axis in axis_map:
14301464
continue
14311465

0 commit comments

Comments
 (0)