From e1a0719ed5d603ce489fcc4215bee9176afaf51b Mon Sep 17 00:00:00 2001 From: Kijin Nam Date: Tue, 4 Aug 2026 11:52:22 -0700 Subject: [PATCH] Use h5netcdf as default NetCDF4 may crash depending on environments due to unsafe threading. This commit makes the code use h5netcdf when it is available for the xarray backend. h5netcdf is known to be safer than netcdf4. BDS-1212 --- pyproject.toml | 7 ++----- suxarray/core/api.py | 20 ++++++++++++++++++-- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ca4dde9..e057ca2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ description = "uxarray extension for SCHISM." readme = "README.rst" requires-python = ">=3.8,<3.13" authors = [ - { name = "California Department of Water Resources", email = "knam@water.ca.gov" } + { name = "California Department of Water Resources", email = "knam@water.ca.gov" }, ] license = { file = "LICENSE" } keywords = ["suxarray"] @@ -35,10 +35,7 @@ dependencies = [ [project.optional-dependencies] vtk = ["vtk"] -test = [ - "pytest>=3", - "vtk" -] +test = ["pytest>=3", "vtk"] [project.urls] Homepage = "https://github.com/cadwrdeltamodeling/suxarray" diff --git a/suxarray/core/api.py b/suxarray/core/api.py index 29be883..de63429 100644 --- a/suxarray/core/api.py +++ b/suxarray/core/api.py @@ -44,6 +44,20 @@ def open_ts_dataset( return ds +def _choose_netcdf_engine() -> str: + """Pick an available NetCDF backend for xarray. + + Prefer h5netcdf when available to avoid netCDF4 binary issues on + some environments. Fallback to netcdf4 for compatibility. + """ + try: + import h5netcdf # noqa: F401 + + return "h5netcdf" + except ImportError: + return "netcdf4" + + def read_schism_nc(grid: Grid, ds_data: xr.Dataset) -> SxDataset: ds_data = ux.core.utils._map_dims_to_ugrid(ds_data, grid._source_dims_dict, grid) if "nSCHISM_vgrid_layers" in ds_data.dims: @@ -94,13 +108,15 @@ def open_grid( `suxarray.Grid` """ + engine = _choose_netcdf_engine() + # if chunks is None: # chunks = { # "time": 12, # } ds_out2d = xr.open_mfdataset( files_out2d, - engine="netcdf4", + engine=engine, mask_and_scale=False, chunks=chunks, preprocess=lambda ds: ds[ @@ -130,7 +146,7 @@ def open_grid( if files_zcoords is not None: ds_zcoords = xr.open_mfdataset( files_zcoords, - engine="netcdf4", + engine=engine, chunks=chunks, join="override", coords="minimal",