-
Notifications
You must be signed in to change notification settings - Fork 260
BIAP6
Ongoing
Image axes can have meaningful labels.
For example in a typical 4D NIfTI file, as we move along the 4th dimension in the image array, we are also moving in time. For example, this would be the first volume (in time):
img = nibabel.load('my_4d.nii') data = img.get_data() vol0 = data[..., 0]
and this would be second volume in time:
vol1 = data[..., 1]
It would therefore be reasonable to label the 4th axis of this image as 'time' or 't'.
We need to know which axis is the "time" axis for many reasons, including being able to select whole image volumes to align during motion correction, and doing spatial smoothing, where we want to avoid smoothing along the time dimension.
It is common to acquire MRI images one slice at a time. In a 3D or 4D NIfTI, the 3rd axis often contains these slices. So this these would be the first and second slices of data collected by the scanner:
slice0 = vol0[:, :, 0] slice1 = vol0[:, :, 1]
In this case we might refer to the 3rd axis as the "slice" axis. We might care about knowing the "slice" axis, because we do processing specific to the slice axis, such as slice-timing correction.
For an individual 2D slice, MRI physicists distinguish between the image axis encoded during a single continual readout of the signal (frequency encoding direction) and the image axis encoded in a series of stepwise changes in the phase encode gradient (phase encoding direction). We care about the phase encoding direction because we usually correct for image distortion only along this direction.
Let us say that the first axis is the frequency encoding axis, and the second is the phase encoding axis. Now we can label all four of our axes:
- "frequency";
- "phase";
- "slice";
- "time".
In fact the NIfTI format can store this information. NIfTI specifies that the
fourth image dimension should have units in terms of time (seconds), frequency
(Hertz, radians per second) or concentraion (parts per million), where the
value difference between elements on the fourth axis is in
img.header['pixdim'][4]
, and the units of this difference are available in
img.header['xyzt_units']
. The field img.header['dim_info']
can
identify the frequency, phase and slice-encoding axes.
In the NIfTI standard, time must be the fourth dimension. Thus we can identify time, at least, by the fact that it is the fourth axis.
This also appears to be true of the MGH format. The dimensions are listed in
order width, height, depth, nframes
and "frames" is always the slowest
changing dimension in the image data buffer. Of course, in numpy, this does
not tell us which axis this must be in the returned array, but at least the
load_mgh.m
MATLAB function (see MGH format) returns the frame axis as
the last axis, as does nibabel.
The ECAT and PAR / REC formats seem to be primarily based on and stored as slices (2D arrays) which can then be concatenated to form volumes, implying a slowest-changing axis of volume.
On the other hand, the MINC format
-
gives specific names to the image data axes so we can directly find the time axis
-
expects (given the common ordering of these names in MINC files) that the time axis will be first:
In [31]: mnc2 = h5py.File('nibabel/tests/data/minc2_4d.mnc', 'r')['minc-2.0'] In [32]: mnc2['dimensions'].values() Out[32]: [<HDF5 dataset "time": shape (2,), type "<f8">, <HDF5 dataset "xspace": shape (), type "<i4">, <HDF5 dataset "yspace": shape (), type "<i4">, <HDF5 dataset "zspace": shape (), type "<i4">]
This reflects MINC's lineage as C-library, where the C convention is for the
first axis in an array is the slowest changing (arr[0]
in a 4D array would
be the first volume).
In fact, HDF5 uses C storage order for standard contiguous arrays on disk - see "7.3.2.5. C versus Fortran Dataspaces" in chapter 7 of the HDF5 user guide <http://www.hdfgroup.org/HDF5/doc/UG/UG_frame12Dataspaces.html>.
BrainVoyager STC files store data in (fastest to slowest changing) order: columns (of slice); rows (of slice); time; slice. The VTC stores the data in the (fast to slow) order: time; Anterior->Posterior; Superior->Inferior; Left->Right.