scverse / scverse/squidpy

Feature request: contour-based inward/outward ring density for cells and transcripts around polygon annotations

Open
#1,160 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
598
Forks
121
Avg merge
3d 11h
Merged PRs (30d)
3

Description

Summary

I would like to propose contour-based inward/outward ring density around polygon
annotations in SpatialData.

This is related to #837, but it narrows the request to a concrete downstream
workflow: instead of only exposing distances to polygon annotations, the goal is
to compute signed distance and ring-based density profiles for both cells and
transcripts around a contour.

Use cases

  • Tumor boundary analyses where we want to quantify cell or transcript density
    as we move inward or outward from an annotated interface.
  • Lumen-edge analyses where density should be summarized in concentric inward and
    outward rings.
  • Tissue compartment or manual contour annotations where the user wants a radial
    density profile rather than only a nearest-distance column.

Proposed inputs

  • Polygon or MultiPolygon annotations from SpatialData used as the contour
    reference.
  • Cells counted by centroid assignment.
  • Transcripts counted by point coordinates.
  • User-defined ring width and inward/outward extent in the dataset coordinate
    system.

Proposed outputs

A per-ring table, optionally stratified by library or sample, with at least:

  • ring_start
  • ring_end
  • count
  • area
  • density = count / area

Signed-distance semantics:

  • boundary = 0
  • inside = negative
  • outside = positive

Why this is not a duplicate of #837

#837 already points toward polygon-aware distance calculations. This request is a
more concrete downstream proposal built on that direction:

  1. add a contour-aware signed-distance primitive
  2. add ring-density aggregation on top of that primitive

So I see this as a focused extension of #837 rather than a separate geometry
system.

Minimal API sketch

Low-level primitive:

sq.tl.var_by_distance(
    sdata,
    groups=...,
    cluster_key=...,
    annotations="tumor_boundary",
    coordinate_system="global",
)

High-level helper:

sq.tl.ring_density(
    sdata,
    contour_key="tumor_boundary",
    target="cells",  # or "transcripts"
    ring_width=25.0,
    inward=100.0,
    outward=100.0,
)

Proposed v1 scope

In scope:

  • SpatialData-first API
  • Polygon and MultiPolygon contour support
  • signed distance to the contour boundary
  • centroid-based cell density
  • point-based transcript density
  • per-ring count, area, and density

Out of scope for v1:

  • weighting cells by polygon overlap with rings
  • 3D contours
  • smoothing or KDE-based density
  • automatic conflict resolution across multiple overlapping contours

Related context

If this direction sounds reasonable, I would be happy to follow up with a minimal
Draft PR that keeps the first implementation intentionally small.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the related issues #837 and #975, plus the nearby PR #807, to understand existing polygon-aware distance and annotation-linking direction. Define a minimal SpatialData-first scope for polygon and MultiPolygon contours, cells and transcripts, and the proposed signed-distance and ring_density APIs. Done should include per-ring ring_start, ring_end, count, area, and density with the stated inward/outward semantics.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
data
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.