NIPY logo

Site Navigation

NIPY Community

Table Of Contents

Previous topic

io.files

This Page

io.imageformats.analyze

Module: io.imageformats.analyze

Inheritance diagram for nipy.io.imageformats.analyze:

Header and image for the basic Mayo Analyze format

The basic principle of the header object is that it manages and contains header information. Each header type may have different attributes that can be set. Some headers can contain only subsets of possible passed values - for example the basic Analyze header can only encode the zooms in an affine transform - not shears, rotations, translations.

The attributes and methods of the object guarantee that the set values will be consistent and valid with the header standard, in some sense. The object API therefore gives “safe” access to the header. You can reach all the named fields in the header directly with the header_data attribute. If you futz with these, the object makes no guarantee that the data in the header are consistent.

Headers do not have filenames, they refer only the block of data in the header. The containing object manages the filenames, and therefore must know how to predict image filenames from header filenames, whether these are different, and so on.

You can access and set fields of a particular header type using standard __getitem__ / __setitem__ syntax:

hdr[‘field’] = 10

Headers also implement general mappingness:

hdr.keys() hdr.items() hdr.values()

Basic attributes of the header object are:

.endianness (read only)
.binaryblock (read only)
.structarr (read only)

Class attributes are:

.default_x_flip

with methods:

.get/set_data_shape
.get/set_data_dtype
.get/set_zooms
.get_base_affine()
.get_best_affine()
.check_fix()
.as_byteswapped(endianness)
.write_to(fileobj)
.__str__
.__eq__
.__ne__

and class methods:

.diagnose_binaryblock(string)
.from_fileobj(fileobj)

More sophisticated headers can add more methods and attributes.

Header checking

We have a file, and we would like feedback as to whether there are any problems with this header, and whether they are fixable:

hdr = AnalyzeHeader.from_fileobj(fileobj, check=False)
AnalyzeHeader.diagnose_binaryblock(hdr.binaryblock)

This will run all known checks, with no fixes, outputing to stdout

In creating a header object, we might want to check the header data. If it passes the error threshold, it goes through:

hdr = AnalyzeHeader.from_fileobj(good_fileobj)

whereas:

hdr = AnalyzeHeader.from_fileobj(bad_fileobj)

would raise some error, with output to logging (see below).

We set the error level (the level of problem that the check=True versions will accept as OK) from global defaults:

nifti.imageglobals.error_level = 30

The same for logging:

nifti.logger = logger

Classes

AnalyzeHeader

class nipy.io.imageformats.analyze.AnalyzeHeader(binaryblock=None, endianness=None, check=True)

Bases: object

Class for basic analyze header

Implements zoom-only setting of affine transform, and no image scaling

Methods

as_byteswapped
check_fix
copy Generic (shallow and deep) copying operations.
diagnose_binaryblock
for_file_pair
from_fileobj
from_mapping
get_base_affine
get_best_affine
get_data_dtype
get_data_offset
get_data_shape
get_datatype
get_slope_inter
get_zooms
items
keys
set_data_dtype
set_data_shape
set_slope_inter
set_zooms
values
write_to
__init__(binaryblock=None, endianness=None, check=True)

Initialize header from binary data block

Parameters :

binaryblock : {None, string} optional

binary block to set into header. By default, None, in which case we insert the default empty header block

endianness : {None, ‘<’,’>’, other endian code} string, optional

endianness of the binaryblock. If None, guess endianness from the data.

check : bool, optional

Whether to check content of header in initialization. Default is True.

Examples

>>> hdr1 = AnalyzeHeader() # an empty header
>>> hdr1.endianness == native_code
True
>>> hdr1.get_data_shape()
(0,)
>>> hdr1.set_data_shape((1,2,3)) # now with some content
>>> hdr1.get_data_shape()
(1, 2, 3)

We can set the binary block directly via this initialization. Here we get it from the header we have just made

>>> binblock2 = hdr1.binaryblock
>>> hdr2 = AnalyzeHeader(binblock2)
>>> hdr2.get_data_shape()
(1, 2, 3)

Empty headers are native endian by default

