Skip to content

Commit 706cc97

Browse files
committed
Revert cucim module-level imports per review feedback
Restore cucim imports inside functions to avoid slow import times and buggy behaviour. Add comment explaining why cucim is not at module level. Also rename unused `mod` to `_mod` in test per CodeRabbit nitpick. Signed-off-by: Soumya Snigdha Kundu <soumya_snigdha.kundu@kcl.ac.uk>
1 parent 5395848 commit 706cc97

2 files changed

Lines changed: 16 additions & 13 deletions

File tree

monai/transforms/utils.py

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,9 @@
8585
cp, has_cp = optional_import("cupy")
8686
cp_ndarray, _ = optional_import("cupy", name="ndarray")
8787
exposure, has_skimage = optional_import("skimage.exposure")
88-
_cucim_skimage, _has_cucim_skimage = optional_import("cucim.skimage")
89-
_cucim_morphology_edt, _has_cucim_morphology = optional_import(
90-
"cucim.core.operations.morphology", name="distance_transform_edt"
91-
)
88+
# NOTE: cucim is deliberately NOT imported at module level.
89+
# Module-level cucim imports caused very slow import times and other buggy behaviour.
90+
# Keep cucim imports inside the functions that need them.
9291

9392
__all__ = [
9493
"allow_missing_keys_mode",
@@ -1151,10 +1150,11 @@ def get_largest_connected_component_mask(
11511150
"""
11521151
# use skimage/cucim.skimage and np/cp depending on whether packages are
11531152
# available and input is non-cpu torch.tensor
1154-
use_cp = has_cp and _has_cucim_skimage and isinstance(img, torch.Tensor) and img.device != torch.device("cpu")
1153+
skimage, has_cucim = optional_import("cucim.skimage")
1154+
use_cp = has_cp and has_cucim and isinstance(img, torch.Tensor) and img.device != torch.device("cpu")
11551155
if use_cp:
11561156
img_ = convert_to_cupy(img.short()) # type: ignore
1157-
label = _cucim_skimage.measure.label
1157+
label = skimage.measure.label
11581158
lib = cp
11591159
else:
11601160
if not has_measure:
@@ -1207,13 +1207,13 @@ def keep_merge_components_with_points(
12071207
margins: include points outside of the region but within the margin.
12081208
"""
12091209

1210-
use_cp = (
1211-
has_cp and _has_cucim_skimage and isinstance(img_pos, torch.Tensor) and img_pos.device != torch.device("cpu")
1212-
)
1210+
cucim_skimage, has_cucim = optional_import("cucim.skimage")
1211+
1212+
use_cp = has_cp and has_cucim and isinstance(img_pos, torch.Tensor) and img_pos.device != torch.device("cpu")
12131213
if use_cp:
12141214
img_pos_ = convert_to_cupy(img_pos.short()) # type: ignore
12151215
img_neg_ = convert_to_cupy(img_neg.short()) # type: ignore
1216-
label = _cucim_skimage.measure.label
1216+
label = cucim_skimage.measure.label
12171217
lib = cp
12181218
else:
12191219
if not has_measure:
@@ -2466,7 +2466,10 @@ def distance_transform_edt(
24662466
Returned only when `return_indices` is True and `indices` is not supplied. dtype np.float64.
24672467
24682468
"""
2469-
use_cp = has_cp and _has_cucim_morphology and isinstance(img, torch.Tensor) and img.device.type == "cuda"
2469+
distance_transform_edt, has_cucim = optional_import(
2470+
"cucim.core.operations.morphology", name="distance_transform_edt"
2471+
)
2472+
use_cp = has_cp and has_cucim and isinstance(img, torch.Tensor) and img.device.type == "cuda"
24702473
if not return_distances and not return_indices:
24712474
raise RuntimeError("Neither return_distances nor return_indices True")
24722475

@@ -2499,7 +2502,7 @@ def distance_transform_edt(
24992502
indices_ = convert_to_cupy(indices)
25002503
img_ = convert_to_cupy(img)
25012504
for channel_idx in range(img_.shape[0]):
2502-
_cucim_morphology_edt(
2505+
distance_transform_edt(
25032506
img_[channel_idx],
25042507
sampling=sampling,
25052508
return_distances=return_distances,

tests/utils/test_optional_import.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ def _do_import():
8888
ref = weakref.ref(marker)
8989
# Call optional_import for a module that does not exist.
9090
# If the traceback is leaked, `marker` stays alive via frame references.
91-
mod, flag = optional_import("nonexistent_module_for_leak_test")
91+
_mod, flag = optional_import("nonexistent_module_for_leak_test")
9292
self.assertFalse(flag)
9393
return ref
9494

0 commit comments

Comments
 (0)