edf_reader/
model.rs

1//! Metadata structures of an EDF file
2
3use crate::parser::Parser;
4use chrono::prelude::*;
5use chrono::Utc;
6
7pub const EDF_HEADER_BYTE_SIZE: usize = 256;
8
9#[derive(Serialize, Deserialize, Debug,Clone,PartialEq)]
10pub struct EDFChannel {
11    pub label: String,                         // 16 ascii
12    pub transducter_type: String,              // 80 ascii
13    pub physical_dimension: String,            // 8 ascii
14    pub physical_minimum: f32,                 // 8 ascii
15    pub physical_maximum: f32,                 // 8 ascii
16    pub digital_minimum: i64,                  // 8 ascii
17    pub digital_maximum: i64,                  // 8 ascii
18    pub prefiltering: String,                  // 80 ascii
19    pub number_of_samples_in_data_record: u64, // 8 ascii
20    pub scale_factor: f32,
21}
22
23/**
24 * EDFHeader :
25 *  - 256 bytes of common metadata
26 *  - NumberOfChannels * channel metadata = N * 256 bytes
27 */
28#[derive(Serialize, Deserialize, Debug,Clone,PartialEq)]
29pub struct EDFHeader {
30    pub file_version: String,
31    pub local_patient_identification: String,
32    pub local_recording_identification: String,
33    pub start_date: String,
34    pub start_time: String,
35    pub record_start_time_in_ms: i64,
36    pub byte_size_header: u64,
37    pub number_of_blocks: u64,
38    pub block_duration: u64,
39    pub number_of_signals: u64,
40
41    pub channels: Vec<EDFChannel>,
42}
43
44impl EDFHeader {
45    pub fn build_general_header(data: Vec<u8>) -> EDFHeader {
46        let mut parser: Parser = Parser::new(data);
47
48        let mut edf_header = EDFHeader {
49            file_version: parser.parse_string(8),
50            local_patient_identification: parser.parse_string(80),
51            local_recording_identification: parser.parse_string(80),
52            start_date: parser.parse_string(8),
53            start_time: parser.parse_string(8),
54            record_start_time_in_ms: 0,
55            byte_size_header: parser.parse_number::<u64>(8),
56            number_of_blocks: parser.move_offset(44).parse_number::<u64>(8),
57            block_duration: parser.parse_number::<u64>(8) * 1000, // to get in mS
58            number_of_signals: parser.parse_number::<u64>(4),
59            channels: Vec::new(),
60        };
61
62        // TODO : create record_start_time
63        edf_header.create_start_time();
64
65        return edf_header;
66    }
67
68    pub fn build_channel_headers(&mut self, data: Vec<u8>) {
69        // check if given data has the good size
70
71        let mut parser = Parser::new(data);
72
73        let label_list = parser.parse_string_list(self.number_of_signals, 16);
74        let transductor_type_list = parser.parse_string_list(self.number_of_signals, 80);
75        let physical_dimension_list = parser.parse_string_list(self.number_of_signals, 8);
76        let physical_minimum_list = parser.parse_number_list::<f32>(self.number_of_signals, 8);
77        let physical_maximum_list = parser.parse_number_list::<f32>(self.number_of_signals, 8);
78        let digital_minimum_list = parser.parse_number_list::<isize>(self.number_of_signals, 8);
79        let digital_maximum_list = parser.parse_number_list::<isize>(self.number_of_signals, 8);
80        let prefiltering_list = parser.parse_string_list(self.number_of_signals, 80);
81        let number_of_samples_in_data_record_list =
82            parser.parse_number_list::<u64>(self.number_of_signals, 8);
83
84        self.channels = (0..self.number_of_signals as usize)
85            .map(|v| EDFChannel {
86                label: label_list[v].clone(),
87                transducter_type: transductor_type_list[v].clone(),
88                physical_dimension: physical_dimension_list[v].clone(),
89                physical_minimum: physical_minimum_list[v],
90                physical_maximum: physical_maximum_list[v],
91                digital_minimum: digital_minimum_list[v] as i64,
92                digital_maximum: digital_maximum_list[v] as i64,
93                prefiltering: prefiltering_list[v].clone(),
94                number_of_samples_in_data_record: number_of_samples_in_data_record_list[v],
95                scale_factor: (physical_maximum_list[v] - physical_minimum_list[v])
96                    / (digital_maximum_list[v] - digital_minimum_list[v]) as f32,
97            })
98            .collect();
99    }
100
101    pub fn get_size_of_data_block(&self) -> u64 {
102        self.channels
103            .iter()
104            .map(|channel| channel.number_of_samples_in_data_record * 2)
105            .sum()
106    }
107
108    fn create_start_time(&mut self) {
109        if self.start_date != "" && self.start_time != "" {
110            let get_integers = |s: &String| -> Vec<u32> {
111                s.split(".").map(|v| v.parse::<u32>().unwrap()).collect()
112            };
113
114            let splitted_date = get_integers(&self.start_date);
115            let splitted_time = get_integers(&self.start_time);
116
117            let real_year: i32 = 2000 + splitted_date[2] as i32;
118
119            let date = Utc
120                .ymd(real_year, splitted_date[1], splitted_date[0])
121                .and_hms(splitted_time[0], splitted_time[1], splitted_time[2]);
122
123            self.record_start_time_in_ms = date.timestamp_millis();
124        }
125    }
126}