trk_io/
header.rs

1use std::{fs::File, io::BufReader, path::Path};
2
3use anyhow::{Context, Result};
4use byteorder::WriteBytesExt;
5#[cfg(feature = "nifti_images")]
6use nifti::NiftiHeader;
7
8use crate::{
9    affine::get_affine_and_translation,
10    cheader::{CHeader, Endianness},
11    Affine, Affine4, Translation,
12};
13
14#[derive(Clone)]
15pub struct Header {
16    c_header: CHeader,
17    pub affine4_to_rasmm: Affine4,
18    pub affine_to_rasmm: Affine,
19    pub translation: Translation,
20    pub nb_streamlines: usize,
21
22    pub scalars_name: Vec<String>,
23    pub properties_name: Vec<String>,
24}
25
26impl Header {
27    #[cfg(feature = "nifti_images")]
28    /// Build a trk header using the affine from a Nifti header.
29    pub fn from_nifti(h: &NiftiHeader) -> Header {
30        let c_header = CHeader::from_nifti(h.dim, h.pixdim, h.srow_x, h.srow_y, h.srow_z);
31        let affine4 = c_header.get_affine_to_rasmm();
32        let (affine, translation) = get_affine_and_translation(&affine4);
33        Header {
34            c_header,
35            affine4_to_rasmm: affine4,
36            affine_to_rasmm: affine,
37            translation,
38            nb_streamlines: 0,
39            scalars_name: vec![],
40            properties_name: vec![],
41        }
42    }
43
44    /// Retrieve a trk header, along with its byte order, from a file in the file system.
45    pub fn from_trk<P: AsRef<Path>>(path: P) -> Result<Header> {
46        let f = File::open(path.as_ref())
47            .with_context(|| format!("Failed to load {:?}", path.as_ref()))?;
48        let mut reader = BufReader::new(f);
49        let (header, _) = Self::read(&mut reader)?;
50        Ok(header)
51    }
52
53    /// Retrieve a copy of the original trk header, as read on disk.
54    pub fn raw_header(&self) -> CHeader {
55        self.c_header.clone()
56    }
57
58    /// Retrieve a trk header, along with its byte order, from the given `BufReader`. It is assumed
59    /// that the `reader` is currently at the start of the trk header.
60    pub fn read(reader: &mut BufReader<File>) -> Result<(Header, Endianness)> {
61        let (c_header, endianness) = CHeader::read(reader)?;
62        let affine4 = c_header.get_affine_to_rasmm();
63        let (affine, translation) = get_affine_and_translation(&affine4);
64        let nb_streamlines = c_header.n_count as usize;
65        let scalars_name = c_header.get_scalars_name();
66        let properties_name = c_header.get_properties_name();
67
68        let header = Header {
69            c_header,
70            affine4_to_rasmm: affine4,
71            affine_to_rasmm: affine,
72            translation,
73            nb_streamlines,
74            scalars_name,
75            properties_name,
76        };
77        Ok((header, endianness))
78    }
79
80    /// Clear all scalars and properties from `self`.
81    pub fn clear_scalars_and_properties(&mut self) {
82        self.clear_scalars();
83        self.clear_properties();
84    }
85
86    /// Clear all scalars from `self`.
87    pub fn clear_scalars(&mut self) {
88        self.scalars_name.clear();
89        self.c_header.clear_scalars();
90    }
91
92    /// Clear all properties from `self`.
93    pub fn clear_properties(&mut self) {
94        self.properties_name.clear();
95        self.c_header.clear_properties();
96    }
97
98    /// Clear all scalars and properties from `self` and copy scalars and properties from `rhs`.
99    pub fn copy_scalars_and_properties(&mut self, rhs: &Self) {
100        self.copy_scalars(rhs);
101        self.copy_properties(rhs);
102    }
103
104    /// Clear all scalars from `self` and copy scalars from `rhs`.
105    pub fn copy_scalars(&mut self, rhs: &Self) {
106        self.clear_scalars();
107        for scalar in &rhs.scalars_name {
108            self.add_scalar(scalar).unwrap(); // Can't fail
109        }
110    }
111
112    /// Clear all properties from `self` and copy properties from `rhs`.
113    pub fn copy_properties(&mut self, rhs: &Self) {
114        self.clear_properties();
115        for property in &rhs.properties_name {
116            self.add_property(property).unwrap(); // Can't fail
117        }
118    }
119
120    pub fn add_scalar(&mut self, name: &str) -> Result<()> {
121        self.c_header.add_scalar(name)?;
122        self.scalars_name.push(name.to_string());
123        Ok(())
124    }
125
126    pub fn add_property(&mut self, name: &str) -> Result<()> {
127        self.c_header.add_property(name)?;
128        self.properties_name.push(name.to_string());
129        Ok(())
130    }
131
132    pub fn write<W: WriteBytesExt>(&self, writer: &mut W) -> Result<()> {
133        Ok(self.c_header.write(writer)?)
134    }
135}
136
137impl Default for Header {
138    fn default() -> Header {
139        Header {
140            c_header: CHeader::default(),
141            affine4_to_rasmm: Affine4::identity(),
142            affine_to_rasmm: Affine::identity(),
143            translation: Translation::zeros(),
144            nb_streamlines: 0,
145            scalars_name: vec![],
146            properties_name: vec![],
147        }
148    }
149}
150
151impl PartialEq for Header {
152    fn eq(&self, other: &Header) -> bool {
153        self.affine_to_rasmm == other.affine_to_rasmm
154            && self.translation == other.translation
155            && self.nb_streamlines == other.nb_streamlines
156            && self.scalars_name == other.scalars_name
157            && self.properties_name == other.properties_name
158    }
159}