@@ -101,11 +101,15 @@ def __new__(mcs, coord, dims):
101
101
102
102
"""
103
103
defn = coord .metadata
104
- points_dtype = coord .points .dtype
105
- bounds_dtype = coord .bounds .dtype if coord .bounds is not None else None
104
+ points_dtype = coord .core_points ().dtype
105
+ bounds_dtype = (
106
+ coord .core_bounds ().dtype
107
+ if coord .core_bounds () is not None
108
+ else None
109
+ )
106
110
kwargs = {}
107
111
# Add scalar flag metadata.
108
- kwargs ["scalar" ] = coord .points .size == 1
112
+ kwargs ["scalar" ] = coord .core_points () .size == 1
109
113
# Add circular flag metadata for dimensional coordinates.
110
114
if hasattr (coord , "circular" ):
111
115
kwargs ["circular" ] = coord .circular
@@ -700,18 +704,27 @@ def _cmp(coord, other):
700
704
701
705
"""
702
706
# A candidate axis must have non-identical coordinate points.
703
- candidate_axis = not array_equal (coord .points , other .points )
707
+ candidate_axis = not array_equal (
708
+ coord .core_points (), other .core_points ()
709
+ )
704
710
705
711
if candidate_axis :
706
712
# Ensure both have equal availability of bounds.
707
- result = (coord .bounds is None ) == (other .bounds is None )
713
+ result = (coord .core_bounds () is None ) == (
714
+ other .core_bounds () is None
715
+ )
708
716
else :
709
- if coord .bounds is not None and other .bounds is not None :
717
+ if (
718
+ coord .core_bounds () is not None
719
+ and other .core_bounds () is not None
720
+ ):
710
721
# Ensure equality of bounds.
711
- result = array_equal (coord .bounds , other .bounds )
722
+ result = array_equal (coord .core_bounds () , other .core_bounds () )
712
723
else :
713
724
# Ensure both have equal availability of bounds.
714
- result = coord .bounds is None and other .bounds is None
725
+ result = (
726
+ coord .core_bounds () is None and other .core_bounds () is None
727
+ )
715
728
716
729
return result , candidate_axis
717
730
@@ -851,9 +864,13 @@ def concatenate(self):
851
864
# Concatenate the new dimension coordinate.
852
865
dim_coords_and_dims = self ._build_dim_coordinates ()
853
866
854
- # Concatenate the new auxiliary coordinates.
867
+ # Concatenate the new auxiliary coordinates (does NOT include
868
+ # scalar coordinates!).
855
869
aux_coords_and_dims = self ._build_aux_coordinates ()
856
870
871
+ # Concatenate the new scalar coordinates.
872
+ scalar_coords = self ._build_scalar_coordinates ()
873
+
857
874
# Concatenate the new cell measures
858
875
cell_measures_and_dims = self ._build_cell_measures ()
859
876
@@ -862,18 +879,21 @@ def concatenate(self):
862
879
863
880
# Concatenate the new aux factories
864
881
aux_factories = self ._build_aux_factories (
865
- dim_coords_and_dims , aux_coords_and_dims
882
+ dim_coords_and_dims , aux_coords_and_dims , scalar_coords
866
883
)
867
884
868
885
# Concatenate the new data payload.
869
886
data = self ._build_data ()
870
887
871
888
# Build the new cube.
889
+ all_aux_coords_and_dims = aux_coords_and_dims + [
890
+ (scalar_coord , ()) for scalar_coord in scalar_coords
891
+ ]
872
892
kwargs = cube_signature .defn ._asdict ()
873
893
cube = iris .cube .Cube (
874
894
data ,
875
895
dim_coords_and_dims = dim_coords_and_dims ,
876
- aux_coords_and_dims = aux_coords_and_dims ,
896
+ aux_coords_and_dims = all_aux_coords_and_dims ,
877
897
cell_measures_and_dims = cell_measures_and_dims ,
878
898
ancillary_variables_and_dims = ancillary_variables_and_dims ,
879
899
aux_factories = aux_factories ,
@@ -1095,7 +1115,7 @@ def _build_aux_coordinates(self):
1095
1115
# Concatenate the points together.
1096
1116
dim = dims .index (self .axis )
1097
1117
points = [
1098
- skton .signature .aux_coords_and_dims [i ].coord .points
1118
+ skton .signature .aux_coords_and_dims [i ].coord .core_points ()
1099
1119
for skton in skeletons
1100
1120
]
1101
1121
points = np .concatenate (tuple (points ), axis = dim )
@@ -1104,7 +1124,9 @@ def _build_aux_coordinates(self):
1104
1124
bnds = None
1105
1125
if coord .has_bounds ():
1106
1126
bnds = [
1107
- skton .signature .aux_coords_and_dims [i ].coord .bounds
1127
+ skton .signature .aux_coords_and_dims [
1128
+ i
1129
+ ].coord .core_bounds ()
1108
1130
for skton in skeletons
1109
1131
]
1110
1132
bnds = np .concatenate (tuple (bnds ), axis = dim )
@@ -1132,12 +1154,22 @@ def _build_aux_coordinates(self):
1132
1154
1133
1155
aux_coords_and_dims .append ((coord .copy (), dims ))
1134
1156
1135
- # Generate all the scalar coordinates for the new concatenated cube.
1136
- for coord in cube_signature .scalar_coords :
1137
- aux_coords_and_dims .append ((coord .copy (), ()))
1138
-
1139
1157
return aux_coords_and_dims
1140
1158
1159
+ def _build_scalar_coordinates (self ):
1160
+ """
1161
+ Generate the scalar coordinates for the new concatenated cube.
1162
+
1163
+ Returns:
1164
+ A list of scalar coordinates.
1165
+
1166
+ """
1167
+ scalar_coords = []
1168
+ for coord in self ._cube_signature .scalar_coords :
1169
+ scalar_coords .append (coord .copy ())
1170
+
1171
+ return scalar_coords
1172
+
1141
1173
def _build_cell_measures (self ):
1142
1174
"""
1143
1175
Generate the cell measures with associated dimension(s)
@@ -1216,7 +1248,9 @@ def _build_ancillary_variables(self):
1216
1248
1217
1249
return ancillary_variables_and_dims
1218
1250
1219
- def _build_aux_factories (self , dim_coords_and_dims , aux_coords_and_dims ):
1251
+ def _build_aux_factories (
1252
+ self , dim_coords_and_dims , aux_coords_and_dims , scalar_coords
1253
+ ):
1220
1254
"""
1221
1255
Generate the aux factories for the new concatenated cube.
1222
1256
@@ -1230,6 +1264,9 @@ def _build_aux_factories(self, dim_coords_and_dims, aux_coords_and_dims):
1230
1264
A list of auxiliary coordinates and dimension(s) tuple pairs from
1231
1265
the concatenated cube.
1232
1266
1267
+ * scalar_coords:
1268
+ A list of scalar coordinates from the concatenated cube.
1269
+
1233
1270
Returns:
1234
1271
A list of :class:`iris.aux_factory.AuxCoordFactory`.
1235
1272
@@ -1240,35 +1277,44 @@ def _build_aux_factories(self, dim_coords_and_dims, aux_coords_and_dims):
1240
1277
old_aux_coords = [a [0 ] for a in cube_signature .aux_coords_and_dims ]
1241
1278
new_dim_coords = [d [0 ] for d in dim_coords_and_dims ]
1242
1279
new_aux_coords = [a [0 ] for a in aux_coords_and_dims ]
1243
- scalar_coords = cube_signature .scalar_coords
1280
+ old_scalar_coords = cube_signature .scalar_coords
1281
+ new_scalar_coords = scalar_coords
1244
1282
1245
1283
aux_factories = []
1246
1284
1247
1285
# Generate all the factories for the new concatenated cube.
1248
- for i , (coord , dims , factory ) in enumerate (
1249
- cube_signature .derived_coords_and_dims
1250
- ):
1251
- # Check whether the derived coordinate of the factory spans the
1252
- # nominated dimension of concatenation.
1253
- if self .axis in dims :
1254
- # Update the dependencies of the factory with coordinates of
1255
- # the concatenated cube. We need to check all coordinate types
1256
- # here (dim coords, aux coords, and scalar coords).
1257
- new_dependencies = {}
1258
- for old_dependency in factory .dependencies .values ():
1259
- if old_dependency in old_dim_coords :
1260
- dep_idx = old_dim_coords .index (old_dependency )
1261
- new_dependency = new_dim_coords [dep_idx ]
1262
- elif old_dependency in old_aux_coords :
1263
- dep_idx = old_aux_coords .index (old_dependency )
1264
- new_dependency = new_aux_coords [dep_idx ]
1265
- else :
1266
- dep_idx = scalar_coords .index (old_dependency )
1267
- new_dependency = scalar_coords [dep_idx ]
1268
- new_dependencies [id (old_dependency )] = new_dependency
1286
+ for _ , _ , factory in cube_signature .derived_coords_and_dims :
1287
+ # Update the dependencies of the factory with coordinates of
1288
+ # the concatenated cube. We need to check all coordinate types
1289
+ # here (dim coords, aux coords, and scalar coords).
1290
+
1291
+ # Note: in contrast to other _build_... methods of this class, we
1292
+ # do NOT need to distinguish between aux factories that span the
1293
+ # nominated concatenation axis and aux factories that do not. The
1294
+ # reason is that ALL aux factories need to be updated with the new
1295
+ # coordinates of the concatenated cube (passed to this function via
1296
+ # dim_coords_and_dims, aux_coords_and_dims, scalar_coords [these
1297
+ # contain ALL new coordinates, not only the ones spanning the
1298
+ # concatenation dimension]), so no special treatment for the aux
1299
+ # factories that span the concatenation dimension is necessary. If
1300
+ # not all aux factories are properly updated with references to the
1301
+ # new coordinates, this may lead to KeyErrors (see
1302
+ # https://github.com/SciTools/iris/issues/5339).
1303
+ new_dependencies = {}
1304
+ for old_dependency in factory .dependencies .values ():
1305
+ if old_dependency in old_dim_coords :
1306
+ dep_idx = old_dim_coords .index (old_dependency )
1307
+ new_dependency = new_dim_coords [dep_idx ]
1308
+ elif old_dependency in old_aux_coords :
1309
+ dep_idx = old_aux_coords .index (old_dependency )
1310
+ new_dependency = new_aux_coords [dep_idx ]
1311
+ else :
1312
+ dep_idx = old_scalar_coords .index (old_dependency )
1313
+ new_dependency = new_scalar_coords [dep_idx ]
1314
+ new_dependencies [id (old_dependency )] = new_dependency
1269
1315
1270
- # Create new factory with the updated dependencies.
1271
- factory = factory .updated (new_dependencies )
1316
+ # Create new factory with the updated dependencies.
1317
+ factory = factory .updated (new_dependencies )
1272
1318
1273
1319
aux_factories .append (factory )
1274
1320
@@ -1307,7 +1353,7 @@ def _build_dim_coordinates(self):
1307
1353
1308
1354
# Concatenate the points together for the nominated dimension.
1309
1355
points = [
1310
- skeleton .signature .dim_coords [dim_ind ].points
1356
+ skeleton .signature .dim_coords [dim_ind ].core_points ()
1311
1357
for skeleton in skeletons
1312
1358
]
1313
1359
points = np .concatenate (tuple (points ))
@@ -1316,7 +1362,7 @@ def _build_dim_coordinates(self):
1316
1362
bounds = None
1317
1363
if self ._cube_signature .dim_coords [dim_ind ].has_bounds ():
1318
1364
bounds = [
1319
- skeleton .signature .dim_coords [dim_ind ].bounds
1365
+ skeleton .signature .dim_coords [dim_ind ].core_bounds ()
1320
1366
for skeleton in skeletons
1321
1367
]
1322
1368
bounds = np .concatenate (tuple (bounds ))
0 commit comments