to_netcdf: Unexpected drop of "units" attribute of attached "bounds"
What happened?
When writing a Dataset to netcdf, any DataArrays that are linked as bounds through another variables attrs['bounds'] entry, have their (specifically) 'units' attribute dropped inside the written netcdf file.
See example
What did you expect to happen?
Units attribute to be written to the netcdf file.
Minimal Complete Verifiable Example
import numpy as np
import xarray as xr
# Create a new Dataset
ds = xr.Dataset()
# Add the x variable, Specify 'x_bnds' as bounds, defined later.
ds['x'] = xr.DataArray(np.arange(10), dims='x', attrs={'units':'m', 'bounds':'x_bnds'})
# Bounds require an extra dimension equal to number of vertices.
ds['nv'] = xr.DataArray(np.r_[0, 1], dims='nv')
# Add the actual bounding values for variable x.
ds['x_bnds'] = xr.DataArray(np.squeeze(np.dstack([np.arange(10)-0.5, np.arange(10)+0.5])),
dims=['x', 'nv'],
attrs={'test':4, 'units':'m', })
print('Units is attached to the bounds in the dataset before writing', 'units' in ds['x_bnds'].attrs)
# Write to netcdf file
ds.to_netcdf('tmp.nc', format='netcdf4', engine='netcdf4')
# Open the dataset and check x_bnds attrs. units is dropped.
new = xr.open_dataset('tmp.nc')
print(new['x_bnds'].attrs)
# Confirm that units were never written to the file.
!h5dump -d /x_bnds tmp.nc
MVCE confirmation
- [X] Minimal example — the example is as focused as reasonably possible to demonstrate the underlying issue in xarray.
- [X] Complete example — the example is self-contained, including all data and the text of any traceback.
- [X] Verifiable example — the example copy & pastes into an IPython prompt or Binder notebook, returning the result.
- [X] New issue — a search of GitHub Issues suggests this is not a duplicate.
- [X] Recent environment — the issue occurs with the latest version of xarray and its dependencies.
Relevant log output
No response
Anything else we need to know?
No response
Environment
INSTALLED VERSIONS
commit: None python: 3.11.5 (main, Sep 11 2023, 08:19:27) [Clang 14.0.6 ] python-bits: 64 OS: Darwin OS-release: 21.6.0 machine: x86_64 processor: i386 byteorder: little LC_ALL: None LANG: en_US.UTF-8 LOCALE: ('en_US', 'UTF-8') libhdf5: 1.12.2 libnetcdf: 4.9.3-development
xarray: 2023.10.1 pandas: 2.1.1 numpy: 1.26.1 scipy: 1.11.3 netCDF4: 1.6.4 pydap: None h5netcdf: None h5py: 3.10.0 Nio: None zarr: None cftime: 1.6.3 nc_time_axis: None PseudoNetCDF: None iris: None bottleneck: None dask: None distributed: None matplotlib: 3.8.0 cartopy: None seaborn: None numbagg: None fsspec: None cupy: None pint: None sparse: None flox: None numpy_groupies: None setuptools: 68.0.0 pip: 23.3 conda: None pytest: None mypy: None IPython: 8.16.1 sphinx: 7.2.6
Thanks for opening your first issue here at xarray! Be sure to follow the issue template! If you have an idea for a solution, we would really welcome a Pull Request with proposed changes. See the Contributing Guide for more. It may take us a while to respond here, but we really value your contribution. Contributors like you help make xarray better. Thank you!
This behaviour is recommended by CF: http://cfconventions.org/Data/cf-conventions/cf-conventions-1.10/cf-conventions.html#cell-boundaries
Boundary variable attributes which determine the coordinate type (units, standard_name, axis and positive) or those which affect the interpretation of the array values (units, calendar, leap_month, leap_year and month_lengths) must always agree exactly with the same attributes of its associated coordinate, scalar coordinate or auxiliary coordinate variable. To avoid duplication, however, it is recommended that these are not provided to a boundary variable.
but I agree, we should just write what the user has assigned.
Okay thank you! I was wondering whether it was in fact expected behaviour.
Hi, I just observed the same thing and was scratching my head where they got amiss. It is not even documented. Apparently the change was introduced here: #2921 (issue) and #2965 (PR). Please make this dropping somehow explicit, by a keyword or something.
Edit: you can remove lines 797--815 in xarray/conventions.py, which looks
like a whole bunch of attributes that get removed. But sometimes having them
(twice) in "bounds" variables is desired.
Cheers.