snr/snr.rs
1use indicatif::ProgressIterator;
2use muscat::processors::Snr;
3use muscat::quicklog::{BatchIter, Log};
4use muscat::util::{progress_bar, save_array};
5use rayon::prelude::{ParallelBridge, ParallelIterator};
6
7fn main() {
8 // Open log file
9 // This uses logs from the python quicklog library.
10 let log = Log::<i16>::new("log").unwrap();
11 let leakage_size = log.leakage_size();
12 let trace_count = log.len();
13
14 let result: Snr = log
15 .into_iter()
16 .progress_with(progress_bar(trace_count))
17 // Process records sharing same leakage numpy files by batches, so batch files get read only
18 // once.
19 // Log entries may have lots of information. The closure argument here extracts the data
20 // required for the analysis, in this case the first byte of an hexadecimal string in the
21 // "data" column of the record.
22 .batches(|record| record.bytes("data")[0])
23 // Use `par_bridge` from rayon crate to make processing multithreaded
24 .par_bridge()
25 .fold(
26 || Snr::new(leakage_size, 256),
27 |mut snr, batch| {
28 for trace in batch {
29 // `process` takes an `ArrayView1` argument, which makes possible to pass a
30 // trace slice: `traces.leakage.slice(s![100..])` for instance.
31 snr.process(&trace.leakage.view(), trace.value as usize)
32 }
33 snr
34 },
35 )
36 // Merge the results of each processing thread
37 .reduce(|| Snr::new(leakage_size, 256), |a, b| a + b);
38
39 // Save the resulting SNR trace to a numpy file
40 save_array("result.npy", &result.snr()).unwrap();
41}