Skip to content

Commit 18b3f12

Browse files
committed
Address review: shallow-copy lazy backend and assert laziness
- Use copy.copy instead of copy.deepcopy for the preserved lazy backend in Image.__deepcopy__: the backend is a read-only access adapter, so a shallow copy preserves the derived crop/pad view without deep-copying nibabel/zarr internals or duplicating open I/O resources. - Assert the padded lazy image stays unloaded before and after deepcopy so the test exercises the lazy-backend code path.
1 parent 2402305 commit 18b3f12

2 files changed

Lines changed: 8 additions & 4 deletions

File tree

src/torchio/data/image.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,7 +1165,7 @@ def __deepcopy__(self, memo: dict) -> Self:
11651165
new._data = self._data.clone()
11661166
new._affine = affine_copy
11671167
elif self._backend is not None:
1168-
new._backend = copy.deepcopy(self._backend, memo)
1168+
new._backend = copy.copy(self._backend)
11691169
elif self._path is not None:
11701170
new = type(self)(
11711171
self._path,
@@ -1183,8 +1183,10 @@ def __deepcopy__(self, memo: dict) -> Self:
11831183
# Preserve a derived lazy backend (e.g. the cropped/padded
11841184
# view installed by CropOrPad). Rebuilding from the source
11851185
# path alone would discard the crop/pad and revert to the
1186-
# full-resolution image.
1187-
new._backend = copy.deepcopy(self._backend, memo)
1186+
# full-resolution image. A shallow copy is enough: the backend
1187+
# is a read-only access adapter, so sharing the underlying
1188+
# storage object avoids deep-copying nibabel/zarr internals.
1189+
new._backend = copy.copy(self._backend)
11881190
elif self._zarr_store is not None:
11891191
new = type(self)(
11901192
self._zarr_store,
@@ -1198,7 +1200,7 @@ def __deepcopy__(self, memo: dict) -> Self:
11981200
new._data = self._data.clone()
11991201
new._affine = affine_copy
12001202
elif self._backend is not None:
1201-
new._backend = copy.deepcopy(self._backend, memo)
1203+
new._backend = copy.copy(self._backend)
12021204
elif self._data is not None:
12031205
new = type(self)(
12041206
self._data.clone(),

tests/test_crop_or_pad.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,9 +580,11 @@ def test_deepcopy_padded_lazy_preserves_shape(self, tmp_path) -> None:
580580
self._make_nii(path, shape=(8, 8, 8))
581581
result = tio.CropOrPad(target_shape=12)(tio.Subject(t1=tio.ScalarImage(path)))
582582
image = result.t1
583+
assert not image.is_loaded
583584

584585
copied = copy.deepcopy(image)
585586
assert copied.shape == (1, 12, 12, 12)
587+
assert not copied.is_loaded
586588
torch.testing.assert_close(copied.data, image.data)
587589

588590
def test_transform_after_lazy_crop_uses_cropped_shape(self, tmp_path) -> None:

0 commit comments

Comments
 (0)