median_smooth.h
1//-*-C++-*-
2/***************************************************************************
3 *
4 * Copyright (C) 2004 by Russell Edwards
5 * Licensed under the Academic Free License version 2.1
6 *
7 ***************************************************************************/
8
9// psrchive/Util/fft/median_smooth.h
10
11#ifndef __fft_smooth_h
12#define __fft_smooth_h
13
14#include <algorithm>
15#include <vector>
16#include <iostream>
17
18namespace fft {
19
20 template <class T>
21 void median_smooth (std::vector<T>& data, unsigned ndim, unsigned wsize)
22 {
23 std::vector<typename T::type> temp (data.size());
24 for (unsigned idim=0; idim<ndim; idim++)
25 {
26 for (unsigned idat=0; idat<data.size(); idat++)
27 temp[idat] = data[idat][idim];
28 median_smooth (temp, wsize);
29 for (unsigned idat=0; idat<data.size(); idat++)
30 data[idat][idim] = temp[idat];
31 }
32 }
33
34 template <class T>
35 void median_smooth (std::vector<T>& data, unsigned wsize)
36 {
37 if (data.size() < 4)
38 return;
39
40 if (wsize < 3)
41 return;
42
43 if (data.size() < wsize + 1)
44 return;
45
46 // make it an odd number
47 if (wsize%2 == 0)
48 wsize ++;
49
50 unsigned ipt = 0, jpt = 0;
51
52 unsigned middle = wsize/2;
53 std::vector<T> window (wsize);
54
55 unsigned rsize = data.size() - wsize + 1;
56 std::vector<T> result (data.size());
57
58 unsigned truncated = 0;
59 unsigned tmid = 0;
60 // deal with leading edge
61 for (ipt=0; ipt < middle; ipt++)
62 {
63 truncated = middle + 1 + ipt;
64 tmid = truncated / 2;
65 for (jpt=0; jpt < truncated; jpt++)
66 window[jpt] = data[jpt];
67 std::nth_element (window.begin(), window.begin()+tmid,
68 window.begin()+truncated);
69 result[ipt] = window[tmid];
70 }
71
72 for (ipt=0; ipt < rsize; ipt++)
73 {
74 for (jpt=0; jpt<wsize; jpt++)
75 window[jpt] = data[ipt+jpt];
76 std::nth_element (window.begin(), window.begin()+middle, window.end());
77 result[ipt+middle] = window[middle];
78 }
79
80 // deal with trailing edge
81 for (ipt=rsize; ipt < data.size()-middle; ipt++)
82 {
83 truncated = data.size() - ipt;
84 tmid = truncated / 2;
85 for (jpt=0; jpt < truncated; jpt++)
86 window[jpt] = data[ipt+jpt];
87 std::nth_element (window.begin(), window.begin()+tmid,
88 window.begin()+truncated);
89 result[ipt+middle] = window[tmid];
90 }
91
92 for (ipt=0; ipt < data.size(); ipt++)
93 data[ipt] = result[ipt];
94
95 } // end median_smooth
96
97 template <class T>
98 T absolute (T x) { if (x<0) return -x; return x; }
99
100 template <class T>
101 void median_filter (std::vector<T>& data, unsigned wsize, T threshold)
102 {
103 std::vector<T> copy (data);
104 median_smooth (copy, wsize);
105
106 const unsigned ndat = copy.size();
107
108 T variance = 0;
109 for (unsigned idat=0; idat < ndat; idat++)
110 {
111 copy[idat] -= data[idat];
112 copy[idat] *= copy[idat];
113 variance += copy[idat];
114 }
115
116 variance /= ndat;
117
118 bool zapped = true;
119 unsigned round = 1;
120 unsigned total_zapped = 0;
121
122 while (zapped)
123 {
124 T cutoff = threshold * threshold * variance;
125
126 zapped = false;
127 round ++;
128
129 for (unsigned idat=0; idat < ndat; idat++)
130 {
131 if (copy[idat] > cutoff ||
132 (idat && absolute(copy[idat]-copy[idat-1]) > 2*cutoff))
133 {
134 variance -= copy[idat]/ndat;
135 copy[idat] = data[idat] = 0;
136 total_zapped ++;
137 zapped = true;
138 }
139 }
140 }
141 }
142
143} // end namespace fft
144
145#endif // ! _fft_smooth_h

Generated using doxygen 1.14.0