slide2vec 1.2.1__tar.gz → 1.2.2__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 (44) hide show
  1. {slide2vec-1.2.1/slide2vec.egg-info → slide2vec-1.2.2}/PKG-INFO +1 -1
  2. {slide2vec-1.2.1 → slide2vec-1.2.2}/pyproject.toml +1 -1
  3. {slide2vec-1.2.1 → slide2vec-1.2.2}/setup.cfg +1 -1
  4. slide2vec-1.2.2/slide2vec/__init__.py +1 -0
  5. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/aggregate.py +2 -2
  6. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/distributed/__init__.py +6 -2
  7. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/embed.py +1 -1
  8. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/main.py +42 -13
  9. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/models/models.py +2 -2
  10. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/utils/config.py +1 -1
  11. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/utils/utils.py +13 -9
  12. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/wsi/wsi.py +1 -1
  13. {slide2vec-1.2.1 → slide2vec-1.2.2/slide2vec.egg-info}/PKG-INFO +1 -1
  14. slide2vec-1.2.1/slide2vec/__init__.py +0 -1
  15. {slide2vec-1.2.1 → slide2vec-1.2.2}/LICENSE +0 -0
  16. {slide2vec-1.2.1 → slide2vec-1.2.2}/MANIFEST.in +0 -0
  17. {slide2vec-1.2.1 → slide2vec-1.2.2}/README.md +0 -0
  18. {slide2vec-1.2.1 → slide2vec-1.2.2}/setup.py +0 -0
  19. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/configs/__init__.py +0 -0
  20. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/data/__init__.py +0 -0
  21. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/data/augmentations.py +0 -0
  22. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/data/dataset.py +0 -0
  23. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/models/__init__.py +0 -0
  24. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/models/layers/__init__.py +0 -0
  25. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/models/layers/attention.py +0 -0
  26. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/models/layers/block.py +0 -0
  27. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/models/layers/dino_head.py +0 -0
  28. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/models/layers/drop_path.py +0 -0
  29. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/models/layers/layer_scale.py +0 -0
  30. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/models/layers/mlp.py +0 -0
  31. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/models/layers/patch_embed.py +0 -0
  32. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/models/layers/swiglu_ffn.py +0 -0
  33. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/models/vision_transformer_dino.py +0 -0
  34. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/models/vision_transformer_dinov2.py +0 -0
  35. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/tiling.py +0 -0
  36. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/utils/__init__.py +0 -0
  37. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/utils/log_utils.py +0 -0
  38. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/wsi/__init__.py +0 -0
  39. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/wsi/utils.py +0 -0
  40. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec.egg-info/SOURCES.txt +0 -0
  41. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec.egg-info/dependency_links.txt +0 -0
  42. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec.egg-info/not-zip-safe +0 -0
  43. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec.egg-info/requires.txt +0 -0
  44. {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: slide2vec
3
- Version: 1.2.1
3
+ Version: 1.2.2
4
4
  Summary: Embedding of whole slide images with Foundation Models
5
5
  Home-page: https://github.com/clemsgrs/slide2vec
6
6
  Author: Clément Grisi
@@ -23,7 +23,7 @@ warn_unused_configs = true
23
23
  no_implicit_reexport = true
24
24
 
25
25
  [tool.bumpver]
26
- current_version = "1.2.1"
26
+ current_version = "1.2.2"
27
27
  version_pattern = "MAJOR.MINOR.PATCH"
28
28
  commit = false # We do version bumping in CI, not as a commit
29
29
  tag = false # Git tag already exists — we don't auto-tag
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = slide2vec
3
- version = 1.2.1
3
+ version = 1.2.2
4
4
  description = Embedding of whole slide images with Foundation Models
5
5
  author = Clément Grisi
6
6
  platforms = unix, linux, osx, cygwin, win32
@@ -0,0 +1 @@
1
+ __version__ = "1.2.2"
@@ -170,9 +170,9 @@ def main(args):
170
170
  ]
171
171
  print("=+=" * 10)
172
172
  print(f"Total number of slides with tile-level features: {slides_with_tile_features}/{total_slides}")
173
- print(f"Failed slide-level feature aggregation: {len(failed_feature_aggregation)}")
173
+ print(f"Failed slide-level feature aggregation: {len(failed_feature_aggregation)}/{total_slides}")
174
174
  print(
175
- f"Completed slide-level feature aggregation: {total_slides - len(failed_feature_aggregation)}"
175
+ f"Completed slide-level feature aggregation: {total_slides - len(failed_feature_aggregation)}/{total_slides}"
176
176
  )
