|
9 | 9 | from .calc_atmos import level_to_height |
10 | 10 | from .calc_land import average_tile, calc_landcover, calc_topsoil, extract_tilefrac |
11 | 11 | from .dataclasses import CMIP6_Experiment |
12 | | -from .ocean_supergrid import om3_grid |
| 12 | +from .ocean_supergrid import om2_grid, om3_grid |
13 | 13 |
|
14 | 14 | # Supported operators |
15 | 15 | OPERATORS = { |
|
24 | 24 | @dataclass |
25 | 25 | class ACCESS_ESM16_CMIP6(CMIP6_Experiment): |
26 | 26 | mapping_file_prefix: str = "Mappings_CMIP6_" |
| 27 | + supergrid = om2_grid |
27 | 28 |
|
28 | 29 | def __post_init__(self): |
29 | 30 | self.initialise("ACCESS-ESM1-5") |
@@ -136,6 +137,129 @@ def cmorise(self, file_paths, compound_name, cmor_dataset_json, mip_table): |
136 | 137 |
|
137 | 138 | cmor.close() |
138 | 139 |
|
| 140 | + def cmorise_ocean(self, file_paths, compound_name, cmor_dataset_json, mip_table): |
| 141 | + _, cmor_name = compound_name.split(".") |
| 142 | + |
| 143 | + # Open the matching files with xarray |
| 144 | + ds = xr.open_mfdataset(file_paths, combine="by_coords", decode_times=False) |
| 145 | + |
| 146 | + # Extract required variables and coordinates |
| 147 | + mapping = self.get_mapping(compound_name=compound_name) |
| 148 | + |
| 149 | + if mapping["calculation"]["type"] == "direct": |
| 150 | + access_var = mapping["calculation"]["formula"] |
| 151 | + variable_units = mapping["units"] |
| 152 | + positive = mapping["positive"] |
| 153 | + var = ds[access_var] |
| 154 | + else: |
| 155 | + raise ValueError("Not implemented") |
| 156 | + |
| 157 | + dim_mapping = mapping["dimensions"] |
| 158 | + _ = ( |
| 159 | + self.supergrid.h_cells() |
| 160 | + if "xt_ocean" in var.dims |
| 161 | + else self.supergrid.q_cells() |
| 162 | + ) |
| 163 | + axes = {dim_mapping.get(axis, axis): axis for axis in var.dims} |
| 164 | + |
| 165 | + i_axis = axes.pop("longitude") |
| 166 | + i_axis = ds[i_axis].values |
| 167 | + j_axis = axes.pop("latitude") |
| 168 | + j_axis = ds[j_axis].values |
| 169 | + x = np.arange(i_axis.size, dtype="float") |
| 170 | + x_bnds = np.array([[x_ - 0.5, x_ + 0.5] for x_ in x]) |
| 171 | + y = np.arange(j_axis.size, dtype="float") |
| 172 | + y_bnds = np.array([[y_ - 0.5, y_ + 0.5] for y_ in y]) |
| 173 | + |
| 174 | + data = var.values |
| 175 | + lat = self.supergrid.lat |
| 176 | + lat_bnds = self.supergrid.lat_bnds |
| 177 | + |
| 178 | + lon = self.supergrid.lon |
| 179 | + lon_bnds = self.supergrid.lon_bnds |
| 180 | + |
| 181 | + # Convert time to numeric values |
| 182 | + time_axis = axes.pop("time") |
| 183 | + time_numeric = ds[time_axis].values |
| 184 | + time_units = ds[time_axis].attrs["units"] |
| 185 | + time_bnds = ds[ds[time_axis].attrs["bounds"]].values |
| 186 | + # TODO: Check that the calendar is the same than the one defined in the model.json |
| 187 | + # Convert if not. |
| 188 | + # calendar = ds[time_axis].attrs["calendar"] |
| 189 | + |
| 190 | + # CMOR setup |
| 191 | + ipth = "Test" |
| 192 | + cmor.setup( |
| 193 | + inpath=ipth, |
| 194 | + set_verbosity=cmor.CMOR_NORMAL, |
| 195 | + netcdf_file_action=cmor.CMOR_REPLACE, |
| 196 | + ) |
| 197 | + |
| 198 | + cmor.dataset_json(cmor_dataset_json) |
| 199 | + current_dir = os.path.dirname(os.path.abspath(__file__)) |
| 200 | + grid_table_id = cmor.load_table( |
| 201 | + os.path.join(current_dir, "cmor_tables", "CMIP6_grids.json") |
| 202 | + ) |
| 203 | + cmor.set_table(grid_table_id) |
| 204 | + |
| 205 | + cmor_axes = [] |
| 206 | + # Define CMOR axes |
| 207 | + yaxis_id = cmor.axis( |
| 208 | + table_entry="j_index", units="1", coord_vals=y, cell_bounds=y_bnds |
| 209 | + ) |
| 210 | + xaxis_id = cmor.axis( |
| 211 | + table_entry="i_index", units="1", coord_vals=x, cell_bounds=x_bnds |
| 212 | + ) |
| 213 | + |
| 214 | + grid_id = cmor.grid( |
| 215 | + axis_ids=np.array([yaxis_id, xaxis_id]), |
| 216 | + latitude=lat, |
| 217 | + longitude=lon, |
| 218 | + latitude_vertices=lat_bnds, |
| 219 | + longitude_vertices=lon_bnds, |
| 220 | + ) |
| 221 | + cmor_axes.append(grid_id) |
| 222 | + |
| 223 | + # Now, load the Omon table to set up the time axis and variable |
| 224 | + current_dir = os.path.dirname(os.path.abspath(__file__)) |
| 225 | + mip_table = os.path.join(current_dir, "cmor_tables", mip_table) |
| 226 | + omon_table_id = cmor.load_table(mip_table) |
| 227 | + cmor.set_table(omon_table_id) |
| 228 | + |
| 229 | + cmorTime = cmor.axis( |
| 230 | + "time", coord_vals=time_numeric, cell_bounds=time_bnds, units=time_units |
| 231 | + ) |
| 232 | + cmor_axes.append(cmorTime) |
| 233 | + |
| 234 | + if axes: |
| 235 | + for axis, dim in axes.items(): |
| 236 | + coord_vals = var[dim].values |
| 237 | + try: |
| 238 | + cell_bounds = var[var[dim].attrs["bounds"]].values |
| 239 | + except KeyError: |
| 240 | + cell_bounds = None |
| 241 | + axis_units = var[dim].attrs["units"] |
| 242 | + cmor_axis = cmor.axis( |
| 243 | + axis, |
| 244 | + coord_vals=coord_vals, |
| 245 | + cell_bounds=cell_bounds, |
| 246 | + units=axis_units, |
| 247 | + ) |
| 248 | + cmor_axes.append(cmor_axis) |
| 249 | + |
| 250 | + # Define CMOR variable |
| 251 | + cmorVar = cmor.variable(cmor_name, variable_units, cmor_axes, positive=positive) |
| 252 | + |
| 253 | + # Write data to CMOR |
| 254 | + data = np.moveaxis(data, 0, -1) |
| 255 | + cmor.write(cmorVar, data, ntimes_passed=len(time_numeric)) |
| 256 | + |
| 257 | + # Finalize and save the file |
| 258 | + filename = cmor.close(cmorVar, file_name=True) |
| 259 | + print("Stored in:", filename) |
| 260 | + |
| 261 | + cmor.close() |
| 262 | + |
139 | 263 |
|
140 | 264 | @dataclass |
141 | 265 | class ACCESS_OM3_CMIP6(CMIP6_Experiment): |
@@ -176,11 +300,11 @@ def cmorise(self, file_paths, compound_name, cmor_dataset_json, mip_table): |
176 | 300 | y_bnds = np.array([[y_ - 0.5, y_ + 0.5] for y_ in y]) |
177 | 301 |
|
178 | 302 | data = var.values |
179 | | - lat = om3_grid.lat |
180 | | - lat_bnds = om3_grid.lat_bnds |
| 303 | + lat = self.supergrid.lat |
| 304 | + lat_bnds = self.supergrid.lat_bnds |
181 | 305 |
|
182 | | - lon = om3_grid.lon |
183 | | - lon_bnds = om3_grid.lon_bnds |
| 306 | + lon = self.supergrid.lon |
| 307 | + lon_bnds = self.supergrid.lon_bnds |
184 | 308 |
|
185 | 309 | # Convert time to numeric values |
186 | 310 | time_axis = axes.pop("time") |
|
0 commit comments