slide2vec 4.5.2__tar.gz → 4.5.3__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 (93) hide show
  1. {slide2vec-4.5.2 → slide2vec-4.5.3}/PKG-INFO +3 -3
  2. {slide2vec-4.5.2 → slide2vec-4.5.3}/pyproject.toml +4 -4
  3. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/__init__.py +1 -1
  4. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/inference.py +8 -1
  5. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec.egg-info/PKG-INFO +3 -3
  6. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec.egg-info/requires.txt +2 -2
  7. {slide2vec-4.5.2 → slide2vec-4.5.3}/tests/test_regression_inference.py +85 -0
  8. {slide2vec-4.5.2 → slide2vec-4.5.3}/LICENSE +0 -0
  9. {slide2vec-4.5.2 → slide2vec-4.5.3}/README.md +0 -0
  10. {slide2vec-4.5.2 → slide2vec-4.5.3}/setup.cfg +0 -0
  11. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/__main__.py +0 -0
  12. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/api.py +0 -0
  13. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/artifacts.py +0 -0
  14. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/cli.py +0 -0
  15. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/configs/__init__.py +0 -0
  16. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/configs/default.yaml +0 -0
  17. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/configs/resources.py +0 -0
  18. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/data/__init__.py +0 -0
  19. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/data/dataset.py +0 -0
  20. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/data/tile_reader.py +0 -0
  21. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/data/tile_store.py +0 -0
  22. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/distributed/__init__.py +0 -0
  23. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/distributed/direct_embed_worker.py +0 -0
  24. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/distributed/pipeline_worker.py +0 -0
  25. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/encoders/__init__.py +0 -0
  26. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/encoders/base.py +0 -0
  27. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/encoders/models/__init__.py +0 -0
  28. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/encoders/models/conch.py +0 -0
  29. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/encoders/models/gigapath.py +0 -0
  30. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/encoders/models/hibou.py +0 -0
  31. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/encoders/models/hoptimus.py +0 -0
  32. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/encoders/models/lunit.py +0 -0
  33. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/encoders/models/midnight.py +0 -0
  34. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/encoders/models/moozy/__init__.py +0 -0
  35. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/encoders/models/moozy/blocks.py +0 -0
  36. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/encoders/models/moozy/case.py +0 -0
  37. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/encoders/models/moozy/loading.py +0 -0
  38. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/encoders/models/moozy/slide.py +0 -0
  39. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/encoders/models/moozy/types.py +0 -0
  40. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/encoders/models/musk.py +0 -0
  41. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/encoders/models/phikon.py +0 -0
  42. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/encoders/models/prism.py +0 -0
  43. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/encoders/models/prost40m.py +0 -0
  44. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/encoders/models/titan.py +0 -0
  45. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/encoders/models/uni.py +0 -0
  46. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/encoders/models/virchow.py +0 -0
  47. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/encoders/registry.py +0 -0
  48. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/encoders/validation.py +0 -0
  49. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/progress.py +0 -0
  50. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/runtime/__init__.py +0 -0
  51. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/runtime/artifacts_collect.py +0 -0
  52. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/runtime/batching.py +0 -0
  53. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/runtime/cpu_budget.py +0 -0
  54. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/runtime/distributed.py +0 -0
  55. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/runtime/distributed_stage.py +0 -0
  56. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/runtime/embedding.py +0 -0
  57. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/runtime/embedding_persist.py +0 -0
  58. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/runtime/embedding_pipeline.py +0 -0
  59. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/runtime/hierarchical.py +0 -0
  60. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/runtime/manifest.py +0 -0
  61. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/runtime/model_settings.py +0 -0
  62. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/runtime/patient_pipeline.py +0 -0
  63. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/runtime/persist_callbacks.py +0 -0
  64. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/runtime/persistence.py +0 -0
  65. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/runtime/process_list.py +0 -0
  66. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/runtime/progress_bridge.py +0 -0
  67. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/runtime/registry.py +0 -0
  68. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/runtime/serialization.py +0 -0
  69. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/runtime/slide_encode.py +0 -0
  70. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/runtime/tiling.py +0 -0
  71. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/runtime/tiling_pipeline.py +0 -0
  72. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/runtime/types.py +0 -0
  73. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/runtime/worker_io.py +0 -0
  74. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/utils/__init__.py +0 -0
  75. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/utils/config.py +0 -0
  76. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/utils/coordinates.py +0 -0
  77. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/utils/log_utils.py +0 -0
  78. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/utils/tiling_io.py +0 -0
  79. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec/utils/utils.py +0 -0
  80. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec.egg-info/SOURCES.txt +0 -0
  81. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec.egg-info/dependency_links.txt +0 -0
  82. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec.egg-info/entry_points.txt +0 -0
  83. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec.egg-info/not-zip-safe +0 -0
  84. {slide2vec-4.5.2 → slide2vec-4.5.3}/slide2vec.egg-info/top_level.txt +0 -0
  85. {slide2vec-4.5.2 → slide2vec-4.5.3}/tests/test_architecture_runtime_split.py +0 -0
  86. {slide2vec-4.5.2 → slide2vec-4.5.3}/tests/test_encoder_registry.py +0 -0
  87. {slide2vec-4.5.2 → slide2vec-4.5.3}/tests/test_hs2p_package_cutover.py +0 -0
  88. {slide2vec-4.5.2 → slide2vec-4.5.3}/tests/test_output_consistency.py +0 -0
  89. {slide2vec-4.5.2 → slide2vec-4.5.3}/tests/test_progress.py +0 -0
  90. {slide2vec-4.5.2 → slide2vec-4.5.3}/tests/test_regression_core.py +0 -0
  91. {slide2vec-4.5.2 → slide2vec-4.5.3}/tests/test_regression_models.py +0 -0
  92. {slide2vec-4.5.2 → slide2vec-4.5.3}/tests/test_runtime_batching.py +0 -0
  93. {slide2vec-4.5.2 → slide2vec-4.5.3}/tests/test_tile_store.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: slide2vec