177
177
  print("=+=" * 10)
178
178
 
@@ -1,8 +1,8 @@
1
+ import datetime
1
2
  import os
2
3
  import random
3
4
  import re
4
5
  import socket
5
- import datetime
6
6
  from typing import Dict, List
7
7
 
8
8
  import torch
@@ -278,7 +278,11 @@ def enable(
278
278
  _check_env_variable(key, value)
279
279
  os.environ[key] = value
280
280
 
281
- dist.init_process_group(backend="nccl", timeout=datetime.timedelta(days=14))
281
+ dist.init_process_group(
282
+ backend="nccl",
283
+ timeout=datetime.timedelta(days=14),
284
+ device_id=torch.device(f"cuda:{torch_env.local_rank}")
285
+ )
282
286
  dist.barrier()
283
287
 
284
288
  # Finalize setup
@@ -275,7 +275,7 @@ def main(args):
275
275
  print(f"Total number of slides with {unit}s: {slides_with_tiles}/{total_slides}")
276
276
  print(f"Failed {unit}-level feature extraction: {len(failed_feature_extraction)}/{slides_with_tiles}")
277
277
  print(
278
- f"Completed {unit}-level feature extraction: {slides_with_tiles - len(failed_feature_extraction)}"
278
+ f"Completed {unit}-level feature extraction: {slides_with_tiles - len(failed_feature_extraction)}/{slides_with_tiles}"
279
279
  )
280
280
  print("=+=" * 10)
281
281
 
@@ -1,16 +1,16 @@
1
+ import argparse
1
2
  import os
2
- import sys
3
- import time
4
- import wandb
5
- import socket
6
3
  import signal
7
- import argparse
8
- import threading
4
+ import socket
9
5
  import subprocess
10
-
6
+ import sys
7
+ import threading
8
+ import time
11
9
  from pathlib import Path
12
10
 
13
- from slide2vec.utils.config import setup, hf_login
11
+ import wandb
12
+
13
+ from slide2vec.utils.config import hf_login, setup
14
14
 
15
15
 
16
16
  def get_args_parser(add_help: bool = True):
@@ -41,10 +41,22 @@ def run_tiling(config_file, run_id):
41
41
  "--config-file",
42
42
  config_file,
43
43
  ]
44
- result = subprocess.run(cmd)
45
- if result.returncode != 0:
44
+ proc = subprocess.Popen(
45
+ cmd,
46
+ stdout=subprocess.PIPE,
47
+ stderr=subprocess.STDOUT,
48
+ text=True,
49
+ bufsize=1,
50
+ universal_newlines=True
51
+ )
52
+ # forward output in real-time
53
+ for line in proc.stdout:
54
+ print(line.rstrip())
55
+ sys.stdout.flush()
56
+ proc.wait()
57
+ if proc.returncode != 0:
46
58
  print("Slide tiling failed. Exiting.")
47
- sys.exit(result.returncode)
59
+ sys.exit(proc.returncode)
48
60
 
49
61
 
50
62
  def run_feature_extraction(config_file, run_id):
@@ -69,10 +81,18 @@ def run_feature_extraction(config_file, run_id):
69
81
  proc = subprocess.Popen(
70
82
  cmd,
71
83
  preexec_fn=os.setsid,
84
+ stdout=subprocess.PIPE,
85
+ stderr=subprocess.STDOUT,
72
86
  text=True,
87
+ bufsize=1,
88
+ universal_newlines=True
73
89
  )
74
90
  try:
75
- proc.communicate()
91
+ # forward output in real-time
92
+ for line in proc.stdout:
93
+ print(line.rstrip())
94
+ sys.stdout.flush()
95
+ proc.wait()
76
96
  except KeyboardInterrupt:
77
97
  print("Received CTRL+C, terminating embed.py process group...")
78
98
  os.killpg(os.getpgid(proc.pid), signal.SIGTERM)
@@ -98,10 +118,18 @@ def run_feature_aggregation(config_file, run_id):
98
118
  proc = subprocess.Popen(
99
119
  cmd,
100
120
  preexec_fn=os.setsid,
121
+ stdout=subprocess.PIPE,
122
+ stderr=subprocess.STDOUT,
101
123
  text=True,
124
+ bufsize=1,
125
+ universal_newlines=True
102
126
  )
103
127
  try:
104
- proc.communicate()
128
+ # forward output in real-time
129
+ for line in proc.stdout:
130
+ print(line.rstrip())
131
+ sys.stdout.flush()
132
+ proc.wait()
105
133
  except KeyboardInterrupt:
106
134
  print("Received CTRL+C, terminating embed.py process group...")
