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
mod section;
use std::path::PathBuf;
use crate::AbfKind;
use super::{Abf, Channel};
use super::channel::FileKind;
use crate::conversion_util as cu;
use memmap2::Mmap;
use section::section_producer::SectionProducer;
impl Abf {
pub fn from_abf_v2(memmap: Mmap, path: PathBuf) -> Self {
let abf_kind = AbfKind::AbfV2;
// let file_version_number = (4..8).map(|i| memmap[i] as i8).collect();
// let file_info_size = cu::from_byte_array_to_u32(&memmap, 8).unwrap();
let actual_episodes = cu::from_byte_array_to_u32(&memmap, 12).unwrap();
// let file_start_date = cu::from_byte_array_to_u32(&memmap, 16).unwrap();
// let file_start_time_ms = cu::from_byte_array_to_u32(&memmap, 20).unwrap();
// let stopwatch_time = cu::from_byte_array_to_u32(&memmap, 24).unwrap();
// let file_type = cu::from_byte_array_to_u16(&memmap, 28);
let data_format: u16 = cu::from_byte_array_to_u16(&memmap, 30);
// let simultaneus_scan: u16 = cu::from_byte_array_to_u16(&memmap, 32);
// let crc_enable: u16 = cu::from_byte_array_to_u16(&memmap, 34);
// let file_crc: u32 = cu::from_byte_array_to_u32(&memmap, 36).unwrap();
// let file_guid: u32= cu::from_byte_array_to_u32(&memmap, 40).unwrap();
let _unknown1 = cu::from_byte_array_to_u32(&memmap, 44).unwrap();
let _unknown2 = cu::from_byte_array_to_u32(&memmap, 48).unwrap();
let _unknown3 = cu::from_byte_array_to_u32(&memmap, 52).unwrap();
// let creator_version = cu::from_byte_array_to_u32(&memmap, 56).unwrap();
// let creator_name_index = cu::from_byte_array_to_u32(&memmap, 60).unwrap();
// let modifier_version = cu::from_byte_array_to_u32(&memmap, 64).unwrap();
// let modifier_name_index = cu::from_byte_array_to_u32(&memmap, 68).unwrap();
// let protocol_path_index = cu::from_byte_array_to_u32(&memmap, 72).unwrap();
// useful sections
let sec_prod = SectionProducer::new(&memmap);
let protocol_section = sec_prod.get_protocol_section();
let adc_section = sec_prod.get_adc_section();
let _dac_section = sec_prod.get_dac_section();
// let epoch_section = sec_prod.get_epoch_section();
// let adc_per_dac_section = sec_prod.get_adc_per_dac_section();
// let epoch_per_dac_section = sec_prod.get_epoch_per_dac_section();
let strings_section = sec_prod.get_strings_section();
let data_section = sec_prod.get_data_section();
// let tag_section = sec_prod.get_tag_section();
// TODO, create 2 possible abfs, one faster with only useful sections and one with all the possible sections
// not useful sections
// let user_list_section = sec_prod.produce_from(172);
// let stats_region_section = sec_prod.produce_from(188);
// let math_section = sec_prod.produce_from(204);
// let scope_section = sec_prod.produce_from(268);
// let delta_section = sec_prod.produce_from(284);
// let voice_tag_section = sec_prod.produce_from(300);
// let synch_array_section = sec_prod.produce_from(316);
// let annotation_section = sec_prod.produce_from(332);
// let stats_section = sec_prod.produce_from(348);
let number_of_channels = adc_section.get_channel_count();
let data = data_section.read(number_of_channels);
// let dataRate = (1e6 / _protocolSection.fADCSequenceInterval)
let adc_infos = adc_section.get_adc_infos();
// let dacs_info = dac_section.get_dacs_info();
let sampling_rate = 1e6 / protocol_section.adc_sequence_interval();
let sweep_count = actual_episodes;
let gains: Vec<f32> = (0..number_of_channels)
.map(|_| 1.0_f32)
.enumerate()
.map(|(ch, sf)| (sf, &adc_infos[ch]))
.map(|(sf, ai)| (sf / ai.instrument_scale_factor, ai))
.map(|(sf, ai)| (sf/ai.signal_gain, ai))
.map(|(sf, ai)| (sf/ai.adc_programmable_gain, ai))
.map(|(sf, ai)| if ai.telegraph_enable != 0 {sf/ai.telegraph_addit_gain} else {sf})
.map(|sf| (sf* protocol_section.adc_range()))
.map(|sf| (sf/ protocol_section.adc_resolution() as f32))
.collect();
let offsets: Vec<f32> = (0..number_of_channels)
.map(|_| 0.0_f32)
.enumerate()
.map(|(ch, sf)| (sf, &adc_infos[ch]))
.map(|(sf, ai)| (sf + ai.instrument_offset, ai))
.map(|(sf, ai)| (sf - ai.signal_offset))
.collect();
let indexed_strings = strings_section.read_indexed_strings();
let sweeps_count = match sweep_count {
0 | 1 => 1,
n => n,
};
// let file_kind = if data_format == 0 {FileKind::I16} else {FileKind::F32};
let file_kind = FileKind::I16;
Self {
abf_kind,
channels_count: number_of_channels as u32,
sweeps_count,
sampling_rate,
channels: (0..number_of_channels)
.map(|ch|{
let data = data.get(&ch).unwrap();
(
ch as u32,
Channel::new(
data.to_owned(),
indexed_strings.get(adc_infos[ch].adc_units_index).unwrap_or(&"nan".to_string()).clone(),
gains[ch],
offsets[ch],
indexed_strings.get(adc_infos[ch].adc_channel_name_index).unwrap_or(&"nan".to_string()).clone(),
sweeps_count,
file_kind,
)
)
})
.collect(),
path,
}
}
}