trackvis
¶
Read and write trackvis files (old interface)
See nibabel.streamlines
for the new interface.
We will deprecate this, the old interface, in some future release.
Error in trackvis data |
|
Error in trackvis header |
|
|
Convenience class to encapsulate trackvis file information |
Error from TrackvisFile class |
|
|
Return voxel to mm affine from trackvis header |
|
Set affine affine into trackvis header trk_hdr |
|
Empty trackvis header |
|
Read trackvis file from fileobj, return streamlines, header |
|
Write header and streamlines to trackvis file fileobj |
TrackvisFile
¶
-
class
nibabel.trackvis.
TrackvisFile
(**kwargs)¶ Bases:
object
Convenience class to encapsulate trackvis file information
- Parameters
- streamlinessequence
sequence of streamlines. This object does not accept generic iterables as input because these can be consumed and make the object unusable. Please use the function interface to work with generators / iterables
- mappingNone or mapping
Mapping defining header attributes
- endianness{None, ‘<’, ‘>’}
Set here explicit endianness if required. Endianness otherwise inferred from streamlines
- filenameNone or str, optional
filename
- points_space{None, ‘voxel’, ‘rasmm’}, optional
Space in which streamline points are expressed in memory. Default (None) means streamlines contain points in trackvis voxmm space (voxel positions * voxel sizes). ‘voxel’ means points are in voxel space (and need to be multiplied by voxel size for saving in file). ‘rasmm’ mean the points are expressed in mm space according to the affine. See
read
andwrite
function docstrings for more detail.- affineNone or (4,4) ndarray, optional
Affine expressing relationship of voxels in an image to mm in RAS mm space. If ‘points_space’ is not None, you can use this to give the relationship between voxels, rasmm and voxmm space (above).
TrackvisFile is deprecated; please use nibabel.streamlines.TrkFile, instead.
deprecated from version: 2.5.0
Will raise <class ‘nibabel.deprecator.ExpiredDeprecationError’> as of version: 4.0.0
-
__init__
(streamlines, mapping=None, endianness=None, filename=None, points_space=None, affine=None)¶ TrackvisFile is deprecated; please use nibabel.streamlines.TrkFile, instead.
deprecated from version: 2.5.0
Will raise <class ‘nibabel.deprecator.ExpiredDeprecationError’> as of version: 4.0.0
-
classmethod
from_file
(file_like, points_space=None)¶
-
get_affine
(atleast_v2=True)¶ Get affine from header in object
- Returns
- aff(4,4) ndarray
affine from header
- atleast_v2None or bool, optional
See
aff_from_hdr
docstring for detail. If True, require valid affine invox_to_ras
field of header.
Notes
This method currently works for trackvis version 1 headers, but we consider it unsafe for version 1 headers, and in future versions of nibabel we will raise an error for trackvis headers < version 2.
-
set_affine
(affine, pos_vox=True, set_order=True)¶ Set affine affine into trackvis header
Affine is mapping from voxel space to Nifti RAS) output coordinate system convention; x: Left -> Right, y: Posterior -> Anterior, z: Inferior -> Superior. Sets affine if possible, and voxel sizes, and voxel axis ordering.
- Parameters
- affine(4,4) array-like
Affine voxel to mm transformation
- pos_vosNone or bool, optional
If None, currently defaults to False - this will change in future versions of nibabel. If False, allow negative voxel sizes in header to record axis flips. Negative voxels cause problems for trackvis (the application). If True, enforce positive voxel sizes.
- set_orderNone or bool, optional
If None, currently defaults to False - this will change in future versions of nibabel. If False, do not set
voxel_order
field in trk_hdr. If True, calculcatevoxel_order
from affine and set into trk_hdr.
- Returns
- None
-
to_file
(file_like)¶
aff_from_hdr¶
-
nibabel.trackvis.
aff_from_hdr
(trk_hdr, atleast_v2=True)¶ Return voxel to mm affine from trackvis header
aff_from_hdr is deprecated; please use nibabel.streamlines.trk.get_affine_trackvis_to_rasmm, instead.
deprecated from version: 2.5.0
Will raise <class ‘nibabel.deprecator.ExpiredDeprecationError’> as of version: 4.0.0
Affine is mapping from voxel space to Nifti (RAS) output coordinate system convention; x: Left -> Right, y: Posterior -> Anterior, z: Inferior -> Superior.
- Parameters
- trk_hdrmapping
Mapping with trackvis header keys
version
. Ifversion == 2
, we also expectvox_to_ras
.- atleast_v2None or bool
If None, currently defaults to False. This will change to True in future versions. If True, require that there is a valid ‘vox_to_ras’ affine, raise HeaderError otherwise. If False, look for valid ‘vox_to_ras’ affine, but fall back to best guess from version 1 fields otherwise.
- Returns
- aff(4,4) array
affine giving mapping from voxel coordinates (affine applied on the left to points on the right) to millimeter coordinates in the RAS coordinate system
Notes
Our initial idea was to try and work round the deficiencies of the version 1 format by using the DICOM orientation fields to store the affine. This proved difficult in practice because trackvis (the application) doesn’t allow negative voxel sizes (needed for recording axis flips) and sets the origin field to 0. In future, we’ll raise an error rather than try and estimate the affine from version 1 fields
aff_to_hdr¶
-
nibabel.trackvis.
aff_to_hdr
(affine, trk_hdr, pos_vox=True, set_order=True)¶ Set affine affine into trackvis header trk_hdr
aff_to_hdr is deprecated; please use the nibabel.streamlines.TrkFile.affine_to_rasmm property, instead.
deprecated from version: 2.5.0
Will raise <class ‘nibabel.deprecator.ExpiredDeprecationError’> as of version: 4.0.0
Affine is mapping from voxel space to Nifti RAS) output coordinate system convention; x: Left -> Right, y: Posterior -> Anterior, z: Inferior -> Superior. Sets affine if possible, and voxel sizes, and voxel axis ordering.
- Parameters
- affine(4,4) array-like
Affine voxel to mm transformation
- trk_hdrmapping
Mapping implementing __setitem__
- pos_vosNone or bool
If None, currently defaults to False - this will change in future versions of nibabel. If False, allow negative voxel sizes in header to record axis flips. Negative voxels cause problems for trackvis (the application). If True, enforce positive voxel sizes.
- set_orderNone or bool
If None, currently defaults to False - this will change in future versions of nibabel. If False, do not set
voxel_order
field in trk_hdr. If True, calculcatevoxel_order
from affine and set into trk_hdr.
- Returns
- None
Notes
version 2 of the trackvis header has a dedicated field for the nifti RAS affine. In theory trackvis 1 has enough information to store an affine, with the fields ‘origin’, ‘voxel_size’ and ‘image_orientation_patient’. Unfortunately, to be able to store any affine, we’d need to be able to set negative voxel sizes, to encode axis flips. This is because ‘image_orientation_patient’ is only two columns of the 3x3 rotation matrix, and we need to know the number of flips to reconstruct the third column reliably. It turns out that negative flips upset trackvis (the application). The application also ignores the origin field, and may not use the ‘image_orientation_patient’ field.
empty_header¶
-
nibabel.trackvis.
empty_header
(endianness=None, version=2)¶ Empty trackvis header
empty_header is deprecated; please use nibabel.streamlines.TrkFile.create_empty_header, instead.
deprecated from version: 2.5.0
Will raise <class ‘nibabel.deprecator.ExpiredDeprecationError’> as of version: 4.0.0
- Parameters
- endianness{‘<’,’>’}, optional
Endianness of empty header to return. Default is native endian.
- versionint, optional
Header version. 1 or 2. Default is 2
- Returns
- hdrstructured array
structured array containing empty trackvis header
Notes
The trackvis header can store enough information to give an affine mapping between voxel and world space. Often this information is missing. We make no attempt to fill it with sensible defaults on the basis that, if the information is missing, it is better to be explicit.
Examples
>>> hdr = empty_header() >>> print(hdr['version']) 2 >>> hdr['id_string'].item() == b'TRACK' True >>> endian_codes[hdr['version'].dtype.byteorder] == native_code True >>> hdr = empty_header(swapped_code) >>> endian_codes[hdr['version'].dtype.byteorder] == swapped_code True >>> hdr = empty_header(version=1) >>> print(hdr['version']) 1
read¶
-
nibabel.trackvis.
read
(fileobj, as_generator=False, points_space=None, strict=True)¶ Read trackvis file from fileobj, return streamlines, header
trackvis.read is deprecated; please use nibabel.streamlines.load, instead.
deprecated from version: 2.5.0
Will raise <class ‘nibabel.deprecator.ExpiredDeprecationError’> as of version: 4.0.0
- Parameters
- fileobjstring or file-like object
If string, a filename; otherwise an open file-like object pointing to trackvis file (and ready to read from the beginning of the trackvis header data)
- as_generatorbool, optional
Whether to return tracks as sequence (False, default) or as a generator (True).
- points_space{None, ‘voxel’, ‘rasmm’}, optional
The coordinates in which you want the points in the output streamlines expressed. If None, then return the points exactly as they are stored in the trackvis file. The points will probably be in trackvis voxmm space - see Notes for
write
function. If ‘voxel’, we convert the points to voxel space simply by dividing by the recorded voxel size. If ‘rasmm’ we’ll convert the points to RAS mm space (real space). For ‘rasmm’ we check if the affine is set and matches the voxel sizes and voxel order.- strict{True, False}, optional
If True, raise error on read for badly-formed file. If False, let pass files with last track having too few points.
- Returns
- streamlinessequence or generator
Returns sequence if as_generator is False, generator if True. Value is sequence or generator of 3 element sequences with elements:
points : ndarray shape (N,3) where N is the number of points
scalars : None or ndarray shape (N, M) where M is the number of scalars per point
properties : None or ndarray shape (P,) where P is the number of properties
- hdrstructured array
structured array with trackvis header fields
Notes
The endianness of the input data can be deduced from the endianness of the returned hdr or streamlines
Points are in trackvis voxel mm. Each track has N points, each with 3 coordinates,
x, y, z
, wherex
is the floating point voxel coordinate along the first image axis, multiplied by the voxel size for that axis.
write¶
-
nibabel.trackvis.
write
(fileobj, streamlines, hdr_mapping=None, endianness=None, points_space=None)¶ Write header and streamlines to trackvis file fileobj
trackvis.write is deprecated; please use nibabel.streamlines.save, instead.
deprecated from version: 2.5.0
Will raise <class ‘nibabel.deprecator.ExpiredDeprecationError’> as of version: 4.0.0
The parameters from the streamlines override conflicting parameters in the hdr_mapping information. In particular, the number of streamlines, the number of scalars, and the number of properties are written according to streamlines rather than hdr_mapping.
- Parameters
- fileobjfilename or file-like
If filename, open file as ‘wb’, otherwise fileobj should be an open file-like object, with a
write
method.- streamlinesiterable
iterable returning 3 element sequences with elements:
points : ndarray shape (N,3) where N is the number of points
scalars : None or ndarray shape (N, M) where M is the number of scalars per point
properties : None or ndarray shape (P,) where P is the number of properties
If streamlines has a
len
(for example, it is a list or a tuple), then we can write the number of streamlines into the header. Otherwise we write 0 for the number of streamlines (a valid trackvis header) and write streamlines into the file until the iterable is exhausted. M - the number of scalars - has to be the same for each streamline in streamlines. Similarly for P. See points_space and Notes for more detail on the coordinate system forpoints
above.- hdr_mappingNone, ndarray or mapping, optional
Information for filling header fields. Can be something dict-like (implementing
items
) or a structured numpy array- endianness{None, ‘<’, ‘>’}, optional
Endianness of file to be written. ‘<’ is little-endian, ‘>’ is big-endian. None (the default) is to use the endianness of the streamlines data.
- points_space{None, ‘voxel’, ‘rasmm’}, optional
The coordinates in which the points in the input streamlines are expressed. If None, then assume the points are as you want them (probably trackvis voxmm space - see Notes). If ‘voxel’, the points are in voxel space, and we will transform them to trackvis voxmm space. If ‘rasmm’ the points are in RAS mm space (real space). We transform them to trackvis voxmm space. If ‘voxel’ or ‘rasmm’ we insist that the voxel sizes and ordering are set to non-default values. If ‘rasmm’ we also check if the affine is set and matches the voxel sizes
- Returns
- None
Notes
Trackvis (the application) expects the
points
in the streamlines be in what we call trackvis voxmm coordinates. If we have a point (x, y, z) in voxmm coordinates, andvoxel_size
has the voxel sizes for each of the 3 dimensions, then x, y, z refer to mm in voxel space. Thus if i, j, k is a point in voxel coordinates, thenx = i * voxel_size[0]; y = j * voxel_size[1]; z = k * voxel_size[2]
. The spatial direction of x, y and z are defined with the “voxel_order” field. For example, if the original image had RAS voxel ordering then “voxel_order” would be “RAS”. RAS here refers to the spatial direction of the voxel axes: “R” means that moving along first voxel axis moves from left to right in space, “A” -> second axis goes from posterior to anterior, “S” -> inferior to superior. If “voxel_order” is empty we assume “LPS”.This information comes from some helpful replies on the trackvis forum about interpreting point coordiantes
Examples
>>> from io import BytesIO >>> file_obj = BytesIO() >>> pts0 = np.random.uniform(size=(10,3)) >>> pts1 = np.random.uniform(size=(10,3)) >>> streamlines = ([(pts0, None, None), (pts1, None, None)]) >>> write(file_obj, streamlines) >>> _ = file_obj.seek(0) # returns 0 >>> streams, hdr = read(file_obj) >>> len(streams) 2
If there are too many streamlines to fit in memory, you can pass an iterable thing instead of a list
>>> file_obj = BytesIO() >>> def gen(): ... yield (pts0, None, None) ... yield (pts0, None, None) >>> write(file_obj, gen()) >>> _ = file_obj.seek(0) >>> streams, hdr = read(file_obj) >>> len(streams) 2