3
- Version: 4.5.2
3
+ Version: 4.5.3
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,sam2,vips]>=4.0.6
18
+ Requires-Dist: hs2p[asap,cucim,openslide,sam2,vips]>=4.0.7
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,sam2,vips]>=4.0.6; extra == "fm"
68
+ Requires-Dist: hs2p[asap,cucim,openslide,sam2,vips]>=4.0.7; 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"
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "slide2vec"
7
- version = "4.5.2"
7
+ version = "4.5.3"
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,sam2,vips]>=4.0.6",
24
+ "hs2p[asap,cucim,openslide,sam2,vips]>=4.0.7",
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,sam2,vips]>=4.0.6",
91
+ "hs2p[asap,cucim,openslide,sam2,vips]>=4.0.7",
92
92
  "wandb",
93
93
  "torch>=2.3,<2.8",
94
94
  "torchvision>=0.18.0",
@@ -164,7 +164,7 @@ no_implicit_reexport = true
164
164
  max-line-length = 160
165
165
 
166
166
  [tool.bumpver]
167
- current_version = "4.5.2"
167
+ current_version = "4.5.3"
168
168
  version_pattern = "MAJOR.MINOR.PATCH"
169
169
  commit = false # We do version bumping in CI, not as a commit
170
170
  tag = false # Git tag already exists — we don't auto-tag
