Skip to content

Commit 6d3ba30

Browse files
committed
Merge branch 'main' into fix/macsima_handle_autofluorescence_channels
2 parents 4e9a34b + 433014e commit 6d3ba30

File tree

19 files changed

+566
-376
lines changed

19 files changed

+566
-376
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ _version.py
3636
node_modules/
3737
.code-workspace
3838

39+
# memray report
40+
*.bin
41+
42+
# speedscope report
43+
profile.speedscope.json
44+
3945
# test datasets (e.g. Xenium ones)
4046
# symlinks
4147
data

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ default_stages:
77
minimum_pre_commit_version: 2.16.0
88
repos:
99
- repo: https://github.com/rbubley/mirrors-prettier
10-
rev: v3.7.4
10+
rev: v3.8.1
1111
hooks:
1212
- id: prettier
1313
- repo: https://github.com/astral-sh/ruff-pre-commit
14-
rev: v0.14.11
14+
rev: v0.15.2
1515
hooks:
1616
- id: ruff
1717
args: [--fix, --exit-non-zero-on-fix, --unsafe-fixes]

asv.conf.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
"project": "spatialdata-io",
44
"project_url": "https://github.com/scverse/spatialdata-io",
55
"repo": ".",
6-
"branches": ["image-reader-chunkwise"],
6+
"branches": ["faster-imports", "main"],
77
"dvcs": "git",
88
"environment_type": "virtualenv",
9-
"pythons": ["3.12"],
9+
"pythons": ["3.13"],
1010
"build_command": [],
1111
"install_command": ["python -m pip install {build_dir}[test]"],
1212
"uninstall_command": ["python -m pip uninstall -y {project}"],
@@ -17,7 +17,7 @@
1717
"hash_length": 8,
1818
"build_cache_size": 2,
1919
"install_timeout": 600,
20-
"repeat": 3,
20+
"repeat": 5,
2121
"processes": 1,
2222
"attribute_selection": ["time_*", "peakmem_*"]
2323
}

benchmarks/benchmark_image.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from spatialdata._logging import logger
1717
from xarray import DataArray
1818

19-
from spatialdata_io import image # type: ignore[attr-defined]
19+
from spatialdata_io import image
2020

2121
# =============================================================================
2222
# CONFIGURATION - Edit these values to match your setup

