1use std::path::Path;
2
3use nifti::{NiftiObject, ReaderOptions};
4
5use crate::any_trx_file::AnyTrxFile;
6use crate::error::{Result, TrxError};
7use crate::header::Header;
8
9pub fn header_from_reference(path: &Path) -> Result<Header> {
15 if path.is_dir() {
16 return Ok(AnyTrxFile::load(path)?.header().clone());
17 }
18
19 let file_name = path
20 .file_name()
21 .and_then(|name| name.to_str())
22 .ok_or_else(|| {
23 TrxError::Argument(format!(
24 "cannot determine reference format for {}",
25 path.display()
26 ))
27 })?;
28
29 if file_name.ends_with(".trx") {
30 return Ok(AnyTrxFile::load(path)?.header().clone());
31 }
32
33 if file_name.ends_with(".nii") || file_name.ends_with(".nii.gz") {
34 return header_from_nifti(path);
35 }
36
37 Err(TrxError::Format(format!(
38 "unsupported reference format for {}",
39 path.display()
40 )))
41}
42
43fn header_from_nifti(path: &Path) -> Result<Header> {
44 let obj = ReaderOptions::new().read_file(path).map_err(|err| {
45 TrxError::Format(format!(
46 "failed to read NIfTI reference {}: {err}",
47 path.display()
48 ))
49 })?;
50 let header = obj.header();
51 let affine = header.affine::<f64>();
52
53 Ok(Header {
54 voxel_to_rasmm: [
55 [
56 affine[(0, 0)],
57 affine[(0, 1)],
58 affine[(0, 2)],
59 affine[(0, 3)],
60 ],
61 [
62 affine[(1, 0)],
63 affine[(1, 1)],
64 affine[(1, 2)],
65 affine[(1, 3)],
66 ],
67 [
68 affine[(2, 0)],
69 affine[(2, 1)],
70 affine[(2, 2)],
71 affine[(2, 3)],
72 ],
73 [
74 affine[(3, 0)],
75 affine[(3, 1)],
76 affine[(3, 2)],
77 affine[(3, 3)],
78 ],
79 ],
80 dimensions: [
81 u64::from(header.dim[1]),
82 u64::from(header.dim[2]),
83 u64::from(header.dim[3]),
84 ],
85 nb_streamlines: 0,
86 nb_vertices: 0,
87 extra: Default::default(),
88 })
89}