Skip to content

Add crs_units and crs_name to from_template() result.attrs#3524

Merged
brendancol merged 3 commits into
mainfrom
issue-3523
Jun 25, 2026
Merged

Add crs_units and crs_name to from_template() result.attrs#3524
brendancol merged 3 commits into
mainfrom
issue-3523

Conversation

@brendancol

Copy link
Copy Markdown
Contributor

Closes #3523

What

from_template() now adds two keys to the returned attrs:

  • crs_units: "m" for projected templates, "degree" for country codes in EPSG:4326 (the same value already on the x/y coordinate units).
  • 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 (LiteCRS table, then pyproj). For a code outside the built-in table with pyproj absent, crs_name is left off rather than raised, so the default path stays dependency-free. A name property was added to LiteCRS to mirror pyproj.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.attrs cross-backend assertions still hold.

Test plan

  • crs_units matches coordinate units for projected and geographic templates
  • crs_name deterministic for built-in-table codes (5070, 4326)
  • crs_name present on the preserve path
  • crs_name omitted (not raised) when _resolve_crs can't import pyproj
  • LiteCRS.name property
  • Full test_templates.py (44) and reproject suite (633) green

@brendancol brendancol left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.pycrs_units is 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_name can differ by resolver: a UTM code in the built-in LiteCRS table 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.attrs cross-backend assertions confirm parity and still pass.
  • crs_name is best-effort: the (ImportError, ValueError, TypeError) catch keeps the default non-reproject path dependency-free, and the omission branch is tested via monkeypatch.
  • LiteCRS.name mirrors pyproj.CRS.name with an EPSG:<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 brendancol left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
@brendancol brendancol merged commit 256de04 into main Jun 25, 2026
9 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

from_template(): add crs_units and crs_name to result.attrs

1 participant