benchmarks/benchmark_imports.py

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
"""ASV benchmarks for spatialdata-io import times.
2+
3+
Measures how long it takes to import the package and individual readers
4+
in a fresh subprocess, isolating import overhead from runtime work.
5+
6+
Running (with the current environment, no virtualenv rebuild):
7+
# Quick sanity check (single iteration):
8+
asv run --python=same --quick --show-stderr -v -b ImportBenchmark
9+
10+
# Full benchmark on current commit:
11+
asv run --python=same --show-stderr -v -b ImportBenchmark
12+
13+
# Compare two branches (using --python=same, one-liner):
14+
git stash && git checkout main && pip install -e . -q \
15+
&& asv run --python=same -v -b ImportBenchmark \
16+
&& git checkout faster-imports && git stash pop && pip install -e . -q \
17+
&& asv run --python=same -v -b ImportBenchmark
18+
# Then view the comparison:
19+
asv compare $(git rev-parse main) $(git rev-parse faster-imports)
20+
21+
# Compare two branches (let ASV build virtualenvs, slower first run):
22+
asv continuous --show-stderr -v -b ImportBenchmark main faster-imports
23+
24+
# Generate an HTML report:
25+
asv publish && asv preview
26+
"""
27+
28+
import subprocess
29+
import sys
30+
31+
32+
def _import_time(statement: str) -> float:
33+
"""Time an import in a fresh subprocess. Returns seconds."""
34+
code = f"import time; t0=time.perf_counter(); {statement}; print(time.perf_counter()-t0)"
35+
result = subprocess.run(
36+
[sys.executable, "-c", code],
37+
capture_output=True,
38+
text=True,
39+
)
40+
if result.returncode != 0:
41+
raise RuntimeError(result.stderr)
42+
return float(result.stdout.strip())
43+
44+
45+
class ImportBenchmark:
46+
"""Import-time benchmarks for spatialdata-io.
47+
48+
Each ``time_*`` method is a separate ASV benchmark.
49+
They run in isolated subprocesses so that one import
50+
does not warm the cache for the next.
51+
"""
52+
53+
# ASV settings tuned for subprocess-based import timing:
54+
timeout = 120 # seconds before ASV kills a benchmark; generous since each
55+
# call spawns a subprocess (~2s each × 10 repeats = ~20s worst case)
56+
repeat = 5 # number of timing samples ASV collects; high because import
57+
# times have variance from OS caching / disk I/O / background load;
58+
# ASV reports the median and IQR from these samples
59+
number = 1 # calls per sample; must be 1 because each call spawns a fresh
60+
# subprocess — running >1 would just re-import in a warm process
61+
warmup_time = 0 # seconds of warm-up iterations before timing; disabled because
62+
# each call is already a cold subprocess — warming up the parent
63+
# process is meaningless
64+
processes = 1 # number of ASV worker processes; 1 avoids parallel subprocesses
65+
# competing for CPU / disk and inflating timings
66+
67+
# -- top-level package -------------------------------------------------
68+
69+
def time_import_spatialdata_io(self) -> float:
70+
"""Wall time: ``import spatialdata_io`` (lazy, no readers loaded)."""
71+
return _import_time("import spatialdata_io")
72+
73+
# -- single reader via the public API ----------------------------------
74+
75+
def time_from_spatialdata_io_import_xenium(self) -> float:
76+
"""Wall time: ``from spatialdata_io import xenium``."""
77+
return _import_time("from spatialdata_io import xenium")
78+
79+
def time_from_spatialdata_io_import_visium(self) -> float:
80+
"""Wall time: ``from spatialdata_io import visium``."""
81+
return _import_time("from spatialdata_io import visium")
82+
83+
def time_from_spatialdata_io_import_visium_hd(self) -> float:
84+
"""Wall time: ``from spatialdata_io import visium_hd``."""
85+
return _import_time("from spatialdata_io import visium_hd")
86+
87+
def time_from_spatialdata_io_import_merscope(self) -> float:
88+
"""Wall time: ``from spatialdata_io import merscope``."""
89+
return _import_time("from spatialdata_io import merscope")
90+
91+
def time_from_spatialdata_io_import_cosmx(self) -> float:
92+
"""Wall time: ``from spatialdata_io import cosmx``."""
93+
return _import_time("from spatialdata_io import cosmx")
94+
95+
# -- key dependencies (reference) --------------------------------------
96+
97+
def time_import_spatialdata(self) -> float:
98+
"""Wall time: ``import spatialdata`` (reference)."""
99+
return _import_time("import spatialdata")
100+
101+
def time_import_anndata(self) -> float:
102+
"""Wall time: ``import anndata`` (reference)."""
103+
return _import_time("import anndata")

benchmarks/benchmark_xenium.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939

4040
from spatialdata import SpatialData
4141

42-
from spatialdata_io import xenium # type: ignore[attr-defined]
42+
from spatialdata_io import xenium
4343

4444
# =============================================================================
4545
# CONFIGURATION - Edit these paths to match your setup

docs/conf.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@
127127
# If building the documentation fails because of a missing link that is outside your control,
128128
# you can add an exception to this list.
129129
("py:class", "Path"),
130+
("py:class", "pathlib._local.Path"),
130131
("py:class", "AnnData"),
131132
("py:class", "SpatialData"),
132133
("py:func", "imageio.imread"), # maybe this can be fixed

pyproject.toml

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,18 @@ requires = ["hatchling", "hatch-vcs"]
55

