This file is indexed.

/usr/lib/python3/dist-packages/nibabel/nifti2.py is in python3-nibabel 2.2.1-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
# emacs: -*- mode: python-mode; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vi: set ft=python sts=4 ts=4 sw=4 et:
### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
#
#   See COPYING file distributed along with the NiBabel package for the
#   copyright and license terms.
#
### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
''' Read / write access to NIfTI2 image format

Format described here:

    https://www.nitrc.org/forum/message.php?msg_id=3738
'''

import numpy as np

from .analyze import AnalyzeHeader
from .batteryrunners import Report
from .spatialimages import HeaderDataError, ImageFileError
from .nifti1 import Nifti1Header, Nifti1Pair, Nifti1Image

r"""
Header struct from : https://www.nitrc.org/forum/message.php?msg_id=3738

/*! \struct nifti_2_header
    \brief Data structure defining the fields in the nifti2 header.
           This binary header should be found at the beginning of a valid
           NIFTI-2 header file.
 */
                        /*************************/ /************/
struct nifti_2_header { /* NIFTI-2 usage         */ /*  offset
                        /*************************/ /************/
int   sizeof_hdr;     /*!< MUST be 540           */   /*   0 */
char  magic[8] ;      /*!< MUST be valid signature.   /*   4 */
short datatype;       /*!< Defines data type!    */   /*  12 */
short bitpix;         /*!< Number bits/voxel.    */   /*  14 */
int64_t dim[8];       /*!< Data array dimensions.*/   /*  16 */
double intent_p1 ;    /*!< 1st intent parameter. */   /*  80 */
double intent_p2 ;    /*!< 2nd intent parameter. */   /*  88 */
double intent_p3 ;    /*!< 3rd intent parameter. */   /*  96 */
double pixdim[8];     /*!< Grid spacings.        */   /* 104 */
int64_t vox_offset;   /*!< Offset into .nii file */   /* 168 */
double scl_slope ;    /*!< Data scaling: slope.  */   /* 176 */
double scl_inter ;    /*!< Data scaling: offset. */   /* 184 */
double cal_max;       /*!< Max display intensity */   /* 192 */
double cal_min;       /*!< Min display intensity */   /* 200 */
double slice_duration;/*!< Time for 1 slice.     */   /* 208 */
double toffset;       /*!< Time axis shift.      */   /* 216 */
int64_t slice_start;  /*!< First slice index.    */   /* 224 */
int64_t slice_end;    /*!< Last slice index.     */   /* 232 */
char  descrip[80];    /*!< any text you like.    */   /* 240 */
char  aux_file[24];   /*!< auxiliary filename.   */   /* 320 */
int qform_code ;      /*!< NIFTI_XFORM_* code.   */   /* 344 */
int sform_code ;      /*!< NIFTI_XFORM_* code.   */   /* 348 */
double quatern_b ;    /*!< Quaternion b param.   */   /* 352 */
double quatern_c ;    /*!< Quaternion c param.   */   /* 360 */
double quatern_d ;    /*!< Quaternion d param.   */   /* 368 */
double qoffset_x ;    /*!< Quaternion x shift.   */   /* 376 */
double qoffset_y ;    /*!< Quaternion y shift.   */   /* 384 */
double qoffset_z ;    /*!< Quaternion z shift.   */   /* 392 */
double srow_x[4] ;    /*!< 1st row affine transform. */  /* 400 */
double srow_y[4] ;    /*!< 2nd row affine transform. */  /* 432 */
double srow_z[4] ;    /*!< 3rd row affine transform. */  /* 464 */
int slice_code ;      /*!< Slice timing order.   */ /* 496 */
int xyzt_units ;      /*!< Units of pixdim[1..4] */ /* 500 */
int intent_code ;     /*!< NIFTI_INTENT_* code.  */ /* 504 */
char intent_name[16]; /*!< 'name' or meaning of data. */ /* 508 */
char dim_info;        /*!< MRI slice ordering.   */      /* 524 */
char unused_str[15];  /*!< unused, filled with \0 */     /* 525 */
} ;                   /**** 540 bytes total ****/
typedef struct nifti_2_header nifti_2_header ;
"""

