Skip to content

Commit ed1bfd4

Browse files
xylarclaude
andcommitted
Add open_dataset and open_mfdataset wrappers to mpas_tools.io
Add thin wrappers around xarray.open_dataset and xarray.open_mfdataset that select the NetCDF engine from the module-level mpas_tools.io.default_engine variable when no engine is passed explicitly. xarray.open_dataset sniffs a file for "magic bits" to auto-select a backend, and that probe can crash on NETCDF3_64BIT_DATA (CDF5) files (see E3SM-Project/polaris#624). Specifying an engine explicitly avoids the sniffing. Since xarray has no global default-engine setting, reusing the existing default_engine variable (already consumed by write_netcdf) gives downstream tools a single, process-wide knob for both reading and writing without modifying every call site. The logger argument is included for API symmetry with write_netcdf and future diagnostics; no error recovery is performed because the CDF5 failure is a hard crash that cannot be caught. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent b1b44b5 commit ed1bfd4

1 file changed

Lines changed: 90 additions & 0 deletions

File tree

  • conda_package/mpas_tools

conda_package/mpas_tools/io.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import netCDF4
88
import numpy
9+
import xarray
910

1011
from mpas_tools.logging import check_call
1112

@@ -180,6 +181,95 @@ def write_netcdf(
180181
os.remove(out_filename)
181182

182183

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+
183273
def update_history(ds):
184274
"""Add or append history to attributes of a data set"""
185275

0 commit comments

Comments
 (0)