1
1
"""Common fixes used for multiple datasets."""
2
+ import logging
3
+
2
4
import iris
3
5
import numpy as np
4
6
from scipy .ndimage import map_coordinates
5
7
6
8
from .fix import Fix
7
9
from .shared import add_plev_from_altitude , fix_bounds
8
10
11
+ logger = logging .getLogger (__name__ )
12
+
9
13
10
14
class ClFixHybridHeightCoord (Fix ):
11
15
"""Fixes for ``cl`` regarding hybrid sigma height coordinates."""
@@ -108,49 +112,74 @@ def fix_metadata(self, cubes):
108
112
class OceanFixGrid (Fix ):
109
113
"""Fixes for tos, siconc in FGOALS-g3."""
110
114
111
- def fix_data (self , cube ):
112
- """
113
- Fix data.
114
-
115
- Calculate missing latitude/longitude boundaries using interpolation.
116
- Based on a similar fix for BCC-CSM2-MR.
115
+ def fix_metadata (self , cubes ):
116
+ """Fix ``latitude`` and ``longitude`` (metadata and bounds).
117
117
118
118
Parameters
119
119
----------
120
- cube : iris.cube.Cube
121
- Input cube to fix .
120
+ cubes : iris.cube.CubeList
121
+ Input cubes .
122
122
123
123
Returns
124
124
-------
125
- iris.cube.Cube
125
+ iris.cube.CubeList
126
+
126
127
"""
127
- rlat = cube .coord ('grid_latitude' ).points
128
- rlon = cube .coord ('grid_longitude' ).points
129
-
130
- # Guess coordinate bounds in rlat, rlon (following BCC-CSM2-MR-1).
131
- rlat_idx_bnds = np .zeros ((len (rlat ), 2 ))
132
- rlat_idx_bnds [:, 0 ] = np .arange (len (rlat )) - 0.5
133
- rlat_idx_bnds [:, 1 ] = np .arange (len (rlat )) + 0.5
134
- rlat_idx_bnds [0 , 0 ] = 0.
135
- rlat_idx_bnds [len (rlat ) - 1 , 1 ] = len (rlat )
136
- rlon_idx_bnds = np .zeros ((len (rlon ), 2 ))
137
- rlon_idx_bnds [:, 0 ] = np .arange (len (rlon )) - 0.5
138
- rlon_idx_bnds [:, 1 ] = np .arange (len (rlon )) + 0.5
139
-
140
- # Calculate latitude/longitude vertices by interpolation
128
+ cube = self .get_cube_from_list (cubes )
129
+ if cube .ndim != 3 :
130
+ logger .warning (
131
+ "OceanFixGrid is designed to work on any data with an "
132
+ "irregular ocean grid, but it was only tested on 3D (time, "
133
+ "latitude, longitude) data so far; got %dD data" , cube .ndim )
134
+
135
+ # Get dimensional coordinates. Note:
136
+ # - First dimension i -> X-direction (= longitude)
137
+ # - Second dimension j -> Y-direction (= latitude)
138
+ (j_dim , i_dim ) = sorted (set (
139
+ cube .coord_dims (cube .coord ('latitude' , dim_coords = False )) +
140
+ cube .coord_dims (cube .coord ('longitude' , dim_coords = False ))
141
+ ))
142
+ i_coord = cube .coord (dim_coords = True , dimensions = i_dim )
143
+ j_coord = cube .coord (dim_coords = True , dimensions = j_dim )
144
+
145
+ # Fix metadata of coordinate i
146
+ i_coord .var_name = 'i'
147
+ i_coord .standard_name = None
148
+ i_coord .long_name = 'cell index along first dimension'
149
+ i_coord .units = '1'
150
+ i_coord .circular = False
151
+
152
+ # Fix metadata of coordinate j
153
+ j_coord .var_name = 'j'
154
+ j_coord .standard_name = None
155
+ j_coord .long_name = 'cell index along second dimension'
156
+ j_coord .units = '1'
157
+
158
+ # Fix points and bounds of index coordinates i and j
159
+ for idx_coord in (i_coord , j_coord ):
160
+ idx_coord .points = np .arange (len (idx_coord .points ))
161
+ idx_coord .bounds = None
162
+ idx_coord .guess_bounds ()
163
+
164
+ # Calculate latitude/longitude vertices by interpolation.
165
+ # Following the CF conventions (see
166
+ # cfconventions.org/cf-conventions/cf-conventions.html#cell-boundaries)
167
+ # we go counter-clockwise around the cells and construct a grid of
168
+ # index values which are in turn used to interpolate longitudes and
169
+ # latitudes in the midpoints between the cell centers.
141
170
lat_vertices = []
142
171
lon_vertices = []
143
- for (i , j ) in [(0 , 0 ), (0 , 1 ), (1 , 1 ), (1 , 0 )]:
144
- (rlat_v , rlon_v ) = np .meshgrid (rlat_idx_bnds [:, i ],
145
- rlon_idx_bnds [:, j ],
146
- indexing = 'ij' )
172
+ for (j , i ) in [(0 , 0 ), (0 , 1 ), (1 , 1 ), (1 , 0 )]:
173
+ (j_v , i_v ) = np .meshgrid (j_coord . bounds [:, j ],
174
+ i_coord . bounds [:, i ],
175
+ indexing = 'ij' )
147
176
lat_vertices .append (
148
177
map_coordinates (cube .coord ('latitude' ).points ,
149
- [rlat_v , rlon_v ],
178
+ [j_v , i_v ],
150
179
mode = 'nearest' ))
151
180
lon_vertices .append (
152
181
map_coordinates (cube .coord ('longitude' ).points ,
153
- [rlat_v , rlon_v ],
182
+ [j_v , i_v ],
154
183
mode = 'wrap' ))
155
184
lat_vertices = np .array (lat_vertices )
156
185
lon_vertices = np .array (lon_vertices )
@@ -160,39 +189,5 @@ def fix_data(self, cube):
160
189
# Copy vertices to cube
161
190
cube .coord ('latitude' ).bounds = lat_vertices
162
191
cube .coord ('longitude' ).bounds = lon_vertices
163
- return cube
164
-
165
- def fix_metadata (self , cubes ):
166
- """
167
- Rename ``var_name`` of 1D-``latitude`` and 1D-``longitude``.
168
-
169
- Parameters
170
- ----------
171
- cubes : iris.cube.CubeList
172
- Input cubes.
173
192
174
- Returns
175
- -------
176
- iris.cube.CubeList
177
- """
178
- cube = self .get_cube_from_list (cubes )
179
- lat_coord = cube .coord ('cell index along second dimension' ,
180
- dimensions = (1 , ))
181
- lon_coord = cube .coord ('cell index along first dimension' ,
182
- dimensions = (2 , ))
183
- lat_coord .standard_name = None
184
- lat_coord .long_name = 'grid_latitude'
185
- lat_coord .var_name = 'i'
186
- lat_coord .units = '1'
187
- lon_coord .standard_name = None
188
- lon_coord .long_name = 'grid_longitude'
189
- lon_coord .var_name = 'j'
190
- lon_coord .units = '1'
191
- lon_coord .circular = False
192
- # FGOALS-g3 data contain latitude and longitude data set to
193
- # >1e30 in some places. Set to 0. to avoid problem in check.py.
194
- cube .coord ('latitude' ).points [cube .coord ('latitude' ).points > 1000. ]\
195
- = 0.
196
- cube .coord ('longitude' ).points [cube .coord ('longitude' ).points > 1000. ]\
197
- = 0.
198
- return cubes
193
+ return iris .cube .CubeList ([cube ])
0 commit comments