File: thresholdtools.h

package info (click to toggle)
aoflagger 3.4.0-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 8,960 kB
  • sloc: cpp: 83,076; python: 10,187; sh: 260; makefile: 178
file content (127 lines) | stat: -rw-r--r-- 5,027 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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#ifndef THRESHOLDTOOLS_H
#define THRESHOLDTOOLS_H

#include <vector>
#include <cmath>
#include <complex>

#include "../structures/image2d.h"
#include "../structures/mask2d.h"

namespace algorithms {

class ThresholdTools {
 public:
  static void MeanAndStdDev(const Image2D* image, const Mask2D* mask,
                            num_t& mean, num_t& stddev);
  static numl_t Sum(const Image2D* image, const Mask2D* mask);
  static numl_t RMS(const Image2D* image, const Mask2D* mask);
  static num_t Mode(const Image2D* input, const Mask2D* mask);
  static num_t WinsorizedMode(const Image2D* image, const Mask2D* mask);
  static num_t WinsorizedMode(const Image2D* image, const Mask2D* maskA,
                              const Mask2D* maskB);
  static num_t WinsorizedMode(const Image2D* image);
  template <typename T>
  static void TrimmedMeanAndStdDev(const std::vector<T>& input, T& mean,
                                   T& stddev);
  template <typename T>
  static void WinsorizedMeanAndStdDev(const std::vector<T>& input, T& mean,
                                      T& stddev);
  static void WinsorizedMeanAndStdDev(const Image2D* image, const Mask2D* mask,
                                      num_t& mean, num_t& stddev);
  static void WinsorizedMeanAndStdDev(const Image2D* image, const Mask2D* maskA,
                                      const Mask2D* maskB, num_t& mean,
                                      num_t& stddev);
  static void WinsorizedMeanAndStdDev(const Image2D* image, num_t& mean,
                                      num_t& stddev);

  template <typename T>
  static double WinsorizedRMS(const std::vector<std::complex<T>>& input);

  static num_t MinValue(const Image2D* image, const Mask2D* mask);
  static num_t MaxValue(const Image2D* image, const Mask2D* mask);
  static void SetFlaggedValuesToZero(Image2D* dest, const Mask2D* mask);
  static void CountMaskLengths(const Mask2D* mask, int* lengths,
                               size_t lengthsSize);

  static void FilterConnectedSamples(Mask2D* mask,
                                     size_t minConnectedSampleArea,
                                     bool eightConnected = true);
  static void FilterConnectedSample(Mask2D* mask, size_t x, size_t y,
                                    size_t minConnectedSampleArea,
                                    bool eightConnected = true);
  static void UnrollPhase(Image2D* image);
  static Image2DPtr ShrinkHorizontally(size_t factor, const Image2D* input,
                                       const Mask2D* mask);
  static Image2DPtr ShrinkVertically(size_t factor, const Image2D* input,
                                     const Mask2D* mask);

  static Image2DPtr FrequencyRectangularConvolution(const Image2D* source,
                                                    size_t convolutionSize) {
    Image2DPtr image(new Image2D(*source));
    const size_t upperWindowHalf = (convolutionSize + 1) / 2;
    for (size_t x = 0; x < image->Width(); ++x) {
      num_t sum = 0.0;
      for (size_t y = 0; y < upperWindowHalf; ++y) sum += image->Value(x, y);
      for (size_t y = upperWindowHalf; y < convolutionSize; ++y) {
        image->SetValue(x, y - upperWindowHalf, sum / (num_t)y);
        sum += image->Value(x, y);
      }
      size_t count = convolutionSize;
      for (size_t y = convolutionSize; y != image->Height(); ++y) {
        image->SetValue(x, y - upperWindowHalf, sum / (num_t)count);
        sum += image->Value(x, y) - image->Value(x, y - convolutionSize);
      }
      for (size_t y = image->Height(); y != image->Height() + upperWindowHalf;
           ++y) {
        image->SetValue(x, y - upperWindowHalf, sum / (num_t)count);
        sum -= image->Value(x, y - convolutionSize);
        --count;
      }
    }
    return image;
  }

  static Mask2DPtr Threshold(const Image2D* image, num_t threshold) {
    Mask2DPtr mask =
        Mask2D::CreateUnsetMaskPtr(image->Width(), image->Height());
    for (size_t y = 0; y < image->Height(); ++y) {
      for (size_t x = 0; x < image->Width(); ++x) {
        mask->SetValue(x, y, image->Value(x, y) >= threshold);
      }
    }
    return mask;
  }

 private:
  ThresholdTools() {}

  // We need this less than operator, because the normal operator
  // does not enforce a strictly ordered set, because a<b != !(b<a) in the case
  // of nans/infs.
  static bool numLessThanOperator(const num_t& a, const num_t& b) {
    if (std::isfinite(a)) {
      if (std::isfinite(b))
        return a < b;
      else
        return true;
    }
    return false;
  }

  template <typename T>
  static bool complexLessThanOperator(const std::complex<T>& a,
                                      const std::complex<T>& b) {
    if (std::isfinite(a.real()) && std::isfinite(a.imag())) {
      if (std::isfinite(b.real()) && std::isfinite(b.imag()))
        return (a * std::conj(a)).real() < (b * std::conj(b)).real();
      else
        return true;
    }
    return false;
  }
};

}  // namespace algorithms

#endif