1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3use std::path::Path;
4
5use crate::error::Result;
6
7#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
9pub struct Header {
10 #[serde(rename = "VOXEL_TO_RASMM")]
13 pub voxel_to_rasmm: [[f64; 4]; 4],
14
15 #[serde(rename = "DIMENSIONS")]
17 pub dimensions: [u64; 3],
18
19 #[serde(rename = "NB_STREAMLINES")]
21 pub nb_streamlines: u64,
22
23 #[serde(rename = "NB_VERTICES")]
25 pub nb_vertices: u64,
26
27 #[serde(flatten)]
29 pub extra: HashMap<String, serde_json::Value>,
30}
31
32impl Header {
33 pub fn from_file(path: &Path) -> Result<Self> {
35 let data = std::fs::read_to_string(path)?;
36 let header: Header = serde_json::from_str(&data)?;
37 Ok(header)
38 }
39
40 pub fn to_json(&self) -> Result<String> {
42 Ok(serde_json::to_string_pretty(self)?)
43 }
44
45 pub fn write_to(&self, path: &Path) -> Result<()> {
47 let json = self.to_json()?;
48 std::fs::write(path, json)?;
49 Ok(())
50 }
51
52 pub fn identity_affine() -> [[f64; 4]; 4] {
54 [
55 [1.0, 0.0, 0.0, 0.0],
56 [0.0, 1.0, 0.0, 0.0],
57 [0.0, 0.0, 1.0, 0.0],
58 [0.0, 0.0, 0.0, 1.0],
59 ]
60 }
61}
62
63#[cfg(test)]
64mod tests {
65 use super::*;
66
67 #[test]
68 fn header_serde_round_trip() {
69 let header = Header {
70 voxel_to_rasmm: Header::identity_affine(),
71 dimensions: [256, 256, 256],
72 nb_streamlines: 100,
73 nb_vertices: 5000,
74 extra: HashMap::new(),
75 };
76
77 let json = header.to_json().unwrap();
78 let parsed: Header = serde_json::from_str(&json).unwrap();
79
80 assert_eq!(parsed.nb_streamlines, 100);
81 assert_eq!(parsed.nb_vertices, 5000);
82 assert_eq!(parsed.dimensions, [256, 256, 256]);
83 assert_eq!(parsed.voxel_to_rasmm[0][0], 1.0);
84 assert_eq!(parsed.voxel_to_rasmm[3][3], 1.0);
85 }
86
87 #[test]
88 fn header_with_extra_fields() {
89 let json = r#"{
90 "VOXEL_TO_RASMM": [[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],
91 "DIMENSIONS": [100, 100, 100],
92 "NB_STREAMLINES": 42,
93 "NB_VERTICES": 420,
94 "CUSTOM_FIELD": "hello"
95 }"#;
96
97 let header: Header = serde_json::from_str(json).unwrap();
98 assert_eq!(header.nb_streamlines, 42);
99 assert_eq!(
100 header.extra.get("CUSTOM_FIELD").unwrap(),
101 &serde_json::Value::String("hello".into())
102 );
103 }
104}