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.
- {slide2vec-6.3.2 → slide2vec-6.3.3}/PKG-INFO +1 -1
- {slide2vec-6.3.2 → slide2vec-6.3.3}/pyproject.toml +2 -2
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/__init__.py +1 -1
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/inference.py +5 -2
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec.egg-info/PKG-INFO +1 -1
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec.egg-info/SOURCES.txt +1 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_patient_manifest.py +1 -2
- slide2vec-6.3.3/tests/test_patient_tiling_only.py +86 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/LICENSE +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/README.md +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/setup.cfg +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/__main__.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/_cufile.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/api.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/artifacts.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/cli.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/configs/__init__.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/configs/default.yaml +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/configs/resources.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/cufile.json +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/data/__init__.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/data/dataset.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/data/tile_reader.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/data/tile_store.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/distributed/__init__.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/distributed/dense_image_worker.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/distributed/dense_worker.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/distributed/direct_embed_worker.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/distributed/image_worker.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/distributed/pin_gpu.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/distributed/pipeline_worker.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/distributed/worker_entry.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/__init__.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/base.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/__init__.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/conch.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/dinov2.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/dinov3.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/genbio.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/gigapath.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/gpfm.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/hibou.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/hoptimus.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/isight.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/lunit.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/mettle.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/midnight.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/moozy/__init__.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/moozy/blocks.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/moozy/case.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/moozy/loading.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/moozy/slide.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/moozy/types.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/mstar.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/musk.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/phikon.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/prism.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/prism2.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/prost40m.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/rudolfv2.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/titan.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/uni.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/virchow.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/models/waiv.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/registry.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/encoders/validation.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/progress.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/__init__.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/artifacts_collect.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/batching.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/cpu_budget.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/dense_encode.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/dense_encoder_input.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/dense_image_reading.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/dense_image_recipe.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/dense_image_shard.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/dense_image_stage.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/dense_regions.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/dense_shard.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/dense_sliding.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/dense_stage.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/distributed.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/distributed_stage.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/effective_encoder_input.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/embedding.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/embedding_persist.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/embedding_pipeline.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/encoder_input_contract.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/feature_identity.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/hierarchical.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/image_shard.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/image_specs.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/image_stage.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/manifest.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/model_settings.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/patient_pipeline.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/persist_callbacks.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/persistence.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/pooled_encoder_input.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/preprocessing.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/process_list.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/progress_bridge.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/registry.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/serialization.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/sharding.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/slide_encode.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/tiling.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/tiling_pipeline.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/types.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/runtime/worker_io.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/utils/__init__.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/utils/config.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/utils/coordinates.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/utils/log_utils.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/utils/tiling_io.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec/utils/utils.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec.egg-info/dependency_links.txt +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec.egg-info/entry_points.txt +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec.egg-info/not-zip-safe +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec.egg-info/requires.txt +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/slide2vec.egg-info/top_level.txt +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_attention_extraction.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_benchmark_tooling.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_cli_noninteractive.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_cufile_compat_mode.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_dense_encode_kit.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_dense_encoder_input.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_dense_extraction.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_dense_image_reading.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_dense_image_resume.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_dense_image_shard.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_dense_image_stage.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_dense_regions.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_dense_shard.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_dense_sliding.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_dense_source_spacing.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_dense_stage.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_dense_worker.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_dinov2_natimage.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_dinov3_natimage.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_encoder_capabilities.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_encoder_input_contract.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_encoder_plugins.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_encoder_preprocessing.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_encoder_provider_failures.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_encoder_registry.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_feature_identity.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_gigapath.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_gpfm_genbio_heavy.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_hs2p5_integration.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_hs2p_package_cutover.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_image_shard.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_image_stage.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_inference_benchmark.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_isight.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_load_model_hf_auth.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_mascaret.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_mettle.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_on_slide_persisted.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_output_consistency.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_patch_size_metadata.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_patient_annotation_sampling.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_phaet.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_pooled_encoder_input.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_pooled_geometry.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_pooled_identity_api.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_prism.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_prism2.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_process_list_performance.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_progress.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_regression_core.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_regression_inference.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_regression_models.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_rudolfv2.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_runtime_batching.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_sharding.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_slide_coordinate_preparation.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_slide_latents.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_soma_migration.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_tile_store.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_tiling_pipeline.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_titan.py +0 -0
- {slide2vec-6.3.2 → slide2vec-6.3.3}/tests/test_worker_gpu_pinning.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "slide2vec"
|
|
7
|
-
version = "6.3.
|
|
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.
|
|
183
|
+
current_version = "6.3.3"
|
|
184
184
|
version_pattern = "MAJOR.MINOR.PATCH"
|
|
185
185
|
commit = false
|
|
186
186
|
tag = false
|
|
@@ -761,7 +761,10 @@ def run_pipeline(
|
|
|
761
761
|
tiling_only: bool = False,
|
|
762
762
|
execution: ExecutionOptions,
|
|
763
763
|
) -> RunResult:
|
|
764
|
-
|
|
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
|
|
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)
|
|
@@ -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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|