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