eventcv_core/transform/
algebra.rs1use crate::{EventStream, EventStreamBuilder};
4
5impl EventStream {
6 pub fn filter_polarity(&self, polarity: bool) -> EventStream {
8 let (width, height) = self.sensor_size();
9 self.remap(width, height, |x, y, t, p| {
10 (p == polarity).then_some((x, y, t, p))
11 })
12 }
13
14 pub fn invert_polarity(&self) -> EventStream {
16 let (width, height) = self.sensor_size();
17 self.map_columns(width, height, |out| {
18 for p in &mut out.ps {
19 *p = !*p;
20 }
21 })
22 }
23
24 pub fn sort_by_time(&self) -> EventStream {
26 let (width, height) = self.sensor_size();
27 let ts = self.ts();
28 let mut order: Vec<usize> = (0..self.len()).collect();
29 order.sort_by_key(|&index| ts[index]); let (xs, ys, ps) = (self.xs(), self.ys(), self.ps());
31 let mut builder =
32 EventStreamBuilder::with_capacity(width, height, self.timestamp_scale_ms(), self.len());
33 for index in order {
34 builder.push(xs[index], ys[index], ts[index], ps[index]);
35 }
36 builder.build()
37 }
38
39 pub fn concat(&self, others: &[&EventStream]) -> EventStream {
42 let (mut width, mut height) = self.sensor_size();
43 for other in others {
44 let (w, h) = other.sensor_size();
45 width = width.max(w);
46 height = height.max(h);
47 }
48 let total = self.len() + others.iter().map(|s| s.len()).sum::<usize>();
49 let mut builder =
50 EventStreamBuilder::with_capacity(width, height, self.timestamp_scale_ms(), total);
51 for stream in std::iter::once(self).chain(others.iter().copied()) {
52 builder.extend_from_stream(stream);
53 }
54 builder.build()
55 }
56}
57
58#[cfg(test)]
59mod tests {
60 use crate::{EventStream, EventStreamBuilder};
61
62 fn sample() -> EventStream {
63 let mut builder = EventStreamBuilder::new(4, 3, 0.001);
64 builder.push(0, 0, 30, true);
65 builder.push(1, 1, 10, false);
66 builder.push(2, 2, 20, true);
67 builder.build()
68 }
69
70 #[test]
71 fn filter_polarity_splits_and_conserves_count() {
72 let s = sample();
73 let on = s.filter_polarity(true);
74 let off = s.filter_polarity(false);
75 assert_eq!(on.len() + off.len(), s.len());
76 assert!(on.ps().iter().all(|&p| p));
77 assert!(off.ps().iter().all(|&p| !p));
78 }
79
80 #[test]
81 fn invert_polarity_is_its_own_inverse() {
82 let s = sample();
83 assert_eq!(s.invert_polarity().invert_polarity().ps(), s.ps());
84 assert_eq!(s.invert_polarity().ps(), &[false, true, false]);
85 }
86
87 #[test]
88 fn sort_by_time_orders_ascending() {
89 let sorted = sample().sort_by_time();
90 assert_eq!(sorted.ts(), &[10, 20, 30]);
91 assert_eq!(sorted.xs(), &[1, 2, 0]); }
93
94 #[test]
95 fn concat_appends_and_takes_max_sensor() {
96 let a = sample();
97 let mut b_builder = EventStreamBuilder::new(8, 6, 0.001);
98 b_builder.push(7, 5, 50, true);
99 let b = b_builder.build();
100
101 let combined = a.concat(&[&b]);
102 assert_eq!(combined.len(), 4);
103 assert_eq!(combined.sensor_size(), (8, 6)); assert_eq!(combined.ts(), &[30, 10, 20, 50]); }
106
107 #[test]
108 fn algebra_ops_handle_empty() {
109 let empty = EventStreamBuilder::new(4, 3, 0.001).build();
110 assert!(empty.filter_polarity(true).is_empty());
111 assert!(empty.sort_by_time().is_empty());
112 assert_eq!(empty.concat(&[&sample()]).len(), 3);
113 }
114}