Add crs_units and crs_name to from_template() result.attrs#3524
Merged
Conversation
brendancol
commented
Jun 25, 2026
brendancol
left a comment
Contributor
Author
There was a problem hiding this comment.
PR Review: Add crs_units and crs_name to from_template() result.attrs
Blockers (must fix before merge)
None.
Suggestions (should fix, not blocking)
None.
Nits (optional improvements)
templates.py—crs_unitsis derived by"degree" if crs == 4326 else "m". That's correct for every code the templates emit today (country codes are 4326, all projected/preserve codes are metre-based), but it's a heuristic rather than an axis-unit lookup. Worth a one-line comment if a future template ever adds a non-metre projected CRS or a non-4326 geographic one.crs_namecan differ by resolver: a UTM code in the built-inLiteCRStable returns"WGS84 / UTM zone 18N", while the pyproj fallback returns"WGS 84 / UTM zone 18N". Descriptive metadata only; the tests assert just on 5070/4326 (identical in both), so it's not a correctness problem, just a seam to be aware of.
What looks good
- Metadata is attached after array creation, so all four backends carry identical attrs. The existing
agg.attrs == ref.attrscross-backend assertions confirm parity and still pass. crs_nameis best-effort: the(ImportError, ValueError, TypeError)catch keeps the default non-reproject path dependency-free, and the omission branch is tested via monkeypatch.LiteCRS.namemirrorspyproj.CRS.namewith anEPSG:<code>fallback, giving one way to read the name across both resolver tiers.
Checklist
- No algorithm/paper involved (pure metadata)
- All implemented backends produce consistent attrs
- No NaN/float concerns (no numeric path touched)
- Edge case covered: pyproj-absent omission branch tested
- No dask chunk concerns (metadata only)
- No premature materialization
- No benchmark needed
- No README matrix change needed
- Docstring Returns section updated
brendancol
commented
Jun 25, 2026
brendancol
left a comment
Contributor
Author
There was a problem hiding this comment.
Follow-up review (commit 54ab7e0)
Nit 1 is addressed: templates.py now carries a one-line comment noting that every template emits either EPSG:4326 (degrees) or a metre-based projected CRS, which is what the crs_units heuristic relies on.
Nit 2 (the LiteCRS vs pyproj UTM name spacing seam) is left as-is. It reflects an existing naming convention in LiteCRS's UTM table; normalizing it would change LiteCRS.name/to_wkt output for every UTM code, which is outside this PR's scope. The new attrs are descriptive metadata and the tests assert only on codes whose names match across both resolvers.
No new findings. test_templates.py (44) green after the follow-up.
# Conflicts: # xrspatial/templates.py
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Closes #3523
What
from_template()now adds two keys to the returnedattrs:crs_units:"m"for projected templates,"degree"for country codes in EPSG:4326 (the same value already on thex/ycoordinateunits).crs_name: the projection's human-readable name, e.g."NAD83 / Conus Albers"(5070),"WGS 84"(4326).The name resolves through the existing two-tier CRS path (
LiteCRStable, then pyproj). For a code outside the built-in table with pyproj absent,crs_nameis left off rather than raised, so the default path stays dependency-free. Anameproperty was added toLiteCRSto mirrorpyproj.CRS.name.Backends
Pure metadata attached after array creation, so all four backends (numpy, cupy, dask+numpy, dask+cupy) carry identical attrs. The existing
agg.attrs == ref.attrscross-backend assertions still hold.Test plan
crs_unitsmatches coordinate units for projected and geographic templatescrs_namedeterministic for built-in-table codes (5070, 4326)crs_namepresent on the preserve pathcrs_nameomitted (not raised) when_resolve_crscan't import pyprojLiteCRS.namepropertytest_templates.py(44) andreprojectsuite (633) green