@@ -11,7 +11,7 @@ from slide2vec.api import (
11
11
  from slide2vec.artifacts import HierarchicalEmbeddingArtifact, SlideEmbeddingArtifact, TileEmbeddingArtifact
12
12
 
13
13
 
14
- __version__ = "4.5.2"
14
+ __version__ = "4.5.3"
15
15
 
16
16
  __all__ = [
17
17
  "Model",
@@ -608,7 +608,14 @@ def run_pipeline(
608
608
  raise ValueError("At least one slide is required")
609
609
  if execution.output_dir is None:
610
610
  raise ValueError("ExecutionOptions.output_dir is required for Pipeline.run(...)")
611
- if execution.num_gpus > 1:
611
+ # `validate_multi_gpu_execution` validates the multi-GPU *embedding* setup
612
+ # and touches `torch.cuda` in the parent process. A tiling-only run has no
613
+ # embedding stage, so skip it: any GPU work during tiling (e.g. SAM2 mask
614
+ # generation on cuda) runs inside the spawned tiling workers, which
615
+ # initialize their own CUDA and do not depend on this parent-side check.
616
+ # Initializing a CUDA context in the parent here only buys needless fork
617
+ # risk for the downstream tiling pool with no benefit.
618
+ if not tiling_only and execution.num_gpus > 1:
612
619
  distributed_stage.validate_multi_gpu_execution(model, execution)
613
620
 
614
621
  output_dir = Path(execution.output_dir)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: slide2vec
3
- Version: 4.5.2
3
+ Version: 4.5.3
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,sam2,vips]>=4.0.6
18
+ Requires-Dist: hs2p[asap,cucim,openslide,sam2,vips]>=4.0.7
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,sam2,vips]>=4.0.6; extra == "fm"
68
+ Requires-Dist: hs2p[asap,cucim,openslide,sam2,vips]>=4.0.7; 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"
@@ -1,4 +1,4 @@
1
- hs2p[asap,cucim,openslide,sam2,vips]>=4.0.6
1
+ hs2p[asap,cucim,openslide,sam2,vips]>=4.0.7
2
2
  omegaconf
3
3
  matplotlib
4
4
  numpy<2
@@ -27,7 +27,7 @@ numpy<2
27
27
  pandas
28
28
  pillow
29
29
  rich
30
- hs2p[asap,cucim,openslide,sam2,vips]>=4.0.6
30
+ hs2p[asap,cucim,openslide,sam2,vips]>=4.0.7
31
31
  wandb
32
32
  torch<2.8,>=2.3
33
33
  torchvision>=0.18.0
@@ -125,6 +125,91 @@ def test_pipeline_run_uses_distributed_embedding_path_when_num_gpus_is_greater_t
125
125
  assert result.tile_artifacts == ["tile-artifact"]
126
126
  assert result.slide_artifacts == ["slide-artifact"]
127
127
 
128
+
129
+ def test_run_pipeline_tiling_only_skips_multi_gpu_validation(monkeypatch, tmp_path: Path):
130
+ """Tiling is CPU-only; it must not initialize CUDA in the parent.
131
+
132
+ ``validate_multi_gpu_execution`` calls ``torch.cuda`` in the parent process,
133
+ which (combined with forking the tiling pool) caused deadlocks. For a
134
+ tiling-only run there is no GPU stage, so the validation must be skipped even
135
+ when ``num_gpus > 1``.
136
+ """
137
+ import slide2vec.inference as inference
138
+
139
+ slide = make_slide("slide-a")
140
+ tiling_result = SimpleNamespace(x=np.array([0, 1]), y=np.array([2, 3]), tile_size_lv0=224)
141
+
142
+ monkeypatch.setattr(
143
+ tiling_pipeline,
144
+ "prepare_tiled_slides",
145
+ lambda *args, **kwargs: ([slide], [tiling_result], tmp_path / "process_list.csv"),
146
+ )
147
+
148
+ validate_calls = []
149
+ monkeypatch.setattr(
150
+ distributed_stage,
151
+ "validate_multi_gpu_execution",
152
+ lambda *args, **kwargs: validate_calls.append(True),
153
+ )
154
+
155
+ result = inference.run_pipeline(
156
+ Model.from_preset("virchow2"),
157
+ slides=[slide],
158
+ preprocessing=DEFAULT_PREPROCESSING,
159
+ tiling_only=True,
160
+ execution=ExecutionOptions(output_dir=tmp_path, num_gpus=2),
161
+ )
162
+
163
+ assert validate_calls == []
164
+ assert result.tile_artifacts == []
165
+ assert result.slide_artifacts == []
166
+ assert result.process_list_path == tmp_path / "process_list.csv"
167
+
168
+
169
+ def test_run_pipeline_validates_multi_gpu_when_not_tiling_only(monkeypatch, tmp_path: Path):
170
+ """The multi-GPU fast-fail check must still run for full embedding runs."""
171
+ import slide2vec.inference as inference
172
+
173
+ slide = make_slide("slide-a")
174
+ tiling_result = SimpleNamespace(x=np.array([0, 1]), y=np.array([2, 3]), tile_size_lv0=224)
175
+
176
+ monkeypatch.setattr(
177
+ tiling_pipeline,
178
+ "prepare_tiled_slides",
179
+ lambda *args, **kwargs: ([slide], [tiling_result], tmp_path / "process_list.csv"),
180
+ )
181
+ monkeypatch.setattr(
182
+ artifacts_collect,
183
+ "run_distributed_embedding_stage",
184
+ lambda *args, **kwargs: None,
185
+ )
186
+ monkeypatch.setattr(
187
+ artifacts_collect,
188
+ "collect_pipeline_artifacts",
189
+ lambda *args, **kwargs: (["tile-artifact"], [], ["slide-artifact"]),
190
+ )
191
+ monkeypatch.setattr(
192
+ artifacts_collect, "update_process_list_after_embedding", lambda *args, **kwargs: None
193
+ )
194
+
195
+ validate_calls = []
196
+ monkeypatch.setattr(
197
+ distributed_stage,
198
+ "validate_multi_gpu_execution",
199
+ lambda *args, **kwargs: validate_calls.append(True),
200
+ )
201
+
202
+ inference.run_pipeline(
203
+ Model.from_preset("virchow2"),
204
+ slides=[slide],
205
+ preprocessing=DEFAULT_PREPROCESSING,
206
+ tiling_only=False,
207
+ execution=ExecutionOptions(output_dir=tmp_path, num_gpus=2),
208
+ )
209
+
210
+ assert validate_calls == [True]
211
+
212
+
128
213
  def test_run_pipeline_distributed_branch_delegates_to_distributed_collection_helper(monkeypatch, tmp_path: Path):
129
214
  import slide2vec.inference as inference
130
215
 
File without changes
File without changes
File without changes
File without changes
File without changes