Repository navigation
Open
Labels
proposalIdea for a new feature.Idea for a new feature.
Description
Problem
Currently, when a Dataset has Zarr conventions declared at the dataset level, individual DataArrays within that Dataset cannot inherit the conventions. This leads to inconsistent behavior:
# Dataset has conventions at group level
ds = xr.Dataset({"var1": (["y", "x"], data)})
ds.attrs = {
"zarr_conventions": [{"name": "proj:", ...}],
"proj:code": "EPSG:4326"
}
print(ds.rio.crs) # ✅ Works: reads from dataset attrs
print(ds["var1"].rio.crs) # ❌ Returns None: DataArray doesn't inheritAccording to Zarr conventions, DataArrays should inherit group-level metadata when they don't have their own conventions declared.
Root Cause
- xarray doesn't maintain parent-child relationships between Dataset and DataArray
- In Implement Zarr spatial and proj conventions support #883
zarr.read_crs(obj)only examinesobj.attrs, not potential parent Dataset attributes XRasterBase.crsproperty has no context about inheritance hierarchy
Proposed Solutions
Option 1: Explicit Parent Registration
Add explicit inheritance support to XRasterBase:
class XRasterBase:
def set_parent_dataset(self, parent_dataset: xarray.Dataset) -> 'XRasterBase':
"""Enable inheritance from parent Dataset"""
self._parent_dataset = parent_dataset
return self
def _read_with_inheritance(self, read_func):
"""Try object-level first, then parent inheritance"""
result = read_func(self._obj)
if (result is None and
isinstance(self._obj, xarray.DataArray) and
self._parent_dataset is not None):
result = read_func(self._parent_dataset)
return result
# Usage:
da = ds["var1"]
da.rio.set_parent_dataset(ds) # Enable inheritance
print(da.rio.crs) # Now inherits EPSG:4326Pros: Explicit, backward compatible, extensible to all metadata types
Cons: Requires manual setup
Option 2: Enhanced Dataset Accessor
Automatically set up inheritance when accessing DataArrays from Dataset:
class RasterDataset(XRasterBase):
def __getitem__(self, key):
"""Auto-enable inheritance for DataArray access"""
result = self._obj[key]
if isinstance(result, xarray.DataArray):
result.rio.set_parent_dataset(self._obj)
return result
def get_array_with_inheritance(self, var_name: str) -> 'RasterArray':
"""Convenience method for inheritance-enabled DataArray access"""
return self._obj[var_name].rio.set_parent_dataset(self._obj)Pros: More automatic, better UX
Cons: Requires careful integration with xarray accessors
Implementation Considerations
- Inheritance Priority: Array-level attributes take precedence over dataset-level
- Convention Consistency: Same inheritance behavior for both CF and Zarr conventions
- Metadata Scope: Extend to CRS, transform, and spatial dimensions
- Performance: Minimal overhead for non-inheritance cases
Breaking Changes
None - inheritance would be opt-in and backward compatible.
Alternative Approaches Considered
- Stack inspection for parent detection
- Global context managers
Metadata
Metadata
Assignees
Labels
proposalIdea for a new feature.Idea for a new feature.
Activity
snowman2 commentedon Dec 16, 2025
I don't think there is a good solution that will be stable. The properties on accessors are very lossy. Once you do an xarray operation, the connection is lost.
It is unfortunate that zarr chose to use attrs. Those are very lossy and not reliable in the xarray world. The CF convention uses a coordinate as it is shared between Dataset and DataArray and is not as easily lost.
I suggest using a coordinate to store the Zarr information to enable persisting the data between Dataset and DataArray.
See:
emmanuelmathot commentedon Dec 16, 2025
You're right that attributes are lossy in xarray, it's a well-known pain point. The zarr geospatial conventions have been months (years including geozarr) in the making with extensive community discussions. Switching to coordinates would break that consensus and interoperability.
Given that context, Could we move forward with Option 1? It would:
We can implement it as a practical solution while continuing to advocate for better attribute support in xarray itself.
snowman2 commentedon Dec 16, 2025
Option 1 is worse than attrs. See #532, #356, #252. The
set_methods are highly discouraged because they are so lossy.emmanuelmathot commentedon Dec 16, 2025
I appreciate your clarification regarding the inheritance issue in xarray. It seems that, despite our hopes, it may not be applicable in rioxarray.
benbovy commentedon Feb 19, 2026
Great to see the ongoing work on Zarr/CF multi-convention support! I'm very supportive of the Zarr geospatial conventions.
Just wanted to chime in briefly.
Would it be acceptable to have a Dataset or DataArray that has both Zarr conventions declared and some extra (index) coordinates? (e.g., #855 that I’m guilty of having left it stale).
It is not a perfect solution since there would be duplicated information and perhaps a bit more to check/maintain in the convention classes. But I don’t think it would break consensus and interoperability: couldn’t one “just” ignore or delete those extra coordinates and continue working with an object that has valid Zarr conventions? Maybe deleting those coordinates could be an option added to the rioxarray methods for writing the CRS or transform?
Xarray coordinates do not only allow better persistence of (meta)data across Xarray operations, they also play a key role in the Xarray user experience since lots of Xarray API & features rely on it (e.g., label indexing, alignment, plotting, etc.). For example, it is very handy to have x/y spatial coordinates attached to a Dataset or DataArray, e.g., for using like
ds.sel(x=…, y=…), even if those coordinates are not explicitly part of the Zarr spatial conventions. Scalar coordinates could also be useful when they are baked by a custom index like xproj.CRSIndex for CRS-aware auto-alignment of Xarray objects, even if the CRS is also encoded in the Dataset/DataArray as attributes following the Zarr proj convention.RichardScottOZ commentedon Feb 19, 2026
Where would that get looked at, in practice...to and from zarr?
benbovy commentedon Feb 19, 2026
The
ZarrConventionclass would still be used to read/write georeferencing information to/from zarr.Actually, thinking more about it: in addition to the ZarrConvention and CFConvention classes there could be another
XarrayIndexesConventionclass, which instead of relying on attributes would rely on Xarray coordinates baked by the following indexes:(BTW note the perfect alignment in scope of those indexes with the Zarr spatial & proj conventions)
Such index-based convention has the great advantage of being optimized for Xarray UX:
After a quick inspection, it looks like the convention protocol added in Rioxarray would already work well for implementing such XarrayIndexesConvention class. Switching from one convention to another seem also rather seamless? This is great if it enables the workflow below:
emmanuelmathot commentedon Feb 20, 2026
Thank you @benbovy for the input. Would
XarrayIndexesConventioninherit from ZarrConventions and extend it? So far, the conventions mechanism allows for 1 convention at a time.Second, I wonder about the performance at opening of the Xarray indices. One of the main driver to have an alternative to CF convention was to avoid opening other arrays to just get attributes from a 0D array. Even if lossy, attributes have the advantage to be available in the consolidated metadata.
benbovy commentedon Feb 20, 2026
No
XarrayIndexesConventionwould be independent, and I think it would work well with the current mechanism of one convention at a time.The basic idea of
XarrayIndexesConventionwould be to either look or createRasterIndexorCRSIndexinstances like this:XarrayIndexConvention is thus neither opening any array nor looking at any attribute. For Rioxarray to detect the georeferencing info using this index-based convention, it needs either that:
Regarding performance, create/assign CRSIndex and RasterIndex objects basically consists in wrapping
CRSandAffinePython objects then create lazy or scalar Xarray variables, so it is almost free I would say.Sorry, this deviates from the original topic of this issue. The index-based convention works well with DataArray-Dataset inheritance, though, so assuming we can - and we want to - easily switch between conventions (one at a time) in a processing pipeline it could provide a solution to this issue.
snowman2 commentedon Feb 20, 2026
xarray indexes aren't a convention for storing metadata on a xarray object that can be persisted on disk. They indexes are a way of representing convention metadata on the xarray object.
Instead,
to_netcdfandto_zarrshould be able to interact with the indexes to convert them to the correct on disk representation.benbovy commentedon Feb 20, 2026
I still see the model with RasterIndex + CRSIndex (and their associated coordinates) as a convention.
Indeed it is not a convention for writing metadata on "disk" like CF and Zarr conventions. But it is still a conventional representation of Xarray objects that contain georeferencing information, which can be used across any Xarray library that supports it (e.g., gdx, xpublish-tiles... maybe other libraries in the future like
odc-geo?), for better interoperability within the Xarray geospatial ecosystem.Is the Rioxarray convention mechanism strictly limited to reading/writing metadata that is meant to persist on disk? If yes, it would be good to clarify that as I didn't see there were such restriction.
What would be the reasons to prevent generalizing Rioxarray's convention concept to simply "where to find the georeferencing info" and "where to put the georeferencing info" in an Xarray object?
Rioxarray's CFConvention and ZarrConvention are parsing (creating) Xarray attributes and/or coordinate variables... Is there any reason why another convention wouldn't be allowed to parse (create) Xarray indexed coordinates?
If an
XarrayIndexesConventionis out of scope or doesn't make sense, how could (should) we tell Rioxarray to get the CRS and/or transform from an Xarray object that we created from scratch with a CRSIndex and/or RasterIndex?Those functions are in general agnostic of the Xarray indexes. Instead, writing the georeferencing info to variables and attributes using either the CF or Zarr conventions is a prerequisite.
snowman2 commentedon Feb 20, 2026
The CF & Zarr conventions are able to be understood by software outside of xarray. Being able to persist on disk enables that.
The xarray indexes are an abstraction layer constructed using information from either the CF or Zarr conventions.
snowman2 commentedon Feb 20, 2026
Here is an example of what it could look like where you read the convention metadata from the xarray object to build the index:
benbovy commentedon Feb 20, 2026
Yes sure one could build the indexes manually.
Then we have this kind of issue:
Also by adding indexes we add their corresponding (spatial + "grid mapping") coordinates, and we're back to
Of course we could let users manually deal with all those inconsistencies... But I thought it would be nice for Rioxarray to provide something to prevent this kind of situation...
It turns out that the convention protocol newly added in rioxarray already provides a nice framework for opt-in integration of
rasterixandxprojwith Rioxarray, as shown in #888 (comment).I honestly don't fully get your point in #888 (comment), but I'd understand that you want to restrict Rioxarray conventions to metadata that can be persisted on disk: it is easy for anyone to relate the ZarrConvention and CFConvention classes here to their "official" declaration, which isn't the case for the index-based rioxarray convention proposal.
(sorry again for hijacking this issue, we can move this discussion into a new issue, if anyone would like to continue it).
snowman2 commentedon Feb 20, 2026
#908