1use bids_core::metadata::BidsMetadata;
8use serde::{Deserialize, Serialize};
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
14#[serde(rename_all = "PascalCase")]
15pub struct EegMetadata {
16 #[serde(default)]
18 pub task_name: Option<String>,
19 #[serde(default)]
21 pub task_description: Option<String>,
22 pub sampling_frequency: f64,
24 #[serde(rename = "EEGChannelCount", default)]
26 pub eeg_channel_count: Option<u32>,
27 #[serde(rename = "EOGChannelCount", default)]
29 pub eog_channel_count: Option<u32>,
30 #[serde(rename = "ECGChannelCount", default)]
32 pub ecg_channel_count: Option<u32>,
33 #[serde(rename = "EMGChannelCount", default)]
35 pub emg_channel_count: Option<u32>,
36 #[serde(default)]
38 pub misc_channel_count: Option<u32>,
39 #[serde(default)]
41 pub trigger_channel_count: Option<u32>,
42 #[serde(rename = "EEGPlacementScheme", default)]
44 pub eeg_placement_scheme: Option<String>,
45 #[serde(rename = "EEGReference", default)]
47 pub eeg_reference: Option<String>,
48 #[serde(rename = "EEGGround", default)]
50 pub eeg_ground: Option<String>,
51 #[serde(default)]
53 pub recording_duration: Option<f64>,
54 #[serde(default)]
56 pub recording_type: Option<String>,
57 #[serde(default)]
59 pub power_line_frequency: Option<f64>,
60 #[serde(default)]
62 pub software_filters: Option<serde_json::Value>,
63 #[serde(default)]
65 pub hardware_filters: Option<serde_json::Value>,
66 #[serde(default)]
68 pub manufacturer: Option<String>,
69 #[serde(default)]
71 pub manufacturers_model_name: Option<String>,
72 #[serde(default)]
74 pub cap_manufacturer: Option<String>,
75 #[serde(default)]
77 pub cap_manufacturers_model_name: Option<String>,
78 #[serde(default)]
80 pub institution_name: Option<String>,
81 #[serde(default)]
83 pub institutional_department_name: Option<String>,
84 #[serde(default)]
86 pub institution_address: Option<String>,
87 #[serde(default)]
89 pub subject_artifact_description: Option<String>,
90}
91
92impl EegMetadata {
93 pub fn from_metadata(md: &BidsMetadata) -> Option<Self> {
95 md.deserialize_as()
96 }
97
98 pub fn total_channel_count(&self) -> u32 {
100 self.eeg_channel_count.unwrap_or(0)
101 + self.eog_channel_count.unwrap_or(0)
102 + self.ecg_channel_count.unwrap_or(0)
103 + self.emg_channel_count.unwrap_or(0)
104 + self.misc_channel_count.unwrap_or(0)
105 + self.trigger_channel_count.unwrap_or(0)
106 }
107}
108
109#[cfg(test)]
110mod tests {
111 use super::*;
112
113 #[test]
114 fn test_eeg_metadata_parse() {
115 let json = r#"{
116 "TaskName": "rest",
117 "SamplingFrequency": 256,
118 "EEGChannelCount": 64,
119 "EOGChannelCount": 2,
120 "ECGChannelCount": 1,
121 "EMGChannelCount": 0,
122 "EEGPlacementScheme": "10-20",
123 "EEGReference": "Cz",
124 "RecordingDuration": 300.0,
125 "RecordingType": "continuous",
126 "PowerLineFrequency": 50
127 }"#;
128
129 let md: EegMetadata = serde_json::from_str(json).unwrap();
130 assert_eq!(md.sampling_frequency, 256.0);
131 assert_eq!(md.eeg_channel_count, Some(64));
132 assert_eq!(md.eeg_reference.as_deref(), Some("Cz"));
133 assert_eq!(md.total_channel_count(), 67);
134 }
135}