66
[project]
77
name = "spatialdata-io"
8-
dynamic= [
9-
"version" # allow version to be set by git tags
8+
dynamic = [
9+
"version" # allow version to be set by git tags
1010
]
1111
description = "SpatialData IO for common techs"
1212
readme = "README.md"
1313
requires-python = ">=3.11"
14-
license = {file = "LICENSE"}
14+
license = { file = "LICENSE" }
1515
authors = [
16-
{name = "scverse"},
16+
{ name = "scverse" },
1717
]
1818
maintainers = [
19-
{name = "scverse", email = "scverse@scverse.scverse"},
19+
{ name = "scverse", email = "scverse@scverse.scverse" },
2020
]
2121
urls.Documentation = "https://spatialdata-io.readthedocs.io/"
2222
urls.Source = "https://github.com/scverse/spatialdata-io"
@@ -26,7 +26,7 @@ dependencies = [
2626
"click",
2727
"numpy",
2828
"scanpy",
29-
"spatialdata>=0.2.6",
29+
"spatialdata>=0.7.3a0",
3030
"scikit-image",
3131
"h5py",
3232
"joblib",
@@ -46,7 +46,7 @@ dev = [
4646
"pre-commit"
4747
]
4848
doc = [
49-
"sphinx>=4.5",
49+
"sphinx>=4.5,<9",
5050
"sphinx-book-theme>=1.0.0",
5151
"myst-nb",
5252
"sphinxcontrib-bibtex>=1.0.0",
@@ -67,7 +67,7 @@ test = [
6767
# update: readthedocs doens't seem to try to install pre-releases even if when trying to install the pre optional-dependency. For
6868
# the moment, if needed, let's add the latest pre-release explicitly here.
6969
pre = [
70-
"spatialdata>=0.4.0rc0"
70+
"spatialdata>=0.7.3a0"
7171
]
7272

7373
[tool.coverage.run]
@@ -80,7 +80,7 @@ omit = [
8080
testpaths = ["tests"]
8181
xfail_strict = true
8282
addopts = [
83-
"--import-mode=importlib", # allow using test files with same name
83+
"--import-mode=importlib", # allow using test files with same name
8484
]
8585

8686
[tool.ruff]
@@ -95,19 +95,19 @@ exclude = [
9595
"setup.py",
9696
]
9797
lint.select = [
98-
"F", # Errors detected by Pyflakes
99-
"E", # Error detected by Pycodestyle
100-
"W", # Warning detected by Pycodestyle
101-
"I", # isort
102-
"D", # pydocstyle
103-
"B", # flake8-bugbear
104-
"TID", # flake8-tidy-imports
105-
"C4", # flake8-comprehensions
106-
"BLE", # flake8-blind-except
107-
"UP", # pyupgrade
108-
"RUF100", # Report unused noqa directives
109-
"TCH", # Typing imports
110-
"NPY", # Numpy specific rules
98+
"F", # Errors detected by Pyflakes
99+
"E", # Error detected by Pycodestyle
100+
"W", # Warning detected by Pycodestyle
101+
"I", # isort
102+
"D", # pydocstyle
103+
"B", # flake8-bugbear
104+
"TID", # flake8-tidy-imports
105+
"C4", # flake8-comprehensions
106+
"BLE", # flake8-blind-except
107+
"UP", # pyupgrade
108+
"RUF100", # Report unused noqa directives
109+
"TCH", # Typing imports
110+
"NPY", # Numpy specific rules
111111
# "PTH", # Use pathlib
112112
# "S" # Security
113113
]
@@ -185,6 +185,8 @@ lint.ignore = [
185185
# Unused imports
186186
"F401",
187187
]
188+
[tool.ruff.lint.per-file-ignores]
189+
"src/spatialdata_io/__init__.py" = ["I001"]
188190

189191
[tool.jupytext]
190192
formats = "ipynb,md"

0 commit comments

Comments
 (0)