Header and image for the basic Mayo Analyze format
This is a binary header format and inherits from WrapStruct
Apart from the attributes and methods of WrapStruct:
Class attributes are:
.get/set_data_shape .get/set_data_dtype .get/set_zooms .get_base_affine() .get_best_affine() .data_to_fileobj .data_from_fileobj
and class methods:
More sophisticated headers can add more methods and attributes.
This - basic - analyze header cannot encode full affines (only diagonal affines), and cannot do integer scaling.
The inability to store affines means that we have to guess what orientation the image has. Most Analyze images are stored on disk in (fastest-changing to slowest-changing) R->L, P->A and I->S order. That is, the first voxel is the rightmost, most posterior and most inferior voxel location in the image, and the next voxel is one voxel towards the left of the image.
Most people refer to this disk storage format as ‘radiological’, on the basis that, if you load up the data as an array img_arr where the first axis is the fastest changing, then take a slice in the I->S axis - img_arr[:,:,10] - then the right part of the brain will be on the left of your displayed slice. Radiologists like looking at images where the left of the brain is on the right side of the image.
Conversely, if the image has the voxels stored with the left voxels first - L->R, P->A, I->S, then this would be ‘neurological’ format. Neurologists like looking at images where the left side of the brain is on the left of the image.
When we are guessing at an affine for Analyze, this translates to the problem of whether the affine should consider proceeding within the data down an X line as being from left to right, or right to left.
By default we assume that the image is stored in R->L format. We encode this choice in the default_x_flip flag that can be True or False. True means assume radiological.
If the image is 3D, and the X, Y and Z zooms are x, y, and z, then:
if default_x_flip is True:: affine = np.diag((-x,y,z,1)) else: affine = np.diag((x,y,z,1))
In our implementation, there is no way of saving this assumed flip into the header. One way of doing this, that we have not used, is to allow negative zooms, in particular, negative X zooms. We did not do this because the image can be loaded with and without a default flip, so the saved zoom will not constrain the affine.
|AnalyzeHeader([binaryblock, endianness, check])||Class for basic analyze header|
|AnalyzeImage(data, affine[, header, extra, ...])||Initialize image|