#diffusion-mri #trackvis #trk


TrackVis (*.trk) reader and writer

47 releases (14 breaking)

new 0.15.1 Nov 14, 2019
0.14.0 Oct 21, 2019
0.13.0 Jul 17, 2019
0.12.0 Feb 25, 2019
0.3.5 Dec 27, 2017

#94 in Data structures

Download history 73/week @ 2019-08-01 63/week @ 2019-08-08 67/week @ 2019-08-15 28/week @ 2019-08-22 120/week @ 2019-08-29 155/week @ 2019-09-05 87/week @ 2019-09-12 499/week @ 2019-09-19 139/week @ 2019-09-26 126/week @ 2019-10-03 18/week @ 2019-10-10 238/week @ 2019-10-17 94/week @ 2019-10-24 157/week @ 2019-10-31 19/week @ 2019-11-07

576 downloads per month



trk-io   Latest Version Build Status dependency status

trk-io implements a TrackVis (.trk) reader and writer.


  • Can read and write TrackVis files. Handles affine transformation as nibabel.streamlines and MI-Brain would.
  • Reading and writing is tested as much as in nibabel.streamlines.
  • Can optionally use the nifti-rs crate, which can then be used to create a trk header from a NiftiHeader, like you would do in nibabel
  • Reader can read all streamlines at once or can be used as a generator.
  • Scalars and properties are supported when reading and writing trk. You can find some examples in trk_color.rs.
  • Write all at once or streamline per streamline.
  • Follows nibabel.streamlines architecture (all 3D points are in a single Vec![Point3D]). Currently, this is only useful for performance, but it may lead to easier changes when and if we support BLAS.
  • Handles endianness.
  • Some useful tools are coded in examples/*.rs. It's a good way to learn how to use this library.


// Read complete streamlines to memory
let tractogram = Reader::new("bundle.trk").unwrap().read_all();
for streamline in &tractogram.streamlines {
    println!("Nb points: {}", streamline.len());
    for point in streamline {
        println!("{}", point);
// Simple read/write. Using a generator, so it will load only
// one streamline in memory.
let reader = Reader::new("full_brain.trk").unwrap();
let mut writer = Writer::new(
    "copy.trk", Some(reader.header.clone()));
for tractogram_item in reader.into_iter() {
    // tractogram_item is a TractogramItem, which is a tuple of
    // (streamline, scalars, properties).
// The new file will be completed only at the end of the scope. The
// 'n_count' field is written in the destructor because we don't
// know how many streamlines the user will write.


There's still a lot of work to do but it should work perfectly for simple use cases. In particular, future versions should be able to:

  • Support TCK reading/writing
  • Create some binary tools using this lib, e.g. show_affine, count_tracks, pruning, strip_info, etc.
  • Support for ops.Range, e.g. streamlines[0..10]

Your help is much appreciated. Consider filing an issue in case something is missing for your use case to work. Pull requests are also welcome.


~65K SLoC