edf_reader/
sync_reader.rs

1//! Read an EDF file synchronously
2
3use crate::file_reader::SyncFileReader;
4
5use crate::model::*;
6
7use std::io::Error;
8
9pub struct SyncEDFReader<T: SyncFileReader> {
10    pub edf_header: EDFHeader,
11    file_reader: T,
12}
13
14impl<T: SyncFileReader> SyncEDFReader<T> {
15    /**
16    Init an EDFReader with a custom FileReader.
17    It can be usefull if the EDF file is not located in the system file. (ie : we cannot use RandomAccessFile).
18    An example of use : read the file with DOM FileAPI in Webassembly
19    */
20    pub fn init_with_file_reader(file_reader: T) -> Result<SyncEDFReader<T>, Error> {
21        let general_header_raw = file_reader.read(0, 256)?;
22
23        let mut edf_header = EDFHeader::build_general_header(general_header_raw);
24
25        let channel_headers_raw = file_reader.read(
26            256,
27            edf_header.number_of_signals * EDF_HEADER_BYTE_SIZE as u64,
28        )?;
29
30        edf_header.build_channel_headers(channel_headers_raw);
31
32        Ok(SyncEDFReader {
33            edf_header,
34            file_reader,
35        })
36    }
37
38    pub fn read_data_window(
39        &self,
40        start_time_ms: u64, // in mS
41        duration_ms: u64,   // in mS
42    ) -> Result<Vec<Vec<f32>>, Error> {
43        super::check_bounds(start_time_ms, duration_ms, &self.edf_header)?;
44
45        // calculate the corresponding blocks to get
46
47        let first_block_start_time = start_time_ms - start_time_ms % self.edf_header.block_duration;
48
49        let first_block_index = first_block_start_time / self.edf_header.block_duration;
50
51        let number_of_blocks_to_get =
52            (duration_ms as f64 / self.edf_header.block_duration as f64).ceil() as u64;
53
54        let offset = self.edf_header.byte_size_header
55            + first_block_index * self.edf_header.get_size_of_data_block();
56
57        let mut data;
58
59        // TODO : better handle of errors
60
61        match self.file_reader.read(
62            offset,
63            number_of_blocks_to_get * self.edf_header.get_size_of_data_block(),
64        ) {
65            Ok(d) => data = d,
66            Err(e) => return Err(e),
67        }
68
69        let mut result: Vec<Vec<f32>> = Vec::new();
70
71        for _ in 0..self.edf_header.number_of_signals {
72            result.push(Vec::new());
73        }
74
75        let mut index = 0;
76
77        for _ in 0..number_of_blocks_to_get {
78            for (j, channel) in self.edf_header.channels.iter().enumerate() {
79                for _ in 0..channel.number_of_samples_in_data_record {
80                    let sample = super::get_sample(&data, index) as f32;
81                    result[j].push(
82                        (sample - channel.digital_minimum as f32) * channel.scale_factor
83                            + channel.physical_minimum,
84                    );
85                    index += 1;
86                }
87            }
88        }
89
90        Ok(result)
91    }
92}