Skip to main content

trx_rs/
reference.rs

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
9/// Load TRX-compatible spatial metadata from a reference file.
10///
11/// Supported reference types:
12/// - `.trx` directories or archives
13/// - `.nii` / `.nii.gz` images
14pub 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}