Skip to content

Commit

Permalink
Include AncillaryVariables and restructure Cube metadata.
Browse files Browse the repository at this point in the history
  • Loading branch information
lbdreyer committed Oct 15, 2019
1 parent c892fa7 commit 1478a64
Show file tree
Hide file tree
Showing 11 changed files with 1,699 additions and 634 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* CF Ancillary Data are now supported in cubes.
30 changes: 23 additions & 7 deletions lib/iris/_concatenate.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# (C) British Crown Copyright 2013 - 2017, Met Office
# (C) British Crown Copyright 2013 - 2019, Met Office
#
# This file is part of Iris.
#
Expand Down Expand Up @@ -301,7 +301,8 @@ def _none_sort(item):
class _CubeSignature(object):
"""
Template for identifying a specific type of :class:`iris.cube.Cube` based
on its metadata, coordinates and cell_measures.
on its metadata and dimensional metadata, including: coordinates,
cell_measures and ancillary_variables.
"""
def __init__(self, cube):
Expand All @@ -322,6 +323,7 @@ def __init__(self, cube):
self.ndim = cube.ndim
self.scalar_coords = []
self.cell_measures_and_dims = cube._cell_measures_and_dims
self.ancillary_variables_and_dims = cube._ancillary_variables_and_dims
self.dim_mapping = []

# Determine whether there are any anonymous cube dimensions.
Expand Down Expand Up @@ -415,6 +417,8 @@ def match(self, other, error_on_mismatch):
- dimensions metadata
- aux coords metadata
- scalar coords
- cell measures
- ancillary variables
- attributes
- dtype
Expand Down Expand Up @@ -471,6 +475,14 @@ def match(self, other, error_on_mismatch):
self.cell_measures_and_dims,
other.cell_measures_and_dims))

# Check ancillary_variables_and_dims
if self.ancillary_variables_and_dims != \
other.ancillary_variables_and_dims:
msgs.append(msg_template.format(
'AncillaryVariables', '',
self.ancillary_variables_and_dims,
other.ancillary_variables_and_dims))

match = not bool(msgs)
if error_on_mismatch and not match:
raise iris.exceptions.ConcatenateError(msgs)
Expand Down Expand Up @@ -670,11 +682,15 @@ def concatenate(self):
kwargs = cube_signature.defn._asdict()
new_cm_and_dims = [(deepcopy(cm), dims) for cm, dims
in self._cube._cell_measures_and_dims]
cube = iris.cube.Cube(data,
dim_coords_and_dims=dim_coords_and_dims,
aux_coords_and_dims=aux_coords_and_dims,
cell_measures_and_dims=new_cm_and_dims,
**kwargs)
new_av_and_dims = [(deepcopy(av), dims) for av, dims
in self._cube._ancillary_variables_and_dims]
cube = iris.cube.Cube(
data,
dim_coords_and_dims=dim_coords_and_dims,
aux_coords_and_dims=aux_coords_and_dims,
cell_measures_and_dims=new_cm_and_dims,
ancillary_variables_and_dims=new_av_and_dims,
**kwargs)
else:
# There are no other source-cubes to concatenate
# with this proto-cube.
Expand Down
21 changes: 18 additions & 3 deletions lib/iris/_merge.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# (C) British Crown Copyright 2010 - 2017, Met Office
# (C) British Crown Copyright 2010 - 2019, Met Office
#
# This file is part of Iris.
#
Expand Down Expand Up @@ -315,7 +315,8 @@ class _CoordSignature(namedtuple('CoordSignature',

class _CubeSignature(namedtuple('CubeSignature',
['defn', 'data_shape', 'data_type',
'cell_measures_and_dims'])):
'cell_measures_and_dims',
'ancillary_variables_and_dims'])):
"""
Criterion for identifying a specific type of :class:`iris.cube.Cube`
based on its metadata.
Expand All @@ -334,6 +335,9 @@ class _CubeSignature(namedtuple('CubeSignature',
* cell_measures_and_dims:
A list of cell_measures and dims for the cube.
* ancillary_variables_and_dims:
A list of ancillary_variables and dims for the cube.
"""

__slots__ = ()
Expand Down Expand Up @@ -405,6 +409,9 @@ def match(self, other, error_on_mismatch):
msgs.append(msg.format(self.data_type, other.data_type))
if (self.cell_measures_and_dims != other.cell_measures_and_dims):
msgs.append('cube.cell_measures differ')
if (self.ancillary_variables_and_dims !=
other.ancillary_variables_and_dims):
msgs.append('cube.ancillary_variables differ')

match = not bool(msgs)
if error_on_mismatch and not match:
Expand Down Expand Up @@ -1134,6 +1141,10 @@ def __init__(self, cube):
# they are checked and preserved through merge
self._cell_measures_and_dims = cube._cell_measures_and_dims

# ancillary_variables are not merge candidates
# they are checked and preserved through merge
self._ancillary_variables_and_dims = cube._ancillary_variables_and_dims

def _report_duplicate(self, nd_indexes, group_by_nd_index):
# Find the first offending source-cube with duplicate metadata.
index = [group_by_nd_index[nd_index][1]
Expand Down Expand Up @@ -1483,10 +1494,13 @@ def _get_cube(self, data):

cms_and_dims = [(deepcopy(cm), dims)
for cm, dims in self._cell_measures_and_dims]
av_and_dims = [(deepcopy(av), dims)
for av, dims in self._ancillary_variables_and_dims]
cube = iris.cube.Cube(data,
dim_coords_and_dims=dim_coords_and_dims,
aux_coords_and_dims=aux_coords_and_dims,
cell_measures_and_dims=cms_and_dims,
ancillary_variables_and_dims=av_and_dims,
**kwargs)

# Add on any aux coord factories.
Expand Down Expand Up @@ -1607,7 +1621,8 @@ def _build_signature(self, cube):
"""

return _CubeSignature(cube.metadata, cube.shape,
cube.dtype, cube._cell_measures_and_dims)
cube.dtype, cube._cell_measures_and_dims,
cube._ancillary_variables_and_dims)

def _add_cube(self, cube, coord_payload):
"""Create and add the source-cube skeleton to the ProtoCube."""
Expand Down
Loading

0 comments on commit 1478a64

Please sign in to comment.