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.
Files changed (85) hide show
  1. {slide2vec-4.2.0 → slide2vec-4.3.0}/PKG-INFO +28 -5
  2. {slide2vec-4.2.0 → slide2vec-4.3.0}/README.md +19 -2
  3. {slide2vec-4.2.0 → slide2vec-4.3.0}/pyproject.toml +11 -4
  4. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/__init__.py +11 -2
  5. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/api.py +35 -9
  6. slide2vec-4.3.0/slide2vec/configs/__init__.py +4 -0
  7. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/configs/default.yaml +8 -5
  8. {slide2vec-4.2.0/slide2vec → slide2vec-4.3.0/slide2vec/configs}/resources.py +2 -1
  9. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/distributed/direct_embed_worker.py +2 -2
  10. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/distributed/pipeline_worker.py +4 -4
  11. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/registry.py +1 -1
  12. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/validation.py +1 -1
  13. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/inference.py +151 -1295
  14. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/progress.py +123 -5
  15. slide2vec-4.3.0/slide2vec/runtime/__init__.py +2 -0
  16. slide2vec-4.3.0/slide2vec/runtime/batching.py +441 -0
  17. slide2vec-4.3.0/slide2vec/runtime/distributed.py +194 -0
  18. slide2vec-4.3.0/slide2vec/runtime/embedding.py +157 -0
  19. slide2vec-4.3.0/slide2vec/runtime/hierarchical.py +105 -0
  20. {slide2vec-4.2.0/slide2vec → slide2vec-4.3.0/slide2vec/runtime}/model_settings.py +1 -0
  21. slide2vec-4.3.0/slide2vec/runtime/persistence.py +165 -0
  22. slide2vec-4.3.0/slide2vec/runtime/progress_bridge.py +52 -0
  23. {slide2vec-4.2.0/slide2vec → slide2vec-4.3.0/slide2vec/runtime}/registry.py +1 -0
  24. slide2vec-4.3.0/slide2vec/runtime/serialization.py +119 -0
  25. slide2vec-4.3.0/slide2vec/runtime/tiling.py +97 -0
  26. slide2vec-4.3.0/slide2vec/runtime/types.py +48 -0
  27. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/utils/config.py +1 -1
  28. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/utils/tiling_io.py +5 -0
  29. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec.egg-info/PKG-INFO +28 -5
  30. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec.egg-info/SOURCES.txt +14 -7
  31. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec.egg-info/requires.txt +9 -2
  32. slide2vec-4.3.0/tests/test_architecture_runtime_split.py +60 -0
  33. {slide2vec-4.2.0 → slide2vec-4.3.0}/tests/test_hs2p_package_cutover.py +6 -4
  34. {slide2vec-4.2.0 → slide2vec-4.3.0}/tests/test_progress.py +376 -8
  35. {slide2vec-4.2.0 → slide2vec-4.3.0}/tests/test_regression_core.py +89 -6
  36. {slide2vec-4.2.0 → slide2vec-4.3.0}/tests/test_regression_inference.py +261 -99
  37. {slide2vec-4.2.0 → slide2vec-4.3.0}/tests/test_regression_models.py +1 -1
  38. slide2vec-4.2.0/slide2vec/configs/__init__.py +0 -4
  39. slide2vec-4.2.0/slide2vec/runtime_types.py +0 -14
  40. slide2vec-4.2.0/tests/test_batch_collator_timing.py +0 -161
  41. slide2vec-4.2.0/tests/test_output_consistency.py +0 -187
  42. slide2vec-4.2.0/tests/test_packaging_metadata.py +0 -23
  43. {slide2vec-4.2.0 → slide2vec-4.3.0}/LICENSE +0 -0
  44. {slide2vec-4.2.0 → slide2vec-4.3.0}/setup.cfg +0 -0
  45. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/__main__.py +0 -0
  46. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/artifacts.py +0 -0
  47. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/cli.py +0 -0
  48. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/data/__init__.py +0 -0
  49. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/data/dataset.py +0 -0
  50. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/data/tile_reader.py +0 -0
  51. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/data/tile_store.py +0 -0
  52. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/distributed/__init__.py +0 -0
  53. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/__init__.py +0 -0
  54. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/base.py +0 -0
  55. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/__init__.py +0 -0
  56. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/conch.py +0 -0
  57. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/gigapath.py +0 -0
  58. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/hibou.py +0 -0
  59. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/hoptimus.py +0 -0
  60. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/lunit.py +0 -0
  61. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/midnight.py +0 -0
  62. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/moozy/__init__.py +0 -0
  63. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/moozy/blocks.py +0 -0
  64. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/moozy/case.py +0 -0
  65. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/moozy/loading.py +0 -0
  66. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/moozy/slide.py +0 -0
  67. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/moozy/types.py +0 -0
  68. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/musk.py +0 -0
  69. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/phikon.py +0 -0
  70. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/prism.py +0 -0
  71. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/prost40m.py +0 -0
  72. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/titan.py +0 -0
  73. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/uni.py +0 -0
  74. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/encoders/models/virchow.py +0 -0
  75. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/main.py +0 -0
  76. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/utils/__init__.py +0 -0
  77. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/utils/coordinates.py +0 -0
  78. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/utils/log_utils.py +0 -0
  79. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec/utils/utils.py +0 -0
  80. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec.egg-info/dependency_links.txt +0 -0
  81. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec.egg-info/entry_points.txt +0 -0
  82. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec.egg-info/not-zip-safe +0 -0
  83. {slide2vec-4.2.0 → slide2vec-4.3.0}/slide2vec.egg-info/top_level.txt +0 -0
  84. {slide2vec-4.2.0 → slide2vec-4.3.0}/tests/test_encoder_registry.py +0 -0
  85. {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.2.0
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]>=3.2.1
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]>=3.2.1; extra == "fm"
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
  [![PyPI version](https://img.shields.io/pypi/v/slide2vec?label=pypi&logo=pypi&color=3776AB)](https://pypi.org/project/slide2vec/)
110
+ [![Docs](https://img.shields.io/badge/docs-website-blue)](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
- - [`docs/cli.md`](docs/cli.md) for the config-driven CLI guide
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
- - [`tutorials/api_walkthrough.ipynb`](tutorials/api_walkthrough.ipynb) for a notebook walkthrough of the API
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
  [![PyPI version](https://img.shields.io/pypi/v/slide2vec?label=pypi&logo=pypi&color=3776AB)](https://pypi.org/project/slide2vec/)
4
+ [![Docs](https://img.shields.io/badge/docs-website-blue)](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
- - [`docs/cli.md`](docs/cli.md) for the config-driven CLI guide
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
- - [`tutorials/api_walkthrough.ipynb`](tutorials/api_walkthrough.ipynb) for a notebook walkthrough of the API
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.2.0"
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]>=3.2.1",
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]>=3.2.1",
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.2.0"
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 EmbeddedSlide, ExecutionOptions, Model, Pipeline, PreprocessingConfig, RunResult
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.2.0"
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.runtime_types import LoadedModel
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.save)
76
- preview_downsample = int(preview_cfg.downsample)
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,
@@ -0,0 +1,4 @@
1
+ from slide2vec.configs.resources import load_config
2
+
3
+
4
+ default_config = load_config("default")
@@ -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 use_otsu=True)
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
- use_otsu: false # use otsu's method instead of simple binary thresholding
46
- use_hsv: true # use HSV thresholding instead of simple binary thresholding
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
- save: true # save preview images of slide tiling and mask overlays
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
- mask_overlay_color: [157, 219, 129] # RGB color used for tissue overlays in batch mask previews
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.inference import _assign_slides_to_ranks
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 = _assign_slides_to_ranks(slide_records, tiling_results, num_gpus=world_size)
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
@@ -2,7 +2,7 @@
2
2
 
3
3
  from typing import Any
4
4
 
5
- from slide2vec.registry import Registry
5
+ from slide2vec.runtime.registry import Registry
6
6
 
7
7
  encoder_registry = Registry("encoders")
8
8
 
@@ -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