107
135
  os.killpg(os.getpgid(proc.pid), signal.SIGTERM)
@@ -153,6 +181,7 @@ def main(args):
153
181
 
154
182
  if __name__ == "__main__":
155
183
  import warnings
184
+
156
185
  import torchvision
157
186
  torchvision.disable_beta_transforms_warning()
158
187
 
@@ -161,7 +161,7 @@ class DINOViT(FeatureExtractor):
161
161
  nn.modules.utils.consume_prefix_in_state_dict_if_present(
162
162
  state_dict, prefix="backbone."
163
163
  )
164
- state_dict, msg = update_state_dict(self.encoder.state_dict(), state_dict)
164
+ state_dict, msg = update_state_dict(model_dict=self.encoder.state_dict(), state_dict=state_dict)
165
165
  if distributed.is_main_process():
166
166
  print(msg)
167
167
  self.encoder.load_state_dict(state_dict, strict=False)
@@ -242,7 +242,7 @@ class CustomViT(FeatureExtractor):
242
242
  nn.modules.utils.consume_prefix_in_state_dict_if_present(
243
243
  state_dict, prefix="backbone."
244
244
  )
245
- state_dict, msg = update_state_dict(self.encoder.state_dict(), state_dict)
245
+ state_dict, msg = update_state_dict(model_dict=self.encoder.state_dict(), state_dict=state_dict)
246
246
  if distributed.is_main_process():
247
247
  print(msg)
248
248
  self.encoder.load_state_dict(state_dict, strict=False)
@@ -56,7 +56,7 @@ def setup(config_file):
56
56
 
57
57
  output_dir = Path(cfg.output_dir, run_id)
58
58
  if distributed.is_main_process():
59
- output_dir.mkdir(exist_ok=True, parents=True)
59
+ output_dir.mkdir(exist_ok=cfg.resume, parents=True)
60
60
  cfg.output_dir = str(output_dir)
61
61
 
62
62
  fix_random_seeds(0)
@@ -126,7 +126,11 @@ def load_csv(cfg):
126
126
  return wsi_paths, mask_paths
127
127
 
128
128
 
129
- def update_state_dict(model_dict, state_dict):
129
+ def update_state_dict(
130
+ *,
131
+ model_dict: dict,
132
+ state_dict: dict,
133
+ ):
130
134
  """
131
135
  Matches weights between `model_dict` and `state_dict`, accounting for:
132
136
  - Key mismatches (missing in model_dict)
@@ -166,13 +170,13 @@ def update_state_dict(model_dict, state_dict):
166
170
  break
167
171
  if not matched_key:
168
172
  # key not found in state_dict
169
- updated_state_dict[model_key] = model_val # Keep original weights
173
+ updated_state_dict[model_key] = model_val # keep original weights
170
174
  missing_keys += 1
171
175
  missing_keys_list.append(model_key)
172
- # Log summary
173
- msg = (
174
- f"{success}/{len(model_dict)} weight(s) loaded successfully\n"
175
- f"{shape_mismatch} weight(s) not loaded due to mismatching shapes: {shape_mismatch_list}\n"
176
- f"{missing_keys} key(s) from checkpoint not found in model: {missing_keys_list}"
177
- )
178
- return updated_state_dict, msg
176
+ # log summary
177
+ msg = f"{success}/{len(model_dict)} weight(s) loaded successfully"
178
+ if shape_mismatch > 0:
179
+ msg += f"\n{shape_mismatch} weight(s) not loaded due to mismatching shapes: {shape_mismatch_list}"
180
+ if missing_keys > 0:
181
+ msg += f"\n{missing_keys} key(s) from checkpoint not found in model: {missing_keys_list}"
182
+ return updated_state_dict, msg
@@ -306,7 +306,7 @@ class WholeSlideImage(object):
306
306
  # resize the mask to the size of the slide at seg_spacing
307
307
  mask = cv2.resize(
308
308
  mask.astype(np.uint8),
309
- (int(height / scale), int(width / scale)),
309
+ (int(round(height / scale, 0)), int(round(width / scale, 0))),
310
310
  interpolation=cv2.INTER_NEAREST,
311
311
  )
312
312
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: slide2vec
3
- Version: 1.2.1
3
+ Version: 1.2.2
4
4
  Summary: Embedding of whole slide images with Foundation Models
5
5
  Home-page: https://github.com/clemsgrs/slide2vec
6
6
  Author: Clément Grisi
@@ -1 +0,0 @@
1
- __version__ = "1.2.1"
File without changes
File without changes
File without changes
File without changes
File without changes