@@ -45,7 +45,7 @@ def wrapper(func):
4545
4646def add_cell_measure (
4747 cube : Cube ,
48- cell_measure_cube : Cube ,
48+ cell_measure_cube : Cube | iris . coords . CellMeasure ,
4949 measure : Literal ["area" , "volume" ],
5050) -> None :
5151 """Add cell measure to cube (in-place).
@@ -60,7 +60,7 @@ def add_cell_measure(
6060 cube:
6161 Iris cube with input data.
6262 cell_measure_cube:
63- Iris cube with cell measure data.
63+ Iris cube or cell measure coord with cell measure data.
6464 measure:
6565 Name of the measure, can be 'area' or 'volume'.
6666
@@ -101,39 +101,73 @@ def add_cell_measure(
101101 )
102102
103103
104- def add_ancillary_variable (cube : Cube , ancillary_cube : Cube ) -> None :
104+ def add_ancillary_variable (
105+ cube : Cube , ancillary_cube : Cube | iris .coords .AncillaryVariable
106+ ) -> None :
105107 """Add ancillary variable to cube (in-place).
106108
107- Note
108- ----
109- This assumes that the ancillary variable spans the rightmost dimensions of
110- the cube.
111-
112109 Parameters
113110 ----------
114111 cube:
115112 Iris cube with input data.
116113 ancillary_cube:
117- Iris cube with ancillary data.
114+ Iris cube or AncillaryVariable with ancillary data.
118115
119116 Returns
120117 -------
121118 iris.cube.Cube
122119 Cube with added ancillary variables
123120 """
124- coord_dims = tuple (range (cube .ndim - len (ancillary_cube .shape ), cube .ndim ))
125- ancillary_data = ancillary_cube .core_data ()
121+ try :
122+ ancillary_var = iris .coords .AncillaryVariable (
123+ ancillary_cube .core_data (),
124+ standard_name = ancillary_cube .standard_name ,
125+ units = ancillary_cube .units ,
126+ var_name = ancillary_cube .var_name ,
127+ attributes = ancillary_cube .attributes ,
128+ long_name = ancillary_cube .long_name ,
129+ )
130+ except AttributeError as err :
131+ msg = (
132+ f"Failed to add { ancillary_cube } to { cube } as ancillary var."
133+ "ancillary_cube should be either an iris.cube.Cube or an "
134+ "iris.coords.AncillaryVariable object."
135+ )
136+ raise ValueError (msg ) from err
137+ # Match the coordinates of the ancillary cube to coordinates and
138+ # dimensions in the input cube before adding the ancillary variable.
139+ data_dims : list [int | None ] = []
140+ if isinstance (ancillary_cube , iris .coords .AncillaryVariable ):
141+ start_dim = cube .ndim - len (ancillary_var .shape )
142+ data_dims = list (range (start_dim , cube .ndim ))
143+ else :
144+ data_dims = [None ] * ancillary_cube .ndim
145+ for coord in ancillary_cube .coords ():
146+ try :
147+ for ancillary_dim , cube_dim in zip (
148+ ancillary_cube .coord_dims (coord ),
149+ cube .coord_dims (coord ),
150+ strict = False ,
151+ ):
152+ data_dims [ancillary_dim ] = cube_dim
153+ except iris .exceptions .CoordinateNotFoundError :
154+ logger .debug (
155+ "%s from ancillary cube not found in cube coords." , coord
156+ )
157+ if None in data_dims :
158+ none_dims = ", " .join (
159+ str (i ) for i , d in enumerate (data_dims ) if d is None
160+ )
161+ msg = (
162+ f"Failed to add { ancillary_cube } to { cube } as ancillary var."
163+ f"No coordinate associated with ancillary cube dimensions"
164+ f"{ none_dims } "
165+ )
166+ raise ValueError (msg )
126167 if ancillary_cube .has_lazy_data ():
127- cube_chunks = tuple (cube .lazy_data ().chunks [d ] for d in coord_dims )
128- ancillary_data = ancillary_data .rechunk (cube_chunks )
129- ancillary_var = iris .coords .AncillaryVariable (
130- ancillary_data ,
131- standard_name = ancillary_cube .standard_name ,
132- units = ancillary_cube .units ,
133- var_name = ancillary_cube .var_name ,
134- attributes = ancillary_cube .attributes ,
135- )
136- cube .add_ancillary_variable (ancillary_var , coord_dims )
168+ cube_chunks = tuple (cube .lazy_data ().chunks [d ] for d in data_dims )
169+ ancillary_var .data = ancillary_cube .lazy_data ().rechunk (cube_chunks )
170+ cube .add_ancillary_variable (ancillary_var , data_dims )
137171 logger .debug (
138172 "Added %s as ancillary variable in cube of %s." ,
139173 ancillary_cube .var_name ,
0 commit comments