slide2vec 4.2.0__tar.gz → 4.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {slide2vec-4.2.0 → slide2vec-4.3.0}/PKG-INFO +28 -5
- {slide2vec-4.2.0 → slide2vec-4.3.0}/README.md +19 -2
- {slide2vec-4.2.0 → slide2vec-4.3.0}/pyproject.toml +11 -4
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/__init__.py +11 -2
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/api.py +35 -9
- slide2vec-4.3.0/slide2vec/configs/__init__.py +4 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/configs/default.yaml +8 -5
- {slide2vec-4.2.0/slide2vec → slide2vec-4.3.0/slide2vec/configs}/resources.py +2 -1
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/distributed/direct_embed_worker.py +2 -2
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/distributed/pipeline_worker.py +4 -4
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/registry.py +1 -1
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/validation.py +1 -1
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/inference.py +151 -1295
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/progress.py +123 -5
- slide2vec-4.3.0/slide2vec/runtime/__init__.py +2 -0
- slide2vec-4.3.0/slide2vec/runtime/batching.py +441 -0
- slide2vec-4.3.0/slide2vec/runtime/distributed.py +194 -0
- slide2vec-4.3.0/slide2vec/runtime/embedding.py +157 -0
- slide2vec-4.3.0/slide2vec/runtime/hierarchical.py +105 -0
- {slide2vec-4.2.0/slide2vec → slide2vec-4.3.0/slide2vec/runtime}/model_settings.py +1 -0
- slide2vec-4.3.0/slide2vec/runtime/persistence.py +165 -0
- slide2vec-4.3.0/slide2vec/runtime/progress_bridge.py +52 -0
- {slide2vec-4.2.0/slide2vec → slide2vec-4.3.0/slide2vec/runtime}/registry.py +1 -0
- slide2vec-4.3.0/slide2vec/runtime/serialization.py +119 -0
- slide2vec-4.3.0/slide2vec/runtime/tiling.py +97 -0
- slide2vec-4.3.0/slide2vec/runtime/types.py +48 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/utils/config.py +1 -1
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/utils/tiling_io.py +5 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec.egg-info/PKG-INFO +28 -5
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec.egg-info/SOURCES.txt +14 -7
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec.egg-info/requires.txt +9 -2
- slide2vec-4.3.0/tests/test_architecture_runtime_split.py +60 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/tests/test_hs2p_package_cutover.py +6 -4
- {slide2vec-4.2.0 → slide2vec-4.3.0}/tests/test_progress.py +376 -8
- {slide2vec-4.2.0 → slide2vec-4.3.0}/tests/test_regression_core.py +89 -6
- {slide2vec-4.2.0 → slide2vec-4.3.0}/tests/test_regression_inference.py +261 -99
- {slide2vec-4.2.0 → slide2vec-4.3.0}/tests/test_regression_models.py +1 -1
- slide2vec-4.2.0/slide2vec/configs/__init__.py +0 -4
- slide2vec-4.2.0/slide2vec/runtime_types.py +0 -14
- slide2vec-4.2.0/tests/test_batch_collator_timing.py +0 -161
- slide2vec-4.2.0/tests/test_output_consistency.py +0 -187
- slide2vec-4.2.0/tests/test_packaging_metadata.py +0 -23
- {slide2vec-4.2.0 → slide2vec-4.3.0}/LICENSE +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/setup.cfg +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/__main__.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/artifacts.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/cli.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/data/__init__.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/data/dataset.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/data/tile_reader.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/data/tile_store.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/distributed/__init__.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/__init__.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/base.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/__init__.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/conch.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/gigapath.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/hibou.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/hoptimus.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/lunit.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/midnight.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/moozy/__init__.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/moozy/blocks.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/moozy/case.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/moozy/loading.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/moozy/slide.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/moozy/types.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/musk.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/phikon.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/prism.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/prost40m.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/titan.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/uni.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/virchow.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/main.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/utils/__init__.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/utils/coordinates.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/utils/log_utils.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/utils/utils.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec.egg-info/dependency_links.txt +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec.egg-info/entry_points.txt +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec.egg-info/not-zip-safe +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec.egg-info/top_level.txt +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/tests/test_encoder_registry.py +0 -0
- {slide2vec-4.2.0 → slide2vec-4.3.0}/tests/test_tile_store.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: slide2vec
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.3.0
|
|
4
4
|
Summary: Embedding of whole slide images with Foundation Models
|
|
5
5
|
Author-email: Clément Grisi <clement.grisi@radboudumc.nl>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -15,7 +15,7 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
15
15
|
Requires-Python: >=3.10
|
|
16
16
|
Description-Content-Type: text/markdown
|
|
17
17
|
License-File: LICENSE
|
|
18
|
-
Requires-Dist: hs2p[asap,cucim,openslide,vips]>=
|
|
18
|
+
Requires-Dist: hs2p[asap,cucim,openslide,sam2,vips]>=4.0.0
|
|
19
19
|
Requires-Dist: omegaconf
|
|
20
20
|
Requires-Dist: matplotlib
|
|
21
21
|
Requires-Dist: numpy<2
|
|
@@ -65,7 +65,7 @@ Requires-Dist: numpy<2; extra == "fm"
|
|
|
65
65
|
Requires-Dist: pandas; extra == "fm"
|
|
66
66
|
Requires-Dist: pillow; extra == "fm"
|
|
67
67
|
Requires-Dist: rich; extra == "fm"
|
|
68
|
-
Requires-Dist: hs2p[asap,cucim,openslide,vips]>=
|
|
68
|
+
Requires-Dist: hs2p[asap,cucim,openslide,sam2,vips]>=4.0.0; extra == "fm"
|
|
69
69
|
Requires-Dist: wandb; extra == "fm"
|
|
70
70
|
Requires-Dist: torch<2.8,>=2.3; extra == "fm"
|
|
71
71
|
Requires-Dist: torchvision>=0.18.0; extra == "fm"
|
|
@@ -89,6 +89,12 @@ Requires-Dist: fairscale; extra == "fm"
|
|
|
89
89
|
Requires-Dist: packaging==23.2; extra == "fm"
|
|
90
90
|
Requires-Dist: ninja==1.11.1.1; extra == "fm"
|
|
91
91
|
Requires-Dist: psutil<6; extra == "fm"
|
|
92
|
+
Provides-Extra: docs
|
|
93
|
+
Requires-Dist: sphinx>=8.1; extra == "docs"
|
|
94
|
+
Requires-Dist: furo; extra == "docs"
|
|
95
|
+
Requires-Dist: myst-parser; extra == "docs"
|
|
96
|
+
Requires-Dist: sphinx-copybutton; extra == "docs"
|
|
97
|
+
Requires-Dist: sphinx-autodoc-typehints; extra == "docs"
|
|
92
98
|
Provides-Extra: testing
|
|
93
99
|
Requires-Dist: pytest>=6.0; extra == "testing"
|
|
94
100
|
Requires-Dist: pytest-cov>=2.0; extra == "testing"
|
|
@@ -101,9 +107,12 @@ Dynamic: license-file
|
|
|
101
107
|
# slide2vec
|
|
102
108
|
|
|
103
109
|
[](https://pypi.org/project/slide2vec/)
|
|
110
|
+
[](https://clemsgrs.github.io/slide2vec/)
|
|
104
111
|
|
|
105
112
|
`slide2vec` is a Python package for efficient encoding of whole-slide images using publicly available foundation models. It builds on [`hs2p`](https://pypi.org/project/hs2p/) for fast preprocessing and exposes a focused surface around `Model`, `Pipeline`, and `ExecutionOptions`.
|
|
106
113
|
|
|
114
|
+
Documentation site: [https://clemsgrs.github.io/slide2vec/](https://clemsgrs.github.io/slide2vec/)
|
|
115
|
+
|
|
107
116
|
## Installation
|
|
108
117
|
|
|
109
118
|
```shell
|
|
@@ -121,6 +130,8 @@ pip install git+https://github.com/Mahmoodlab/CONCH.git
|
|
|
121
130
|
pip install git+https://github.com/prov-gigapath/prov-gigapath.git
|
|
122
131
|
```
|
|
123
132
|
|
|
133
|
+
AtlasPatch-backed tissue segmentation is available through hs2p's `sam2` path in the bundled install.
|
|
134
|
+
|
|
124
135
|
## Python API
|
|
125
136
|
|
|
126
137
|
```python
|
|
@@ -137,6 +148,17 @@ x = embedded.x
|
|
|
137
148
|
y = embedded.y
|
|
138
149
|
```
|
|
139
150
|
|
|
151
|
+
Use `list_models()` when you want to inspect the shipped presets programmatically:
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
from slide2vec import list_models
|
|
155
|
+
|
|
156
|
+
all_models = list_models()
|
|
157
|
+
tile_models = list_models("tile")
|
|
158
|
+
slide_models = list_models("slide")
|
|
159
|
+
patient_models = list_models("patient")
|
|
160
|
+
```
|
|
161
|
+
|
|
140
162
|
Use `Pipeline(...)` for manifest-driven batch processing when you want artifacts written to disk instead of only in-memory outputs:
|
|
141
163
|
|
|
142
164
|
```python
|
|
@@ -235,7 +257,8 @@ docker run --rm -it \
|
|
|
235
257
|
|
|
236
258
|
## Documentation
|
|
237
259
|
|
|
238
|
-
- [
|
|
260
|
+
- [Documentation website](https://clemsgrs.github.io/slide2vec/) for the polished docs site
|
|
239
261
|
- [`docs/python-api.md`](docs/python-api.md) for the detailed API reference
|
|
240
|
-
- [`
|
|
262
|
+
- [`docs/cli.md`](docs/cli.md) for the config-driven CLI guide
|
|
241
263
|
- [`docs/models.md`](docs/models.md) for the full supported-model catalog
|
|
264
|
+
- [`tutorials/api_walkthrough.ipynb`](tutorials/api_walkthrough.ipynb) for a notebook walkthrough of the API
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
# slide2vec
|
|
2
2
|
|
|
3
3
|
[](https://pypi.org/project/slide2vec/)
|
|
4
|
+
[](https://clemsgrs.github.io/slide2vec/)
|
|
4
5
|
|
|
5
6
|
`slide2vec` is a Python package for efficient encoding of whole-slide images using publicly available foundation models. It builds on [`hs2p`](https://pypi.org/project/hs2p/) for fast preprocessing and exposes a focused surface around `Model`, `Pipeline`, and `ExecutionOptions`.
|
|
6
7
|
|
|
8
|
+
Documentation site: [https://clemsgrs.github.io/slide2vec/](https://clemsgrs.github.io/slide2vec/)
|
|
9
|
+
|
|
7
10
|
## Installation
|
|
8
11
|
|
|
9
12
|
```shell
|
|
@@ -21,6 +24,8 @@ pip install git+https://github.com/Mahmoodlab/CONCH.git
|
|
|
21
24
|
pip install git+https://github.com/prov-gigapath/prov-gigapath.git
|
|
22
25
|
```
|
|
23
26
|
|
|
27
|
+
AtlasPatch-backed tissue segmentation is available through hs2p's `sam2` path in the bundled install.
|
|
28
|
+
|
|
24
29
|
## Python API
|
|
25
30
|
|
|
26
31
|
```python
|
|
@@ -37,6 +42,17 @@ x = embedded.x
|
|
|
37
42
|
y = embedded.y
|
|
38
43
|
```
|
|
39
44
|
|
|
45
|
+
Use `list_models()` when you want to inspect the shipped presets programmatically:
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
from slide2vec import list_models
|
|
49
|
+
|
|
50
|
+
all_models = list_models()
|
|
51
|
+
tile_models = list_models("tile")
|
|
52
|
+
slide_models = list_models("slide")
|
|
53
|
+
patient_models = list_models("patient")
|
|
54
|
+
```
|
|
55
|
+
|
|
40
56
|
Use `Pipeline(...)` for manifest-driven batch processing when you want artifacts written to disk instead of only in-memory outputs:
|
|
41
57
|
|
|
42
58
|
```python
|
|
@@ -135,7 +151,8 @@ docker run --rm -it \
|
|
|
135
151
|
|
|
136
152
|
## Documentation
|
|
137
153
|
|
|
138
|
-
- [
|
|
154
|
+
- [Documentation website](https://clemsgrs.github.io/slide2vec/) for the polished docs site
|
|
139
155
|
- [`docs/python-api.md`](docs/python-api.md) for the detailed API reference
|
|
140
|
-
- [`
|
|
156
|
+
- [`docs/cli.md`](docs/cli.md) for the config-driven CLI guide
|
|
141
157
|
- [`docs/models.md`](docs/models.md) for the full supported-model catalog
|
|
158
|
+
- [`tutorials/api_walkthrough.ipynb`](tutorials/api_walkthrough.ipynb) for a notebook walkthrough of the API
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "slide2vec"
|
|
7
|
-
version = "4.
|
|
7
|
+
version = "4.3.0"
|
|
8
8
|
description = "Embedding of whole slide images with Foundation Models"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -21,7 +21,7 @@ classifiers = [
|
|
|
21
21
|
"Programming Language :: Python :: 3.13",
|
|
22
22
|
]
|
|
23
23
|
dependencies = [
|
|
24
|
-
"hs2p[asap,cucim,openslide,vips]>=
|
|
24
|
+
"hs2p[asap,cucim,openslide,sam2,vips]>=4.0.0",
|
|
25
25
|
"omegaconf",
|
|
26
26
|
"matplotlib",
|
|
27
27
|
"numpy<2",
|
|
@@ -88,7 +88,7 @@ fm = [
|
|
|
88
88
|
"pandas",
|
|
89
89
|
"pillow",
|
|
90
90
|
"rich",
|
|
91
|
-
"hs2p[asap,cucim,openslide,vips]>=
|
|
91
|
+
"hs2p[asap,cucim,openslide,sam2,vips]>=4.0.0",
|
|
92
92
|
"wandb",
|
|
93
93
|
"torch>=2.3,<2.8",
|
|
94
94
|
"torchvision>=0.18.0",
|
|
@@ -113,6 +113,13 @@ fm = [
|
|
|
113
113
|
"ninja==1.11.1.1",
|
|
114
114
|
"psutil<6",
|
|
115
115
|
]
|
|
116
|
+
docs = [
|
|
117
|
+
"sphinx>=8.1",
|
|
118
|
+
"furo",
|
|
119
|
+
"myst-parser",
|
|
120
|
+
"sphinx-copybutton",
|
|
121
|
+
"sphinx-autodoc-typehints",
|
|
122
|
+
]
|
|
116
123
|
testing = [
|
|
117
124
|
"pytest>=6.0",
|
|
118
125
|
"pytest-cov>=2.0",
|
|
@@ -157,7 +164,7 @@ no_implicit_reexport = true
|
|
|
157
164
|
max-line-length = 160
|
|
158
165
|
|
|
159
166
|
[tool.bumpver]
|
|
160
|
-
current_version = "4.
|
|
167
|
+
current_version = "4.3.0"
|
|
161
168
|
version_pattern = "MAJOR.MINOR.PATCH"
|
|
162
169
|
commit = false # We do version bumping in CI, not as a commit
|
|
163
170
|
tag = false # Git tag already exists — we don't auto-tag
|
|
@@ -1,11 +1,20 @@
|
|
|
1
|
-
from slide2vec.api import
|
|
1
|
+
from slide2vec.api import (
|
|
2
|
+
EmbeddedSlide,
|
|
3
|
+
ExecutionOptions,
|
|
4
|
+
Model,
|
|
5
|
+
Pipeline,
|
|
6
|
+
PreprocessingConfig,
|
|
7
|
+
RunResult,
|
|
8
|
+
list_models,
|
|
9
|
+
)
|
|
2
10
|
from slide2vec.artifacts import HierarchicalEmbeddingArtifact, SlideEmbeddingArtifact, TileEmbeddingArtifact
|
|
3
11
|
|
|
4
12
|
|
|
5
|
-
__version__ = "4.
|
|
13
|
+
__version__ = "4.3.0"
|
|
6
14
|
|
|
7
15
|
__all__ = [
|
|
8
16
|
"Model",
|
|
17
|
+
"list_models",
|
|
9
18
|
"Pipeline",
|
|
10
19
|
"PreprocessingConfig",
|
|
11
20
|
"ExecutionOptions",
|
|
@@ -20,9 +20,9 @@ from slide2vec.encoders.registry import (
|
|
|
20
20
|
resolve_preprocessing_defaults,
|
|
21
21
|
)
|
|
22
22
|
from slide2vec.encoders.validation import validate_encoder_config
|
|
23
|
-
from slide2vec.model_settings import canonicalize_model_name, normalize_precision_name
|
|
23
|
+
from slide2vec.runtime.model_settings import canonicalize_model_name, normalize_precision_name
|
|
24
24
|
from slide2vec.progress import emit_progress
|
|
25
|
-
from slide2vec.
|
|
25
|
+
from slide2vec.runtime.types import LoadedModel
|
|
26
26
|
from slide2vec.utils.utils import cpu_worker_limit, slurm_cpu_limit
|
|
27
27
|
|
|
28
28
|
PathLike = str | Path
|
|
@@ -72,8 +72,17 @@ class PreprocessingConfig:
|
|
|
72
72
|
gpu_decode = bool(tiling.gpu_decode)
|
|
73
73
|
adaptive_batching = bool(tiling.adaptive_batching)
|
|
74
74
|
preview_cfg = tiling.preview
|
|
75
|
-
preview_save = bool(preview_cfg.
|
|
76
|
-
|
|
75
|
+
preview_save = bool(preview_cfg.save_mask_preview)
|
|
76
|
+
preview_tiling_save = bool(preview_cfg.save_tiling_preview)
|
|
77
|
+
preview_kwargs: dict[str, Any] = {
|
|
78
|
+
"save_mask_preview": preview_save,
|
|
79
|
+
"save_tiling_preview": preview_tiling_save,
|
|
80
|
+
"downsample": int(preview_cfg.downsample),
|
|
81
|
+
}
|
|
82
|
+
preview_kwargs["tissue_contour_color"] = tuple(
|
|
83
|
+
int(channel) for channel in preview_cfg.tissue_contour_color
|
|
84
|
+
)
|
|
85
|
+
preview_kwargs["mask_overlay_alpha"] = float(preview_cfg.mask_overlay_alpha)
|
|
77
86
|
return cls(
|
|
78
87
|
backend=tiling.backend,
|
|
79
88
|
requested_spacing_um=float(tiling.params.requested_spacing_um),
|
|
@@ -104,11 +113,7 @@ class PreprocessingConfig:
|
|
|
104
113
|
resume=bool(cfg.resume),
|
|
105
114
|
segmentation=dict(tiling.seg_params),
|
|
106
115
|
filtering=dict(tiling.filter_params),
|
|
107
|
-
preview=
|
|
108
|
-
"save_mask_preview": preview_save,
|
|
109
|
-
"save_tiling_preview": preview_save,
|
|
110
|
-
"downsample": preview_downsample,
|
|
111
|
-
},
|
|
116
|
+
preview=preview_kwargs,
|
|
112
117
|
)
|
|
113
118
|
|
|
114
119
|
def with_backend(self, backend: str) -> "PreprocessingConfig":
|
|
@@ -444,6 +449,27 @@ class Model:
|
|
|
444
449
|
return self._backend
|
|
445
450
|
|
|
446
451
|
|
|
452
|
+
def list_models(level: str | None = None) -> list[str]:
|
|
453
|
+
"""Return the available preset model names in a stable order.
|
|
454
|
+
|
|
455
|
+
Args:
|
|
456
|
+
level: Optional model level filter. Supported values are ``"tile"``,
|
|
457
|
+
``"slide"``, and ``"patient"``.
|
|
458
|
+
"""
|
|
459
|
+
if level is None:
|
|
460
|
+
return sorted(encoder_registry.names())
|
|
461
|
+
|
|
462
|
+
normalized_level = str(level).strip().lower()
|
|
463
|
+
if normalized_level not in {"tile", "slide", "patient"}:
|
|
464
|
+
raise ValueError("list_models(level=...) must be one of: tile, slide, patient")
|
|
465
|
+
|
|
466
|
+
return sorted(
|
|
467
|
+
name
|
|
468
|
+
for name in encoder_registry.names()
|
|
469
|
+
if encoder_registry.info(name)["level"] == normalized_level
|
|
470
|
+
)
|
|
471
|
+
|
|
472
|
+
|
|
447
473
|
class Pipeline:
|
|
448
474
|
def __init__(
|
|
449
475
|
self,
|
|
@@ -38,12 +38,14 @@ tiling:
|
|
|
38
38
|
# downsample controls which pyramid level is read for tissue segmentation.
|
|
39
39
|
# Larger values are faster and use less memory; smaller values can improve mask precision.
|
|
40
40
|
downsample: 64 # find the closest downsample in the slide for tissue segmentation
|
|
41
|
-
sthresh: 8 # segmentation threshold (positive integer, using a higher threshold leads to less foreground and more background detection) (not used when
|
|
41
|
+
sthresh: 8 # segmentation threshold (positive integer, using a higher threshold leads to less foreground and more background detection) (not used when method="otsu")
|
|
42
42
|
sthresh_up: 255 # upper threshold value for scaling the binary mask
|
|
43
43
|
mthresh: 7 # median filter size (positive, odd integer)
|
|
44
44
|
close: 4 # additional morphological closing to apply following initial thresholding (positive integer)
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
method: "hsv" # tissue segmentation method: "hsv", "otsu", "threshold", or "sam2"
|
|
46
|
+
sam2_checkpoint_path: # optional when method="sam2"; if empty, hs2p downloads the default AtlasPatch checkpoint from Hugging Face
|
|
47
|
+
sam2_config_path: # optional local override for the SAM2 model config; if empty, hs2p downloads the default AtlasPatch config from Hugging Face
|
|
48
|
+
sam2_device: "cpu" # device for SAM2 inference, e.g. "cpu", "cuda", or "cuda:0"
|
|
47
49
|
filter_params:
|
|
48
50
|
ref_tile_size: ${tiling.params.requested_tile_size_px} # reference tile size at the target spacing
|
|
49
51
|
a_t: 4 # area filter threshold for tissue (positive integer, the minimum size of detected foreground contours to consider, relative to the reference tile size ref_tile_size, e.g. a value 10 means only detected foreground contours of size greater than 10 [ref_tile_size, ref_tile_size] tiles at spacing tiling.params.requested_spacing_um will be kept)
|
|
@@ -60,9 +62,10 @@ tiling:
|
|
|
60
62
|
blur_threshold: 50.0 # minimum blur score (higher is sharper)
|
|
61
63
|
qc_spacing_um: 2.0 # spacing at which pixel-based QC is evaluated
|
|
62
64
|
preview:
|
|
63
|
-
|
|
65
|
+
save_mask_preview: true # save preview images of mask overlays
|
|
66
|
+
save_tiling_preview: true # save preview images of tile layouts
|
|
64
67
|
downsample: 32 # downsample to use for preview rendering
|
|
65
|
-
|
|
68
|
+
tissue_contour_color: [157, 219, 129] # RGB color used for tissue contours in batch mask previews
|
|
66
69
|
mask_overlay_alpha: 0.5 # alpha used for tissue overlays in batch mask previews
|
|
67
70
|
|
|
68
71
|
speed:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
from contextlib import contextmanager
|
|
1
2
|
from importlib.resources import as_file, files
|
|
2
3
|
from pathlib import Path
|
|
3
4
|
from typing import Iterator
|
|
4
|
-
from contextlib import contextmanager
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
def config_resource(*parts: str):
|
|
@@ -24,3 +24,4 @@ def config_path(*parts: str) -> Iterator[Path]:
|
|
|
24
24
|
resource = config_resource(*parts)
|
|
25
25
|
with as_file(resource) as resolved:
|
|
26
26
|
yield resolved
|
|
27
|
+
|
|
@@ -26,11 +26,10 @@ def main(argv=None) -> int:
|
|
|
26
26
|
_compute_tile_embeddings_for_slide,
|
|
27
27
|
_is_hierarchical_preprocessing,
|
|
28
28
|
_resolve_hierarchical_geometry,
|
|
29
|
-
deserialize_execution,
|
|
30
|
-
deserialize_preprocessing,
|
|
31
29
|
load_successful_tiled_slides,
|
|
32
30
|
)
|
|
33
31
|
from slide2vec.progress import JsonlProgressReporter, activate_progress_reporter
|
|
32
|
+
from slide2vec.runtime.serialization import deserialize_execution, deserialize_preprocessing
|
|
34
33
|
|
|
35
34
|
parser = get_args_parser(add_help=True)
|
|
36
35
|
args = parser.parse_args(argv)
|
|
@@ -49,6 +48,7 @@ def main(argv=None) -> int:
|
|
|
49
48
|
model_spec["name"],
|
|
50
49
|
device=f"cuda:{local_rank}",
|
|
51
50
|
output_variant=model_spec.get("output_variant"),
|
|
51
|
+
allow_non_recommended_settings=bool(model_spec["allow_non_recommended_settings"]),
|
|
52
52
|
)
|
|
53
53
|
preprocessing = deserialize_preprocessing(request["preprocessing"])
|
|
54
54
|
execution = deserialize_execution(request["execution"])
|
|
@@ -3,7 +3,7 @@ from contextlib import nullcontext
|
|
|
3
3
|
import json
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
|
|
6
|
-
from slide2vec.
|
|
6
|
+
from slide2vec.runtime.distributed import assign_slides_to_ranks
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
def get_args_parser(add_help: bool = True) -> argparse.ArgumentParser:
|
|
@@ -21,11 +21,10 @@ def main(argv=None) -> int:
|
|
|
21
21
|
from slide2vec.inference import (
|
|
22
22
|
_compute_embedded_slides,
|
|
23
23
|
_persist_embedded_slide,
|
|
24
|
-
deserialize_execution,
|
|
25
|
-
deserialize_preprocessing,
|
|
26
24
|
load_successful_tiled_slides,
|
|
27
25
|
)
|
|
28
26
|
from slide2vec.progress import JsonlProgressReporter, activate_progress_reporter
|
|
27
|
+
from slide2vec.runtime.serialization import deserialize_execution, deserialize_preprocessing
|
|
29
28
|
|
|
30
29
|
parser = get_args_parser(add_help=True)
|
|
31
30
|
args = parser.parse_args(argv)
|
|
@@ -43,11 +42,12 @@ def main(argv=None) -> int:
|
|
|
43
42
|
model_spec["name"],
|
|
44
43
|
device=f"cuda:{local_rank}",
|
|
45
44
|
output_variant=model_spec.get("output_variant"),
|
|
45
|
+
allow_non_recommended_settings=bool(model_spec["allow_non_recommended_settings"]),
|
|
46
46
|
)
|
|
47
47
|
preprocessing = deserialize_preprocessing(request["preprocessing"])
|
|
48
48
|
execution = deserialize_execution(request["execution"])
|
|
49
49
|
slide_records, tiling_results = load_successful_tiled_slides(output_dir)
|
|
50
|
-
assignments =
|
|
50
|
+
assignments = assign_slides_to_ranks(slide_records, tiling_results, num_gpus=world_size)
|
|
51
51
|
assigned_ids = assignments.get(global_rank, [])
|
|
52
52
|
if not assigned_ids:
|
|
53
53
|
return 0
|
|
@@ -8,7 +8,7 @@ from slide2vec.encoders.registry import (
|
|
|
8
8
|
resolve_encoder_output,
|
|
9
9
|
resolve_preprocessing_requirements,
|
|
10
10
|
)
|
|
11
|
-
from slide2vec.model_settings import normalize_precision_name
|
|
11
|
+
from slide2vec.runtime.model_settings import normalize_precision_name
|
|
12
12
|
|
|
13
13
|
logger = logging.getLogger("slide2vec")
|
|
14
14
|
|