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