Skip to content

Commit 0215ce5

Browse files
moloneyeffigies
authored andcommitted
BF+TST: Handle case with extra-spatial index that is unique per frame
Not sure if this ever actually happens in real multiframe data, but it does in non-multiframe and I can imagine if a DimensionIndexSequence element refrences a per-frame AcquisitionTime then this could happen.
1 parent 019f448 commit 0215ce5

File tree

2 files changed

+47
-7
lines changed

2 files changed

+47
-7
lines changed

nibabel/nicom/dicomwrappers.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -598,21 +598,32 @@ def image_shape(self):
598598
unique = np.unique(row)
599599
if len(unique) != count:
600600
raise WrapperError("Number of slice indices and positions don't match")
601+
elif count == n_frames:
602+
if shape[-1] == 'remaining':
603+
raise WrapperError('At most one index have ambiguous size')
604+
shape.append('remaining')
605+
continue
601606
new_parts, leftover = divmod(curr_parts, count)
602-
allowed_val_counts = [new_parts * frames_per_part]
603-
if row_idx != slice_dim_idx:
604-
# Except for the slice dim, having a unique value for each frame is valid
605-
allowed_val_counts.append(n_frames)
606-
if leftover != 0 or any(
607-
np.count_nonzero(row == val) not in allowed_val_counts for val in unique
608-
):
607+
expected = new_parts * frames_per_part
608+
if leftover != 0 or any(np.count_nonzero(row == val) != expected for val in unique):
609609
if row_idx == slice_dim_idx:
610610
raise WrapperError('Missing slices from multiframe')
611611
del_indices[row_idx] = count
612612
continue
613+
if shape[-1] == 'remaining':
614+
shape[-1] = new_parts
615+
frames_per_part *= shape[-1]
616+
new_parts = 1
613617
frames_per_part *= count
614618
shape.append(count)
615619
curr_parts = new_parts
620+
if shape[-1] == 'remaining':
621+
if curr_parts > 1:
622+
shape[-1] = curr_parts
623+
curr_parts = 1
624+
else:
625+
del_indices[len(shape)] = 1
626+
shape = shape[:-1]
616627
if del_indices:
617628
if curr_parts > 1:
618629
ns_failed = [k for k, v in del_indices.items() if v != 1]

nibabel/nicom/tests/test_dicomwrappers.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,35 @@ def test_shape(self):
626626
)
627627
fake_mf.update(fake_shape_dependents(div_seq, sid_dim=0))
628628
assert MFW(fake_mf).image_shape == (32, 64, 2, 3)
629+
# Test invalid 4D indices
630+
div_seq = ((1, 1, 1), (1, 2, 1), (1, 1, 2), (1, 2, 2), (1, 1, 3), (1, 2, 4))
631+
fake_mf.update(fake_shape_dependents(div_seq, sid_dim=0))
632+
with pytest.raises(didw.WrapperError):
633+
MFW(fake_mf).image_shape
634+
div_seq = ((1, 1, 1), (1, 2, 1), (1, 1, 2), (1, 2, 2), (1, 1, 3), (1, 2, 2))
635+
fake_mf.update(fake_shape_dependents(div_seq, sid_dim=0))
636+
with pytest.raises(didw.WrapperError):
637+
MFW(fake_mf).image_shape
638+
# Time index that is unique to each frame
639+
div_seq = ((1, 1, 1), (1, 2, 2), (1, 1, 3), (1, 2, 4), (1, 1, 5), (1, 2, 6))
640+
fake_mf.update(fake_shape_dependents(div_seq, sid_dim=0))
641+
assert MFW(fake_mf).image_shape == (32, 64, 2, 3)
642+
div_seq = (
643+
(1, 1, 1, 1),
644+
(1, 2, 2, 1),
645+
(1, 1, 3, 1),
646+
(1, 2, 4, 1),
647+
(1, 1, 5, 1),
648+
(1, 2, 6, 1),
649+
(1, 1, 7, 2),
650+
(1, 2, 8, 2),
651+
(1, 1, 9, 2),
652+
(1, 2, 10, 2),
653+
(1, 1, 11, 2),
654+
(1, 2, 12, 2),
655+
)
656+
fake_mf.update(fake_shape_dependents(div_seq, sid_dim=0))
657+
assert MFW(fake_mf).image_shape == (32, 64, 2, 3, 2)
629658

630659
def test_iop(self):
631660
# Test Image orient patient for multiframe

0 commit comments

Comments
 (0)