Add global-projection templates to from_template (web_mercator, wgs84/latlon, equal_earth)#3550
Merged
Conversation
Add web_mercator (EPSG:3857), equal_earth (EPSG:8857), and wgs84/latlon aliases for the EPSG:4326 world grid. All resolve to real EPSG codes so attrs['crs'] stays an int. Reuses the existing backend dispatch, so all four backends work.
brendancol
commented
Jun 27, 2026
brendancol
left a comment
Contributor
Author
There was a problem hiding this comment.
PR Review: Add global-projection templates to from_template
Blockers (must fix before merge)
None.
Suggestions (should fix, not blocking)
xrspatial/_template_data.py: theweb_mercatorandequal_earthentries carryarea_epsg=8857/shape_epsg=3395, sofrom_template('web_mercator', preserve='shape')will reproject a global template into yet another projection. That combination works but is odd, and nothing tests it. Either add a one-line build test or drop the keys if preserve-on-global is out of scope.
Nits (optional improvements)
xrspatial/_template_data.py: the Web Mercator latitude limit is written as85.051129, but the exact value is85.0511287798. It only matters on the rarely-used preserve path, so it is cosmetic. The nearby comment cites the precise definition, which makes the rounded literal look slightly off.
What looks good
wgs84/latlonreuse theworldgrid through_REGION_ALIASESrather than copying the bounds, so there is one source of truth.- All four projections resolve to real EPSG ints, matching the project convention. The ESRI-only projections (Robinson, Gall-Peters, Mollweide) are documented as deliberately left out.
- No new backend code: coverage comes from the existing
_make_datadispatch, and the dask path stays lazy viada.full. - Tests cover the array contract, the alias-equals-world check, case-insensitive lookup, exact resolution, bounds containment, and the CF grid-mapping behavior for 3857/8857.
Checklist
- Algorithm matches reference (EPSG codes and projected bounds verified with pyproj)
- All implemented backends produce consistent results (shared dispatch)
- NaN handling is correct (NaN-filled, asserted)
- Edge cases covered (case-insensitive, exact resolution, bounds)
- Dask chunk boundaries handled (lazy da.full, no overlap needed)
- No premature materialization
- Benchmark not needed (no compute kernel)
- README feature matrix updated
- Docstrings present and accurate
brendancol
commented
Jun 27, 2026
brendancol
left a comment
Contributor
Author
There was a problem hiding this comment.
Follow-up review (after commit b1719cb)
Both items from the first pass are resolved.
- Suggestion (preserve on global templates): kept the
area_epsg/shape_epsghints, since they match theworldentry and steerpreserve='shape'to World Mercator (EPSG:3395) instead of a stray UTM zone for the (0, 0) centroid. Addedtest_global_preserve_picks_world_projectionto lock that in for bothweb_mercatorandequal_earth. - Nit (latitude limit): the Web Mercator lonlat band now uses the exact
85.0511287798, matching the comment.
No new findings. Tests: 82 passed locally (numpy, cupy, dask backends).
3 tasks
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 #3549
Adds whole-world templates to
from_template, each resolving to a real EPSG code:web_mercator-> EPSG:3857 (WGS 84 / Pseudo-Mercator)equal_earth-> EPSG:8857 (Equal Earth, the equal-area option)wgs84andlatlon-> aliases for the existing EPSG:4326worldgrid (single source of truth via a small_REGION_ALIASESmap)Robinson, Gall-Peters, and Mollweide were requested but only have ESRI codes, not EPSG. Storing those as a bare int would be ambiguous with EPSG and would break the CF metadata path, so they are left out;
equal_earthcovers the equal-area case with a real EPSG code. The reasoning is written up in the issue.The new names go through the same backend dispatch as the rest of
from_template, so numpy, cupy, dask+numpy, and dask+cupy all work with no new backend-specific code. The dask path stays lazy (da.full).Test plan
pytest xrspatial/tests/test_templates.py(80 passed, including the cupy and dask backends that run on this box)wgs84/latlonproduce the same grid and attrs asworldgrid_mapping_name, socrs_wktcarries the name