Advertisement
Ravat

Untitled

Apr 19th, 2017
263
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 5.71 KB | None | 0 0
  1. use std::iter::Sum;
  2. use num::Float;
  3.  
  4. use ndarray::prelude::*;
  5. use ndarray::{IntoDimension, Zip, Si, S, Data};
  6. use itertools::{zip, Itertools};
  7.  
  8. #[derive(Debug, Clone, Copy)]
  9. pub enum Boundary {
  10.     Nearest,
  11.     Reflect,
  12.     Wrap,
  13.     Mirror,
  14. }
  15.  
  16. fn __pad<S, D>(array: &ArrayBase<S, D>, window_size: &D, boundary: Boundary) -> Array<S::Elem, D>
  17.     where S: Data,
  18.           S::Elem: Copy,
  19.           D: Dimension
  20. {
  21.     let window_size = window_size.as_array_view();
  22.     debug_assert_eq!(window_size.len(), array.ndim());
  23.  
  24.     let mut pad_array: Array<S::Elem, D> = unsafe {
  25.         let mut size = array.raw_dim().clone();
  26.         Zip::from(size.as_array_view_mut()).and(window_size).apply(|mut s, &w| {
  27.             *s += w - 1;
  28.         });
  29.         Array::uninitialized(size)
  30.     };
  31.  
  32.     {
  33.         let mut pad_array = {
  34.             let dyn_size = pad_array.shape().to_owned();
  35.             pad_array.view_mut().into_shape(dyn_size).unwrap()
  36.         };
  37.  
  38.         let mut slice: Vec<Si> = zip(window_size, array.shape())
  39.             .map(|(window_size, size)| {
  40.                 Si((window_size / 2) as isize,
  41.                    Some((window_size / 2 + size) as isize),
  42.                    1)
  43.             })
  44.             .collect();
  45.  
  46.         pad_array.slice_mut(slice.as_slice()).assign(&array);
  47.  
  48.         for (k, (&window_size, &size)) in zip(window_size, array.shape()).enumerate() {
  49.             let bound = (window_size / 2) as isize;
  50.  
  51.             if bound == 0 {
  52.                 continue;
  53.             }
  54.  
  55.             slice[k] = S;
  56.             let centre = pad_array.slice_mut(slice.as_slice());
  57.             let (mut left, centre) = centre.split_at(Axis(k), window_size / 2);
  58.             let (centre, mut right) = centre.split_at(Axis(k), size);
  59.  
  60.             let mut assign_to_axis_slice = {
  61.                 let mut slice = vec![S; array.ndim()];
  62.  
  63.                 move |to: &mut ArrayViewMut<S::Elem, _>, s| {
  64.                     slice[k] = s;
  65.                     let from = centre.slice(slice.as_slice());
  66.                     to.assign(&from);
  67.                 }
  68.             };
  69.  
  70.             use self::Boundary::*;
  71.             match boundary {
  72.                 Nearest => {
  73.                     assign_to_axis_slice(&mut left, Si(0, Some(1), 1));
  74.                     assign_to_axis_slice(&mut right, Si(-1, None, 1));
  75.                 }
  76.                 Reflect => {
  77.                     assign_to_axis_slice(&mut left, Si(-bound - 1, Some(-1), -1));
  78.                     assign_to_axis_slice(&mut right, Si(1, Some(bound + 1), -1));
  79.                 }
  80.                 Mirror => {
  81.                     assign_to_axis_slice(&mut left, Si(-bound, None, -1));
  82.                     assign_to_axis_slice(&mut right, Si(0, Some(bound), -1));
  83.                 }
  84.                 Wrap => {
  85.                     assign_to_axis_slice(&mut left, Si(-bound, None, 1));
  86.                     assign_to_axis_slice(&mut right, Si(0, Some(bound), 1));
  87.                 }
  88.             }
  89.         }
  90.     }
  91.  
  92.     pad_array
  93. }
  94.  
  95. pub fn pad<A, D, W>(array: ArrayView<A, D>, window_size: W, boundary: Boundary) -> Array<A, D>
  96.     where A: Copy,
  97.           D: Dimension,
  98.           W: IntoDimension<Dim = D>
  99. {
  100.     __pad(&array, &window_size.into_dimension(), boundary)
  101. }
  102.  
  103. pub fn rolling_mean<A, D, W>(x: ArrayView<A, D>, w: W, b: Boundary) -> Array<A, D>
  104.     where A: Float,
  105.           D: Dimension,
  106.           W: IntoDimension<Dim = D>
  107. {
  108.     let w = w.into_dimension();
  109.  
  110.     let y = __pad(&x, &w, b);
  111.  
  112.     let mut x = x.to_owned();
  113.     Zip::from(x.view_mut())
  114.         .and(y.windows(w))
  115.         .apply(|mut x, y| *x = y.scalar_sum() / A::from(y.len()).unwrap());
  116.     x
  117. }
  118.  
  119. pub fn rel_max<A, D, W>(x: ArrayView<A, D>, w: W, b: Boundary) -> Array<bool, D>
  120.     where A: PartialOrd + Copy,
  121.           D: Dimension,
  122.           W: IntoDimension<Dim = D>
  123. {
  124.     let w = w.into_dimension();
  125.  
  126.     let y = __pad(&x, &w, b);
  127.  
  128.     let mut b = unsafe { Array::uninitialized(x.raw_dim()) };
  129.  
  130.     let mut j = w.clone();
  131.     j.as_array_view_mut().mapv_inplace(|j| j / 2);
  132.  
  133.     Zip::from(b.view_mut())
  134.         .and(y.windows(w))
  135.         .apply(|mut b, y| *b = y.iter().all(|x| *x <= y[j.clone()]));
  136.     b
  137. }
  138.  
  139. pub fn locate_nearest_peak<A, D, F, I>(b: ArrayView<bool, D>, i: &[A], f: F) -> Option<D>
  140.     where A: Float + Sum<A>,
  141.           D: Dimension,
  142.           F: Fn(&D::Pattern) -> I,
  143.           I: IntoIterator<Item = A>
  144. {
  145.     b.indexed_iter()
  146.         .filter(|&(_, &b)| b)
  147.         .map(|(j, _)| {
  148.             let d = i.iter()
  149.                 .zip(f(&j))
  150.                 .map(|(&i, j)| (i - j).powi(2))
  151.                 .sum::<A>();
  152.             (j, d)
  153.         })
  154.         .fold1(|(j0, d0), (j1, d1)| if d1 < d0 { (j1, d1) } else { (j0, d0) })
  155.         .map(|(j, _)| j.into_dimension())
  156. }
  157.  
  158. #[cfg(test)]
  159. mod test {
  160.     use super::*;
  161.  
  162.     #[test]
  163.     fn test() {
  164.         let x = array![1., 2., 3.];
  165.  
  166.         let y = pad(x.view(), 1, Boundary::Wrap);
  167.         assert_eq!(y, x);
  168.  
  169.         let y = pad(x.view(), 5, Boundary::Wrap);
  170.         assert_eq!(y, array![2., 3., 1., 2., 3., 1., 2.]);
  171.  
  172.         let y = pad(x.view(), 5, Boundary::Nearest);
  173.         assert_eq!(y, array![1., 1., 1., 2., 3., 3., 3.]);
  174.  
  175.         let y = pad(x.view(), 5, Boundary::Reflect);
  176.         assert_eq!(y, array![2., 1., 1., 2., 3., 3., 2.]);
  177.  
  178.         let y = pad(x.view(), 5, Boundary::Mirror);
  179.         assert_eq!(y, array![3., 2., 1., 2., 3., 2., 1.]);
  180.  
  181.         let x = array![[1, 2], [3, 4]];
  182.  
  183.         let y = pad(x.view(), (3, 3), Boundary::Wrap);
  184.         assert_eq!(y,
  185.                    array![[4, 3, 4, 3], [2, 1, 2, 1], [4, 3, 4, 3], [2, 1, 2, 1]]);
  186.  
  187.         let x = Array1::<usize>::zeros(10);
  188.         assert_eq!(12, pad(x.view(), 3, Boundary::Wrap).len());
  189.     }
  190. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement