11"""Preprocessor functions for ancillary variables and cell measures."""
22
33import logging
4- from typing import Iterable
4+ from collections .abc import Callable
5+ from typing import Iterable , Literal
56
67import iris .coords
7- import iris .cube
8+ from iris .cube import Cube
89
910logger = logging .getLogger (__name__ )
1011
1112PREPROCESSOR_SUPPLEMENTARIES = {}
1213
1314
14- def register_supplementaries (variables , required ):
15+ def register_supplementaries (
16+ variables : list [str ],
17+ required : Literal ["require_at_least_one" , "prefer_at_least_one" ],
18+ ) -> Callable :
1519 """Register supplementary variables required for a preprocessor function.
1620
1721 Parameters
1822 ----------
19- variables: :obj:`list` of :obj`str`
23+ variables:
2024 List of variable names.
2125 required:
2226 How strong the requirement is. Can be 'require_at_least_one' if at
@@ -39,16 +43,25 @@ def wrapper(func):
3943 return wrapper
4044
4145
42- def add_cell_measure (cube , cell_measure_cube , measure ):
43- """Add a cube as a cell_measure in the cube containing the data.
46+ def add_cell_measure (
47+ cube : Cube ,
48+ cell_measure_cube : Cube ,
49+ measure : Literal ["area" , "volume" ],
50+ ) -> None :
51+ """Add cell measure to cube (in-place).
52+
53+ Note
54+ ----
55+ This assumes that the cell measure spans the rightmost dimensions of the
56+ cube.
4457
4558 Parameters
4659 ----------
47- cube: iris.cube.Cube
60+ cube:
4861 Iris cube with input data.
49- cell_measure_cube: iris.cube.Cube
62+ cell_measure_cube:
5063 Iris cube with cell measure data.
51- measure: str
64+ measure:
5265 Name of the measure, can be 'area' or 'volume'.
5366
5467 Returns
@@ -65,47 +78,62 @@ def add_cell_measure(cube, cell_measure_cube, measure):
6578 raise ValueError (
6679 f"measure name must be 'area' or 'volume', got { measure } instead"
6780 )
68- measure = iris .coords .CellMeasure (
69- cell_measure_cube .core_data (),
81+ coord_dims = tuple (
82+ range (cube .ndim - len (cell_measure_cube .shape ), cube .ndim )
83+ )
84+ cell_measure_data = cell_measure_cube .core_data ()
85+ if cell_measure_cube .has_lazy_data ():
86+ cube_chunks = tuple (cube .lazy_data ().chunks [d ] for d in coord_dims )
87+ cell_measure_data = cell_measure_data .rechunk (cube_chunks )
88+ cell_measure = iris .coords .CellMeasure (
89+ cell_measure_data ,
7090 standard_name = cell_measure_cube .standard_name ,
7191 units = cell_measure_cube .units ,
7292 measure = measure ,
7393 var_name = cell_measure_cube .var_name ,
7494 attributes = cell_measure_cube .attributes ,
7595 )
76- start_dim = cube .ndim - len (measure .shape )
77- cube .add_cell_measure (measure , range (start_dim , cube .ndim ))
96+ cube .add_cell_measure (cell_measure , coord_dims )
7897 logger .debug (
7998 "Added %s as cell measure in cube of %s." ,
8099 cell_measure_cube .var_name ,
81100 cube .var_name ,
82101 )
83102
84103
85- def add_ancillary_variable (cube , ancillary_cube ):
86- """Add cube as an ancillary variable in the cube containing the data.
104+ def add_ancillary_variable (cube : Cube , ancillary_cube : Cube ) -> None :
105+ """Add ancillary variable to cube (in-place).
106+
107+ Note
108+ ----
109+ This assumes that the ancillary variable spans the rightmost dimensions of
110+ the cube.
87111
88112 Parameters
89113 ----------
90- cube: iris.cube.Cube
114+ cube:
91115 Iris cube with input data.
92- ancillary_cube: iris.cube.Cube
116+ ancillary_cube:
93117 Iris cube with ancillary data.
94118
95119 Returns
96120 -------
97121 iris.cube.Cube
98122 Cube with added ancillary variables
99123 """
124+ coord_dims = tuple (range (cube .ndim - len (ancillary_cube .shape ), cube .ndim ))
125+ ancillary_data = ancillary_cube .core_data ()
126+ 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 )
100129 ancillary_var = iris .coords .AncillaryVariable (
101- ancillary_cube . core_data () ,
130+ ancillary_data ,
102131 standard_name = ancillary_cube .standard_name ,
103132 units = ancillary_cube .units ,
104133 var_name = ancillary_cube .var_name ,
105134 attributes = ancillary_cube .attributes ,
106135 )
107- start_dim = cube .ndim - len (ancillary_var .shape )
108- cube .add_ancillary_variable (ancillary_var , range (start_dim , cube .ndim ))
136+ cube .add_ancillary_variable (ancillary_var , coord_dims )
109137 logger .debug (
110138 "Added %s as ancillary variable in cube of %s." ,
111139 ancillary_cube .var_name ,
@@ -114,10 +142,10 @@ def add_ancillary_variable(cube, ancillary_cube):
114142
115143
116144def add_supplementary_variables (
117- cube : iris . cube . Cube ,
118- supplementary_cubes : Iterable [iris . cube . Cube ],
119- ) -> iris . cube . Cube :
120- """Add ancillary variables and/or cell measures.
145+ cube : Cube ,
146+ supplementary_cubes : Iterable [Cube ],
147+ ) -> Cube :
148+ """Add ancillary variables and/or cell measures to cube (in-place) .
121149
122150 Parameters
123151 ----------
@@ -131,7 +159,7 @@ def add_supplementary_variables(
131159 iris.cube.Cube
132160 Cube with added ancillary variables and/or cell measures.
133161 """
134- measure_names = {
162+ measure_names : dict [ str , Literal [ "area" , "volume" ]] = {
135163 "areacella" : "area" ,
136164 "areacello" : "area" ,
137165 "volcello" : "volume" ,
@@ -145,15 +173,14 @@ def add_supplementary_variables(
145173 return cube
146174
147175
148- def remove_supplementary_variables (cube : iris . cube . Cube ):
149- """Remove supplementary variables.
176+ def remove_supplementary_variables (cube : Cube ) -> Cube :
177+ """Remove supplementary variables from cube (in-place) .
150178
151- Strip cell measures or ancillary variables from the cube containing the
152- data.
179+ Strip cell measures or ancillary variables from the cube.
153180
154181 Parameters
155182 ----------
156- cube: iris.cube.Cube
183+ cube:
157184 Iris cube with data and cell measures or ancillary variables.
158185
159186 Returns
0 commit comments