>>> hdr2.endianness == native_code
True

You can pass valid opposite endian headers with the endianness parameter. Even empty headers can have endianness

>>> hdr3 = AnalyzeHeader(endianness=swapped_code)
>>> hdr3.endianness == swapped_code
True

If you do not pass an endianness, and you pass some data, we will try to guess from the passed data.

>>> binblock3 = hdr3.binaryblock
>>> hdr4 = AnalyzeHeader(binblock3)
>>> hdr4.endianness == swapped_code
True
as_byteswapped(endianness=None)

return new byteswapped header object with given endianness

Guaranteed to make a copy even if endianness is the same as the current endianness.

Parameters :

endianness : None or string, optional

endian code to which to swap. None means swap from current endianness, and is the default

Returns :

hdr : header object

hdr object with given endianness

Examples

>>> hdr = AnalyzeHeader()
>>> hdr.endianness == native_code
True
>>> bs_hdr = hdr.as_byteswapped()
>>> bs_hdr.endianness == swapped_code
True
>>> bs_hdr = hdr.as_byteswapped(swapped_code)
>>> bs_hdr.endianness == swapped_code
True
>>> bs_hdr is hdr
False
>>> bs_hdr == hdr
True

If you write to the resulting byteswapped data, it does not change the original.

>>> bs_hdr['dim'][1] = 2
>>> bs_hdr == hdr
False

If you swap to the same endianness, it returns a copy

>>> nbs_hdr = hdr.as_byteswapped(native_code)
>>> nbs_hdr.endianness == native_code
True
>>> nbs_hdr is hdr
False
binaryblock

binary block of data as string

Returns :

binaryblock : string

string giving binary data block

Examples

>>> # Make default empty header
>>> hdr = AnalyzeHeader()
>>> len(hdr.binaryblock)
348
check_fix(logger=<logging.Logger object at 0x950fcac>, error_level=40)

Check header data with checks

copy()

Return copy of header

>>> hdr = AnalyzeHeader()
>>> hdr['dim'][0]
0
>>> hdr['dim'][0] = 2
>>> hdr2 = hdr.copy()
>>> hdr2 is hdr
False
>>> hdr['dim'][0] = 3
>>> hdr2['dim'][0]
2
classmethod diagnose_binaryblock(klass, binaryblock, endianness=None)

Run checks over header binary data, return string

endianness

endian code of binary data

The endianness code gives the current byte order interpretation of the binary data.

Notes

Endianness gives endian interpretation of binary data. It is read only because the only common use case is to set the endianness on initialization, or occasionally byteswapping the data - but this is done via the as_byteswapped method

Examples

>>> hdr = AnalyzeHeader()
>>> code = hdr.endianness
>>> code == native_code
True
for_file_pair(is_pair=True)

Adapt header to separate or same image and header file

This is a rare and exotic case for Analyze files, common for Nifti1. For Analyze, we only need to check that, if the file is single, then the data offset is large enough to leave room for the header.

Parameters :

is_pair : bool, optional

True if adapting header to file pair state, False for single

Returns :

hdr : header

copied and possibly modified header

Examples

The header starts off as being for two files

>>> hdr = AnalyzeHeader()
>>> hdr.get_data_offset()
0

This is the same as the default behavior for this method

>>> pair_hdr = hdr.for_file_pair()
>>> pair_hdr.get_data_offset()
0

But we can switch it to be for one

>>> unpair_hdr = hdr.for_file_pair(False)
>>> unpair_hdr.get_data_offset()
352

The original header is not affected (a copy is returned)

>>> hdr.get_data_offset()
0
classmethod from_fileobj(klass, fileobj, endianness=None, check=True)

Return read header with given or guessed endiancode

Parameters :

fileobj : file-like object

Needs to implement read method

endianness : None or endian code, optional

Code specifying endianness of read data

Returns :

hdr : AnalyzeHeader object

AnalyzeHeader object initialized from data in fileobj

Examples

>>> import StringIO
>>> hdr = AnalyzeHeader()
>>> fileobj = StringIO.StringIO(hdr.binaryblock)
>>> fileobj.seek(0)
>>> hdr2 = AnalyzeHeader.from_fileobj(fileobj)
>>> hdr2.binaryblock == hdr.binaryblock
True

