From 582cdfab68f91fdbcd5104e5c28b84617e0aecdb Mon Sep 17 00:00:00 2001 From: mathiasg Date: Thu, 2 Jul 2020 11:20:05 -0400 Subject: [PATCH 1/3] ENH: Update NIfTI header dimensions for CIFTI-2 compliance --- nibabel/cifti2/cifti2.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/nibabel/cifti2/cifti2.py b/nibabel/cifti2/cifti2.py index f1886d4066..c41e8e0509 100644 --- a/nibabel/cifti2/cifti2.py +++ b/nibabel/cifti2/cifti2.py @@ -19,6 +19,7 @@ import re from collections.abc import MutableSequence, MutableMapping, Iterable from collections import OrderedDict +import numpy as np from .. import xmlutils as xml from ..filebasedimages import FileBasedHeader from ..dataobj_images import DataobjImage @@ -1484,8 +1485,14 @@ def update_headers(self): >>> img.update_headers() >>> img.nifti_header.get_data_shape() == (2, 3, 4) True + >>> np.array_equal(img.nifti_header['dim'], [7, 1, 1, 1, 1, 2, 3, 4]) + True ''' self._nifti_header.set_data_shape(self._dataobj.shape) + _dims = np.ones((8), dtype=int) + _dims[0] = 7 if len(self._dataobj.shape) == 3 else 6 + _dims[5:8] = (self._dataobj.shape + (1,))[:3] + self._nifti_header['dim'] = _dims def get_data_dtype(self): return self._nifti_header.get_data_dtype() From f2f6dc924ec1ea22b5150d922e09720fcdb7df4f Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Thu, 2 Jul 2020 13:07:23 -0400 Subject: [PATCH 2/3] RF: Set NIfTI-2 header shape through API call --- nibabel/cifti2/cifti2.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/nibabel/cifti2/cifti2.py b/nibabel/cifti2/cifti2.py index c41e8e0509..59de70f5b0 100644 --- a/nibabel/cifti2/cifti2.py +++ b/nibabel/cifti2/cifti2.py @@ -19,7 +19,6 @@ import re from collections.abc import MutableSequence, MutableMapping, Iterable from collections import OrderedDict -import numpy as np from .. import xmlutils as xml from ..filebasedimages import FileBasedHeader from ..dataobj_images import DataobjImage @@ -1483,16 +1482,12 @@ def update_headers(self): >>> img.shape == (2, 3, 4) True >>> img.update_headers() - >>> img.nifti_header.get_data_shape() == (2, 3, 4) + >>> img.nifti_header.get_data_shape() == (1, 1, 1, 1, 2, 3, 4) True - >>> np.array_equal(img.nifti_header['dim'], [7, 1, 1, 1, 1, 2, 3, 4]) + >>> img.shape == (2, 3, 4) True ''' - self._nifti_header.set_data_shape(self._dataobj.shape) - _dims = np.ones((8), dtype=int) - _dims[0] = 7 if len(self._dataobj.shape) == 3 else 6 - _dims[5:8] = (self._dataobj.shape + (1,))[:3] - self._nifti_header['dim'] = _dims + self._nifti_header.set_data_shape((1, 1, 1, 1) + self._dataobj.shape) def get_data_dtype(self): return self._nifti_header.get_data_dtype() From 36673738bf80431ab48aa099a977b080ab1b6b0f Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Thu, 2 Jul 2020 13:12:07 -0400 Subject: [PATCH 3/3] DOC: Add the spec text to explain the dim discrepancy --- nibabel/cifti2/cifti2.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/nibabel/cifti2/cifti2.py b/nibabel/cifti2/cifti2.py index 59de70f5b0..2630606a8f 100644 --- a/nibabel/cifti2/cifti2.py +++ b/nibabel/cifti2/cifti2.py @@ -1476,6 +1476,16 @@ def to_file_map(self, file_map=None): def update_headers(self): ''' Harmonize NIfTI headers with image data + Ensures that the NIfTI-2 header records the data shape in the last three + ``dim`` fields. Per the spec: + + Because the first four dimensions in NIfTI are reserved for space and time, the CIFTI + dimensions are stored in the NIfTI header in dim[5] and up, where dim[5] is the length + of the first CIFTI dimension (number of values in a row), dim[6] is the length of the + second CIFTI dimension, and dim[7] is the length of the third CIFTI dimension, if + applicable. The fields dim[1] through dim[4] will be 1; dim[0] will be 6 or 7, + depending on whether a third matrix dimension exists. + >>> import numpy as np >>> data = np.zeros((2,3,4)) >>> img = Cifti2Image(data)