-
Notifications
You must be signed in to change notification settings - Fork 96
Add Convention option & extract CF logic to cf.py #899
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
snowman2
merged 30 commits into
corteva:master
from
emmanuelmathot:feature/convention-option-cf-refactor
Feb 3, 2026
Merged
Changes from all commits
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
ddc9338
REF: Refactor convention handling and add CF support in rioxarray
emmanuelmathot 81ca317
ENH: Add `convention` option to `set_options()` and extract CF conven…
emmanuelmathot 00956fe
Merge branch 'master' into feature/convention-option-cf-refactor
emmanuelmathot fde2529
Add Convention option & extract CF logic to cf.py
emmanuelmathot 6c023fa
Refactor code structure for improved readability and maintainability
emmanuelmathot d88e548
REF: Remove unused functions and constants to streamline code in riox…
emmanuelmathot 8ea47c1
Refactor code structure for improved readability and maintainability
emmanuelmathot 43d6bdd
Refactor code structure for improved readability and maintainability
emmanuelmathot 2fe9212
Implement feature X to enhance user experience and fix bug Y in module Z
emmanuelmathot 5587996
Update rioxarray/_options.py
emmanuelmathot 524ae5c
Update rioxarray/_options.py
emmanuelmathot b52cdb3
Refactor convention handling to support auto-detection of CRS, transf…
emmanuelmathot db71c16
Update rioxarray/_convention/__init__.py
emmanuelmathot 7cfe70c
Refactor convention handling to support writing CRS and transform, an…
emmanuelmathot ef5ca43
Refactor convention handling to improve grid mapping writing and enha…
emmanuelmathot 6d5b2db
grid_mapping in CF
emmanuelmathot 4ebffdf
Refactor grid mapping handling to improve clarity and consistency in …
emmanuelmathot f4a0fee
Pass grid_mapping_name to read_transform in write_crs for accurate tr…
emmanuelmathot 7d3fcae
Refactor grid mapping handling in write_crs and write_transform to us…
emmanuelmathot 03b5d7b
Refactor convention handling to prioritize globally set conventions f…
emmanuelmathot 56b466c
Refactor code structure for improved readability and maintainability
emmanuelmathot 7194119
Update rioxarray/rioxarray.py
emmanuelmathot f733dbc
Update rioxarray/rioxarray.py
emmanuelmathot 921cece
Update rioxarray/rioxarray.py
emmanuelmathot 10e0019
Update rioxarray/rioxarray.py
emmanuelmathot af4efcf
pylint
emmanuelmathot 41caadd
remove uv.lock
emmanuelmathot 2fcf2e7
Add asterisk for keyword-only arguments in write_crs and write_transf…
emmanuelmathot d35805d
Refactor write_crs and write_transform functions to use keyword-only …
emmanuelmathot bf0e184
satisfy mypy
emmanuelmathot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,214 @@ | ||||||||
| """Convention modules for rioxarray. | ||||||||
|
|
||||||||
| This module defines the common interface for convention implementations | ||||||||
| and provides helpers for selecting conventions. | ||||||||
| """ | ||||||||
|
|
||||||||
| from typing import Dict, Optional, Protocol, Tuple, Union | ||||||||
|
|
||||||||
| import rasterio.crs | ||||||||
| import xarray | ||||||||
| from affine import Affine | ||||||||
|
|
||||||||
| from rioxarray._convention.cf import CFConvention | ||||||||
| from rioxarray._options import CONVENTION, get_option | ||||||||
| from rioxarray.crs import crs_from_user_input | ||||||||
| from rioxarray.enum import Convention | ||||||||
|
|
||||||||
|
|
||||||||
| class ConventionProtocol(Protocol): | ||||||||
| """Protocol defining the interface for convention modules.""" | ||||||||
|
|
||||||||
| @staticmethod | ||||||||
| def read_crs( | ||||||||
| obj: Union[xarray.Dataset, xarray.DataArray], **kwargs | ||||||||
| ) -> Optional[rasterio.crs.CRS]: | ||||||||
| """Read CRS from the object using this convention.""" | ||||||||
|
|
||||||||
| @staticmethod | ||||||||
| def read_transform( | ||||||||
| obj: Union[xarray.Dataset, xarray.DataArray], **kwargs | ||||||||
| ) -> Optional[Affine]: | ||||||||
| """Read transform from the object using this convention.""" | ||||||||
|
|
||||||||
| @staticmethod | ||||||||
| def read_spatial_dimensions( | ||||||||
| obj: Union[xarray.Dataset, xarray.DataArray], | ||||||||
| ) -> Optional[Tuple[str, str]]: | ||||||||
| """Read spatial dimensions (y_dim, x_dim) from the object using this convention.""" | ||||||||
|
|
||||||||
| @staticmethod | ||||||||
| def write_crs( | ||||||||
| obj: Union[xarray.Dataset, xarray.DataArray], | ||||||||
| crs: rasterio.crs.CRS, | ||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
| **kwargs, | ||||||||
| ) -> Union[xarray.Dataset, xarray.DataArray]: | ||||||||
| """Write CRS to the object using this convention.""" | ||||||||
|
|
||||||||
| @staticmethod | ||||||||
| def write_transform( | ||||||||
| obj: Union[xarray.Dataset, xarray.DataArray], | ||||||||
| transform: Affine, | ||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
| **kwargs, | ||||||||
| ) -> Union[xarray.Dataset, xarray.DataArray]: | ||||||||
| """Write transform to the object using this convention.""" | ||||||||
|
|
||||||||
|
|
||||||||
| # Convention classes mapped by Convention enum | ||||||||
| _CONVENTION_MODULES: Dict[Convention, ConventionProtocol] = { | ||||||||
| Convention.CF: CFConvention # type: ignore[dict-item] | ||||||||
| } | ||||||||
|
|
||||||||
|
|
||||||||
| def _get_convention(convention: Convention | None) -> ConventionProtocol: | ||||||||
| """ | ||||||||
| Get the convention module for writing. | ||||||||
|
|
||||||||
| Parameters | ||||||||
| ---------- | ||||||||
| convention : Convention enum value or None | ||||||||
| The convention to use. If None, uses the global default. | ||||||||
|
|
||||||||
| Returns | ||||||||
| ------- | ||||||||
| ConventionProtocol | ||||||||
| The module implementing the convention | ||||||||
| """ | ||||||||
| if convention is None: | ||||||||
| convention = get_option(CONVENTION) or Convention.CF | ||||||||
| convention = Convention(convention) | ||||||||
| return _CONVENTION_MODULES[convention] | ||||||||
|
|
||||||||
|
|
||||||||
| def read_crs_auto( | ||||||||
| obj: Union[xarray.Dataset, xarray.DataArray], | ||||||||
| **kwargs, | ||||||||
| ) -> Optional[rasterio.crs.CRS]: | ||||||||
| """ | ||||||||
| Auto-detect and read CRS by trying convention readers. | ||||||||
|
|
||||||||
| If a convention is set globally via set_options(), that convention | ||||||||
| is tried first for better performance. Then other conventions are | ||||||||
| tried as fallback. | ||||||||
|
|
||||||||
| Parameters | ||||||||
| ---------- | ||||||||
| obj : xarray.Dataset or xarray.DataArray | ||||||||
| Object to read CRS from | ||||||||
| **kwargs | ||||||||
| Convention-specific parameters (e.g., grid_mapping for CF) | ||||||||
|
|
||||||||
| Returns | ||||||||
| ------- | ||||||||
| rasterio.crs.CRS or None | ||||||||
| CRS object, or None if not found in any convention | ||||||||
| """ | ||||||||
| # Try the configured convention first (if set) | ||||||||
| configured_convention = get_option(CONVENTION) | ||||||||
| if configured_convention is not None: | ||||||||
| result = _CONVENTION_MODULES[configured_convention].read_crs(obj, **kwargs) | ||||||||
| if result is not None: | ||||||||
| return result | ||||||||
|
|
||||||||
| # Try all other conventions | ||||||||
| for conv_enum, convention in _CONVENTION_MODULES.items(): | ||||||||
| if conv_enum == configured_convention: | ||||||||
| continue # Already tried this one | ||||||||
| result = convention.read_crs(obj, **kwargs) | ||||||||
| if result is not None: | ||||||||
| return result | ||||||||
|
|
||||||||
| # Legacy fallback: look in attrs for 'crs' (not part of any convention) | ||||||||
| try: | ||||||||
| return crs_from_user_input(obj.attrs["crs"]) | ||||||||
| except KeyError: | ||||||||
| pass | ||||||||
|
|
||||||||
| return None | ||||||||
|
|
||||||||
|
|
||||||||
| def read_transform_auto( | ||||||||
| obj: Union[xarray.Dataset, xarray.DataArray], | ||||||||
| **kwargs, | ||||||||
| ) -> Optional[Affine]: | ||||||||
| """ | ||||||||
| Auto-detect and read transform by trying convention readers. | ||||||||
|
|
||||||||
| If a convention is set globally via set_options(), that convention | ||||||||
| is tried first for better performance. Then other conventions are | ||||||||
| tried as fallback. | ||||||||
|
|
||||||||
| Parameters | ||||||||
| ---------- | ||||||||
| obj : xarray.Dataset or xarray.DataArray | ||||||||
| Object to read transform from | ||||||||
| **kwargs | ||||||||
| Convention-specific parameters (e.g., grid_mapping for CF) | ||||||||
|
|
||||||||
| Returns | ||||||||
| ------- | ||||||||
| affine.Affine or None | ||||||||
| Transform object, or None if not found in any convention | ||||||||
| """ | ||||||||
| # Try the configured convention first (if set) | ||||||||
| configured_convention = get_option(CONVENTION) | ||||||||
| if configured_convention is not None: | ||||||||
| result = _CONVENTION_MODULES[configured_convention].read_transform( | ||||||||
| obj, **kwargs | ||||||||
| ) | ||||||||
| if result is not None: | ||||||||
| return result | ||||||||
|
|
||||||||
| # Try all other conventions | ||||||||
| for conv_enum, convention in _CONVENTION_MODULES.items(): | ||||||||
| if conv_enum == configured_convention: | ||||||||
| continue # Already tried this one | ||||||||
| result = convention.read_transform(obj, **kwargs) | ||||||||
| if result is not None: | ||||||||
| return result | ||||||||
|
|
||||||||
| # Legacy fallback: look in attrs for 'transform' (not part of any convention) | ||||||||
| try: | ||||||||
| return Affine(*obj.attrs["transform"][:6]) | ||||||||
| except KeyError: | ||||||||
| pass | ||||||||
|
|
||||||||
| return None | ||||||||
|
|
||||||||
|
|
||||||||
| def read_spatial_dimensions_auto( | ||||||||
| obj: Union[xarray.Dataset, xarray.DataArray], | ||||||||
| ) -> Optional[Tuple[str, str]]: | ||||||||
| """ | ||||||||
| Auto-detect and read spatial dimensions by trying convention readers. | ||||||||
|
|
||||||||
| If a convention is set globally via set_options(), that convention | ||||||||
| is tried first for better performance. Then other conventions are | ||||||||
| tried as fallback. | ||||||||
|
|
||||||||
| Parameters | ||||||||
| ---------- | ||||||||
| obj : xarray.Dataset or xarray.DataArray | ||||||||
| Object to read spatial dimensions from | ||||||||
|
|
||||||||
| Returns | ||||||||
| ------- | ||||||||
| tuple of (y_dim, x_dim) or None | ||||||||
| Tuple of dimension names, or None if not found in any convention | ||||||||
| """ | ||||||||
| # Try the configured convention first (if set) | ||||||||
| configured_convention = get_option(CONVENTION) | ||||||||
| if configured_convention is not None: | ||||||||
| result = _CONVENTION_MODULES[configured_convention].read_spatial_dimensions(obj) | ||||||||
| if result is not None: | ||||||||
| return result | ||||||||
|
|
||||||||
| # Try all other conventions | ||||||||
| for conv_enum, convention in _CONVENTION_MODULES.items(): | ||||||||
| if conv_enum == configured_convention: | ||||||||
| continue # Already tried this one | ||||||||
| result = convention.read_spatial_dimensions(obj) | ||||||||
| if result is not None: | ||||||||
| return result | ||||||||
|
|
||||||||
| return None | ||||||||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.