# nifti2 flat header definition for first 540 bytes
# First number in comments indicates offset in file header in bytes
header_dtd = [
    ('sizeof_hdr', 'i4'),       # 0; must be 540
    ('magic', 'S4'),            # 4; must be 'ni2\0' or 'n+2\0'
    ('eol_check', 'i1', (4,)),  # 8; must be 0D 0A 1A 0A
    ('datatype', 'i2'),         # 12; it's the datatype
    ('bitpix', 'i2'),           # 14; number of bits per voxel
    ('dim', 'i8', (8,)),        # 16; data array dimensions
    ('intent_p1', 'f8'),        # 80; first intent parameter
    ('intent_p2', 'f8'),        # 88; second intent parameter
    ('intent_p3', 'f8'),        # 96; third intent parameter
    ('pixdim', 'f8', (8,)),     # 104; grid spacings (units below)
    ('vox_offset', 'i8'),       # 168; offset to data in image file
    ('scl_slope', 'f8'),        # 176; data scaling slope
    ('scl_inter', 'f8'),        # 184; data scaling intercept
    ('cal_max', 'f8'),          # 192; max display intensity
    ('cal_min', 'f8'),          # 200; min display intensity
    ('slice_duration', 'f8'),   # 208; time for 1 slice
    ('toffset', 'f8'),          # 216; time axis shift
    ('slice_start', 'i8'),      # 224; first slice index
    ('slice_end', 'i8'),        # 232; last slice index
    ('descrip', 'S80'),         # 240; any text
    ('aux_file', 'S24'),        # 320; auxiliary filename
    ('qform_code', 'i4'),       # 344; xform code
    ('sform_code', 'i4'),       # 348; xform code
    ('quatern_b', 'f8'),        # 352; quaternion b param
    ('quatern_c', 'f8'),        # 360; quaternion c param
    ('quatern_d', 'f8'),        # 368; quaternion d param
    ('qoffset_x', 'f8'),        # 376; quaternion x shift
    ('qoffset_y', 'f8'),        # 384; quaternion y shift
    ('qoffset_z', 'f8'),        # 392; quaternion z shift
    ('srow_x', 'f8', (4,)),     # 400; 1st row affine transform
    ('srow_y', 'f8', (4,)),     # 432; 2nd row affine transform
    ('srow_z', 'f8', (4,)),     # 464; 3rd row affine transform
    ('slice_code', 'i4'),       # 496; slice timing order
    ('xyzt_units', 'i4'),       # 500; inits of pixdim[1..4]
    ('intent_code', 'i4'),      # 504; NIFTI intent code
    ('intent_name', 'S16'),     # 508; name or meaning of data
    ('dim_info', 'u1'),         # 524; MRI slice ordering code
    ('unused_str', 'S15'),      # 525; unused, filled with \0
]  # total 540

# Full header numpy dtype
header_dtype = np.dtype(header_dtd)


