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 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 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 pub fn raw_header(&self) -> CHeader {
55 self.c_header.clone()
56 }
57
58 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 pub fn clear_scalars_and_properties(&mut self) {
82 self.clear_scalars();
83 self.clear_properties();
84 }
85
86 pub fn clear_scalars(&mut self) {
88 self.scalars_name.clear();
89 self.c_header.clear_scalars();
90 }
91
92 pub fn clear_properties(&mut self) {
94 self.properties_name.clear();
95 self.c_header.clear_properties();
96 }
97
98 pub fn copy_scalars_and_properties(&mut self, rhs: &Self) {
100 self.copy_scalars(rhs);
101 self.copy_properties(rhs);
102 }
103
104 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(); }
110 }
111
112 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(); }
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}