OPAL (Object Oriented Parallel Accelerator Library) 2022.1
OPAL
SavitzkyGolay.cpp
Go to the documentation of this file.
2#include "gsl/gsl_fft_real.h"
3#include "gsl/gsl_fft_halfcomplex.h"
4#include <iostream>
5
6#include <cmath>
7
8SavitzkyGolayFilter::SavitzkyGolayFilter(int np, int nl, int nr, int m):
9 NumberPoints_m(np),
10 NumberPointsLeft_m(nl),
11 NumberPointsRight_m(nr),
12 PolynomialOrder_m(m),
13 Coefs_m(np, 0.0),
14 CoefsDeriv_m(np, 0.0) {
17}
18
19void SavitzkyGolayFilter::apply(std::vector<double> &LineDensity) {
20 std::vector<double> temp(LineDensity.size(), 0.0);
21 convlv(LineDensity, Coefs_m, 1, temp);
22 LineDensity.assign(temp.begin(), temp.end());
23}
24
25void SavitzkyGolayFilter::calc_derivative(std::vector<double> &LineDensity, const double &/*h*/) {
26 std::vector<double> temp(LineDensity.size(), 0.0);
28 LineDensity.assign(temp.begin(), temp.end());
29}
30
31
32void savgol(std::vector<double> &c, const int &np, const int &nl, const int &nr, const int &ld, const int &m) {
33 int j, k, imj, ipj, kk, mm;
34 double d, sum;
35
36 if (np < nl + nr + 1 || nl < 0 || nr < 0 || ld > m || nl + nr < m) {
37 std::cerr << "bad args in savgol" << std::endl;
38 return;
39 }
40 std::vector<int> indx(m + 1, 0);
41 std::vector<double> a((m + 1) * (m + 1), 0.0);
42 std::vector<double> b(m + 1, 0.0);
43
44 for (ipj = 0; ipj <= (m << 1); ++ipj) {
45 sum = (ipj ? 0.0 : 1.0);
46 for (k = 1; k <= nr; ++k)
47 sum += (int)pow((double)k, (double)ipj);
48 for (k = 1; k <= nl; ++k)
49 sum += (int)pow((double) - k, (double)ipj);
50 mm = (ipj < 2 * m - ipj ? ipj : 2 * m - ipj);
51 for (imj = -mm; imj <= mm; imj += 2)
52 a[(ipj + imj) / 2 * (m + 1) + (ipj - imj) / 2] = sum;
53 }
54 ludcmp(a, indx, d);
55
56 for (j = 0; j < m + 1; ++j)
57 b[j] = 0.0;
58 b[ld] = 1.0;
59
60 lubksb(a, indx, b);
61 for (kk = 0; kk < np; ++kk)
62 c[kk] = 0.0;
63 for (k = -nl; k <= nr; ++k) {
64 sum = b[0];
65 double fac = 1.0;
66 for (mm = 1; mm <= m; ++mm)
67 sum += b[mm] * (fac *= k);
68 kk = (np - k) % np;
69 c[kk] = sum;
70 }
71
72}
73
74void convlv(const std::vector<double> &data, const std::vector<double> &respns, const int &isign, std::vector<double> &ans) {
75 int n = data.size();
76 int m = respns.size();
77
78 double *tempfd1 = new double[n];
79 double *tempfd2 = new double[n];
80
81 gsl_fft_halfcomplex_wavetable *hc;
82 gsl_fft_real_wavetable *real = gsl_fft_real_wavetable_alloc(n);
83 gsl_fft_real_workspace *work = gsl_fft_real_workspace_alloc(n);
84
85
86 for (int i = 0; i < n; ++ i) {
87 tempfd1[i] = 0.0;
88 tempfd2[i] = data[i];
89 }
90
91 tempfd1[0] = respns[0];
92 for (int i = 1; i < (m + 1) / 2; ++i) {
93 tempfd1[i] = respns[i];
94 tempfd1[n - i] = respns[m - i];
95 }
96
97 gsl_fft_real_transform(tempfd1, 1, n, real, work);
98 gsl_fft_real_transform(tempfd2, 1, n, real, work);
99
100 gsl_fft_real_wavetable_free(real);
101 hc = gsl_fft_halfcomplex_wavetable_alloc(n);
102
103 if (isign == 1) {
104 for (int i = 1; i < n - 1; i += 2) {
105 double tmp = tempfd1[i];
106 tempfd1[i] = (tempfd1[i] * tempfd2[i] - tempfd1[i + 1] * tempfd2[i + 1]);
107 tempfd1[i + 1] = (tempfd1[i + 1] * tempfd2[i] + tmp * tempfd2[i + 1]);
108 }
109 tempfd1[0] *= tempfd2[0];
110 tempfd1[n - 1] *= tempfd2[n - 1];
111 }
112
113 gsl_fft_halfcomplex_inverse(tempfd1, 1, n, hc, work);
114
115 for (int i = 0; i < n; ++i) {
116 ans[i] = tempfd1[i];
117 }
118
119 gsl_fft_halfcomplex_wavetable_free(hc);
120 gsl_fft_real_workspace_free(work);
121
122 delete[] tempfd1;
123 delete[] tempfd2;
124}
125
126void ludcmp(std::vector<double> &a, std::vector<int> &indx, double &d) {
127 const double TINY = 1.0e-20;
128 int i, imax = -1, j, k;
129 double big, dum, sum, temp;
130
131 int n = indx.size();
132 std::vector<double> vv(n, 0.0);
133
134 d = 1.0;
135 for (i = 0; i < n; ++i) {
136 big = 0.0;
137 for (j = 0; j < n; ++j)
138 if ((temp = std::abs(a[i * n + j])) > big) big = temp;
139
140 if (big == 0.0) {
141 std::cerr << "Singular matrix in routine ludcmp" << std::endl;
142 return;
143 }
144 vv[i] = 1. / big;
145 }
146
147 for (j = 0; j < n; ++j) {
148 for (i = 0; i < j; ++i) {
149 sum = a[i * n + j];
150 for (k = 0; k < i; ++k)
151 sum -= a[i * n + k] * a[k * n + j];
152 a[i * n + j] = sum;
153 }
154 big = 0.0;
155 for (i = j; i < n; ++i) {
156 sum = a[i * n + j];
157 for (k = 0; k < j; ++k)
158 sum -= a[i * n + k] * a[k * n + j];
159 a[i * n + j] = sum;
160 if ((dum = vv[i] * std::abs(sum)) >= big) {
161 big = dum;
162 imax = i;
163 }
164 }
165
166 if (j != imax) {
167 for (k = 0; k < n; ++k) {
168 dum = a[imax * n + k];
169 a[imax * n + k] = a[j * n + k];
170 a[j * n + k] = dum;
171 }
172 d = -d;
173 vv[imax] = vv[j];
174 }
175 indx[j] = imax;
176 if (a[j * n + j] == 0.0) a[j * n + j] = TINY;
177 if (j != n - 1) {
178 dum = 1. / a[j * n + j];
179 for (i = j + 1; i < n; ++i)
180 a[i * n + j] *= dum;
181 }
182 }
183}
184
185void lubksb(std::vector<double> &a, std::vector<int> &indx, std::vector<double> &b) {
186 int i, ii = 0, ip, j;
187 double sum;
188 int n = indx.size();
189
190 for (i = 0; i < n; ++i) {
191 ip = indx[i];
192 sum = b[ip];
193 b[ip] = b[i];
194 if (ii != 0)
195 for (j = ii - 1; j < i; ++j)
196 sum -= a[i * n + j] * b[j];
197 else if (sum != 0.0)
198 ii = i + 1;
199 b[i] = sum;
200 }
201 for (i = n - 1; i >= 0; --i) {
202 sum = b[i];
203 for (j = i + 1; j < n; ++j)
204 sum -= a[i * n + j] * b[j];
205 b[i] = sum / a[i * n + i];
206 }
207
208}
void convlv(const std::vector< double > &data, const std::vector< double > &respns, const int &isign, std::vector< double > &ans)
void ludcmp(std::vector< double > &a, std::vector< int > &indx, double &d)
void lubksb(std::vector< double > &a, std::vector< int > &indx, std::vector< double > &b)
void savgol(std::vector< double > &c, const int &np, const int &nl, const int &nr, const int &ld, const int &m)
FLieGenerator< T, N > real(const FLieGenerator< std::complex< T >, N > &)
Take real part of a complex generator.
const int nr
Definition: ClassicRandom.h:24
Tps< T > pow(const Tps< T > &x, int y)
Integer power.
Definition: TpsMath.h:76
T::PETE_Expr_t::PETE_Return_t sum(const PETE_Expr< T > &expr)
Definition: PETE.h:1111
std::complex< double > a
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
constexpr double c
The velocity of light in m/s.
Definition: Physics.h:45
void apply(std::vector< double > &histogram)
std::vector< double > Coefs_m
Definition: SavitzkyGolay.h:20
std::vector< double > CoefsDeriv_m
Definition: SavitzkyGolay.h:21
SavitzkyGolayFilter(int np, int nl, int nr, int m)
void calc_derivative(std::vector< double > &histogram, const double &h)