|
6 | 6 |
|
7 | 7 | import netCDF4 |
8 | 8 | import numpy |
| 9 | +import xarray |
9 | 10 |
|
10 | 11 | from mpas_tools.logging import check_call |
11 | 12 |
|
@@ -180,6 +181,95 @@ def write_netcdf( |
180 | 181 | os.remove(out_filename) |
181 | 182 |
|
182 | 183 |
|
| 184 | +def open_dataset(filename, engine=None, logger=None, **kwargs): |
| 185 | + """ |
| 186 | + Open an ``xarray.Dataset`` from a NetCDF file, accounting for quirks |
| 187 | + specific to MPAS components. This is a thin wrapper around |
| 188 | + :py:func:`xarray.open_dataset` that selects the NetCDF ``engine`` from |
| 189 | + ``mpas_tools.io.default_engine`` when ``engine`` is not given. |
| 190 | +
|
| 191 | + Specifying an ``engine`` explicitly is important because |
| 192 | + :py:func:`xarray.open_dataset` otherwise sniffs the file for "magic bits" |
| 193 | + to auto-select a backend, and that probe can crash on |
| 194 | + ``NETCDF3_64BIT_DATA`` (CDF5) files. Setting |
| 195 | + ``mpas_tools.io.default_engine`` (e.g. to ``'netcdf4'``) provides a single, |
| 196 | + process-wide way to avoid that crash without modifying every call site. |
| 197 | +
|
| 198 | + Parameters |
| 199 | + ---------- |
| 200 | + filename : str or path-like or file-like |
| 201 | + The path to the NetCDF file to open, passed on to |
| 202 | + :py:func:`xarray.open_dataset` |
| 203 | +
|
| 204 | + engine : {'netcdf4', 'scipy', 'h5netcdf'}, optional |
| 205 | + The library to use for reading the NetCDF file. The default is |
| 206 | + ``mpas_tools.io.default_engine``, which can be modified but which |
| 207 | + defaults to ``None`` (xarray auto-selects the backend) |
| 208 | +
|
| 209 | + logger : logging.Logger, optional |
| 210 | + A logger to write messages to. Reserved for future diagnostics; no |
| 211 | + error recovery is performed because the CDF5 backend-sniffing failure |
| 212 | + is a hard crash that cannot be caught. |
| 213 | +
|
| 214 | + **kwargs |
| 215 | + Additional keyword arguments passed on to |
| 216 | + :py:func:`xarray.open_dataset` (e.g. ``decode_times``, ``decode_cf``, |
| 217 | + ``mask_and_scale``) |
| 218 | +
|
| 219 | + Returns |
| 220 | + ------- |
| 221 | + ds : xarray.Dataset |
| 222 | + The opened dataset |
| 223 | + """ |
| 224 | + if engine is None: |
| 225 | + engine = default_engine |
| 226 | + |
| 227 | + return xarray.open_dataset(filename, engine=engine, **kwargs) |
| 228 | + |
| 229 | + |
| 230 | +def open_mfdataset(paths, engine=None, logger=None, **kwargs): |
| 231 | + """ |
| 232 | + Open a multi-file ``xarray.Dataset`` from NetCDF files, accounting for |
| 233 | + quirks specific to MPAS components. This is a thin wrapper around |
| 234 | + :py:func:`xarray.open_mfdataset` that selects the NetCDF ``engine`` from |
| 235 | + ``mpas_tools.io.default_engine`` when ``engine`` is not given. |
| 236 | +
|
| 237 | + See :py:func:`mpas_tools.io.open_dataset` for why specifying an ``engine`` |
| 238 | + explicitly (via ``mpas_tools.io.default_engine``) is useful for |
| 239 | + ``NETCDF3_64BIT_DATA`` (CDF5) files. |
| 240 | +
|
| 241 | + Parameters |
| 242 | + ---------- |
| 243 | + paths : str or sequence of str or path-like |
| 244 | + The paths to the NetCDF files to open, passed on to |
| 245 | + :py:func:`xarray.open_mfdataset` |
| 246 | +
|
| 247 | + engine : {'netcdf4', 'scipy', 'h5netcdf'}, optional |
| 248 | + The library to use for reading the NetCDF files. The default is |
| 249 | + ``mpas_tools.io.default_engine``, which can be modified but which |
| 250 | + defaults to ``None`` (xarray auto-selects the backend) |
| 251 | +
|
| 252 | + logger : logging.Logger, optional |
| 253 | + A logger to write messages to. Reserved for future diagnostics; no |
| 254 | + error recovery is performed because the CDF5 backend-sniffing failure |
| 255 | + is a hard crash that cannot be caught. |
| 256 | +
|
| 257 | + **kwargs |
| 258 | + Additional keyword arguments passed on to |
| 259 | + :py:func:`xarray.open_mfdataset` (e.g. ``combine``, ``concat_dim``, |
| 260 | + ``decode_times``) |
| 261 | +
|
| 262 | + Returns |
| 263 | + ------- |
| 264 | + ds : xarray.Dataset |
| 265 | + The opened dataset |
| 266 | + """ |
| 267 | + if engine is None: |
| 268 | + engine = default_engine |
| 269 | + |
| 270 | + return xarray.open_mfdataset(paths, engine=engine, **kwargs) |
| 271 | + |
| 272 | + |
183 | 273 | def update_history(ds): |
184 | 274 | """Add or append history to attributes of a data set""" |
185 | 275 |
|
|
0 commit comments