Reason or Problem
from_template(name, resolution=r) does not honor the requested resolution exactly. It keeps the template's bounding box fixed, divides it by the resolution, rounds the cell count to an integer, then recomputes the realized cell size from the fixed box. When the box extent is not an exact multiple of the resolution, the returned res drifts.
Example:
>>> from xrspatial import from_template
>>> from_template('nyc', resolution=10).attrs['res']
(10.0, 10.000757432304487)
The NYC bbox is 55510 m wide and 52814 m tall. 55510 divides evenly by 10, so res_x stays 10. 52814 does not, so res_y comes back as 10.000757. A user who asked for 10 m cells expects (10.0, 10.0).
Proposal
Honor the requested resolution exactly. Hold the lower-left corner fixed and nudge the far edges (right, top) out to the nearest exact multiple of the cell size, the same way the reproject grid path already does in _compute_output_grid. The grid extent shifts by less than half a cell while res matches the request.
Design:
In from_template, after computing width/height with round(), set right = left + width * res_x and top = bottom + height * res_y, then build the coordinates and the res attr from the requested resolution. This mirrors xrspatial/reproject/_grid.py lines 457-459.
Usage:
>>> from_template('nyc', resolution=10).attrs['res']
(10.0, 10.0)
Value: Resolution becomes a guarantee rather than advisory. Grids from from_template line up with other rasters at the same resolution, which matters for stacking, alignment, and tiling.
Drawbacks
The grid no longer reaches the registry bbox's exact stated far edge; right/top move by up to half a cell. Pixel centers still fall inside the original bbox.
Alternatives
Leave the behavior as is and document the drift. Rejected because it makes resolution advisory rather than a guarantee.
Reason or Problem
from_template(name, resolution=r)does not honor the requested resolution exactly. It keeps the template's bounding box fixed, divides it by the resolution, rounds the cell count to an integer, then recomputes the realized cell size from the fixed box. When the box extent is not an exact multiple of the resolution, the returnedresdrifts.Example:
The NYC bbox is 55510 m wide and 52814 m tall. 55510 divides evenly by 10, so res_x stays 10. 52814 does not, so res_y comes back as 10.000757. A user who asked for 10 m cells expects (10.0, 10.0).
Proposal
Honor the requested resolution exactly. Hold the lower-left corner fixed and nudge the far edges (right, top) out to the nearest exact multiple of the cell size, the same way the reproject grid path already does in
_compute_output_grid. The grid extent shifts by less than half a cell whileresmatches the request.Design:
In
from_template, after computing width/height with round(), setright = left + width * res_xandtop = bottom + height * res_y, then build the coordinates and theresattr from the requested resolution. This mirrorsxrspatial/reproject/_grid.pylines 457-459.Usage:
Value: Resolution becomes a guarantee rather than advisory. Grids from
from_templateline up with other rasters at the same resolution, which matters for stacking, alignment, and tiling.Drawbacks
The grid no longer reaches the registry bbox's exact stated far edge; right/top move by up to half a cell. Pixel centers still fall inside the original bbox.
Alternatives
Leave the behavior as is and document the drift. Rejected because it makes resolution advisory rather than a guarantee.