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}