source: trunk/MagicSoft/Mars/mtools/MFFT.cc@ 4196

Last change on this file since 4196 was 3957, checked in by tbretz, 21 years ago
*** empty log message ***
File size: 23.2 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of MARS, the MAGIC Analysis and Reconstruction
5! * Software. It is distributed to you in the hope that it can be a useful
6! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
7! * It is distributed WITHOUT ANY WARRANTY.
8! *
9! * Permission to use, copy, modify and distribute this software and its
10! * documentation for any purpose is hereby granted without fee,
11! * provided that the above copyright notice appear in all copies and
12! * that both that copyright notice and this permission notice appear
13! * in supporting documentation. It is provided "as is" without express
14! * or implied warranty.
15! *
16!
17!
18! Author(s): Markus Gaug 01/2004 <mailto:markus@ifae.es>
19!
20! Copyright: MAGIC Software Development, 2001-2004
21!
22!
23\* ======================================================================== */
24
25//////////////////////////////////////////////////////////////////////////////
26// //
27// Fast Fourier Transforms //
28// //
29// (Most of the code is adapted from Numerical Recipies in C++, 2nd ed., //
30// pp. 509-563) //
31// //
32// Usage: //
33// //
34// 1) Functions RealFunctionFFT: (FOURIER TRANSFORM) //
35// * Take as argument arrays of real numbers, //
36// in some cases the dimension of the array has to be given separately//
37// * Return a COMPLEX array with the following meaning: //
38// array[0]: The value of F(0) (has only real component) //
39// array[1]: The value of F(N/2) (has only real component) //
40// array[2i]: The real part of F(i) //
41// array[2i+1]: The imaginary part of F(i) //
42// * Note that F(N-i)* = F(i), therefore only the positive frequency //
43// half is stored. //
44// * The dimension MUST be an integer power of 2, //
45// otherwise, the array will be shortened!! //
46// //
47// 2) Functions RealFunctionIFFT: (INVERSER FOURIER TRANSFORM) //
48// * Take as argument a COMPLEX array //
49// of Fourier-transformed REAL numbers //
50// with the following meaning: //
51// array[0]: The value of F(0) (has only real component) //
52// array[1]: The value of F(N/2) (has only real component) //
53// array[2i]: The real part of F(i) //
54// array[2i+1]: The imaginary part of F(i) //
55// * Returns the original complex array of dimension 2N-1 //
56// //
57// 3) Functions PowerSpectrumDensity: //
58// * Return a histogram with the spectral density, i.e. //
59// P(k) = 1/(N*N) * |F(k)|*|F(k)| //
60// * The histogram is ranged between 0 and 1./(2*binwidth) //
61// * The number of bins equals N/2+1 //
62// * Note that histograms with unequal binwidth can not yet be treated! //
63// * If the PSD does NOT CONVERGE to 0 at the maximum bin, //
64// you HAVE TO sample your data finer! //
65//
66// Fourier-Transformation:
67// =======================
68
69// (taken from http://www.parasitaere-kapazitaeten.net/Pd/ft.htm)
70//
71// The Fourier-Transformation is a mathematical function that breaks
72// down a signal (like sound) into its frequency-spectrum as a set of
73// sinusoidal components, converting it from the Time Domain to the
74// Frequency Domain.
75//
76// In the Time Domain the signal x[ ] consists of N samples, labeled
77// from 0 to N-1. In the Frequency Domain the RFFT produces two signals
78// (signalvectors), treated as complex numbers representing the Real Part:
79// Re X[ ] and the Imaginary Part: Im X[ ]. They are seen as the Cosine-
80// und Sine-Components of the base frequencies. Each of these two signals
81// contains one more sample than the half of the original signal: N/2 + 1
82// samples. (this results from the fact, that the sine-components of the
83// first frequency (0) and the last (nyquist, N/2) are always 0). With the
84// complex Fourier-Transformation N complexe values are transformed to N
85// new complex values. For both it applies to: the Frequency Domain
86// contains exactly the same information as the Time-Domain.
87//
88// A Real FFT over 64 samples produces values for 33 cosine- and 33
89// sine-wave-amplitudes with the frequencies 0, 1, 2, 3, ..., 30, 31, 32.
90// The first value (frequency 0) is the DC (direct current), the other
91// values have to be seen in practice as factors of a
92// fundamental-frequency which can be calculated by dividing samplerate by
93// windowsize. The highest frequency is the nyquist-frequency
94// (samplerate/2).
95//
96//////////////////////////////////////////////////////////////////////////////
97
98#include "MFFT.h"
99
100#include <TMath.h>
101
102#include "MLog.h"
103#include "MLogManip.h"
104
105ClassImp(MFFT);
106
107using namespace std;
108
109// ---------------------------------------------------------------------------
110//
111// Default Constructor
112// Initializes random number generator and default variables
113//
114MFFT::MFFT() : fDim(0)
115{
116}
117
118// --------------------------------------------------------------------------
119//
120// Destructor.
121//
122MFFT::~MFFT()
123{
124}
125
126void MFFT::TransformF(const Int_t isign, TArrayF &data)
127{
128
129 UInt_t n,mmax,m,j,istep,i;
130 Float_t wtemp,wr,wpr,wpi,wi,theta;
131 Float_t tempr,tempi;
132
133 Int_t nn = fDim/2;
134 n = nn << 1;
135
136 //
137 // The bit-reversal section of the routine:
138 // Exchange the two complex numbers
139 //
140 j=1;
141 for (i=1;i<n;i+=2) {
142 if (j > i) {
143 Swap(data[j-1],data[i-1]);
144 Swap(data[j],data[i]);
145 }
146 m=nn;
147 while (m >= 2 && j > m) {
148 j -= m;
149 m >>= 1;
150 }
151 j += m;
152 }
153 //
154 // Here begins the Danielson-Lanczos section of the routine
155 //
156 mmax=2;
157 while (n > mmax) { // Outer loop executed log_2(nn) times
158
159 istep = mmax << 1;
160 //
161 // Initialize the trigonometric recurrence:
162 //
163 theta = isign*(6.28318530717959/mmax);
164
165 wtemp = TMath::Sin(0.5*theta);
166 wpr = -2.0*wtemp*wtemp;
167 wpi = TMath::Sin(theta);
168
169 wr=1.0;
170 wi=0.0;
171
172 for (m=1; m<mmax; m+=2) {
173 for (i=m; i<=n; i+=istep) {
174 //
175 // The Danielson-Lanczos formula:
176 //
177 j = i+mmax;
178 tempr = wr*data[j-1] - wi*data[j];
179 tempi = wr*data[j] + wi*data[j-1];
180 data[j-1] = data[i-1] - tempr;
181 data[j] = data[i] - tempi;
182 data[i-1] += tempr;
183 data[i] += tempi;
184 }
185
186 //
187 // Trigonometric recurrence
188 //
189 wr = (wtemp=wr)*wpr - wi*wpi+wr;
190 wi = wi*wpr + wtemp*wpi+wi;
191
192 }
193 mmax=istep;
194 }
195}
196
197
198void MFFT::TransformD(const Int_t isign, TArrayD &data)
199{
200
201 UInt_t n,mmax,m,j,istep,i;
202 Double_t wtemp,wr,wpr,wpi,wi,theta;
203 Double_t tempr,tempi;
204
205 Int_t nn = fDim/2;
206 n = nn << 1;
207
208 //
209 // The bit-reversal section of the routine:
210 // Exchange the two complex numbers
211 //
212 j=1;
213 for (i=1;i<n;i+=2) {
214 if (j > i) {
215 Swap(data[j-1],data[i-1]);
216 Swap(data[j],data[i]);
217 }
218 m=nn;
219 while (m >= 2 && j > m) {
220 j -= m;
221 m >>= 1;
222 }
223 j += m;
224 }
225 //
226 // Here begins the Danielson-Lanczos section of the routine
227 //
228 mmax=2;
229 while (n > mmax) { // Outer loop executed log_2(nn) times
230
231 istep = mmax << 1;
232 //
233 // Initialize the trigonometric recurrence:
234 //
235 theta = isign*(6.28318530717959/mmax);
236
237 wtemp = TMath::Sin(0.5*theta);
238 wpr = -2.0*wtemp*wtemp;
239 wpi = TMath::Sin(theta);
240
241 wr=1.0;
242 wi=0.0;
243
244 for (m=1; m<mmax; m+=2) {
245 for (i=m; i<=n; i+=istep) {
246 //
247 // The Danielson-Lanczos formula:
248 //
249 j = i+mmax;
250 tempr = wr*data[j-1] - wi*data[j];
251 tempi = wr*data[j] + wi*data[j-1];
252 data[j-1] = data[i-1] - tempr;
253 data[j] = data[i] - tempi;
254 data[i-1] += tempr;
255 data[i] += tempi;
256 }
257
258 //
259 // Trigonometric recurrence
260 //
261 wr = (wtemp=wr)*wpr - wi*wpi+wr;
262 wi = wi*wpr + wtemp*wpi+wi;
263
264 }
265 mmax=istep;
266 }
267}
268
269//
270// Calculates the Fourier transform of a set of n real-valued data points.
271// Replaces this data (which is stored in array data[1..n]) by the positive
272// frequency half of its complex Fourier transform. The real-valued first
273// and last components of the complex transform are returned as elements
274// data[1] and data[2], respectively. n must be a power of 2. This routine
275// also calculates the inverse transform of a complex data array if it is
276// the transform of real data. (Result in this case mus be multiplied by
277// 2/n.). From NUMERICAL RECIPES IN C++.
278//
279void MFFT::RealFTF(const Int_t isign)
280{
281
282 Int_t i,i1,i2,i3,i4;
283 Float_t c1=0.5,c2,h1r,h1i,h2r,h2i;
284 Float_t wr,wi,wpr,wpi,wtemp,theta;
285
286 //
287 // Initialize the recurrence
288 //
289 theta = TMath::Pi() / (Double_t)(fDim>>1);
290
291 if(isign==1) // forward transform
292 {
293 c2 = -0.5;
294 TransformF(1,fDataF);
295 }
296 else // set up backward transform
297 {
298 c2 = 0.5;
299 theta = -theta;
300 }
301
302 wtemp = TMath::Sin(0.5*theta);
303 wpr = -2.0*wtemp*wtemp;
304 wpi = TMath::Sin(theta);
305
306 wr = 1.0 + wpr;
307 wi = wpi;
308
309 for(i=1;i<(fDim>>2);i++) // case i=0 done separately below
310 {
311
312 i2 = 1 + (i1 = i+i);
313 i4 = 1 + (i3 = fDim-i1);
314
315 //
316 // The two separate transforms are separated out of the data
317 //
318 h1r = c1*(fDataF[i1]+fDataF[i3]);
319 h1i = c1*(fDataF[i2]-fDataF[i4]);
320 h2r = -c2*(fDataF[i2]+fDataF[i4]);
321 h2i = c2*(fDataF[i1]-fDataF[i3]);
322
323 //
324 // Here, they are recombined to from the true transform
325 // of the orginal real data
326 //
327 fDataF[i1] = h1r + wr*h2r - wi*h2i;
328 fDataF[i2] = h1i + wr*h2i + wi*h2r;
329 fDataF[i3] = h1r - wr*h2r + wi*h2i;
330 fDataF[i4] = -h1i + wr*h2i + wi*h2r;
331
332 //
333 // The recurrence
334 //
335 wr = (wtemp=wr)*wpr - wi*wpi + wr;
336 wi = wi*wpr + wtemp*wpi + wi;
337 }
338
339 //
340 // Squeeze the first and last data together to get them all
341 // within the original array
342 //
343 if(isign==1)
344 {
345 fDataF[0] = (h1r=fDataF[0]) + fDataF[1];
346 fDataF[1] = h1r - fDataF[1];
347 }
348 else
349 {
350
351 fDataF[0] = c1*((h1r=fDataF[0]) + fDataF[1]);
352 fDataF[1] = c1*(h1r-fDataF[1]);
353
354 //
355 // The inverse transform for the case isign = -1
356 //
357 TransformF(-1,fDataF);
358
359 //
360 // normalize correctly (not done in original NR's)
361 //
362 for(i=1;i<=fDim;i++)
363 fDataF[i] *= (2./fDim);
364 }
365}
366void MFFT::RealFTD(const Int_t isign)
367{
368
369 Int_t i,i1,i2,i3,i4;
370 Float_t c1=0.5,c2,h1r,h1i,h2r,h2i;
371 Double_t wr,wi,wpr,wpi,wtemp,theta;
372
373 //
374 // Initialize the recurrence
375 //
376 theta=3.141592653589793/(Double_t) (fDim>>1);
377
378 if(isign==1) // forward transform
379 {
380 c2 = -0.5;
381 TransformD(1,fDataD);
382 }
383 else // set up backward transform
384 {
385 c2 = 0.5;
386 theta = -theta;
387 }
388
389 wtemp = TMath::Sin(0.5*theta);
390 wpr = -2.0*wtemp*wtemp;
391 wpi = TMath::Sin(theta);
392
393 wr = 1.0 + wpr;
394 wi = wpi;
395
396 for(i=1;i<(fDim>>2);i++) // case i=0 done separately below
397 {
398
399 i2 = 1 + (i1 = i+i);
400 i4 = 1 + (i3 = fDim-i1);
401
402 //
403 // The two separate transforms are separated out of the data
404 //
405 h1r = c1*(fDataD[i1]+fDataD[i3]);
406 h1i = c1*(fDataD[i2]-fDataD[i4]);
407 h2r = -c2*(fDataD[i2]+fDataD[i4]);
408 h2i = c2*(fDataD[i1]-fDataD[i3]);
409
410 //
411 // Here, they are recombined to from the true transform
412 // of the orginal real data
413 //
414 fDataD[i1] = h1r + wr*h2r - wi*h2i;
415 fDataD[i2] = h1i + wr*h2i + wi*h2r;
416 fDataD[i3] = h1r - wr*h2r + wi*h2i;
417 fDataD[i4] = -h1i + wr*h2i + wi*h2r;
418
419 //
420 // The recurrence
421 //
422 wr = (wtemp=wr)*wpr - wi*wpi + wr;
423 wi = wi*wpr + wtemp*wpi + wi;
424 }
425
426 //
427 // Squeeze the first and last data together to get them all
428 // within the original array
429 //
430 if(isign==1)
431 {
432 fDataD[0] = (h1r=fDataD[0]) + fDataD[1];
433 fDataD[1] = h1r - fDataD[1];
434 }
435 else
436 {
437
438 fDataD[0] = c1*((h1r=fDataD[0]) + fDataD[1]);
439 fDataD[1] = c1*(h1r-fDataD[1]);
440
441 //
442 // The inverse transform for the case isign = -1
443 //
444 TransformD(-1,fDataD);
445
446 //
447 // normalize correctly (not done in original NR's)
448 //
449 for(i=1;i<=fDim;i++)
450 fDataD[i] *= (2./fDim);
451 }
452}
453
454
455//
456// Fast Fourier Transform for float arrays
457//
458Float_t* MFFT::RealFunctionFFT(const Int_t n, const Float_t *data)
459{
460
461 fDim = n;
462 CheckDim(n);
463
464 fDataF.Set(fDim);
465 //
466 // Clone the array
467 //
468 for (Int_t i=0;i<fDim;i++)
469 fDataF[i] = data[i];
470
471 RealFTF(1);
472
473 return fDataF.GetArray();
474
475}
476
477//
478// Fast Inverse Fourier Transform for float arrays
479//
480Float_t* MFFT::RealFunctionIFFT(const Int_t n, const Float_t *data)
481{
482
483 fDim = n;
484 CheckDim(fDim);
485
486 fDataF.Set(fDim);
487 //
488 // Clone the array
489 //
490 for (Int_t i=0;i<fDim;i++)
491 fDataF[i] = data[i];
492
493 RealFTF(-1);
494
495 return fDataF.GetArray();
496
497}
498
499//
500// Fast Fourier Transform for double arrays
501//
502Double_t* MFFT::RealFunctionFFT(const Int_t n, const Double_t *data)
503{
504
505 fDim = n;
506 CheckDim(n);
507
508 fDataD.Set(fDim);
509 //
510 // Clone the array
511 //
512 for (Int_t i=0;i<fDim;i++)
513 fDataD[i] = data[i];
514
515 RealFTD(1);
516
517 return fDataD.GetArray();
518
519}
520
521//
522// Fast Inverse Fourier Transform for double arrays
523//
524Double_t* MFFT::RealFunctionIFFT(const Int_t n, const Double_t *data)
525{
526
527 fDim = n;
528 CheckDim(fDim);
529
530 fDataD.Set(fDim);
531 //
532 // Clone the array
533 //
534 for (Int_t i=0;i<fDim;i++)
535 fDataD[i] = data[i];
536
537 RealFTD(-1);
538
539 return fDataD.GetArray();
540
541}
542
543//
544// Fast Fourier Transform for TArrayF's
545//
546TArrayF* MFFT::RealFunctionFFT(const TArrayF *data)
547{
548
549 fDim = data->GetSize();
550 CheckDim(fDim);
551
552 fDataF.Set(fDim);
553 //
554 // Clone the array
555 //
556 for (Int_t i=0;i<fDim;i++)
557 fDataF[i] = data->At(i);
558
559 RealFTF(1);
560
561 return new TArrayF(fDim,fDataF.GetArray());
562
563}
564
565//
566// Inverse Fast Fourier Transform for TArrayF's
567//
568TArrayF* MFFT::RealFunctionIFFT(const TArrayF *data)
569{
570
571 fDim = data->GetSize();
572 CheckDim(fDim);
573
574 fDataF.Set(fDim);
575 //
576 // Clone the array
577 //
578 for (Int_t i=0;i<fDim;i++)
579 fDataF[i] = data->At(i);
580
581 RealFTF(-1);
582
583 return new TArrayF(fDim,fDataF.GetArray());
584}
585
586
587//
588// Fast Fourier Transform for TArrayD's
589//
590TArrayD* MFFT::RealFunctionFFT(const TArrayD *data)
591{
592
593 fDim = data->GetSize();
594 CheckDim(fDim);
595
596 fDataD.Set(fDim);
597 //
598 // Clone the array
599 //
600 for (Int_t i=0;i<fDim;i++)
601 fDataD[i] = data->At(i);
602
603 RealFTD(1);
604
605 return new TArrayD(fDim,fDataD.GetArray());
606
607}
608
609//
610// Inverse Fast Fourier Transform for TArrayD's
611//
612TArrayD* MFFT::RealFunctionIFFT(const TArrayD *data)
613{
614
615 fDim = data->GetSize();
616 CheckDim(fDim);
617
618 fDataD.Set(fDim);
619 //
620 // Clone the array
621 //
622 for (Int_t i=0;i<fDim;i++)
623 fDataD[i] = data->At(i);
624
625 RealFTD(-1);
626
627 return new TArrayD(fDim,fDataD.GetArray());
628}
629
630
631//
632// Power Spectrum Density Calculation
633//
634TH1D* MFFT::PowerSpectrumDensity(const TH1D *hist)
635{
636
637 TH1D *newhist = (TH1D*)CheckHist(hist,1);
638
639 fDataD.Set(fDim);
640 //
641 // Copy the hist into an array
642 //
643 for (Int_t i=0;i<fDim;i++)
644 fDataD[i] = hist->GetBinContent(i);
645
646 RealFTD(1);
647
648 Int_t dim2 = fDim*fDim;
649 Double_t c02;
650 Double_t ck2;
651 Double_t cn2;
652 //
653 // Fill the new histogram:
654 //
655 // 1) P(0) = 1/(N*N) |C(0)|*|C(0)|
656 // (stored in fData{0])
657 //
658 c02 = fDataD[0]*fDataD[0];
659 newhist->Fill(c02/dim2);
660 //
661 // 2) P(k) = 1/(N*N) (|C(k)|*|C(k)| + |C(N-k)|*|C(N-k)|)
662 //
663 for (Int_t k=2;k<fDim-2;k+=2)
664 {
665
666 Int_t ki = k+1;
667 ck2 = (fDataD[k]*fDataD[k] + fDataD[ki]*fDataD[ki]);
668 newhist->Fill(ck2/dim2);
669 }
670 //
671 // 3) P(N) = 1/(N*N) (|C(n/2)|*|C(n/2)|)
672 // (stored in fData[1])
673 //
674 cn2 = (fDataD[1]*fDataD[1]);
675 newhist->Fill(cn2/dim2);
676
677 return newhist;
678}
679
680//
681// Power Spectrum Density calculation for TArrayF
682//
683TArrayF* MFFT::PowerSpectrumDensity(const TArrayF *array)
684{
685
686 fDim = array->GetSize();
687 CheckDim(fDim);
688
689 fDataF.Set(fDim);
690 //
691 // Copy the hist into an array
692 //
693 for (Int_t i=0;i<fDim;i++)
694 fDataF[i] = array->At(i);
695
696 RealFTF(1);
697
698 const Int_t dim2 = fDim*fDim;
699 const Int_t dim05 = fDim/2;
700 Float_t c02;
701 Float_t ck2;
702 Float_t cn2;
703
704 TArrayF *newarray = new TArrayF(dim05);
705
706 //
707 // Fill the new histogram:
708 //
709 // 1) P(0) = 1/(N*N) |C(0)|*|C(0)|
710 //
711 c02 = (fDataF[0]*fDataF[0]);
712 // newarray->AddAt(c02/dim2,0);
713 //
714 // 2) P(k) = 1/(N*N) (|C(k)|*|C(k)|))
715 //
716 for (Int_t k=1;k<dim05-1;k++)
717 {
718 const Int_t k2 = k+k;
719 ck2 = (fDataF[k2]*fDataF[k2] + fDataF[k2+1]*fDataF[k2+1]);
720 newarray->AddAt(ck2/dim2,k);
721 }
722 //
723 // 3) P(N) = 1/(N*N) (|C(n/2)|*|C(n/2)|)
724 //
725 cn2 = (fDataF[1]*fDataF[1]);
726 // newarray->AddAt(cn2,dim05-1);
727
728 return newarray;
729}
730
731
732//
733// Power Spectrum Density calculation for TArrayI
734//
735TArrayF* MFFT::PowerSpectrumDensity(const TArrayI *array)
736{
737
738 fDim = array->GetSize();
739 CheckDim(fDim);
740
741 fDataF.Set(fDim);
742 //
743 // Copy the hist into an array
744 //
745 for (Int_t i=0;i<fDim;i++)
746 fDataF[i] = (Float_t)array->At(i);
747
748 RealFTF(1);
749
750 const Int_t dim2 = fDim*fDim;
751 const Int_t dim05 = fDim/2;
752 Float_t c02;
753 Float_t ck2;
754 Float_t cn2;
755
756 TArrayF *newarray = new TArrayF(dim05);
757
758 //
759 // Fill the new histogram:
760 //
761 // 1) P(0) = 1/(N*N) |C(0)|*|C(0)|
762 //
763 c02 = (fDataF[0]*fDataF[0]);
764 // newarray->AddAt(c02/dim2,0);
765 //
766 // 2) P(k) = 1/(N*N) (|C(k)|*|C(k)|))
767 //
768 for (Int_t k=1;k<dim05-1;k++)
769 {
770 const Int_t k2 = k+k;
771 ck2 = (fDataF[k2]*fDataF[k2] + fDataF[k2+1]*fDataF[k2+1]);
772 newarray->AddAt(ck2/dim2,k);
773 }
774 //
775 // 3) P(N) = 1/(N*N) (|C(n/2)|*|C(n/2)|)
776 //
777 cn2 = (fDataF[1]*fDataF[1]);
778 // newarray->AddAt(cn2,dim05-1);
779
780 return newarray;
781}
782
783
784TArrayD* MFFT::PowerSpectrumDensity(const TArrayD *array)
785{
786
787 fDim = array->GetSize();
788 CheckDim(fDim);
789
790 fDataD.Set(fDim);
791 //
792 // Copy the hist into an array
793 //
794 for (Int_t i=0;i<fDim;i++)
795 fDataD[i] = array->At(i);
796
797 RealFTD(1);
798
799 const Int_t dim2 = fDim*fDim;
800 const Int_t dim05 = fDim/2;
801 Float_t c02;
802 Float_t ck2;
803 Float_t cn2;
804
805 TArrayD *newarray = new TArrayD(dim05);
806
807 //
808 // Fill the new histogram:
809 //
810 // 1) P(0) = 1/(N*N) |C(0)|*|C(0)|
811 //
812 c02 = (fDataD[0]*fDataD[0]);
813 // newarray->AddAt(c02/dim2,0);
814 //
815 // 2) P(k) = 1/(N*N) (|C(k)|*|C(k)|))
816 //
817 for (Int_t k=1;k<dim05-1;k++)
818 {
819 const Int_t k2 = k+k;
820 ck2 = (fDataD[k2]*fDataD[k2] + fDataD[k2+1]*fDataD[k2+1]);
821 newarray->AddAt(ck2/dim2,k);
822 }
823 //
824 // 3) P(N) = 1/(N*N) (|C(n/2)|*|C(n/2)|)
825 //
826 cn2 = (fDataD[1]*fDataD[1]);
827 // newarray->AddAt(cn2,dim05-1);
828
829 return newarray;
830}
831
832
833//
834// Power Spectrum Density calculation for TH1
835//
836TH1F* MFFT::PowerSpectrumDensity(const TH1 *hist)
837{
838
839 TH1F *newhist = (TH1F*)CheckHist(hist,0);
840
841 fDataF.Set(fDim);
842 //
843 // Copy the hist into an array
844 //
845 for (Int_t i=0;i<fDim;i++)
846 fDataF[i] = hist->GetBinContent(i);
847
848 RealFTF(1);
849
850 Int_t dim2 = fDim*fDim;
851 Float_t c02;
852 Float_t ck2;
853 Float_t cn2;
854 //
855 // Fill the new histogram:
856 //
857 // 1) P(0) = 1/(N*N) |C(0)|*|C(0)|
858 //
859 c02 = (fDataF[0]*fDataF[0]);
860 newhist->Fill(0.,c02/dim2);
861 //
862 // 2) P(k) = 1/(N*N) (|C(k)|*|C(k)|))
863 //
864 for (Int_t k=2;k<fDim;k+=2)
865 {
866 ck2 = (fDataF[k]*fDataF[k] + fDataF[k+1]*fDataF[k+1]);
867 newhist->Fill(k/2.,ck2/dim2);
868 }
869 //
870 // 3) P(N) = 1/(N*N) (|C(n/2)|*|C(n/2)|)
871 //
872 cn2 = (fDataF[1]*fDataF[1]);
873 newhist->Fill(fDim/2.-1.,cn2/dim2);
874
875 return newhist;
876}
877
878
879//
880// Power Spectrum Density calculation for TH1I
881//
882TH1F* MFFT::PowerSpectrumDensity(const TH1F *hist)
883{
884 return PowerSpectrumDensity((TH1*)hist);
885}
886
887//
888// Power Spectrum Density calculation for TH1I
889//
890TH1F* MFFT::PowerSpectrumDensity(const TH1I *hist)
891{
892 return PowerSpectrumDensity((TH1*)hist);
893}
894
895
896void MFFT::CheckDim(Int_t a)
897{
898
899 // If even number, return 0
900 if (a==2) return;
901
902 // If odd number, return the closest power of 2
903 if (a & 1)
904 {
905 Int_t b = 1;
906 while (b < fDim/2+1)
907 b <<= 1;
908
909 fDim = b;
910 // gLog << warn << "Dimension of Data is not a multiple of 2, will take only first "
911 // << fDim << " entries! " << endl;
912 return;
913 }
914
915 CheckDim(a>>1);
916}
917
918TH1* MFFT::CheckHist(const TH1 *hist, const Int_t flag)
919{
920
921 // number of entries
922 fDim = hist->GetNbinsX();
923 CheckDim(fDim);
924
925 // Step width
926 Double_t delta = hist->GetBinWidth(1);
927
928 // Nyquist frequency
929 Axis_t fcrit = 1./(2.*delta);
930 Axis_t low = -0.5;
931 Axis_t up = fcrit;
932
933 switch (flag)
934 {
935 case 0:
936 return new TH1F(Form("%s%s",hist->GetName()," PSD"),
937 Form("%s%s",hist->GetTitle()," - Power Spectrum Density"),
938 fDim/2,low,up);
939 break;
940 case 1:
941 return new TH1D(Form("%s%s",hist->GetName()," PSD"),
942 Form("%s%s",hist->GetTitle()," - Power Spectrum Density"),
943 fDim/2,low,up);
944 break;
945 default:
946 return new TH1F(Form("%s%s",hist->GetName()," PSD"),
947 Form("%s%s",hist->GetTitle()," - Power Spectrum Density"),
948 fDim/2,low,up);
949 break;
950 }
951}
952
953//
954// Real function spectrum with data windowing
955//
956TArrayF* MFFT::RealFunctionSpectrum(const TArrayF *data)
957{
958
959 fDim = data->GetSize();
960 CheckDim(fDim);
961
962 fDataF.Set(fDim);
963 //
964 // Copy the hist into an array
965 //
966 for (Int_t i=0;i<fDim;i++)
967 fDataF[i] = data->At(i);
968
969 fWindowF.Set(fDim);
970
971 Int_t dim2 = fDim/2;
972
973 TArrayF *power = new TArrayF(dim2);
974
975 //
976 // Start program spctrm from NR's
977 //
978 Float_t w, facp, facm, sumw=0.;
979
980 facm = dim2;
981 facp = 1./dim2;
982
983 for (Int_t j=0;j<dim2;j++)
984 {
985 Int_t j2 = j+j;
986 w = ApplyWindow(j,facm,facp);
987 sumw += w*w;
988 fWindowF[j2] = fDataF[j]*w;
989 fWindowF[j2+1] = fDataF[dim2+j]*w;
990 }
991
992 TransformF(1,fWindowF);
993
994 power->AddAt(fWindowF[0]*fWindowF[0] + fWindowF[1]*fWindowF[1],0);
995
996 // power->AddAt(fWindowF[0]*fWindowF[0],0);
997 // power->AddAt(fWindowF[1]*fWindowF[1],dim2-1);
998
999
1000 for (Int_t j=1;j<dim2;j++)
1001 // for (Int_t j=1;j<dim2;j++)
1002 {
1003 Int_t j2 = j+j;
1004 Float_t buf = fWindowF[j2+1] *fWindowF[j2+1]
1005 + fWindowF[j2 ] *fWindowF[j2 ]
1006 + fWindowF[fDim-j2+1]*fWindowF[fDim-j2+1]
1007 + fWindowF[fDim-j2 ]*fWindowF[fDim-j2 ] ;
1008 power->AddAt(buf/sumw/(fDim+fDim),j);
1009 }
1010
1011 return power;
1012
1013}
Note: See TracBrowser for help on using the repository browser.