You can write to the resulting object data

>>> hdr2['dim'][1] = 1
classmethod from_mapping(klass, field_mapping=None, endianness=None, check=True)

Initialize header from mapping

get_base_affine()

Get affine from basic (shared) header fields

Note that we get the translations from the center of the image.

Examples

>>> hdr = AnalyzeHeader()
>>> hdr.set_data_shape((3, 5, 7))
>>> hdr.set_zooms((3, 2, 1))
>>> hdr.default_x_flip
True
>>> hdr.get_base_affine() # from center of image
array([[-3.,  0.,  0.,  3.],
       [ 0.,  2.,  0., -4.],
       [ 0.,  0.,  1., -3.],
       [ 0.,  0.,  0.,  1.]])
>>> hdr.set_data_shape((3, 5))
>>> hdr.get_base_affine()
array([[-3.,  0.,  0.,  3.],
       [ 0.,  2.,  0., -4.],
       [ 0.,  0.,  1., -0.],
       [ 0.,  0.,  0.,  1.]])
>>> hdr.set_data_shape((3, 5, 7))
>>> hdr.get_base_affine() # from center of image
array([[-3.,  0.,  0.,  3.],
       [ 0.,  2.,  0., -4.],
       [ 0.,  0.,  1., -3.],
       [ 0.,  0.,  0.,  1.]])
get_best_affine()

Get affine from basic (shared) header fields

Note that we get the translations from the center of the image.

Examples

>>> hdr = AnalyzeHeader()
>>> hdr.set_data_shape((3, 5, 7))
>>> hdr.set_zooms((3, 2, 1))
>>> hdr.default_x_flip
True
>>> hdr.get_base_affine() # from center of image
array([[-3.,  0.,  0.,  3.],
       [ 0.,  2.,  0., -4.],
       [ 0.,  0.,  1., -3.],
       [ 0.,  0.,  0.,  1.]])
>>> hdr.set_data_shape((3, 5))
>>> hdr.get_base_affine()
array([[-3.,  0.,  0.,  3.],
       [ 0.,  2.,  0., -4.],
       [ 0.,  0.,  1., -0.],
       [ 0.,  0.,  0.,  1.]])
>>> hdr.set_data_shape((3, 5, 7))
>>> hdr.get_base_affine() # from center of image
array([[-3.,  0.,  0.,  3.],
       [ 0.,  2.,  0., -4.],
       [ 0.,  0.,  1., -3.],
       [ 0.,  0.,  0.,  1.]])
get_data_dtype()

Get numpy dtype for data

For examples see set_data_dtype

get_data_offset()

Return offset into data file to read data

Examples

>>> hdr = AnalyzeHeader()
>>> hdr.get_data_offset()
0
>>> hdr['vox_offset'] = 12
>>> hdr.get_data_offset()
12
get_data_shape()

Get shape of data

Examples

>>> hdr = AnalyzeHeader()
>>> 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)
get_datatype(code_repr='label')

Return representation of datatype code

This method returns the datatype code, or a string label for the code. Usually you are more interested in the data dtype. To do that more useful thing, use get_data_dtype

Parameters :

code_repr : string

string giving output form of datatype code representation. Default is ‘label’; use ‘code’ for integer representation.

Returns :

datatype_code : string or integer

string label for datatype code or code

Examples

>>> hdr = AnalyzeHeader()
>>> hdr['datatype'] = 4 # int16
>>> hdr.get_datatype()
'int16'
get_slope_inter()

Get scalefactor and intercept

These are not implemented for basic Analyze

get_zooms()

Get zooms from header

Returns :

z : tuple

tuple of header zoom values

Examples

>>> hdr = AnalyzeHeader()
>>> hdr.get_zooms()
()
>>> hdr.set_data_shape((1,2))
>>> hdr.get_zooms()
(1.0, 1.0)
>>> hdr.set_zooms((3, 4))
>>> hdr.get_zooms()
(3.0, 4.0)
items()

