Stop surface_distance outputs adopting the dask graph token as .name (#3708) - #3716
Open
brendancol wants to merge 1 commit into
Open
Stop surface_distance outputs adopting the dask graph token as .name (#3708)#3716brendancol wants to merge 1 commit into
brendancol wants to merge 1 commit into
Conversation
…3708) surface_distance, surface_allocation and surface_direction built their result with xr.DataArray(..., coords=, dims=, attrs=) and left name unset. DataArray.__init__ then falls back to getattr(data, "name"), which on a dask array is the graph key, so the dask backends returned '_trim-<hash>' (bounded map_overlap route), 'xrspatial.surface_*-<hash>' (unbounded iterative route) or 'asarray-<hash>' (dask+cupy unbounded) while numpy and cupy returned None. The divergence is user-visible through .to_dataset(): the numpy result raises "unable to convert unnamed DataArray", the dask result silently creates a variable named after the hash, and the hash moves when chunking or max_distance changes. Route the three functions through a shared _wrap_result() helper that resets .name to None after construction, matching the proximity/allocation/direction trio this module mirrors. Same bug class as cost_distance #3344 and pathfinding #3652. Tests cover .name parity over 4 backends x 3 functions x bounded/unbounded max_distance, plus an attrs/coords/dims/dtype preservation guard. The 12 dask cases fail without the fix. Also records the metadata sweep result for this module in .claude/sweep-metadata-state.csv.
Contributor
Author
|
Verification run on the dev box (CUDA available, so cupy and dask+cupy executed rather than skipping):
The diff is three call sites plus one helper; no behavioral change to the distance, allocation or direction values themselves. |
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.
Fixes #3708.
surface_distance,surface_allocationandsurface_directionbuilt their result withxr.DataArray(result_data, coords=..., dims=..., attrs=...)and leftnameunset.DataArray.__init__then falls back togetattr(data, "name", None), which on a dask array is the graph key, so the dask backends returned a hash-suffixed name while numpy and cupy returnedNone.Three different tokens leaked depending on the route taken:
max_distance.namebeforeNonemap_overlap_trim-<hash>xrspatial.surface_distance-<hash>map_overlap_trim-<hash>asarray-<hash>The clearest user-facing symptom is
.to_dataset():The numpy branch asks the user for a name. The dask branch silently produces a variable named after a hash that moves when chunking or
max_distancechanges, so a saved dataset is not stable across runs.Change
The three public functions now go through a shared
_wrap_result()helper that resets.nametoNoneafter construction. That matches theproximity/allocation/directiontrio this module mirrors (xrspatial/proximity.py:1757,:1919,:2086). Recurring bug class: slope #2837, aspect #2841, focal #2733, viewshed #2743, zonal #2611, cost_distance #3344, pathfinding #3652.Nothing else about the returned object changes.
Tests
test_output_name_consistent_across_backendscovers 4 backends x 3 functions x bounded/unboundedmax_distance, so both dask routes are exercised. The 12 dask cases fail on the parent commit and pass here.test_output_preserves_attrs_coords_dimsis a regression guard for the rest of the metadata contract the audit found already correct:res/crs/transform/nodatavals, extra scalar coords, coord values, dim names, and the float32 output dtype.Full suite: 73 passed (was 37). CUDA is available on the dev box, so the cupy and dask+cupy parametrisations ran for real rather than skipping.
Audit scope
Found by
/deep-sweep --only-hydro(metadata sweep). Everything else in this module's metadata handling checked out across all four backends and both dask routes, including custom dim names viax=/y=..namewas the only divergence. The state row in.claude/sweep-metadata-state.csvrecords two LOW items left unfixed: attrs are copied verbatim so a user-suppliednodatavals=(-9999,)survives onto output that uses NaN as its sentinel, and aunitsattr carries ontosurface_directionoutput measured in degrees. Both follow the library-wideattrs=raster.attrsconvention rather than being specific to this module.