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.
- {slide2vec-1.2.1/slide2vec.egg-info → slide2vec-1.2.2}/PKG-INFO +1 -1
- {slide2vec-1.2.1 → slide2vec-1.2.2}/pyproject.toml +1 -1
- {slide2vec-1.2.1 → slide2vec-1.2.2}/setup.cfg +1 -1
- slide2vec-1.2.2/slide2vec/__init__.py +1 -0
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/aggregate.py +2 -2
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/distributed/__init__.py +6 -2
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/embed.py +1 -1
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/main.py +42 -13
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/models/models.py +2 -2
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/utils/config.py +1 -1
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/utils/utils.py +13 -9
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/wsi/wsi.py +1 -1
- {slide2vec-1.2.1 → slide2vec-1.2.2/slide2vec.egg-info}/PKG-INFO +1 -1
- slide2vec-1.2.1/slide2vec/__init__.py +0 -1
- {slide2vec-1.2.1 → slide2vec-1.2.2}/LICENSE +0 -0
- {slide2vec-1.2.1 → slide2vec-1.2.2}/MANIFEST.in +0 -0
- {slide2vec-1.2.1 → slide2vec-1.2.2}/README.md +0 -0
- {slide2vec-1.2.1 → slide2vec-1.2.2}/setup.py +0 -0
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/configs/__init__.py +0 -0
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/data/__init__.py +0 -0
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/data/augmentations.py +0 -0
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/data/dataset.py +0 -0
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/models/__init__.py +0 -0
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/models/layers/__init__.py +0 -0
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/models/layers/attention.py +0 -0
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/models/layers/block.py +0 -0
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/models/layers/dino_head.py +0 -0
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/models/layers/drop_path.py +0 -0
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/models/layers/layer_scale.py +0 -0
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/models/layers/mlp.py +0 -0
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/models/layers/patch_embed.py +0 -0
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/models/layers/swiglu_ffn.py +0 -0
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/models/vision_transformer_dino.py +0 -0
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/models/vision_transformer_dinov2.py +0 -0
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/tiling.py +0 -0
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/utils/__init__.py +0 -0
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/utils/log_utils.py +0 -0
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/wsi/__init__.py +0 -0
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec/wsi/utils.py +0 -0
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec.egg-info/SOURCES.txt +0 -0
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec.egg-info/dependency_links.txt +0 -0
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec.egg-info/not-zip-safe +0 -0
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec.egg-info/requires.txt +0 -0
- {slide2vec-1.2.1 → slide2vec-1.2.2}/slide2vec.egg-info/top_level.txt +0 -0
|
@@ -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.
|
|
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
|
|
@@ -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(
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
45
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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=
|
|
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(
|
|
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 #
|
|
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
|
-
#
|
|
173
|
-
msg = (
|
|
174
|
-
|
|
175
|
-
f"{shape_mismatch} weight(s) not loaded due to mismatching shapes: {shape_mismatch_list}
|
|
176
|
-
|
|
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 +0,0 @@
|
|
|
1
|
-
__version__ = "1.2.1"
|
|
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
|