Skip to content

Commit 3a985f5

Browse files
committed
enh+wip: support for philips dcm w/ derived volume
* if DICOM has MR Diffusion Sequence (0018, 9117), discard any derived frames * out correct final shape * TODO: fix get_data() repr
1 parent ad0b13f commit 3a985f5

File tree

4 files changed

+25
-5
lines changed

4 files changed

+25
-5
lines changed

nibabel/nicom/dicomwrappers.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from .dwiparams import B2q, nearest_pos_semi_def, q2bg
2222
from ..openers import ImageOpener
2323
from ..onetime import setattr_on_read as one_time
24-
from ..pydicom_compat import tag_for_keyword
24+
from ..pydicom_compat import tag_for_keyword, Sequence
2525

2626

2727
class WrapperError(Exception):
@@ -461,10 +461,19 @@ def __init__(self, dcm_data):
461461
Wrapper.__init__(self, dcm_data)
462462
self.dcm_data = dcm_data
463463
self.frames = dcm_data.get('PerFrameFunctionalGroupsSequence')
464+
self._nframes = self.get('NumberOfFrames')
464465
try:
465466
self.frames[0]
466467
except TypeError:
467468
raise WrapperError("PerFrameFunctionalGroupsSequence is empty.")
469+
# DWI image where derived isotropic, ADC or trace volume was appended to the series
470+
if self.frames[0].get([0x18, 0x9117]):
471+
self.frames = Sequence(
472+
frame for frame in self.frames if
473+
frame.get([0x18, 0x9117])[0].get([0x18, 0x9075]).value
474+
!= 'ISOTROPIC'
475+
)
476+
self._nframes = len(self.frames)
468477
try:
469478
self.shared = dcm_data.get('SharedFunctionalGroupsSequence')[0]
470479
except TypeError:
@@ -503,8 +512,7 @@ def image_shape(self):
503512
if None in (rows, cols):
504513
raise WrapperError("Rows and/or Columns are empty.")
505514
# Check number of frames
506-
n_frames = self.get('NumberOfFrames')
507-
assert len(self.frames) == n_frames
515+
assert len(self.frames) == self._nframes
508516
frame_indices = np.array(
509517
[frame.FrameContentSequence[0].DimensionIndexValues
510518
for frame in self.frames])
@@ -528,12 +536,15 @@ def image_shape(self):
528536
# Store frame indices
529537
self._frame_indices = frame_indices
530538
if n_dim < 4: # 3D volume
531-
return rows, cols, n_frames
539+
return rows, cols, self._nframes
532540
# More than 3 dimensions
533541
ns_unique = [len(np.unique(row)) for row in self._frame_indices.T]
542+
if len(ns_unique) == 3:
543+
# derived volume is included
544+
ns_unique.pop(1)
534545
shape = (rows, cols) + tuple(ns_unique)
535546
n_vols = np.prod(shape[3:])
536-
if n_frames != n_vols * shape[2]:
547+
if self._nframes != n_vols * shape[2]:
537548
raise WrapperError("Calculated shape does not match number of "
538549
"frames.")
539550
return tuple(shape)
Binary file not shown.

nibabel/nicom/tests/test_dicomwrappers.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
DATA_FILE_SLC_NORM = pjoin(IO_DATA_PATH, 'csa_slice_norm.dcm')
3636
DATA_FILE_DEC_RSCL = pjoin(IO_DATA_PATH, 'decimal_rescale.dcm')
3737
DATA_FILE_4D = pjoin(IO_DATA_PATH, '4d_multiframe_test.dcm')
38+
DATA_FILE_4D_DERIVED = pjoin(IO_DATA_PATH, '4d_multiframe_with_derived.dcm')
3839

3940
# This affine from our converted image was shown to match our image spatially
4041
# with an image from SPM DICOM conversion. We checked the matching with SPM
@@ -616,6 +617,13 @@ def test_data_real(self):
616617
assert_equal(sha1(dat_str).hexdigest(),
617618
'149323269b0af92baa7508e19ca315240f77fa8c')
618619

620+
@dicom_test
621+
def test_data_derived_shape(self):
622+
# Test 4D diffusion data with an additional trace volume included
623+
# Excludes the trace volume and generates the correct shape
624+
dw = didw.wrapper_from_file(DATA_FILE_4D_DERIVED)
625+
assert_equal(dw.image_shape, (96, 96, 60, 33))
626+
619627
@dicom_test
620628
def test_data_fake(self):
621629
# Test algorithm for get_data

nibabel/pydicom_compat.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
read_file = pydicom.read_file
4141

4242
if have_dicom:
43+
from pydicom.sequence import Sequence
4344
try:
4445
# Versions >= 1.0
4546
tag_for_keyword = pydicom.datadict.tag_for_keyword

0 commit comments

Comments
 (0)