Skip to main content

bids_eeg/
coordsystem.rs

1//! Coordinate system information from `_coordsystem.json`.
2//!
3//! Describes the coordinate system used for electrode positions, including
4//! the system name, units, and description.
5
6use serde::{Deserialize, Serialize};
7
8/// Coordinate system information from _coordsystem.json.
9///
10/// See: <https://bids-specification.readthedocs.io/en/stable/modality-specific-files/electroencephalography.html>
11#[derive(Debug, Clone, Serialize, Deserialize)]
12#[serde(rename_all = "PascalCase")]
13pub struct CoordinateSystem {
14    /// Coordinate system name (e.g., "CapTrak", "EEGLAB", "Other").
15    #[serde(rename = "EEGCoordinateSystem")]
16    pub eeg_coordinate_system: String,
17
18    /// Units of the electrode coordinates (e.g., "mm", "cm", "m").
19    #[serde(rename = "EEGCoordinateUnits")]
20    pub eeg_coordinate_units: String,
21
22    /// Description of the coordinate system if "Other" is used.
23    #[serde(rename = "EEGCoordinateSystemDescription", default)]
24    pub eeg_coordinate_system_description: Option<String>,
25
26    /// Method used to determine electrode positions.
27    #[serde(rename = "EEGCoordinateProcessingDescription", default)]
28    pub eeg_coordinate_processing_description: Option<String>,
29
30    /// Reference for the iEEG coordinate system.
31    #[serde(rename = "iEEGCoordinateSystem", default)]
32    pub ieeg_coordinate_system: Option<String>,
33
34    /// Units for iEEG coordinates.
35    #[serde(rename = "iEEGCoordinateUnits", default)]
36    pub ieeg_coordinate_units: Option<String>,
37
38    /// Description for iEEG coordinate system.
39    #[serde(rename = "iEEGCoordinateSystemDescription", default)]
40    pub ieeg_coordinate_system_description: Option<String>,
41
42    /// Processing description for iEEG coordinates.
43    #[serde(rename = "iEEGCoordinateProcessingDescription", default)]
44    pub ieeg_coordinate_processing_description: Option<String>,
45
46    /// Fiducials in the coordinate system.
47    #[serde(default)]
48    pub fiducials: Option<serde_json::Value>,
49
50    /// Anatomical landmarks.
51    #[serde(rename = "AnatomicalLandmarkCoordinates", default)]
52    pub anatomical_landmark_coordinates: Option<serde_json::Value>,
53
54    /// Coordinate system for anatomical landmarks.
55    #[serde(rename = "AnatomicalLandmarkCoordinateSystem", default)]
56    pub anatomical_landmark_coordinate_system: Option<String>,
57
58    /// Units for anatomical landmark coordinates.
59    #[serde(rename = "AnatomicalLandmarkCoordinateUnits", default)]
60    pub anatomical_landmark_coordinate_units: Option<String>,
61
62    /// Photo of the head with landmark markers.
63    #[serde(rename = "IntendedFor", default)]
64    pub intended_for: Option<serde_json::Value>,
65}
66
67impl CoordinateSystem {
68    /// Load from a JSON file.
69    pub fn from_file(path: &std::path::Path) -> bids_core::error::Result<Self> {
70        let contents = std::fs::read_to_string(path)?;
71        let cs: Self = serde_json::from_str(&contents)?;
72        Ok(cs)
73    }
74}
75
76#[cfg(test)]
77mod tests {
78    use super::*;
79
80    #[test]
81    fn test_coordsystem_parse() {
82        let json = r#"{
83            "EEGCoordinateSystem": "CapTrak",
84            "EEGCoordinateUnits": "mm",
85            "EEGCoordinateSystemDescription": "RAS orientation"
86        }"#;
87
88        let cs: CoordinateSystem = serde_json::from_str(json).unwrap();
89        assert_eq!(cs.eeg_coordinate_system, "CapTrak");
90        assert_eq!(cs.eeg_coordinate_units, "mm");
91    }
92}