/usr/lib/python3/dist-packages/nibabel/spm2analyze.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 | # 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 SPM2 version of analyze image format '''
import numpy as np
from . import spm99analyze as spm99 # module import
image_dimension_dtd = spm99.image_dimension_dtd[:]
image_dimension_dtd[
image_dimension_dtd.index(('funused2', 'f4'))
] = ('scl_inter', 'f4')
# Full header numpy dtype combined across sub-fields
header_dtype = np.dtype(spm99.header_key_dtd +
image_dimension_dtd +
spm99.data_history_dtd)
class Spm2AnalyzeHeader(spm99.Spm99AnalyzeHeader):
''' Class for SPM2 variant of basic Analyze header
SPM2 variant adds the following to basic Analyze format:
* voxel origin;
* slope scaling of data;
* reading - but not writing - intercept of data.
'''
# Copies of module level definitions
template_dtype = header_dtype
def get_slope_inter(self):
''' Get data scaling (slope) and intercept from header data
Uses the algorithm from SPM2 spm_vol_ana.m by John Ashburner
Parameters
----------
self : header
Mapping with fields:
* scl_slope - slope
* scl_inter - possible intercept (SPM2 use - shared by nifti)
* glmax - the (recorded) maximum value in the data (unscaled)
* glmin - recorded minimum unscaled value
* cal_max - the calibrated (scaled) maximum value in the dataset
* cal_min - ditto minimum value
Returns
-------
scl_slope : None or float
slope. None if there is no valid scaling from these fields
scl_inter : None or float
intercept. Also None if there is no valid slope, intercept
Examples
--------
>>> fields = {'scl_slope': 1, 'scl_inter': 0, 'glmax': 0, 'glmin': 0,
... 'cal_max': 0, 'cal_min': 0}
>>> hdr = Spm2AnalyzeHeader()
>>> for key, value in fields.items():
... hdr[key] = value
>>> hdr.get_slope_inter()
(1.0, 0.0)
>>> hdr['scl_inter'] = 0.5
>>> hdr.get_slope_inter()
(1.0, 0.5)
>>> hdr['scl_inter'] = np.nan
>>> hdr.get_slope_inter()
(1.0, 0.0)
If 'scl_slope' is 0, nan or inf, cannot use 'scl_slope'.
Without valid information in the gl / cal fields, we cannot get
scaling, and return None
>>> hdr['scl_slope'] = 0
>>> hdr.get_slope_inter()
(None, None)
>>> hdr['scl_slope'] = np.nan
>>> hdr.get_slope_inter()
(None, None)
Valid information in the gl AND cal fields are needed
>>> hdr['cal_max'] = 0.8
>>> hdr['cal_min'] = 0.2
>>> hdr.get_slope_inter()
(None, None)
>>> hdr['glmax'] = 110
>>> hdr['glmin'] = 10
>>> np.allclose(hdr.get_slope_inter(), [0.6/100, 0.2-0.6/100*10])
True
'''
# get scaling factor from 'scl_slope' (funused1)
slope = float(self['scl_slope'])
if np.isfinite(slope) and slope:
# try to get offset from scl_inter
inter = float(self['scl_inter'])
if not np.isfinite(inter):
inter = 0.0
return slope, inter
# no non-zero and finite scaling, try gl/cal fields
unscaled_range = self['glmax'] - self['glmin']
scaled_range = self['cal_max'] - self['cal_min']
if unscaled_range and scaled_range:
slope = float(scaled_range) / unscaled_range
inter = self['cal_min'] - slope * self['glmin']
return slope, inter
return None, None
@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 (binaryblock[344:348] not in (b'ni1\x00', b'n+1\x00') and
348 in (hdr_struct['sizeof_hdr'], bs_hdr_struct['sizeof_hdr']))
class Spm2AnalyzeImage(spm99.Spm99AnalyzeImage):
""" Class for SPM2 variant of basic Analyze image
"""
header_class = Spm2AnalyzeHeader
load = Spm2AnalyzeImage.load
save = Spm2AnalyzeImage.instance_to_filename
|