slide2vec 6.3.2__tar.gz → 6.3.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 (183) hide show
  1. {slide2vec-6.3.2 → slide2vec-6.3.3}/PKG-INFO +1 -1
  2. {slide2vec-6.3.2 → slide2vec-6.3.3}/pyproject.toml +2 -2
  3. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/__init__.py +1 -1
  4. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/inference.py +5 -2
  5. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec.egg-info/PKG-INFO +1 -1
  6. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec.egg-info/SOURCES.txt +1 -0
  7. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_patient_manifest.py +1 -2
  8. slide2vec-6.3.3/tests/test_patient_tiling_only.py +86 -0
  9. {slide2vec-6.3.2 → slide2vec-6.3.3}/LICENSE +0 -0
  10. {slide2vec-6.3.2 → slide2vec-6.3.3}/README.md +0 -0
  11. {slide2vec-6.3.2 → slide2vec-6.3.3}/setup.cfg +0 -0
  12. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/__main__.py +0 -0
  13. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/_cufile.py +0 -0
  14. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/api.py +0 -0
  15. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/artifacts.py +0 -0
  16. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/cli.py +0 -0
  17. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/configs/__init__.py +0 -0
  18. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/configs/default.yaml +0 -0
  19. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/configs/resources.py +0 -0
  20. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/cufile.json +0 -0
  21. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/data/__init__.py +0 -0
  22. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/data/dataset.py +0 -0
  23. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/data/tile_reader.py +0 -0
  24. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/data/tile_store.py +0 -0
  25. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/distributed/__init__.py +0 -0
  26. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/distributed/dense_image_worker.py +0 -0
  27. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/distributed/dense_worker.py +0 -0
  28. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/distributed/direct_embed_worker.py +0 -0
  29. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/distributed/image_worker.py +0 -0
  30. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/distributed/pin_gpu.py +0 -0
  31. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/distributed/pipeline_worker.py +0 -0
  32. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/distributed/worker_entry.py +0 -0
  33. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/__init__.py +0 -0
  34. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/base.py +0 -0
  35. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/__init__.py +0 -0
  36. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/conch.py +0 -0
  37. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/dinov2.py +0 -0
  38. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/dinov3.py +0 -0
  39. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/genbio.py +0 -0
  40. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/gigapath.py +0 -0
  41. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/gpfm.py +0 -0
  42. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/hibou.py +0 -0
  43. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/hoptimus.py +0 -0
  44. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/isight.py +0 -0
  45. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/lunit.py +0 -0
  46. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/mettle.py +0 -0
  47. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/midnight.py +0 -0
  48. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/moozy/__init__.py +0 -0
  49. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/moozy/blocks.py +0 -0
  50. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/moozy/case.py +0 -0
  51. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/moozy/loading.py +0 -0
  52. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/moozy/slide.py +0 -0
  53. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/moozy/types.py +0 -0
  54. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/mstar.py +0 -0
  55. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/musk.py +0 -0
  56. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/phikon.py +0 -0
  57. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/prism.py +0 -0
  58. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/prism2.py +0 -0
  59. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/prost40m.py +0 -0
  60. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/rudolfv2.py +0 -0
  61. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/titan.py +0 -0
  62. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/uni.py +0 -0
  63. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/virchow.py +0 -0
  64. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/waiv.py +0 -0
  65. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/registry.py +0 -0
  66. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/validation.py +0 -0
  67. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/progress.py +0 -0
  68. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/__init__.py +0 -0
  69. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/artifacts_collect.py +0 -0
  70. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/batching.py +0 -0
  71. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/cpu_budget.py +0 -0
  72. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/dense_encode.py +0 -0
  73. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/dense_encoder_input.py +0 -0
  74. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/dense_image_reading.py +0 -0
  75. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/dense_image_recipe.py +0 -0
  76. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/dense_image_shard.py +0 -0
  77. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/dense_image_stage.py +0 -0
  78. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/dense_regions.py +0 -0
  79. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/dense_shard.py +0 -0
  80. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/dense_sliding.py +0 -0
  81. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/dense_stage.py +0 -0
  82. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/distributed.py +0 -0
  83. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/distributed_stage.py +0 -0
  84. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/effective_encoder_input.py +0 -0
  85. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/embedding.py +0 -0
  86. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/embedding_persist.py +0 -0
  87. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/embedding_pipeline.py +0 -0
  88. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/encoder_input_contract.py +0 -0
  89. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/feature_identity.py +0 -0
  90. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/hierarchical.py +0 -0
  91. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/image_shard.py +0 -0
  92. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/image_specs.py +0 -0
  93. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/image_stage.py +0 -0
  94. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/manifest.py +0 -0
  95. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/model_settings.py +0 -0
  96. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/patient_pipeline.py +0 -0
  97. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/persist_callbacks.py +0 -0
  98. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/persistence.py +0 -0
  99. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/pooled_encoder_input.py +0 -0
  100. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/preprocessing.py +0 -0
  101. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/process_list.py +0 -0
  102. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/progress_bridge.py +0 -0
  103. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/registry.py +0 -0
  104. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/serialization.py +0 -0
  105. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/sharding.py +0 -0
  106. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/slide_encode.py +0 -0
  107. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/tiling.py +0 -0
  108. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/tiling_pipeline.py +0 -0
  109. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/types.py +0 -0
  110. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/worker_io.py +0 -0
  111. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/utils/__init__.py +0 -0
  112. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/utils/config.py +0 -0
  113. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/utils/coordinates.py +0 -0
  114. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/utils/log_utils.py +0 -0
  115. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/utils/tiling_io.py +0 -0
  116. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/utils/utils.py +0 -0
  117. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec.egg-info/dependency_links.txt +0 -0
  118. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec.egg-info/entry_points.txt +0 -0
  119. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec.egg-info/not-zip-safe +0 -0
  120. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec.egg-info/requires.txt +0 -0
  121. {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec.egg-info/top_level.txt +0 -0
  122. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_attention_extraction.py +0 -0
  123. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_benchmark_tooling.py +0 -0
  124. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_cli_noninteractive.py +0 -0
  125. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_cufile_compat_mode.py +0 -0
  126. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_dense_encode_kit.py +0 -0
  127. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_dense_encoder_input.py +0 -0
  128. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_dense_extraction.py +0 -0
  129. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_dense_image_reading.py +0 -0
  130. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_dense_image_resume.py +0 -0
  131. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_dense_image_shard.py +0 -0
  132. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_dense_image_stage.py +0 -0
  133. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_dense_regions.py +0 -0
  134. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_dense_shard.py +0 -0
  135. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_dense_sliding.py +0 -0
  136. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_dense_source_spacing.py +0 -0
  137. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_dense_stage.py +0 -0
  138. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_dense_worker.py +0 -0
  139. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_dinov2_natimage.py +0 -0
  140. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_dinov3_natimage.py +0 -0
  141. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_encoder_capabilities.py +0 -0
  142. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_encoder_input_contract.py +0 -0
  143. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_encoder_plugins.py +0 -0
  144. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_encoder_preprocessing.py +0 -0
  145. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_encoder_provider_failures.py +0 -0
  146. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_encoder_registry.py +0 -0
  147. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_feature_identity.py +0 -0
  148. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_gigapath.py +0 -0
  149. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_gpfm_genbio_heavy.py +0 -0
  150. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_hs2p5_integration.py +0 -0
  151. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_hs2p_package_cutover.py +0 -0
  152. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_image_shard.py +0 -0
  153. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_image_stage.py +0 -0
  154. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_inference_benchmark.py +0 -0
  155. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_isight.py +0 -0
  156. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_load_model_hf_auth.py +0 -0
  157. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_mascaret.py +0 -0
  158. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_mettle.py +0 -0
  159. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_on_slide_persisted.py +0 -0
  160. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_output_consistency.py +0 -0
  161. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_patch_size_metadata.py +0 -0
  162. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_patient_annotation_sampling.py +0 -0
  163. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_phaet.py +0 -0
  164. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_pooled_encoder_input.py +0 -0
  165. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_pooled_geometry.py +0 -0
  166. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_pooled_identity_api.py +0 -0
  167. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_prism.py +0 -0
  168. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_prism2.py +0 -0
  169. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_process_list_performance.py +0 -0
  170. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_progress.py +0 -0
  171. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_regression_core.py +0 -0
  172. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_regression_inference.py +0 -0
  173. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_regression_models.py +0 -0
  174. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_rudolfv2.py +0 -0
  175. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_runtime_batching.py +0 -0
  176. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_sharding.py +0 -0
  177. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_slide_coordinate_preparation.py +0 -0
  178. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_slide_latents.py +0 -0
  179. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_soma_migration.py +0 -0
  180. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_tile_store.py +0 -0
  181. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_tiling_pipeline.py +0 -0
  182. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_titan.py +0 -0
  183. {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_worker_gpu_pinning.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: slide2vec
3
- Version: 6.3.2
3
+ Version: 6.3.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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "slide2vec"
7
- version = "6.3.2"
7
+ version = "6.3.3"
8
8
  description = "Embedding of whole slide images with Foundation Models"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -180,7 +180,7 @@ no_implicit_reexport = true
180
180
  max-line-length = 160
181
181
 
182
182
  [tool.bumpver]
183
- current_version = "6.3.2"
183
+ current_version = "6.3.3"
184
184
  version_pattern = "MAJOR.MINOR.PATCH"
185
185
  commit = false
186
186
  tag = false
@@ -31,7 +31,7 @@ from slide2vec.encoders import (
31
31
  )
32
32
 
33
33
 
34
- __version__ = "6.3.2"
34
+ __version__ = "6.3.3"
35
35
 
36
36
  __all__ = [
37
37
  "Model",
@@ -761,7 +761,10 @@ def run_pipeline(
761
761
  tiling_only: bool = False,
762
762
  execution: ExecutionOptions,
763
763
  ) -> RunResult:
764
- if model.level == "patient":
764
+ # Tiling does not use patient ids or the patient pipeline: only a run that
765
+ # embeds patients needs them.
766
+ embeds_patients = model.level == "patient" and not tiling_only
767
+ if embeds_patients:
765
768
  patient_id_map = manifest.resolve_patient_id_map(slides=slides, manifest_path=manifest_path)
766
769
  else:
767
770
  patient_id_map = None
@@ -781,7 +784,7 @@ def run_pipeline(
781
784
  distributed_stage.validate_multi_gpu_execution(model, execution)
782
785
 
783
786
  resolved_preprocessing = tiling_pipeline.resolve_model_preprocessing(model, preprocessing)
784
- if model.level == "patient" and not tiling_only:
787
+ if embeds_patients:
785
788
  patient_pipeline.reject_per_annotation_sampling(model, resolved_preprocessing)
786
789
  output_dir = Path(execution.output_dir)
787
790
  output_dir.mkdir(parents=True, exist_ok=True)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: slide2vec
3
- Version: 6.3.2
3
+ Version: 6.3.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
@@ -157,6 +157,7 @@ tests/test_output_consistency.py
157
157
  tests/test_patch_size_metadata.py
158
158
  tests/test_patient_annotation_sampling.py
159
159
  tests/test_patient_manifest.py
160
+ tests/test_patient_tiling_only.py
160
161
  tests/test_phaet.py
161
162
  tests/test_pooled_encoder_input.py
162
163
  tests/test_pooled_geometry.py
@@ -60,7 +60,7 @@ def test_slide_manifest_preserves_leading_zero_sample_ids(tmp_path: Path):
60
60
  assert [slide.sample_id for slide in slides] == ["0007", "0008"]
61
61
 
62
62
 
63
- def test_patient_tiling_only_validates_ids_before_creating_output(tmp_path: Path):
63
+ def test_patient_run_validates_ids_before_creating_output(tmp_path: Path):
64
64
  manifest = tmp_path / "manifest.csv"
65
65
  manifest.write_text(
66
66
  "sample_id,image_path,patient_id\n"
@@ -75,7 +75,6 @@ def test_patient_tiling_only_validates_ids_before_creating_output(tmp_path: Path
75
75
  run_pipeline(
76
76
  SimpleNamespace(level="patient"),
77
77
  manifest_path=manifest,
78
- tiling_only=True,
79
78
  execution=SimpleNamespace(output_dir=output_dir, num_gpus=1),
80
79
  )
81
80
 
@@ -0,0 +1,86 @@
1
+ """Patient-level models and slides that carry no patient id.
2
+
3
+ Tiling does not use patient ids, so a tiling-only run must not need them. An
4
+ embedding run groups slides by patient, so it still needs one per slide. Ways this
5
+ can fail:
6
+
7
+ - a tiling-only run rejects slides without a patient id (for example hs2p
8
+ ``SlideSpec`` objects, which have no ``patient_id`` field);
9
+ - a full run accepts such slides and groups or names patients wrongly;
10
+ - a full run rejects them only after the slides were tiled or the model was loaded.
11
+ """
12
+
13
+ from pathlib import Path
14
+
15
+ import pandas as pd
16
+ import pytest
17
+ from hs2p import SlideSpec
18
+
19
+ from slide2vec.api import ExecutionOptions, Model, Pipeline, PreprocessingConfig
20
+ from tests.output_consistency_config import (
21
+ TILING_FILTER_PARAMS,
22
+ TILING_MASKS,
23
+ TILING_PARAMS,
24
+ TILING_SEG_PARAMS,
25
+ )
26
+
27
+
28
+ pytest.importorskip("openslide")
29
+
30
+ FIXTURES = Path(__file__).parent / "fixtures" / "input"
31
+ SAMPLE_IDS = ["slide-a", "slide-b"]
32
+
33
+
34
+ def _slides() -> list[SlideSpec]:
35
+ return [
36
+ SlideSpec(
37
+ sample_id=sample_id,
38
+ image_path=FIXTURES / "test-wsi.tif",
39
+ mask_path=FIXTURES / "test-mask.tif",
40
+ )
41
+ for sample_id in SAMPLE_IDS
42
+ ]
43
+
44
+
45
+ def _model_and_pipeline(output_dir: Path) -> tuple[Model, Pipeline]:
46
+ model = Model.from_preset("moozy", device="cpu")
47
+ pipeline = Pipeline(
48
+ model,
49
+ PreprocessingConfig(
50
+ backend="openslide",
51
+ mask_backend="openslide",
52
+ masks=TILING_MASKS,
53
+ segmentation=TILING_SEG_PARAMS,
54
+ filtering=TILING_FILTER_PARAMS,
55
+ preview={"save_mask_preview": False, "save_tiling_preview": False},
56
+ **TILING_PARAMS,
57
+ ),
58
+ execution=ExecutionOptions(output_dir=output_dir, num_gpus=1, num_preprocessing_workers=1),
59
+ )
60
+ return model, pipeline
61
+
62
+
63
+ def test_tiling_only_patient_run_tiles_slides_without_patient_ids(tmp_path):
64
+ model, pipeline = _model_and_pipeline(tmp_path / "out")
65
+
66
+ result = pipeline.run(slides=_slides(), tiling_only=True)
67
+
68
+ rows = pd.read_csv(result.process_list_path, dtype=str, keep_default_na=False)
69
+ assert rows["sample_id"].tolist() == SAMPLE_IDS
70
+ assert rows["tiling_status"].tolist() == ["success"] * len(SAMPLE_IDS)
71
+ assert all(Path(path).is_file() for path in rows["coordinates_npz_path"])
72
+ assert result.tile_artifacts == []
73
+ assert result.slide_artifacts == []
74
+ assert result.patient_artifacts == []
75
+ assert model._backend is None # tiling only: the model was never loaded
76
+
77
+
78
+ def test_full_patient_run_rejects_slides_without_patient_ids_before_tiling(tmp_path):
79
+ output_dir = tmp_path / "out"
80
+ model, pipeline = _model_and_pipeline(output_dir)
81
+
82
+ with pytest.raises(ValueError, match="Patient-level models require a 'patient_id' for every slide"):
83
+ pipeline.run(slides=_slides())
84
+
85
+ assert model._backend is None # nothing was loaded, so nothing was embedded
86
+ assert not output_dir.exists() # nor tiled
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes