Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
162 commits
Select commit Hold shift + click to select a range
5c08081
init
selmanozleyen Apr 2, 2026
5847d84
doc clarifications
selmanozleyen Apr 2, 2026
179ba06
don't expose the builders
selmanozleyen Apr 2, 2026
e187aba
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 2, 2026
cdb5699
deduplicate
selmanozleyen Apr 2, 2026
847a46b
Merge branch 'feat/spatial_neighbours' of https://github.com/selmanoz…
selmanozleyen Apr 2, 2026
69cda1a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 2, 2026
fddc027
arrange builders
selmanozleyen Apr 2, 2026
a30988a
Merge branch 'feat/spatial_neighbours' of https://github.com/selmanoz…
selmanozleyen Apr 2, 2026
f194b10
better behaviour
selmanozleyen Apr 2, 2026
ae1eba1
move classes
selmanozleyen Apr 2, 2026
a86572b
Merge branch 'main' into feat/spatial_neighbours
selmanozleyen Apr 2, 2026
039b852
cleanup
selmanozleyen Apr 2, 2026
4699993
Merge branch 'feat/spatial_neighbours' of https://github.com/selmanoz…
selmanozleyen Apr 2, 2026
b5dcf9f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 2, 2026
4c11adf
add docs
selmanozleyen Apr 2, 2026
2b937e9
Merge branch 'feat/spatial_neighbours' of https://github.com/selmanoz…
selmanozleyen Apr 2, 2026
ea1ce93
remove leftover
selmanozleyen Apr 2, 2026
ebb7fd5
resolution in reolve func
selmanozleyen Apr 2, 2026
69a9394
reduce dup code
selmanozleyen Apr 2, 2026
77755ed
deprecate invalid n_neighs
selmanozleyen Apr 2, 2026
d8a8145
expose new functions and deprecate the flat one
selmanozleyen Apr 2, 2026
2e75b3f
move branches to classes
selmanozleyen Apr 2, 2026
8c1c2ef
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 2, 2026
268d30c
remove radius abstraction
selmanozleyen Apr 2, 2026
3f41243
Merge branch 'feat/spatial_neighbours' of https://github.com/selmanoz…
selmanozleyen Apr 2, 2026
aa9734a
add extensibility page
selmanozleyen Apr 2, 2026
67bad43
unprivate methods and add extensibility page
selmanozleyen Apr 2, 2026
65fa245
give a better example
selmanozleyen Apr 2, 2026
85bfdeb
apply signature suggestion
selmanozleyen Apr 9, 2026
79f584f
reorganize abstractions
selmanozleyen Apr 9, 2026
43cdbb6
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 9, 2026
e632f74
remove unnecessary abstraction
selmanozleyen Apr 9, 2026
1f9da0e
Merge branch 'feat/spatial_neighbours' of https://github.com/selmanoz…
selmanozleyen Apr 9, 2026
c026860
put the warning in resolve graph builder code
selmanozleyen Apr 9, 2026
10cc2f0
remove n_neighs from RadiusBuilder
selmanozleyen Apr 9, 2026
6477f18
definition of Adj, Dst and rename to adj, dst
selmanozleyen Apr 9, 2026
516b3e0
Generalize the base class for extensibility
selmanozleyen Apr 10, 2026
141fdb6
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 10, 2026
1fe316b
update docs
selmanozleyen Apr 10, 2026
bc6746a
Merge branch 'feat/spatial_neighbours' of https://github.com/selmanoz…
selmanozleyen Apr 10, 2026
bb1ec50
clarify delauney vs grid
selmanozleyen Apr 10, 2026
84cbdc4
dtype rec
selmanozleyen Apr 10, 2026
6d942ec
be a bit more verbose on funcitons
selmanozleyen Apr 10, 2026
ae9a4e6
spatial_neighbours_from_builder
selmanozleyen Apr 10, 2026
cd3f6fd
update docs to refer to each other
selmanozleyen Apr 10, 2026
95012dc
refer to the classes properly
selmanozleyen Apr 10, 2026
5a02b59
mark as TODO's
selmanozleyen Apr 13, 2026
3af98cc
rename sugg
selmanozleyen Apr 13, 2026
e8a19d7
add combine into API
selmanozleyen Apr 13, 2026
ac682a3
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 13, 2026
0f3329c
update docs
selmanozleyen Apr 13, 2026
00ec2b0
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 13, 2026
042f749
[pre-commit.ci] pre-commit autoupdate (#1149)
pre-commit-ci[bot] Apr 10, 2026
1a87841
Functions to QC histopathology images (#1036)
timtreis Apr 10, 2026
1cb6fde
remove coord_type abstraction
selmanozleyen Apr 13, 2026
8afcd03
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 13, 2026
3c4dffb
Merge branch 'main' into feat/spatial_neighbours
selmanozleyen Apr 13, 2026
21f02c3
make builder positional consistently
selmanozleyen Apr 13, 2026
744c757
make more abstractions
selmanozleyen Apr 13, 2026
dbc7f0d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 13, 2026
d7e5e5f
graphmatrixT exposure
selmanozleyen Apr 13, 2026
13768e2
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 13, 2026
ea3f3ca
Merge branch 'main' into feat/spatial_neighbours
selmanozleyen Apr 20, 2026
21f248e
add radius: float | int | tuple t
selmanozleyen May 12, 2026
3bbc535
4 or 6
selmanozleyen May 12, 2026
a0426e6
Merge branch 'main' into feat/spatial_neighbours
selmanozleyen May 12, 2026
f3eab97
Merge branch 'main' into feat/spatial_neighbours
selmanozleyen May 15, 2026
8436656
Merge branch 'main' into feat/spatial_neighbours
timtreis May 19, 2026
07d59bf
Merge branch 'main' into feat/spatial_neighbours
selmanozleyen May 19, 2026
3e9fc41
Merge branch 'main' into feat/spatial_neighbours
selmanozleyen May 21, 2026
77627dc
mark snn as ilustrative
selmanozleyen May 21, 2026
0afbe3c
add uns params
selmanozleyen May 21, 2026
1711a62
deprecation warnings alignment
selmanozleyen May 21, 2026
4632b74
set diag isnt defaulted to none
selmanozleyen May 21, 2026
f4805c1
fix
selmanozleyen May 21, 2026
f2b0fa0
radius is also positional
selmanozleyen May 21, 2026
0ed1604
n_neighs on grid mode
selmanozleyen May 21, 2026
c85ba43
make radius kw only
selmanozleyen May 26, 2026
d9264a8
put a working example
selmanozleyen May 27, 2026
9c89dc2
Merge branch 'main' into feat/spatial_neighbours
selmanozleyen May 27, 2026
52b4e79
fix api.md
selmanozleyen May 27, 2026
60e888f
Merge branch 'main' into feat/spatial_neighbours
selmanozleyen May 28, 2026
bfbb3e8
be more compatible with main
selmanozleyen May 28, 2026
7e4ddec
Merge branch 'main' into feat/spatial_neighbours
selmanozleyen May 28, 2026
9dd330e
align more to main
selmanozleyen May 28, 2026
cf38fe3
Merge branch 'feat/spatial_neighbours'
selmanozleyen May 28, 2026
6c61ddc
save state
selmanozleyen Jun 1, 2026
e2266de
save state
selmanozleyen Jun 1, 2026
b2d25cb
refactor
selmanozleyen Jun 1, 2026
14d36b0
undo lock file
selmanozleyen Jun 1, 2026
86c9d76
Merge remote-tracking branch 'origin/main' into feat/experimental-fit…
selmanozleyen Jun 1, 2026
8e4bb93
undo changes with main
selmanozleyen Jun 1, 2026
9a489f2
resuse resolve_labels_array
selmanozleyen Jun 1, 2026
1955bed
Merge branch 'main' into feat/experimental-fit-core
selmanozleyen Jun 1, 2026
068f3e7
Merge branch 'main' into feat/experimental-fit-core
selmanozleyen Jun 1, 2026
759e09e
Update api.md
selmanozleyen Jun 1, 2026
ad200ea
Update api.md
selmanozleyen Jun 1, 2026
0e9b8c1
Merge branch 'main' into feat/experimental-fit-core
selmanozleyen Jun 8, 2026
c9eb7e4
rename file and refactor
selmanozleyen Jun 8, 2026
77f3e7d
move files
selmanozleyen Jun 8, 2026
57f9d21
fix imports
selmanozleyen Jun 8, 2026
5d69264
fixes
selmanozleyen Jun 8, 2026
6587efe
remove bloat code
selmanozleyen Jun 8, 2026
e45e247
typr hints
selmanozleyen Jun 8, 2026
beb1476
add tests
selmanozleyen Jun 8, 2026
5eeb95d
reduce bloat
selmanozleyen Jun 8, 2026
3c2ed02
reduce bloat
selmanozleyen Jun 8, 2026
1ea9996
remove useless file
selmanozleyen Jun 8, 2026
ee741ab
fix
selmanozleyen Jun 8, 2026
ba91e4f
undo rasterize changes
selmanozleyen Jun 8, 2026
1d65f4a
doc landmark
selmanozleyen Jun 8, 2026
a3da05a
remove bloat
selmanozleyen Jun 8, 2026
373ca02
docs
selmanozleyen Jun 8, 2026
aaf48c7
doc debloatr
selmanozleyen Jun 8, 2026
4387a61
expose result classes
selmanozleyen Jun 8, 2026
85df8fc
refactoring, testing, typing and bug fix on copy mode
selmanozleyen Jun 11, 2026
599186f
landmark is positional only now
selmanozleyen Jun 11, 2026
8cfc770
expose api
selmanozleyen Jun 11, 2026
96bc445
Merge branch 'main' into feat/experimental-fit-core
selmanozleyen Jun 11, 2026
30e14cf
Merge branch 'main' into feat/experimental-fit-core
selmanozleyen Jun 16, 2026
d617b45
Merge branch 'main' into feat/experimental-fit-core
selmanozleyen Jun 19, 2026
f0868c1
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 19, 2026
e6b4075
lower bound jax
selmanozleyen Jun 19, 2026
bff9092
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 19, 2026
81a16f2
align expose
selmanozleyen Jun 19, 2026
f5ccd46
api refactor
selmanozleyen Jun 20, 2026
461f5ee
expose methods in a nice place
selmanozleyen Jun 20, 2026
f6b907e
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 20, 2026
265ad0b
reduce bloat
selmanozleyen Jun 20, 2026
9740f5d
Merge branch 'main' into feat/experimental-fit-core
selmanozleyen Jun 20, 2026
035e6e9
format
selmanozleyen Jun 20, 2026
6e12e46
cleanup
selmanozleyen Jun 22, 2026
cbe72b5
file orga
selmanozleyen Jun 22, 2026
4e5909c
file orga
selmanozleyen Jun 22, 2026
3f9ab34
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 22, 2026
5646282
fix tests and imports
selmanozleyen Jun 22, 2026
f0415af
Merge branch 'feat/experimental-fit-core' of https://github.com/selma…
selmanozleyen Jun 22, 2026
4a6e6ff
fix merge error
selmanozleyen Jun 22, 2026
bb20bc0
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 22, 2026
44a5a22
fix merge error
selmanozleyen Jun 22, 2026
62ec52f
Merge branch 'feat/experimental-fit-core' of https://github.com/selma…
selmanozleyen Jun 22, 2026
6ed6344
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 22, 2026
6a0b106
autodoc mock jax
selmanozleyen Jun 22, 2026
21cd780
remove casting
selmanozleyen Jun 22, 2026
9236ac3
strict=True
selmanozleyen Jun 22, 2026
5c663a2
add jax docs
selmanozleyen Jun 22, 2026
c07a707
speed up rasterize by avoiding loop
selmanozleyen Jun 22, 2026
f41aeb1
apply suggestion
selmanozleyen Jun 22, 2026
e405382
Merge branch 'main' into feat/experimental-fit-core
timtreis Jun 23, 2026
70ed3ca
Merge branch 'main' into feat/experimental-fit-core
timtreis Jul 7, 2026
5388c37
wip stalign reference tests
selmanozleyen Jul 31, 2026
9006b1b
fix stalign port divergences
selmanozleyen Jul 31, 2026
8cf5728
redesign align io with paths
selmanozleyen Jul 31, 2026
b4e5788
fuse lddmm loop add early stopping
selmanozleyen Jul 31, 2026
d9fe88a
unify align registry and modalities
selmanozleyen Jul 31, 2026
68763c9
guard shared coordinate system
selmanozleyen Jul 31, 2026
bffde5c
regenerate bundle on linux
selmanozleyen Jul 31, 2026
4e2e19f
route reference tests through public api
selmanozleyen Jul 31, 2026
b19d2e9
assess image path against reference
selmanozleyen Jul 31, 2026
12ecd75
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 31, 2026
8e09320
extend STalign alignment API
selmanozleyen Jul 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,40 @@ jobs:
DISPLAY: :42
run: uvx hatch run ${{ matrix.env.name }}:run -v --color=yes -n auto

# Numerical comparison against the vendored STalign reference (scverse/squidpy#1243).
# Scheduled runs only: it needs float64 and is far slower than the wiring tests.
#
# Deliberately confined to one cell. jax is only installed in the -jax env, and the
# tolerances are calibrated on Linux -- macOS Accelerate and Linux OpenBLAS reduce in
# different orders, which shows up over a few hundred gradient steps.
#
# HATCH_TEST_ARGS lands after the `-m "not reference"` in hatch.toml's run script,
# and pytest's -m is last-wins, so this selects exactly the reference tests.
- name: run STalign reference comparison
if: >-
github.event_name == 'schedule'
&& matrix.os == 'ubuntu-latest'
&& matrix.env.name == 'hatch-test.py3.13-stable-jax'
env:
HATCH_TEST_ARGS: " -m reference"
JAX_ENABLE_X64: "1"
JAX_PLATFORMS: cpu
MKL_NUM_THREADS: "1"
OMP_NUM_THREADS: "1"
run: >-
uvx hatch run ${{ matrix.env.name }}:run -v --color=yes
--junitxml=stalign-reference.xml

# Every comparison records its measured relative error via record_property, so this
# artifact is a running log of how far the port has drifted -- including on green runs.
- name: Archive STalign reference measurements
if: always() && github.event_name == 'schedule' && matrix.env.name == 'hatch-test.py3.13-stable-jax'
uses: actions/upload-artifact@v4
with:
name: stalign_reference_${{ runner.os }}
path: ${{ github.workspace }}/stalign-reference.xml
if-no-files-found: ignore

- name: Archive figures generated during testing
if: always()
uses: actions/upload-artifact@v4
Expand Down
21 changes: 21 additions & 0 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,25 @@ See the {doc}`extensibility guide </extensibility>` for how to implement a custo
gr.neighbors.GridBuilder
```

The ``method=`` argument of {func}`~squidpy.experimental.tl.align` and
{func}`~squidpy.experimental.tl.align` dispatches to a registered
fitting function. The method-specific arguments are documented on each function
below; the fitted maps are returned (with ``output_mode="object"``) as the
result types listed alongside.

```{eval-rst}
.. currentmodule:: squidpy
.. autosummary::
:toctree: api

experimental.methods.align_samples._stalign.fit_stalign
experimental.methods.align_samples._stalign.fit_stalign_image
experimental.methods.align_landmarks._landmark.fit_similarity
experimental.methods.align_landmarks._landmark.fit_affine
experimental.methods.align_samples._stalign.StalignResult
experimental.methods.align_landmarks._landmark.AffineFitResult
```

## Experimental
```{eval-rst}
.. module:: squidpy.experimental
Expand All @@ -150,6 +169,8 @@ See the {doc}`extensibility guide </extensibility>` for how to implement a custo
experimental.im.calculate_image_features
experimental.tl.calculate_tiling_qc
experimental.tl.TilingQCParams
experimental.tl.align
experimental.tl.AlignResult
experimental.tl.assign_stitch_groups
experimental.tl.StitchParams
experimental.im.make_stitched_labels
Expand Down
3 changes: 3 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@
autodoc_member_order = "groupwise"
autodoc_typehints = "signature"
autodoc_docstring_signature = True
autodoc_mock_imports = ["jax"]
napoleon_google_docstring = False
napoleon_numpy_docstring = True
napoleon_include_init_with_doc = False
Expand Down Expand Up @@ -147,6 +148,8 @@
("py:class", "NDArray"),
("py:class", "np.number"),
("py:class", "csr_matrix"),
# optional dep mocked at build time (see autodoc_mock_imports), so no resolvable target
("py:class", "jax.Array"),
# no idea why those aren’t exported
("py:class", "squidpy._constants._constants.SpatialAutocorr"),
("py:class", "squidpy._constants._constants.CoordType"),
Expand Down
57 changes: 57 additions & 0 deletions docs/release/notes-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,63 @@
## Features

- {func}`squidpy.experimental.im.calculate_image_features` now featurizes tiles on a shared dask engine: `n_jobs > 1` runs worker processes via a `dask.distributed.LocalCluster` (or an active `Client`), and per-tile BLAS/OpenMP threads are pinned to avoid oversubscription. This also speeds up the serial path. {func}`squidpy.experimental.tl.calculate_tiling_qc` shares the same engine. Adds `distributed` and `threadpoolctl` as dependencies.
- Add a numerical reference suite for the experimental STalign port, comparing it against the
original PyTorch implementation. Deselected by default; runs on the scheduled job. Reference
values are generated out of band by
[theislab/squidpy-ports](https://github.com/theislab/squidpy-ports), so `torch` is not a squidpy
dependency.
[#1243](https://github.com/scverse/squidpy/issues/1243)
- **Breaking (experimental):** {func}`squidpy.experimental.tl.align` now locates data with `in_`
and `out` paths instead of a stack of key arguments. `ref_key`, `query_key`, `spatial_key`,
`key_added` and `output_mode` are replaced by `in_` (e.g. `"obsm/spatial"`,
`"tables/slice1/obsm/spatial"`, `"images/he"`, `"shapes/landmarks"`), `out`, and `copy`.
`out=None` (the default) returns the fitted alignment and writes nothing. This follows the shape
proposed for scanpy in [scanpy#4007](https://github.com/scverse/scanpy/issues/4007).
- **Breaking (experimental):** `squidpy.experimental.tl.align_by_landmarks` is folded into
{func}`squidpy.experimental.tl.align` as `by="landmarks"`. `on` becomes `by`, gaining a
`"landmarks"` value alongside `"obs"` and `"images"`; `in_` then names the correspondences and
`apply_to` names what moves. Writing to `out="cs/<name>"` registers the fitted affine on a whole
SpatialData coordinate system instead of materialising anything; because that moves every element
registered there, it refuses when the reference shares the query's coordinate system.
- **Breaking (experimental):** the `align_samples`, `align_images` and `align_landmarks` registries
collapse into a single `ALIGN` registry of `AlignMethod` records, each declaring which modalities
it implements. Asking for one a method does not support now fails immediately and says what it
does support. `fit_stalign` is renamed `fit_stalign_obs` for symmetry with `fit_stalign_image`.
- {func}`squidpy.experimental.tl.align` can now align on images. The fitted diffeomorphism cannot
be expressed as a SpatialData transformation, so writing to an `images/...` path materialises the
warped image rather than registering it lazily. Adds an `align_images` method family and
`squidpy.experimental.methods.align_samples.fit_stalign_image`.
- The experimental STalign solver now runs its whole gradient descent as a single compiled
`lax.while_loop` instead of a Python loop around a jitted step, about **4.6x faster** per
iteration (2.20 to 0.46 ms on the reference fixture, so `niter=5000` drops from ~11s to ~2.4s).
Numerically unchanged: the reference suite still matches the original implementation at 1, 5, 50
and 500 iterations.
- The reference suite now covers `fit_stalign_image`, the last part of the experimental
STalign port without one. It reproduces the original to ~4e-12 on the affine and ~2e-12 on the
velocity field over a full trajectory.
- The experimental STalign solver returns the per-iteration `energies` trace and `n_iter`, and
accepts optional `tol` / `patience` early stopping. Off by default. Note the objective changes
definition at iteration 50, when the mixture-weight E step engages, so the convergence window
deliberately never spans that point.
- **Breaking (experimental):** {func}`squidpy.experimental.tl.align_by_landmarks` takes `in_` /
`out` / `copy` in place of `spatial_key` / `key_added` / `output_mode`, and its coordinate-system
arguments are renamed `cs_ref` / `cs_query`. Because `out` is always named explicitly, the guard
that refused to overwrite an auto-derived key is gone.

## Bugfixes

- The experimental STalign estimator no longer differentiates through the contrast-transform ridge
solve. That solve is an expectation-maximisation M step and must be held constant; treating it as
part of the objective changed the search direction. Gradients now agree with the original
implementation to ~1e-15, previously ~1e-3.
- **Breaking (experimental):** the rasterisation and velocity grids in the experimental STalign
estimator were one sample longer per axis than intended, and their length varied with
floating-point rounding. Output shapes change accordingly.
- The experimental STalign rasteriser now deposits each point bilinearly rather than snapping it to
the nearest cell, and conserves mass at the image border. Relative error against the original
implementation drops from 6.2 %/2.0 %/6.0 % to 4.1 %/0.8 %/2.9 % across the default blur scales.
- `lddmm(niter=0)` no longer raises `UnboundLocalError`.

- Fix {func}`squidpy.tl.var_by_distance` behaviour when providing {mod}`numpy` arrays of coordinates as anchor point.
- Update :attr:`squidpy.pl.var_by_distance` to show multiple variables on same plot.
[@LLehner](https://github.com/LLehner)
Expand Down
13 changes: 11 additions & 2 deletions hatch.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,22 @@ extra-dependencies = ["diff-cover"]
matrix = [
{ deps = ["stable"], python = ["3.12", "3.13", "3.14"] },
{ deps = ["pre"], python = ["3.14"] },
{ deps = ["stable"], python = ["3.13"], extras = ["jax"] },
]
overrides.matrix.deps.env-vars = [
{ key = "UV_PRERELEASE", value = "allow", if = ["pre"] },
]
overrides.matrix.extras.features = [
{ value = "jax", if = ["jax"] },
]
# default commands (only `cov-report` is overridden)
scripts.run = "pytest{env:HATCH_TEST_ARGS:} -p no:cov {args}"
scripts.run-cov = "coverage run -m pytest{env:HATCH_TEST_ARGS:} -p no:cov {args}"
#
# The `-m "not reference"` is the actual gate on the STalign reference suite: a CLI flag
# works on every pytest, whereas pyproject's `[tool.pytest]` table is only read by
# pytest >= 9. HATCH_TEST_ARGS is interpolated after it and pytest's `-m` is last-wins,
# so the scheduled job re-enables the suite with HATCH_TEST_ARGS=' -m reference'.
scripts.run = 'pytest -m "not reference"{env:HATCH_TEST_ARGS:} -p no:cov {args}'
scripts.run-cov = 'coverage run -m pytest -m "not reference"{env:HATCH_TEST_ARGS:} -p no:cov {args}'
scripts.cov-combine = ["coverage combine"]
scripts.cov-report = [
"coverage report",
Expand Down
12 changes: 12 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ dependencies = [
"xarray>=2024.10",
"zarr>=3",
]
optional-dependencies.jax = [
"jax>=0.4",
]
optional-dependencies.leiden = [
"leidenalg",
"spatialleiden>=0.4",
Expand Down Expand Up @@ -275,9 +278,18 @@ python_files = [ "test_*.py" ]
testpaths = [ "tests/" ]
addopts = [
"--ignore=docs",
# Local convenience only. The real exclusion is the `-m "not reference"` baked into
# hatch.toml's run/run-cov, because that is a CLI flag and so survives any pytest that
# does not read this table. Keeping both means a bare `pytest` is also quiet.
"-m",
"not reference",
]
markers = [
"internet: tests that require internet",
"""\
reference: numerical comparison against the vendored STalign reference (slow, needs JAX_ENABLE_X64=1, scheduled runs \
only)\
""",
# the below markers are just there because we import from anndata.tests.helpers,
# which means pytest sees them despite us not using them.
"gpu: tests that require GPU",
Expand Down
35 changes: 35 additions & 0 deletions src/squidpy/experimental/methods/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""In-memory model-fitting core for experimental methods.

The :mod:`.registry` subpackage holds the registry machinery and the :data:`ALIGN`
registry; each family subpackage (e.g. :mod:`.align_samples`, :mod:`.align_landmarks`)
holds the estimator implementations. Importing this package imports those subpackages so
the estimators register themselves. Each subpackage stays cheap to import -- heavy or
optional dependencies (e.g. JAX) are pulled in lazily, only when an estimator actually
runs.
"""

from __future__ import annotations

# Import for side effects: populates ALIGN.
from squidpy.experimental.methods import align_landmarks, align_samples # noqa: F401
from squidpy.experimental.methods.registry import (
ALIGN,
AlignImagesFn,
AlignLandmarksFn,
AlignMethod,
AlignObsFn,
AlignResult,
Modality,
Registry,
)

__all__ = [
"ALIGN",
"AlignImagesFn",
"AlignLandmarksFn",
"AlignMethod",
"AlignObsFn",
"AlignResult",
"Modality",
"Registry",
]
21 changes: 21 additions & 0 deletions src/squidpy/experimental/methods/align_landmarks/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"""``align_landmarks`` family: closed-form alignment from paired landmarks.

Importing this package registers the family's estimators into
:data:`~squidpy.experimental.methods.registry.ALIGN`. Only the
implementations are re-exported here; the registry itself lives in (and is public
from) :mod:`squidpy.experimental.methods`.
"""

from __future__ import annotations

from squidpy.experimental.methods.align_landmarks._landmark import (
AffineFitResult,
fit_affine,
fit_similarity,
)

__all__ = [
"AffineFitResult",
"fit_affine",
"fit_similarity",
]
Loading
Loading