slide2vec 4.4.0__tar.gz → 4.5.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 (95) hide show
  1. {slide2vec-4.4.0 → slide2vec-4.5.0}/PKG-INFO +3 -3
  2. {slide2vec-4.4.0 → slide2vec-4.5.0}/pyproject.toml +4 -4
  3. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/__init__.py +1 -1
  4. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/api.py +7 -15
  5. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/cli.py +5 -7
  6. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/distributed/direct_embed_worker.py +36 -15
  7. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/distributed/pipeline_worker.py +22 -8
  8. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/encoders/__init__.py +1 -1
  9. slide2vec-4.5.0/slide2vec/inference.py +919 -0
  10. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/progress.py +56 -10
  11. slide2vec-4.5.0/slide2vec/runtime/artifacts_collect.py +155 -0
  12. slide2vec-4.5.0/slide2vec/runtime/cpu_budget.py +67 -0
  13. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/runtime/distributed.py +7 -5
  14. slide2vec-4.5.0/slide2vec/runtime/distributed_stage.py +278 -0
  15. slide2vec-4.5.0/slide2vec/runtime/embedding_persist.py +131 -0
  16. slide2vec-4.5.0/slide2vec/runtime/embedding_pipeline.py +416 -0
  17. slide2vec-4.5.0/slide2vec/runtime/manifest.py +134 -0
  18. slide2vec-4.5.0/slide2vec/runtime/patient_pipeline.py +130 -0
  19. slide2vec-4.5.0/slide2vec/runtime/persist_callbacks.py +170 -0
  20. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/runtime/persistence.py +33 -10
  21. slide2vec-4.5.0/slide2vec/runtime/process_list.py +301 -0
  22. slide2vec-4.5.0/slide2vec/runtime/slide_encode.py +52 -0
  23. slide2vec-4.5.0/slide2vec/runtime/tiling_pipeline.py +196 -0
  24. slide2vec-4.5.0/slide2vec/runtime/worker_io.py +51 -0
  25. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/utils/config.py +15 -24
  26. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/utils/log_utils.py +1 -1
  27. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/utils/tiling_io.py +34 -0
  28. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec.egg-info/PKG-INFO +3 -3
  29. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec.egg-info/SOURCES.txt +12 -1
  30. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec.egg-info/requires.txt +2 -2
  31. {slide2vec-4.4.0 → slide2vec-4.5.0}/tests/test_architecture_runtime_split.py +0 -1
  32. {slide2vec-4.4.0 → slide2vec-4.5.0}/tests/test_hs2p_package_cutover.py +69 -0
  33. {slide2vec-4.4.0 → slide2vec-4.5.0}/tests/test_progress.py +152 -28
  34. {slide2vec-4.4.0 → slide2vec-4.5.0}/tests/test_regression_core.py +42 -42
  35. {slide2vec-4.4.0 → slide2vec-4.5.0}/tests/test_regression_inference.py +495 -274
  36. slide2vec-4.4.0/slide2vec/inference.py +0 -2591
  37. slide2vec-4.4.0/slide2vec/main.py +0 -8
  38. {slide2vec-4.4.0 → slide2vec-4.5.0}/LICENSE +0 -0
  39. {slide2vec-4.4.0 → slide2vec-4.5.0}/README.md +0 -0
  40. {slide2vec-4.4.0 → slide2vec-4.5.0}/setup.cfg +0 -0
  41. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/__main__.py +0 -0
  42. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/artifacts.py +0 -0
  43. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/configs/__init__.py +0 -0
  44. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/configs/default.yaml +0 -0
  45. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/configs/resources.py +0 -0
  46. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/data/__init__.py +0 -0
  47. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/data/dataset.py +0 -0
  48. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/data/tile_reader.py +0 -0
  49. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/data/tile_store.py +0 -0
  50. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/distributed/__init__.py +0 -0
  51. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/encoders/base.py +0 -0
  52. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/encoders/models/__init__.py +0 -0
  53. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/encoders/models/conch.py +0 -0
  54. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/encoders/models/gigapath.py +0 -0
  55. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/encoders/models/hibou.py +0 -0
  56. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/encoders/models/hoptimus.py +0 -0
  57. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/encoders/models/lunit.py +0 -0
  58. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/encoders/models/midnight.py +0 -0
  59. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/encoders/models/moozy/__init__.py +0 -0
  60. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/encoders/models/moozy/blocks.py +0 -0
  61. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/encoders/models/moozy/case.py +0 -0
  62. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/encoders/models/moozy/loading.py +0 -0
  63. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/encoders/models/moozy/slide.py +0 -0
  64. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/encoders/models/moozy/types.py +0 -0
  65. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/encoders/models/musk.py +0 -0
  66. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/encoders/models/phikon.py +0 -0
  67. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/encoders/models/prism.py +0 -0
  68. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/encoders/models/prost40m.py +0 -0
  69. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/encoders/models/titan.py +0 -0
  70. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/encoders/models/uni.py +0 -0
  71. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/encoders/models/virchow.py +0 -0
  72. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/encoders/registry.py +0 -0
  73. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/encoders/validation.py +0 -0
  74. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/runtime/__init__.py +0 -0
  75. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/runtime/batching.py +0 -0
  76. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/runtime/embedding.py +0 -0
  77. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/runtime/hierarchical.py +0 -0
  78. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/runtime/model_settings.py +0 -0
  79. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/runtime/progress_bridge.py +0 -0
  80. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/runtime/registry.py +0 -0
  81. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/runtime/serialization.py +0 -0
  82. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/runtime/tiling.py +0 -0
  83. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/runtime/types.py +0 -0
  84. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/utils/__init__.py +0 -0
  85. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/utils/coordinates.py +0 -0
  86. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec/utils/utils.py +0 -0
  87. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec.egg-info/dependency_links.txt +0 -0
  88. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec.egg-info/entry_points.txt +0 -0
  89. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec.egg-info/not-zip-safe +0 -0
  90. {slide2vec-4.4.0 → slide2vec-4.5.0}/slide2vec.egg-info/top_level.txt +0 -0
  91. {slide2vec-4.4.0 → slide2vec-4.5.0}/tests/test_encoder_registry.py +0 -0
  92. {slide2vec-4.4.0 → slide2vec-4.5.0}/tests/test_output_consistency.py +0 -0
  93. {slide2vec-4.4.0 → slide2vec-4.5.0}/tests/test_regression_models.py +0 -0
  94. {slide2vec-4.4.0 → slide2vec-4.5.0}/tests/test_runtime_batching.py +0 -0
  95. {slide2vec-4.4.0 → slide2vec-4.5.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.4.0
3
+ Version: 4.5.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,sam2,vips]>=4.0.1
18
+ Requires-Dist: hs2p[asap,cucim,openslide,sam2,vips]>=4.0.5
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.1; extra == "fm"
68
+ Requires-Dist: hs2p[asap,cucim,openslide,sam2,vips]>=4.0.5; 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.4.0"
7
+ version = "4.5.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,sam2,vips]>=4.0.1",
24
+ "hs2p[asap,cucim,openslide,sam2,vips]>=4.0.5",
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.1",
91
+ "hs2p[asap,cucim,openslide,sam2,vips]>=4.0.5",
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.4.0"
167
+ current_version = "4.5.0"
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.4.0"
14
+ __version__ = "4.5.0"
15
15
 
