Skip to content

Commit 39931c2

Browse files
committed
DOC: Add short explanation and references to image_shape function for the Multi-frame DICOM wrapper
1 parent 7f3b4bb commit 39931c2

File tree

2 files changed

+38
-7
lines changed

2 files changed

+38
-7
lines changed

nibabel/nicom/dicomwrappers.py

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,30 @@ def __init__(self, dcm_data):
461461

462462
@one_time
463463
def image_shape(self):
464-
"""The array shape as it will be returned by ``get_data()``"""
464+
"""The array shape as it will be returned by ``get_data()``
465+
466+
The shape is determined by the `Rows` DICOM attribute, `Columns`
467+
DICOM attribute, and the set of frame indices given by the
468+
`FrameContentSequence[0].DimensionIndexValues` DICOM attribute of each
469+
element in the `PerFrameFunctionalGroupsSequence`. The first two
470+
axes of the returned shape correspond to the rows, and columns
471+
respectively. The remaining axes correspond to those of the frame
472+
indices with order preserved.
473+
474+
What each axis in the frame indices refers to is given by the
475+
corresponding entry in the `DimensionIndexSequence` DICOM attribute.
476+
WARNING, any axis refering to the `StackID` DICOM attribute will have
477+
been removed from the frame indices in determining the shape. This is
478+
because only a file containing a single stack is currently allowed by
479+
this wrapper.
480+
481+
References
482+
----------
483+
- C.7.6.17 Multi-frame Dimension Module of Supplement 49 of the DICOM
484+
standard.
485+
- C.7.6.16.2.2 Frame Content Macro of Supplement 49 of the DICOM
486+
standard.
487+
"""
465488
rows, cols = self.get('Rows'), self.get('Columns')
466489
if None in (rows, cols):
467490
raise WrapperError("Rows and/or Columns are empty.")
@@ -471,25 +494,23 @@ def image_shape(self):
471494
frame_indices = np.array(
472495
[frame.FrameContentSequence[0].DimensionIndexValues
473496
for frame in self.frames])
474-
475497
# Check that there is only one multiframe stack index
476498
stack_ids = set(frame.FrameContentSequence[0].StackID
477499
for frame in self.frames)
478500
if len(stack_ids) > 1:
479501
raise WrapperError("File contains more than one StackID. "
480502
"Cannot handle multi-stack files")
481-
482503
# Determine if one of the Dimension indices refers to the stack id
483504
dim_seq = [(dim.DimensionIndexPointer, dim.FunctionalGroupPointer)
484505
for dim in self.get('DimensionIndexSequence')]
485-
# the pointer pair (StackID tag, FrameContentSequence tag) that
486-
# indicates that the dimension refers to the StackID
506+
# the pointer pair (StackID Dicom-tag, FrameContentSequence Dicom-tag)
507+
# that indicates that the corresponding axis in the DimensionIndexValues
508+
# attribute refers to the StackID
487509
stack_id_dim_pointer = ((0x20, 0x9056), (0x20, 0x9111))
488510
# remove superfluous stack id index if present
489511
if stack_id_dim_pointer in dim_seq:
490512
stack_dim_idx = dim_seq.index(stack_id_dim_pointer)
491513
frame_indices = np.delete(frame_indices, stack_dim_idx, axis=1)
492-
493514
# account for the 2 additional dimensions (row and column) not included
494515
# in the indices
495516
n_dim = frame_indices.shape[1] + 2

nibabel/nicom/tests/test_dicomwrappers.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
from hashlib import sha1
77
from decimal import Decimal
88
from copy import copy
9-
from collections import namedtuple
109

1110
import numpy as np
1211

@@ -383,6 +382,17 @@ class Fake(object):
383382

384383

385384
def fake_shape_dependents(div_seq, sid_seq=None, sid_dim=None):
385+
""" Make a fake dictionary of data that ``image_shape`` is dependent on.
386+
387+
Parameters
388+
----------
389+
div_seq : list of tuples
390+
list of values to use for the `DimensionIndexValues` of each frame.
391+
sid_seq : list of int
392+
list of values to use for the `StackID` of each frame.
393+
sid_dim : int
394+
the index of the column in 'div_seq' to use as 'sid_seq'
395+
"""
386396
class DimIdxSeqElem(object):
387397
def __init__(self, dip=(0, 0), fgp=(0, 0)):
388398
self.DimensionIndexPointer = dip

0 commit comments

Comments
 (0)