Skip to content

Add high-level overlay API and refactor CLI to use it - #80

Merged
tomalrussell merged 13 commits into
mainfrom
claude/python-api-cli-consistency-gvi8ul
Aug 24, 2026
Merged

Add high-level overlay API and refactor CLI to use it#80
tomalrussell merged 13 commits into
mainfrom
claude/python-api-cli-consistency-gvi8ul

Conversation

@tomalrussell

@tomalrussell tomalrussell commented Aug 24, 2026

Copy link
Copy Markdown
Member

Introduce snail.overlay to provide simplified APIs for overlaying raster values onto vector features, and refactors the CLI and internal code to use these new functions. The changes aim to make snail more accessible as a Python library while maintaining backward compatibility.

  • snail.overlay module has three main functions:
    • overlay_raster(): Split features along a single raster grid and attribute cell values
    • overlay_rasters(): Split features along multiple raster grids in one call
    • split_features(): Split features along a grid without attributing raster values
  • overlay handles point, linestring, and polygon features
  • Support single- and multi-band rasters with default or user-specified column names
  • Implicitly reproject features to raster CRS for processing, then back to original CRS
  • Accept rasters as file paths, open rasterio datasets, or xarray DataArrays
  • CLI --all-layers flag to split all layers in a multi-layer vector file
  • GeoParquet output format (.parquet and .geoparquet extensions)

Implementation notes

  • Multi-band rasters automatically create columns named "{column}_band_{n}" for each band, while single-band rasters use just the column name
  • The process command now supports wildcard layer specifications to process all layers in a file

claude added 2 commits August 24, 2026 13:13
Work through the remaining checklist in #54:

- Add snail.overlay_raster and snail.overlay_rasters, high-level functions
  taking (features, raster path/s, open dataset/s or DataArray/s) and
  returning split features with attributed values, plus
  snail.split_features; export from the package root and refactor the CLI
  on top of them. --lazy-rasters is threaded through as a `lazy` argument
- Handle multi-band rasters in `snail process`, attributing one column per
  band named "{key}_band_{n}" (previously each band overwrote a single
  column); single-band values keep the plain key. `snail split` uses the
  same naming, so both commands agree
- Reproject features to the raster grid CRS implicitly for splitting,
  indexing and value lookup, returning results in the original CRS. Fixes
  `snail split` applying cell indices in the features CRS, which gave wrong
  indices whenever it differed from the raster CRS. Features or grids with
  no CRS are assumed to match, with a warning
- Coerce MultiLineString geometries in split_linestrings (merge and
  explode, with a warning) instead of failing downstream
- Add `snail split --all-layers` (each layer to a GeoPackage output layer)
  and a "*" wildcard layer value in the `snail process` features CSV,
  expanding to one output per layer
- Default `snail process` output paths to
  "{features_stem}_{layer}__{rasters_csv_stem}.parquet" next to the input
  instead of "{path}.processed.parquet", and respect output format by
  extension (GeoParquet or any geopandas-writable format) in both commands
- Allow a per-row missing "bands" value in the rasters CSV to default to
  all bands
- Fix `-vv` raising TypeError: the log level was set to a bound logger
  method rather than logging.INFO
- Document the Python API, `snail process` semantics (all features
  intersected with all rasters, one column per raster file/band) and the
  optional CSV columns in the README and docs

Fixes #54

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014foLdPo81QBhpRGUn2kkUG
Fixes ruff LOG015 (root-logger calls) and UP007/UP045 (Optional/Union
annotations) reported by CI.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014foLdPo81QBhpRGUn2kkUG
@tomalrussell

Copy link
Copy Markdown
Member Author

Closes #54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a high-level raster/vector overlay API and refactors CLI workflows around it.

Changes:

  • Introduces single- and multi-raster overlay APIs with CRS handling.
  • Adds multi-layer CLI processing and GeoParquet output.
  • Expands overlay and CLI tests and documentation.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/snail/overlay.py Implements the high-level overlay API.
src/snail/io.py Adds raster-source and vector-output helpers.
src/snail/intersection.py Adds CRS-aware multi-grid splitting.
src/snail/cli.py Refactors commands to use overlay APIs.
src/snail/__init__.py Exports the new public functions.
tests/test_overlay.py Tests overlay behavior and inputs.
tests/test_cli.py Tests CLI layers and output formats.
tests/conftest.py Adds raster and vector fixtures.
README.md Documents APIs and CLI workflows.
docs/source/index.rst Adds high-level usage documentation.
Suppressed comments (1)

src/snail/io.py:74

  • Duplicate user-supplied keys (or otherwise colliding generated band names) silently overwrite the earlier raster's Series in this dictionary, so the result no longer contains one column per requested raster band. Reject collisions rather than returning incomplete data.
        column = band_column_name(raster.key, band_number, len(raster.bands))
        raster_data[column] = get_raster_values_for_splits(

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/snail/intersection.py Outdated
Comment thread src/snail/cli.py
Comment thread src/snail/overlay.py Outdated
Comment thread src/snail/io.py Outdated
band_number,
)
raster_data[raster.key] = get_raster_values_for_splits(
column = band_column_name(raster.key, band_number, len(raster.bands))
Comment thread src/snail/overlay.py Outdated
@tomalrussell
tomalrussell merged commit d8c2128 into main Aug 24, 2026
9 checks passed
@tomalrussell
tomalrussell deleted the claude/python-api-cli-consistency-gvi8ul branch August 24, 2026 17:22
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.

3 participants