You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Also save the grid during obj.to_netcdf(); create Grid.to_netcdf() #1836
…, or, provide some other public API for saving uxarray arrays/datasets to files along with the underlying grid.
Right now, obj.to_netcdf(filename) is equivalent to obj.to_xarray().to_netcdf(filename), i.e. all grid information is being lost (for obj a UxDataArray or UxDataset). The result can be loaded via xr.open_dataset(filename), but attempting to load the result via ux.open_dataset(filename) produces a GridInvalidError: Failed to parse uxgrid information from xarray.Dataset..
One "obvious" workaround to attempt is to try to also save obj.uxgrid.to_netcdf(gridfile) and then do ux.open_dataset(gridfile, filename), however this crashes with AttributeError: 'Grid' object has no attribute 'to_netcdf'.
uxarray should implement some clear and simple interface for round-trips from local memory to files, allowing people to save their uxarray data, share it with other people if desired, and load it later.
The simplest user experience, in my opinion, would be for obj.to_netcdf(filename) to save a single dataset which includes the grid information by default, compatible with the "single-file ux.open_dataset" feature (see #1479). That way, the round-trip syntax is extremely simple: obj.to_netcdf(filename) followed by ux.open_dataset(filename) will recover a dataset with all the same values as in obj (though, possibly with some extra data_vars related to the grid, too, so they wouldn't be exactly equal). An optional kwarg like grid_file could also enable workflows like obj.to_netcdf(filename, grid_file=gridfile) followed by ux.open_dataset(gridfile, filename), to get a result which equals obj, exactly.
A full solution to this issue must provide some way for obj.to_netcdf() to save the grid too, and must also implement Grid.to_netcdf. If for some reason it is decided that some paths of obj.to_netcdf() should not save the grid, a warning should be raised whenever the grid is not saved (users wanting to avoid saving the grid should just use obj.to_xarray().to_netcdf() instead.
As a design choice, we implemented to_xarray() out of our objects (including Grid) and deferred file writes, i.e. to_netcdf(), to xarray. I get that to_netcdf() is still callable for UxDataset and UxDataArraythrough their xarray parent classes, but that's implicit, and the explicitly documented UXarray way should still be:
That said, if we haven't done great job documenting this through user guides or usage examples, we should do that shouldn't introduce file writes in our API.
Also, IIRC, it was intentional to not handle Grid's xarray conversion as part of UXDataset's or UxDataArray's to_xarray() to emphasize Grid was not a native xarray object and should be dealt with explicitly if desired
@erogluorhan Thank you for providing the extra context here, and for pointing out the option to use uxgrid.to_xarray().to_netcdf(), that makes a lot of sense. I agree it is important to document how to write to files. It should be easy for users to discover how to save UxDataArrays/UxDatasets as a file (or multiple files) that can be later loaded back into memory.
Due to the inheritance, for better or for worse, file writes are already part of the API. E.g., calling help(uxarr) or help(uxds) includes the to_netcdf() method details. Just confirming, even if we don't override UxDataset.to_netcdf() or UxDataArray.to_netcdf(), are you also opposed to adding Grid.to_netcdf()? The fact that it is missing, while the former two exist in the API (via inheritance), made me think there was no canonical way to write grids to files.
The implementation would be simple, something like:
classGrid:
# ... other methodsdefto_netcdf(self, path, *args, **kwargs):
"""writes this Grid's dataset to the file or file-like object specified by `path`. *args and **kwargs passed directly to :meth:`xr.Dataset.to_netcdf()`. """returnself.to_xarray().to_netcdf(path, *args, **kwargs)
Also, IIRC, it was intentional to not handle Grid's xarray conversion as part of UXDataset's or UxDataArray's to_xarray() to emphasize Grid was not a native xarray object and should be dealt with explicitly if desired
Agreed, the uxgrid should definitely be dropped during UxDataset.to_xarray()!
Just confirming, even if we don't override UxDataset.to_netcdf() or UxDataArray.to_netcdf(), are you also opposed to adding Grid.to_netcdf()?
I think I am still opposed to it and would rather want only better documentation about how to use to_xarray().to_netcdf() for any of them instead (despite seeing your point with it due to inheritance with dataset and data array). Implementation-wise though, I agree it would be straightforward (my concern is whether we should implement it though).
From internal discussion today: triaged as "to-do" in the sense that adding something into the docs / user guide should be prioritized soon-ish. However, we didn't yet decide the way to proceed with the API itself (e.g., whether to add Grid.to_netcdf() or not add it); that should be discussed further before working on API changes.
Also note, there are other methods to input/output files, such as to_zarr(), which should be considered here too.
Activity
erogluorhan commentedon Oct 22, 2026
As a design choice, we implemented
to_xarray()out of our objects (includingGrid) and deferred file writes, i.e.to_netcdf(), to xarray. I get thatto_netcdf()is still callable forUxDatasetandUxDataArraythrough their xarray parent classes, but that's implicit, and the explicitly documented UXarray way should still be:That said, if we haven't done great job documenting this through user guides or usage examples, we should do that shouldn't introduce file writes in our API.
erogluorhan commentedon Oct 22, 2026
Also, IIRC, it was intentional to not handle
Grid's xarray conversion as part ofUXDataset's orUxDataArray'sto_xarray()to emphasizeGridwas not a native xarray object and should be dealt with explicitly if desiredSevans711 commentedon Oct 22, 2026
@erogluorhan Thank you for providing the extra context here, and for pointing out the option to use uxgrid.to_xarray().to_netcdf(), that makes a lot of sense. I agree it is important to document how to write to files. It should be easy for users to discover how to save UxDataArrays/UxDatasets as a file (or multiple files) that can be later loaded back into memory.
Due to the inheritance, for better or for worse, file writes are already part of the API. E.g., calling help(uxarr) or help(uxds) includes the
to_netcdf()method details. Just confirming, even if we don't override UxDataset.to_netcdf() or UxDataArray.to_netcdf(), are you also opposed to adding Grid.to_netcdf()? The fact that it is missing, while the former two exist in the API (via inheritance), made me think there was no canonical way to write grids to files.The implementation would be simple, something like:
Possibly-related: #1647
Agreed, the uxgrid should definitely be dropped during UxDataset.to_xarray()!
erogluorhan commentedon Oct 23, 2026
Thanks for the further discussion, Sam!
I think I am still opposed to it and would rather want only better documentation about how to use
to_xarray().to_netcdf()for any of them instead (despite seeing your point with it due to inheritance with dataset and data array). Implementation-wise though, I agree it would be straightforward (my concern is whether we should implement it though).@dylannelson @cmdupuis3 @rajeeja any thoughts?
Sevans711 commentedon Oct 26, 2026
From internal discussion today: triaged as "to-do" in the sense that adding something into the docs / user guide should be prioritized soon-ish. However, we didn't yet decide the way to proceed with the API itself (e.g., whether to add Grid.to_netcdf() or not add it); that should be discussed further before working on API changes.
Also note, there are other methods to input/output files, such as to_zarr(), which should be considered here too.
UxObject.to_xarray().to_netcdf()) #1855