Return items from header data

keys()

Return keys from header data

set_data_dtype(datatype)

Set numpy dtype for data from code or dtype or type

Examples

>>> hdr = AnalyzeHeader()
>>> hdr.set_data_dtype(np.uint8)
>>> hdr.get_data_dtype()
dtype('uint8')
>>> hdr.set_data_dtype(np.dtype(np.uint8))
>>> hdr.get_data_dtype()
dtype('uint8')
>>> hdr.set_data_dtype('implausible')
Traceback (most recent call last):
   ...
HeaderDataError: data dtype "implausible" not recognized
>>> hdr.set_data_dtype('none')
Traceback (most recent call last):
   ...
HeaderDataError: data dtype "none" known but not supported
>>> hdr.set_data_dtype(np.void)
Traceback (most recent call last):
   ...
HeaderDataError: data dtype "<type 'numpy.void'>" known but not supported
set_data_shape(shape)

Set shape of data

set_slope_inter(slope, inter)

Set raises error for Analyze header

set_zooms(zooms)

Set zooms into header fields

See docstring for get_zooms for examples

structarr

header data, with data fields

Examples

>>> hdr1 = AnalyzeHeader() # an empty header
>>> sz = hdr1.structarr['sizeof_hdr']
>>> hdr1.structarr = None
Traceback (most recent call last):
   ...
AttributeError: can't set attribute
values()

Return values from header data

write_to(fileobj)

Write header to fileobj

Write starts at fileobj current file position.

Parameters :

fileobj : file-like object

Should implement write method

Returns :

None :

Examples

>>> hdr = AnalyzeHeader()
>>> import StringIO
>>> str_io = StringIO.StringIO()
>>> hdr.write_to(str_io)
>>> hdr.binaryblock == str_io.getvalue()
True

AnalyzeImage

class nipy.io.imageformats.analyze.AnalyzeImage(data, affine, header=None, extra=None)

Bases: nipy.io.imageformats.spatialimages.SpatialImage

__init__(data, affine, header=None, extra=None)
static filespec_to_files(filespec)
classmethod from_filename(klass, filename)
classmethod from_files(klass, files)
classmethod from_filespec(klass, img, filespec)
classmethod from_image(klass, img)

Create new instance of own class from img

This is a class method

Parameters :

img : spatialimage instance

In fact, an object with the API of spatialimage - specifically get_data, get_affine, get_header and extra.

Returns :

cimg : spatialimage instance

Image, of our own class

get_affine()
get_data()

Lazy load of data

get_data_dtype()
get_header()

Return header

Update header to match data, affine etc in object

get_shape()
get_unscaled_data()

Return image data without image scaling applied

Summary: please use the get_data method instead of this method unless you are sure what you are doing, and that you will only be using image formats for which this method exists and returns sensible results.

Use this method with care; the modified Analyze-type formats such as SPM formats, and nifti1, specify that the image data array, as they are expecting to return it, is given by the raw data on disk, multiplied by a scalefactor and maybe with the addition of a constant. This method returns the data on the disk, without these format-specific scalings applied. Please use this method only if you absolutely need the unscaled data, and the magnitude of the data, as given by the scalefactor, is not relevant to your application. The Analyze-type formats have a single scalefactor +/- offset per image on disk. If you do not care about the absolute values, and will be removing the mean from the data, then the unscaled values will have preserved intensity ratios compared to the mean-centered scaled data. However, this is not necessarily true of other formats with more complicated scaling - such as MINC.

Note that - unlike the scaled get_data method, we do not cache the array, to minimize the memory taken by the object.

classmethod instance_to_filename(klass, img, filename)

Save img in our own format, to name implied by filename

This is a class method

Parameters :

img : spatialimage instance

In fact, an object with the API of spatialimage - specifically get_data, get_affine, get_header and extra.

filename : str

Filename, implying name to which to save image.

classmethod load(klass, filename)
classmethod save(klass, img, filename)
set_data_dtype(dtype)
to_filename(filename)

Write image to files implied by filename string

Returns :None :
to_files(files=None)

Write image to files passed, or self._files

to_filespec(filename)