16
16
  __all__ = [
17
17
  "Model",
@@ -111,20 +111,14 @@ class PreprocessingConfig:
111
111
  int(channel) for channel in preview_cfg.tissue_contour_color
112
112
  )
113
113
  preview_kwargs["mask_overlay_alpha"] = float(preview_cfg.mask_overlay_alpha)
114
+ region_size_px = getattr(tiling.params, "requested_region_size_px", None)
115
+ region_tile_multiple = getattr(tiling.params, "region_tile_multiple", None)
114
116
  return cls(
115
117
  backend=tiling.backend,
116
118
  requested_spacing_um=float(tiling.params.requested_spacing_um),
117
119
  requested_tile_size_px=int(tiling.params.requested_tile_size_px),
118
- requested_region_size_px=(
119
- int(v)
120
- if (v := getattr(tiling.params, "requested_region_size_px", None)) is not None
121
- else None
122
- ),
123
- region_tile_multiple=(
124
- int(v)
125
- if (v := getattr(tiling.params, "region_tile_multiple", None)) is not None
126
- else None
127
- ),
120
+ requested_region_size_px=int(region_size_px) if region_size_px is not None else None,
121
+ region_tile_multiple=int(region_tile_multiple) if region_tile_multiple is not None else None,
128
122
  tolerance=float(tiling.params.tolerance),
129
123
  overlap=float(tiling.params.overlap),
130
124
  tissue_threshold=float(tiling.params.tissue_threshold),
@@ -615,11 +609,9 @@ def _require_output_dir_for_persistence(execution: ExecutionOptions, *, method_n
615
609
 
616
610
 
617
611
  def _recommended_execution_precision(model: Model | None) -> str:
618
- name = None if model is None else model.name
619
- if name and name in encoder_registry:
620
- info = encoder_registry.info(name)
621
- return info["precision"] if "precision" in info and info["precision"] is not None else "fp32"
622
- return "fp32"
612
+ if model is None or model.name not in encoder_registry:
613
+ return "fp32"
614
+ return encoder_registry.info(model.name).get("precision") or "fp32"
623
615
 
624
616
 
625
617
  def _resolve_direct_api_preprocessing(
@@ -1,8 +1,8 @@
1
1
  import argparse
2
2
 
3
3
  from slide2vec.api import ExecutionOptions, Model, Pipeline, PreprocessingConfig
4
+ from slide2vec.progress import activate_progress_reporter, create_cli_progress_reporter
4
5
  from slide2vec.utils.config import setup, hf_login
5
- import slide2vec.progress as progress
6
6
 
7
7
 
8
8
  def get_args_parser(add_help: bool = True):
@@ -27,10 +27,8 @@ def build_model_and_pipeline(args):
27
27
  hf_login()
28
28
  model = Model.from_preset(
29
29
  cfg.model.name,
30
- output_variant=getattr(cfg.model, "output_variant", None),
31
- allow_non_recommended_settings=bool(
32
- getattr(cfg.model, "allow_non_recommended_settings", False)
33
- ),
30
+ output_variant=cfg.model.output_variant,
31
+ allow_non_recommended_settings=bool(cfg.model.allow_non_recommended_settings),
34
32
  device="cpu" if args.run_on_cpu else "auto",
35
33
  )
36
34
  preprocessing = PreprocessingConfig.from_config(cfg)
@@ -42,8 +40,8 @@ def build_model_and_pipeline(args):
42
40
  def main(argv=None):
43
41
  args = parse_args(argv)
44
42
  pipeline, cfg = build_model_and_pipeline(args)
45
- reporter = progress.create_cli_progress_reporter(output_dir=getattr(cfg, "output_dir", None))
46
- with progress.activate_progress_reporter(reporter):
43
+ reporter = create_cli_progress_reporter(output_dir=cfg.output_dir)
44
+ with activate_progress_reporter(reporter):
47
45
  return pipeline.run(
48
46
  manifest_path=cfg.csv,
49
47
  tiling_only=args.tiling_only,
@@ -18,15 +18,12 @@ def main(argv=None) -> int:
18
18
  import torch.distributed as dist
19
19
 
20
20
  import slide2vec.distributed as distributed
21
+ import slide2vec.inference as inference
21
22
  from slide2vec.api import Model
22
- from slide2vec.inference import (
23
- _build_hierarchical_index,
24
- _compute_embedded_slides,
25
- _compute_hierarchical_embedding_shard_for_slide,
26
- _compute_tile_embeddings_for_slide,
27
- _is_hierarchical_preprocessing,
28
- _resolve_hierarchical_geometry,
29
- load_successful_tiled_slides,
23
+ from slide2vec.runtime.hierarchical import (
24
+ build_hierarchical_index,
25
+ is_hierarchical_preprocessing,
26
+ resolve_hierarchical_geometry,
30
27
  )
31
28
  from slide2vec.progress import JsonlProgressReporter, activate_progress_reporter
32
29
  from slide2vec.runtime.serialization import deserialize_execution, deserialize_preprocessing
@@ -52,7 +49,10 @@ def main(argv=None) -> int:
52
49
  )
53
50
  preprocessing = deserialize_preprocessing(request["preprocessing"])
54
51
  execution = deserialize_execution(request["execution"])
55
- slide_records, tiling_results = load_successful_tiled_slides(output_dir)
52
+ load_successful_tiled_slides_fn = getattr(inference, "load_successful_tiled_slides", None)
53
+ if not callable(load_successful_tiled_slides_fn):
54
+ from slide2vec.runtime.manifest import load_successful_tiled_slides as load_successful_tiled_slides_fn
55
+ slide_records, tiling_results = load_successful_tiled_slides_fn(output_dir)
56
56
  paired_by_sample = {
57
57
  slide.sample_id: (slide, tiling_result)
58
58
  for slide, tiling_result in zip(slide_records, tiling_results)
@@ -74,15 +74,24 @@ def main(argv=None) -> int:
74
74
  sample_id = request["sample_id"]
75
75
  slide, tiling_result = paired_by_sample[sample_id]
76
76
  loaded = model._load_backend()
77
- if _is_hierarchical_preprocessing(preprocessing):
78
- geometry = _resolve_hierarchical_geometry(preprocessing, tiling_result)
79
- index = _build_hierarchical_index(
77
+ if is_hierarchical_preprocessing(preprocessing):
78
+ geometry = resolve_hierarchical_geometry(preprocessing, tiling_result)
79
+ index = build_hierarchical_index(
80
80
  tiling_result,
81
81
  region_tile_multiple=int(preprocessing.region_tile_multiple),
82
82
  tile_size_lv0=int(geometry["tile_size_lv0"]),
83
83
  )
84
84
  flat_indices = np.array_split(index.flat_index, world_size)[global_rank]
85
- shard_indices, tile_embeddings = _compute_hierarchical_embedding_shard_for_slide(
85
+ compute_hierarchical_embedding_shard_for_slide_fn = getattr(
86
+ inference,
87
+ "_compute_hierarchical_embedding_shard_for_slide",
88
+ None,
89
+ )
90
+ if not callable(compute_hierarchical_embedding_shard_for_slide_fn):
91
+ from slide2vec.runtime.embedding_pipeline import (
92
+ compute_hierarchical_embedding_shard_for_slide as compute_hierarchical_embedding_shard_for_slide_fn,
93
+ )
94
+ shard_indices, tile_embeddings = compute_hierarchical_embedding_shard_for_slide_fn(
86
95
  loaded,
87
96
  slide,
88
97
  tiling_result,
@@ -98,7 +107,16 @@ def main(argv=None) -> int:
98
107
  else:
99
108
  num_tiles = len(tiling_result.x)
100
109
  tile_indices = np.array_split(np.arange(num_tiles, dtype=np.int64), world_size)[global_rank]
101
- tile_embeddings = _compute_tile_embeddings_for_slide(
110
+ compute_tile_embeddings_for_slide_fn = getattr(
111
+ inference,
112
+ "_compute_tile_embeddings_for_slide",
113
+ None,
114
+ )
115
+ if not callable(compute_tile_embeddings_for_slide_fn):
116
+ from slide2vec.runtime.embedding_pipeline import (
117
+ compute_tile_embeddings_for_slide as compute_tile_embeddings_for_slide_fn,
118
+ )
119
+ tile_embeddings = compute_tile_embeddings_for_slide_fn(
102
120
  loaded,
103
121
  model,
104
122
  slide,
@@ -128,7 +146,10 @@ def main(argv=None) -> int:
128
146
  }
129
147
  torch.save(payload, coordination_dir / f"{embedded_slide.sample_id}.embedded.pt")
130
148
 
131
- _compute_embedded_slides(
149
+ compute_embedded_slides_fn = getattr(inference, "_compute_embedded_slides", None)
150
+ if not callable(compute_embedded_slides_fn):
151
+ from slide2vec.runtime.embedding_pipeline import compute_embedded_slides as compute_embedded_slides_fn
152
+ compute_embedded_slides_fn(
132
153
  model,
133
154
  assigned_slides,
134
155
  assigned_tiling_results,
@@ -17,12 +17,9 @@ def main(argv=None) -> int:
17
17
  import torch.distributed as dist
18
18
 
19
19
  import slide2vec.distributed as distributed
20
+ import slide2vec.inference as inference
20
21
  from slide2vec.api import Model
21
- from slide2vec.inference import (
22
- _build_incremental_persist_callback,
23
- _compute_embedded_slides,
24
- load_successful_tiled_slides,
25
- )
22
+ from slide2vec.runtime.persist_callbacks import build_incremental_persist_callback
26
23
  from slide2vec.progress import JsonlProgressReporter, activate_progress_reporter
27
24
  from slide2vec.runtime.serialization import deserialize_execution, deserialize_preprocessing
28
25
 
@@ -47,7 +44,20 @@ def main(argv=None) -> int:
47
44
  preprocessing = deserialize_preprocessing(request["preprocessing"])
48
45
  execution = deserialize_execution(request["execution"])
49
46
  tiling_input_dir = Path(request.get("tiling_input_dir", str(output_dir)))
50
- slide_records, tiling_results = load_successful_tiled_slides(tiling_input_dir)
47
+ load_successful_tiled_slides_fn = getattr(inference, "load_successful_tiled_slides", None)
48
+ if not callable(load_successful_tiled_slides_fn):
49
+ from slide2vec.runtime.manifest import load_successful_tiled_slides as load_successful_tiled_slides_fn
50
+ slide_records, tiling_results = load_successful_tiled_slides_fn(tiling_input_dir)
51
+ requested_sample_ids = request.get("sample_ids")
52
+ if requested_sample_ids is not None:
53
+ requested_sample_id_set = {str(sample_id) for sample_id in requested_sample_ids}
54
+ paired = [
55
+ (slide, tiling_result)
56
+ for slide, tiling_result in zip(slide_records, tiling_results)
57
+ if slide.sample_id in requested_sample_id_set
58
+ ]
59
+ slide_records = [slide for slide, _ in paired]
60
+ tiling_results = [tiling_result for _, tiling_result in paired]
51
61
  assignments = assign_slides_to_ranks(slide_records, tiling_results, num_gpus=world_size)
52
62
  assigned_ids = assignments.get(global_rank, [])
53
63
  if not assigned_ids:
@@ -70,13 +80,17 @@ def main(argv=None) -> int:
70
80
  )
71
81
  context = activate_progress_reporter(reporter) if reporter is not None else nullcontext()
72
82
  with context:
73
- persist_callback, _, _ = _build_incremental_persist_callback(
83
+ build_incremental_persist_callback_fn = getattr(inference, "_build_incremental_persist_callback", build_incremental_persist_callback)
84
+ persist_callback, _, _ = build_incremental_persist_callback_fn(
74
85
  model=model,
75
86
  preprocessing=preprocessing,
76
87
  execution=execution,
77
88
  process_list_path=None,
78
89
  )
79
- _compute_embedded_slides(
90
+ compute_embedded_slides_fn = getattr(inference, "_compute_embedded_slides", None)
91
+ if not callable(compute_embedded_slides_fn):
92
+ from slide2vec.runtime.embedding_pipeline import compute_embedded_slides as compute_embedded_slides_fn
93
+ compute_embedded_slides_fn(
80
94
  model,
81
95
  assigned_slides,
82
96
  assigned_tiling_results,
@@ -21,7 +21,7 @@ from slide2vec.encoders.registry import (
21
21
  )
22
22
 
23
23
  # Trigger registration of all built-in encoders.
24
- from slide2vec.encoders import models as _models_pkg # noqa: F401
24
+ from slide2vec.encoders import models # noqa: F401
25
25
 
26
26
  __all__ = [
27
27
  "Encoder",