hrv_algos/preprocessing/
noise.rs1use rand::distributions::{Distribution, Uniform};
4
5pub trait ApplyDithering: Iterator<Item = f64> {
28 fn apply_dithering(self, quantization: Option<f64>) -> DitheringIter<Self>
29 where
30 Self: Sized;
31}
32
33impl<I> ApplyDithering for I
34where
35 I: Iterator<Item = f64>,
36{
37 fn apply_dithering(self, quantization: Option<f64>) -> DitheringIter<Self> {
38 let limit = quantization.unwrap_or(1.0) / 2.0;
39 DitheringIter {
40 iter: self,
41 dist: Uniform::new(-limit, limit),
42 }
43 }
44}
45
46pub struct DitheringIter<I: Iterator<Item = f64>> {
48 iter: I,
49 dist: Uniform<f64>,
50}
51
52impl<I: Iterator<Item = f64>> Iterator for DitheringIter<I> {
53 type Item = f64;
54
55 fn next(&mut self) -> Option<Self::Item> {
56 self.iter.next().map(|value| {
57 let mut rng = rand::thread_rng();
59 let u1 = self.dist.sample(&mut rng);
60 let u2 = self.dist.sample(&mut rng);
61 value + (u1 + u2) / 2.0
62 })
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69
70 #[test]
71 fn test_dithering_iter() {
72 let data = vec![1.0, 2.0, 3.0];
73 let gt = data.clone();
74 let dithered: Vec<f64> = data.into_iter().apply_dithering(Some(0.1)).collect();
75 assert_eq!(dithered.len(), 3);
76 for (orig, dith) in gt.iter().zip(dithered.iter()) {
78 assert!((orig - dith).abs() <= 0.05);
79 }
80 }
81 #[test]
82 fn test_dithering_iter_default() {
83 let data = vec![1.0, 2.0, 3.0];
84 let gt = data.clone();
85 let dithered: Vec<f64> = data.into_iter().apply_dithering(None).collect();
86 assert_eq!(dithered.len(), 3);
87 for (orig, dith) in gt.iter().zip(dithered.iter()) {
89 assert!((orig - dith).abs() <= 0.5);
90 }
91 }
92}