OPAL (Object Oriented Parallel Accelerator Library) 2024.2
OPAL
lomb.cpp
Go to the documentation of this file.
1/*****************************************************************************/
2/* */
3/* Class for Lomb Periodograms & Co. */
4/* ================================= */
5/* */
6/* (update: ASM, September 2001) */
7/*****************************************************************************/
8#include "lomb.h"
9
10#include "Physics/Physics.h"
11
12#include <cmath>
13#include <iostream>
14
16/*---------------------------------------------------------------------------*
17 * constructor
18 * ===========
19 *
20 *---------------------------------------------------------------------------*/
21{}
22
23
25/*---------------------------------------------------------------------------*
26 * destructor
27 * ==========
28 *
29 *---------------------------------------------------------------------------*/
30{
31 // Do nothing......
32}
33
34
35int LOMB_class::period(std::vector<LOMB_TYPE> *indata, std::vector<LOMB_TYPE> *outdata,
36 double ofac, double hifac, int *nout, int *jmax, double *prob,
37 int amp)
38/*---------------------------------------------------------------------------*
39 * NR routine
40 * ==========
41 *
42 *---------------------------------------------------------------------------*/
43{
44 int i, j, ntmp;
45 int n = 0;
46 double ave, c, cc, cwtau, effm, expy, pnow, pymax, s, ss, sumc, sumcy, sums, sumsh, sumsy;
47 double swtau, var, wtau, xave, xdiff, xmax, xmin, yy;
48 //double arg,wtemp,*wi,*wpi,*wpr,*wr;
49 double arg, wtemp;
50
51 std::vector<double> wi, wpi, wpr, wr;
52
53 LOMB_TYPE pt;
54
55 CI_lt p, q;
56 /*---------------------------------------------------------------------------*/
57
58 wi.erase(wi.begin(), wi.end());
59 wpi.erase(wpi.begin(), wpi.end());
60 wpr.erase(wpr.begin(), wpr.end());
61 wr.erase(wr.begin(), wr.end());
62
63 p = indata->begin();
64 q = indata->end();
65
66 n = q - p;
67
68 ntmp = (int)(0.5 * ofac * hifac * n);
69
70 *nout = ntmp;
71
72 if (avevar(indata, &ave, &var) != 0) {
73 std::cerr << "LOMB: Average failed!\n";
74 return(-1);
75 }
76
77 p = indata->begin();
78 xmax = xmin = (*p).x;
79
80 for (p = indata->begin(); p != indata->end(); p++) {
81 if ((*p).x > xmax) xmax = (*p).x;
82 if ((*p).x < xmin) xmin = (*p).x;
83 }
84
85 xdiff = xmax - xmin;
86 xave = 0.5 * (xmax + xmin);
87 pymax = 0.0;
88 pnow = 1. / (xdiff * ofac);
89
90 for (p = indata->begin(); p != indata->end(); p++) {
91
92 arg = Physics::two_pi * (((*p).x - xave) * pnow);
93 wpr.push_back((-2. * std::pow(std::sin(0.5 * arg) , 2)));
94 wpi.push_back(std::sin(arg));
95 wr.push_back(std::cos(arg));
96 wi.push_back(std::sin(arg));
97
98 }
99
100 // check wr range and data range !!!!
101 if ((wr.end() - wr.begin()) != n) {
102 std::cerr << "LOMB: Vector range mismatch!!!\n";
103 return(-1);
104 }
105
106 for (i = 0; i < (*nout); i++) {
107 pt.x = pnow;
108 sumsh = 0. ;
109 sumc = 0.;
110
111 for (j = 0; j < n; j++) {
112 c = wr[j];
113 s = wi[j];
114
115 sumsh += s * c;
116 sumc += (c - s) * (c + s);
117 }
118
119 wtau = 0.5 * std::atan2(2.0 * sumsh, sumc);
120 swtau = std::sin(wtau);
121 cwtau = std::cos(wtau);
122 sums = 0.;
123 sumc = 0.;
124 sumsy = 0.;
125 sumcy = 0.;
126
127 for (j = 0, p = indata->begin() ; j < n && p != indata->end() ; j++, p++) {
128 s = wi[j];
129 c = wr[j];
130 ss = s * cwtau - c * swtau;
131 cc = c * cwtau + s * swtau;
132 sums += ss * ss;
133 sumc += cc * cc;
134 yy = (*p).y - ave;
135 sumsy += yy * ss;
136 sumcy += yy * cc;
137 wtemp = wr[j];
138 wr[j] = (wr[j] * wpr[j] - wi[j] * wpi[j]) + wr[j];
139 wi[j] = (wi[j] * wpr[j] + wtemp * wpi[j]) + wi[j];
140
141 }
142
143 pt.y = 0.5 * (sumcy * sumcy / sumc + sumsy * sumsy / sums) / var;
144 if (amp) pt.y = std::sqrt(std::pow((sumcy / sumc), 2.) + std::pow((sumsy / sums), 2.));
145
146 if (pt.y >= pymax) {
147 pymax = pt.y;
148 *jmax = i;
149 }
150
151 outdata->push_back(pt);
152
153 pnow += 1. / (ofac * xdiff);
154 }
155
156 expy = std::exp(-pymax);
157 effm = 2. * (*nout) / ofac;
158 *prob = effm * expy;
159
160 if (*prob > 0.01) *prob = 1. - std::pow((1. - expy), effm);
161
162 wi.erase(wi.begin(), wi.end());
163 wpi.erase(wpi.begin(), wpi.end());
164 wpr.erase(wpr.begin(), wpr.end());
165 wr.erase(wr.begin(), wr.end());
166
167 return(0);
168
169}
170
171
172int LOMB_class::avevar(std::vector<LOMB_TYPE> *data, double *ave, double *var)
173/*---------------------------------------------------------------------------*
174 * NR routine
175 * ==========
176 *
177 *---------------------------------------------------------------------------*/
178{
179 int n;
180 double s, ep;
181
182 CI_lt p, q;
183
184 /*---------------------------------------------------------------------------*/
185
186 *ave = 0.;
187 p = data->begin();
188 q = data->end();
189
190 n = q - p;
191
192 if (n < 2) {
193 std::cerr << "Only one datapoint -> no averaging....\n";
194 return(-1);
195 }
196
197 for (p = data->begin(); p != data->end(); p++) *ave += (*p).y;
198
199 *ave = *ave / n;
200 *var = 0.;
201 ep = 0.;
202
203 for (p = data->begin(); p != data->end(); p++) {
204 s = (*p).y - *ave;
205 ep += s;
206 *var += s * s;
207 }
208
209 *var = (*var - ep * ep / n) / (n - 1);
210
211 return(0);
212}
213
214
215double LOMB_class::signi(double *peak, int *nout, double *ofac)
216/*---------------------------------------------------------------------------*
217 * Calculate the significance of a peak in an Lomb Periodogram
218 * ===========================================================
219 *
220 * Input: double* peak: Peak of periodogram
221 * int* nout: Number of frequencies
222 * double* ofac: Oversampling factor
223 * Output: double Sign: Significance of peak
224 *---------------------------------------------------------------------------*/
225{
226 double expy, effm, prob;
227
228 /*---------------------------------------------------------------------------*/
229
230 expy = std::exp(-1 * (*peak));
231 effm = 2. * (double)(*nout) / (*ofac);
232 prob = effm * expy ;
233 if (prob > 0.01) prob = 1. - std::pow((1. - expy), effm);
234
235 return(prob);
236}
237
238
239int LOMB_class::moment(std::vector<LOMB_TYPE> *indata, double *ave, double *adev,
240 double *sdev, double *var, double *skew, double *curt)
241/*---------------------------------------------------------------------------*
242 * Calculate the first moments of a distribution (free after NR)
243 * =============================================================
244 *
245 * Input: vector indata: (periodogram) value vector of type LOMB_TYPE
246 * Output: double* ave : average
247 * double* adev : average deviation
248 * double* sdev : standard deviation
249 * double* var : variance
250 * double* skew : skewness
251 * double* curt : kurtosis
252 *---------------------------------------------------------------------------*/
253{
254
255 int n;
256 double pnr, s, ep;
257
258 CI_lt p, q;
259 /*---------------------------------------------------------------------------*/
260
261 p = indata->begin();
262 q = indata->end();
263
264 n = q - p;
265
266 if (n < 2) {
267 std::cerr << "To few data points for moment analysis!\n";
268 return(-1);
269 }
270
271 /*
272 * First pass to get the mean
273 * --------------------------
274 */
275 s = 0;
276 double nn = 0;
277 for (p = indata->begin(); p != indata->end(); p++) {
278 s += (*p).y * (*p).x;
279 nn += (*p).y;
280 }
281
282 *ave = s / (double)nn;
283
284 /*
285 * Second pass
286 * ------------
287 */
288
289 *adev = 0.;
290 *var = 0.;
291 *skew = 0.;
292 *curt = 0.;
293 ep = 0.;
294
295 for (p = indata->begin(); p != indata->end(); p++) {
296 s = ((*p).x - *ave);
297 ep += s * (*p).y;
298 *adev = *adev + (double)std::abs((double)s);
299
300 pnr = s * s;
301 *var += pnr * (*p).y;
302
303 pnr *= s;
304 *skew += pnr * (*p).y;
305
306 pnr *= s;
307 *curt += pnr * (*p).y;
308 }
309
310 *adev = *adev / (double)nn;
311
312 *var = (*var - ep * ep / (double)nn) / ((double)(nn - 1));
313
314 *sdev = std::sqrt(*var);
315
316 if (*var != 0.) {
317 *skew = *skew / ((double)nn * std::pow(*sdev, 3.));
318 *curt = *curt / ((double)nn * std::pow(*var, 2.)) - 3.;
319 } else {
320 std::cerr << "No skew or kurtosis when zero variance in moment\n";
321 }
322
323 return(0);
324}
std::vector< LOMB_TYPE >::const_iterator CI_lt
Definition lomb.h:17
arg(a))
constexpr double two_pi
The value of.
Definition Physics.h:33
double x
Definition lomb.h:14
double y
Definition lomb.h:14
virtual ~LOMB_class(void)
Definition lomb.cpp:24
int avevar(std::vector< LOMB_TYPE > *data, double *ave, double *var)
Definition lomb.cpp:172
LOMB_class(int)
Definition lomb.cpp:15
double signi(double *peak, int *nout, double *ofac)
Definition lomb.cpp:215
int moment(std::vector< LOMB_TYPE > *indata, double *ave, double *adev, double *sdev, double *var, double *skew, double *curt)
Definition lomb.cpp:239
int period(std::vector< LOMB_TYPE > *indata, std::vector< LOMB_TYPE > *outdata, double ofac, double hifac, int *nout, int *jmax, double *prob, int amp)
Definition lomb.cpp:35