class Nifti2Header(Nifti1Header):
    """ Class for NIfTI2 header

    NIfTI2 is a slightly simplified variant of NIfTI1 which replaces 32-bit
    floats with 64-bit floats, and increases some integer widths to 32 or 64
    bits.
    """
    template_dtype = header_dtype
    pair_vox_offset = 0
    single_vox_offset = 544

    # Magics for single and pair
    pair_magic = b'ni2'
    single_magic = b'n+2'

    # Size of header in sizeof_hdr field
    sizeof_hdr = 540

    # Quaternion threshold near 0, based on float64 preicision
    quaternion_threshold = -np.finfo(np.float64).eps * 3

    def get_data_shape(self):
        ''' Get shape of data

        Examples
        --------
        >>> hdr = Nifti2Header()
        >>> hdr.get_data_shape()
        (0,)
        >>> hdr.set_data_shape((1,2,3))
        >>> hdr.get_data_shape()
        (1, 2, 3)

        Expanding number of dimensions gets default zooms

        >>> hdr.get_zooms()
        (1.0, 1.0, 1.0)

        Notes
        -----
        Does not use Nifti1 freesurfer hack for large vectors described in
        :meth:`Nifti1Header.set_data_shape`
        '''
        return AnalyzeHeader.get_data_shape(self)

    def set_data_shape(self, shape):
        ''' Set shape of data

        If ``ndims == len(shape)`` then we set zooms for dimensions higher than
        ``ndims`` to 1.0

        Parameters
        ----------
        shape : sequence
           sequence of integers specifying data array shape

        Notes
        -----
        Does not apply nifti1 Freesurfer hack for long vectors (see
        :meth:`Nifti1Header.set_data_shape`)
        '''
        AnalyzeHeader.set_data_shape(self, shape)

    @classmethod
    def default_structarr(klass, endianness=None):
        ''' Create empty header binary block with given endianness '''
        hdr_data = super(Nifti2Header, klass).default_structarr(endianness)
        hdr_data['eol_check'] = (13, 10, 26, 10)
        return hdr_data

    ''' Checks only below here '''

    @classmethod
    def _get_checks(klass):
        # Add our own checks
        return (super(Nifti2Header, klass)._get_checks() +
                (klass._chk_eol_check,))

    @staticmethod
    def _chk_eol_check(hdr, fix=False):
        rep = Report(HeaderDataError)
        if np.all(hdr['eol_check'] == (13, 10, 26, 10)):
            return hdr, rep
        if np.all(hdr['eol_check'] == 0):
            rep.problem_level = 20
            rep.problem_msg = 'EOL check all 0'
            if fix:
                hdr['eol_check'] = (13, 10, 26, 10)
                rep.fix_msg = 'setting EOL check to 13, 10, 26, 10'
            return hdr, rep
        rep.problem_level = 40
        rep.problem_msg = ('EOL check not 0 or 13, 10, 26, 10; data may be '
                           'corrupted by EOL conversion')
        if fix:
            hdr['eol_check'] = (13, 10, 26, 10)
            rep.fix_msg = 'setting EOL check to 13, 10, 26, 10'
        return hdr, rep

    @classmethod
    def may_contain_header(klass, binaryblock):
        if len(binaryblock) < klass.sizeof_hdr:
            return False

        hdr_struct = np.ndarray(shape=(), dtype=header_dtype,
                                buffer=binaryblock[:klass.sizeof_hdr])
        bs_hdr_struct = hdr_struct.byteswap()
        return 540 in (hdr_struct['sizeof_hdr'], bs_hdr_struct['sizeof_hdr'])


class Nifti2PairHeader(Nifti2Header):
    ''' Class for NIfTI2 pair header '''
    # Signal whether this is single (header + data) file
    is_single = False


class Nifti2Pair(Nifti1Pair):
    """ Class for NIfTI2 format image, header pair
    """
    header_class = Nifti2PairHeader
    _meta_sniff_len = header_class.sizeof_hdr


class Nifti2Image(Nifti1Image):
    """ Class for single file NIfTI2 format image
    """
    header_class = Nifti2Header
    _meta_sniff_len = header_class.sizeof_hdr


def load(filename):
    """ Load NIfTI2 single or pair image from `filename`

    Parameters
    ----------
    filename : str
        filename of image to be loaded

    Returns
    -------
    img : Nifti2Image or Nifti2Pair
        nifti2 single or pair image instance

    Raises
    ------
    ImageFileError
        if `filename` doesn't look like nifti2;
    IOError
        if `filename` does not exist.
    """
    try:
        img = Nifti2Image.load(filename)
    except ImageFileError:
        return Nifti2Pair.load(filename)
    return img


def save(img, filename):
    """ Save NIfTI2 single or pair to `filename`

    Parameters
    ----------
    filename : str
        filename to which to save image
    """
    try:
        Nifti2Image.instance_to_filename(img, filename)
    except ImageFileError:
        Nifti2Pair.instance_to_filename(img, filename)