File: medianwindow.h

package info (click to toggle)
aoflagger 3.5.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,000 kB
  • sloc: cpp: 67,891; python: 497; sh: 242; makefile: 22
file content (69 lines) | stat: -rw-r--r-- 2,023 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#ifndef MEDIANWINDOW_H
#define MEDIANWINDOW_H

#include <algorithm>
#include <limits>
#include <vector>

#include "../structures/samplerow.h"

namespace algorithms {

template <typename NumType>
class MedianWindow {
 public:
  static void SubtractMedian(SampleRow& sampleRow, unsigned windowSize) {
    if (windowSize > sampleRow.Size() * 2) windowSize = sampleRow.Size() * 2;
    SampleRow copy(sampleRow);
    MedianWindow<num_t> window;
    unsigned rightPtr, leftPtr = 0;
    for (rightPtr = 0; rightPtr < ((windowSize - 1) / 2); ++rightPtr) {
      if (!copy.ValueIsMissing(rightPtr)) window.Add(copy.Value(rightPtr));
    }

    for (unsigned i = 0; i < sampleRow.Size(); ++i) {
      if (rightPtr < sampleRow.Size()) {
        if (!copy.ValueIsMissing(rightPtr)) window.Add(copy.Value(rightPtr));
        ++rightPtr;
      }
      if (rightPtr > windowSize) {
        if (!copy.ValueIsMissing(leftPtr)) window.Remove(copy.Value(leftPtr));
        ++leftPtr;
      }
      sampleRow.SetValue(i, copy.Value(i) - window.Median());
    }
  }

 private:
  std::vector<NumType> data_;
  void Add(NumType sample) {
    // Add after the last value, to reduce the number of elements to shift.
    data_.insert(std::upper_bound(data_.begin(), data_.end(), sample), sample);
  }
  void Remove(NumType sample) {
    // Remove the last occurance, to reduce the number of elements to shift.
    data_.erase(std::upper_bound(data_.begin(), data_.end(), sample) - 1);
  }

  NumType Median() const {
    if (data_.size() == 0) return std::numeric_limits<NumType>::quiet_NaN();
    if (data_.size() % 2 == 0) {
      unsigned m = data_.size() / 2 - 1;
      typename std::vector<NumType>::const_iterator i = data_.begin();
      i += m;
      NumType lMid = *i;
      ++i;
      NumType rMid = *i;
      return (lMid + rMid) / 2.0;
    } else {
      unsigned m = data_.size() / 2;
      typename std::vector<NumType>::const_iterator i = data_.begin();
      i += m;
      return *i;
    }
  }
};

}  // namespace algorithms

#endif