#include "TH1D.h" #include "TVirtualFFT.h" #include "TF1.h" #include "TCanvas.h" #include "TMath.h" void FFT() { //This tutorial illustrates the Fast Fourier Transforms interface in ROOT. //FFT transform types provided in ROOT: // - "C2CFORWARD" - a complex input/output discrete Fourier transform (DFT) // in one or more dimensions, -1 in the exponent // - "C2CBACKWARD"- a complex input/output discrete Fourier transform (DFT) // in one or more dimensions, +1 in the exponent // - "R2C" - a real-input/complex-output discrete Fourier transform (DFT) // in one or more dimensions, // - "C2R" - inverse transforms to "R2C", taking complex input // (storing the non-redundant half of a logically Hermitian array) // to real output // - "R2HC" - a real-input DFT with output in ¡Èhalfcomplex¡É format, // i.e. real and imaginary parts for a transform of size n stored as // r0, r1, r2, ..., rn/2, i(n+1)/2-1, ..., i2, i1 // - "HC2R" - computes the reverse of FFTW_R2HC, above // - "DHT" - computes a discrete Hartley transform // Sine/cosine transforms: // DCT-I (REDFT00 in FFTW3 notation) // DCT-II (REDFT10 in FFTW3 notation) // DCT-III(REDFT01 in FFTW3 notation) // DCT-IV (REDFT11 in FFTW3 notation) // DST-I (RODFT00 in FFTW3 notation) // DST-II (RODFT10 in FFTW3 notation) // DST-III(RODFT01 in FFTW3 notation) // DST-IV (RODFT11 in FFTW3 notation) //First part of the tutorial shows how to transform the histograms //Second part shows how to transform the data arrays directly //Authors: Anna Kreshuk and Jens Hoffmann //********* Histograms ********// //prepare the canvas for drawing TCanvas *myc = new TCanvas("myc", "Fast Fourier Transform", 800, 600); myc->SetFillColor(45); TPad *c1_1 = new TPad("c1_1", "c1_1",0.01,0.67,0.49,0.99); TPad *c1_2 = new TPad("c1_2", "c1_2",0.51,0.67,0.99,0.99); TPad *c1_3 = new TPad("c1_3", "c1_3",0.01,0.34,0.49,0.65); TPad *c1_4 = new TPad("c1_4", "c1_4",0.51,0.34,0.99,0.65); TPad *c1_5 = new TPad("c1_5", "c1_5",0.01,0.01,0.49,0.32); TPad *c1_6 = new TPad("c1_6", "c1_6",0.51,0.01,0.99,0.32); c1_1->Draw(); c1_2->Draw(); c1_3->Draw(); c1_4->Draw(); c1_5->Draw(); c1_6->Draw(); c1_1->SetFillColor(30); c1_1->SetFrameFillColor(42); c1_2->SetFillColor(30); c1_2->SetFrameFillColor(42); c1_3->SetFillColor(30); c1_3->SetFrameFillColor(42); c1_4->SetFillColor(30); c1_4->SetFrameFillColor(42); c1_5->SetFillColor(30); c1_5->SetFrameFillColor(42); c1_6->SetFillColor(30); c1_6->SetFrameFillColor(42); c1_1->cd(); TH1::AddDirectory(kFALSE); //A function to sample TF1 *fsin = new TF1("fsin", "sin(x)+sin(2*x)+sin(0.5*x)+1", 0, 4*TMath::Pi()); fsin->Draw(); Int_t n=25; TH1D *hsin = new TH1D("hsin", "hsin", n+1, 0, 4*TMath::Pi()); Double_t x; //Fill the histogram with function values for (Int_t i=0; i<=n; i++){ x = (Double_t(i)/n)*(4*TMath::Pi()); hsin->SetBinContent(i+1, fsin->Eval(x)); } hsin->Draw("same"); fsin->GetXaxis()->SetLabelSize(0.05); fsin->GetYaxis()->SetLabelSize(0.05); c1_2->cd(); //Compute the transform and look at the magnitude of the output TH1 *hm =0; TVirtualFFT::SetTransform(0); hm = hsin->FFT(hm, "MAG"); hm->SetTitle("Magnitude of the 1st transform"); hm->Draw(); //NOTE: for "real" frequencies you have to divide the x-axes range with the range of your function //(in this case 4*Pi); y-axes has to be rescaled by a factor of 1/SQRT(n) to be right: this is not done automatically! hm->SetStats(kFALSE); hm->GetXaxis()->SetLabelSize(0.05); hm->GetYaxis()->SetLabelSize(0.05); c1_3->cd(); //Look at the phase of the output TH1 *hp = 0; hp = hsin->FFT(hp, "PH"); hp->SetTitle("Phase of the 1st transform"); hp->Draw(); hp->SetStats(kFALSE); hp->GetXaxis()->SetLabelSize(0.05); hp->GetYaxis()->SetLabelSize(0.05); //Look at the DC component and the Nyquist harmonic: Double_t re, im; //That's the way to get the current transform object: TVirtualFFT *fft = TVirtualFFT::GetCurrentTransform(); c1_4->cd(); //Use the following method to get just one point of the output fft->GetPointComplex(0, re, im); printf("1st transform: DC component: %f\n", re); fft->GetPointComplex(n/2+1, re, im); printf("1st transform: Nyquist harmonic: %f\n", re); //Use the following method to get the full output: Double_t *re_full = new Double_t[n]; Double_t *im_full = new Double_t[n]; fft->GetPointsComplex(re_full,im_full); //Now let's make a backward transform: TVirtualFFT *fft_back = TVirtualFFT::FFT(1, &n, "C2R M K"); fft_back->SetPointsComplex(re_full,im_full); fft_back->Transform(); TH1 *hb = 0; //Let's look at the output hb = TH1::TransformHisto(fft_back,hb,"Re"); hb->SetTitle("The backward transform result"); hb->Draw(); //NOTE: here you get at the x-axes number of bins and not real values //(in this case 25 bins has to be rescaled to a range between 0 and 4*Pi; //also here the y-axes has to be rescaled (factor 1/bins) hb->SetStats(kFALSE); hb->GetXaxis()->SetLabelSize(0.05); hb->GetYaxis()->SetLabelSize(0.05); delete fft_back; fft_back=0; //********* Data array - same transform ********// //Allocate an array big enough to hold the transform output //Transform output in 1d contains, for a transform of size N, //N/2+1 complex numbers, i.e. 2*(N/2+1) real numbers //our transform is of size n+1, because the histogram has n+1 bins Double_t *in = new Double_t[2*((n+1)/2+1)]; Double_t re_2,im_2; for (Int_t i=0; i<=n; i++){ x = (Double_t(i)/n)*(4*TMath::Pi()); in[i] = fsin->Eval(x); } //Make our own TVirtualFFT object (using option "K") //Third parameter (option) consists of 3 parts: //-transform type: // real input/complex output in our case //-transform flag: // the amount of time spent in planning // the transform (see TVirtualFFT class description) //-to create a new TVirtualFFT object (option "K") or use the global (default) Int_t n_size = n+1; TVirtualFFT *fft_own = TVirtualFFT::FFT(1, &n_size, "R2C ES K"); if (!fft_own) return; fft_own->SetPoints(in); fft_own->Transform(); //Copy all the output points: fft_own->GetPoints(in); //Draw the real part of the output c1_5->cd(); TH1 *hr = 0; hr = TH1::TransformHisto(fft_own, hr, "RE"); hr->SetTitle("Real part of the 3rd (array) tranfsorm"); hr->Draw(); hr->SetStats(kFALSE); hr->GetXaxis()->SetLabelSize(0.05); hr->GetYaxis()->SetLabelSize(0.05); c1_6->cd(); TH1 *him = 0; him = TH1::TransformHisto(fft_own, him, "IM"); him->SetTitle("Im. part of the 3rd (array) transform"); him->Draw(); him->SetStats(kFALSE); him->GetXaxis()->SetLabelSize(0.05); him->GetYaxis()->SetLabelSize(0.05); myc->cd(); //Now let's make another transform of the same size //The same transform object can be used, as the size and the type of the transform //haven't changed TF1 *fcos = new TF1("fcos", "cos(x)+cos(0.5*x)+cos(2*x)+1", 0, 4*TMath::Pi()); for (Int_t i=0; i<=n; i++){ x = (Double_t(i)/n)*(4*TMath::Pi()); in[i] = fcos->Eval(x); } fft_own->SetPoints(in); fft_own->Transform(); fft_own->GetPointComplex(0, re_2, im_2); printf("2nd transform: DC component: %f\n", re_2); fft_own->GetPointComplex(n/2+1, re_2, im_2); printf("2nd transform: Nyquist harmonic: %f\n", re_2); delete fft_own; delete [] in; delete [] re_full; delete [] im_full; } FFT.C:1 FFT.C:2 FFT.C:3 FFT.C:4 FFT.C:5 FFT.C:6 FFT.C:7 FFT.C:8 FFT.C:9 FFT.C:10 FFT.C:11 FFT.C:12 FFT.C:13 FFT.C:14 FFT.C:15 FFT.C:16 FFT.C:17 FFT.C:18 FFT.C:19 FFT.C:20 FFT.C:21 FFT.C:22 FFT.C:23 FFT.C:24 FFT.C:25 FFT.C:26 FFT.C:27 FFT.C:28 FFT.C:29 FFT.C:30 FFT.C:31 FFT.C:32 FFT.C:33 FFT.C:34 FFT.C:35 FFT.C:36 FFT.C:37 FFT.C:38 FFT.C:39 FFT.C:40 FFT.C:41 FFT.C:42 FFT.C:43 FFT.C:44 FFT.C:45 FFT.C:46 FFT.C:47 FFT.C:48 FFT.C:49 FFT.C:50 FFT.C:51 FFT.C:52 FFT.C:53 FFT.C:54 FFT.C:55 FFT.C:56 FFT.C:57 FFT.C:58 FFT.C:59 FFT.C:60 FFT.C:61 FFT.C:62 FFT.C:63 FFT.C:64 FFT.C:65 FFT.C:66 FFT.C:67 FFT.C:68 FFT.C:69 FFT.C:70 FFT.C:71 FFT.C:72 FFT.C:73 FFT.C:74 FFT.C:75 FFT.C:76 FFT.C:77 FFT.C:78 FFT.C:79 FFT.C:80 FFT.C:81 FFT.C:82 FFT.C:83 FFT.C:84 FFT.C:85 FFT.C:86 FFT.C:87 FFT.C:88 FFT.C:89 FFT.C:90 FFT.C:91 FFT.C:92 FFT.C:93 FFT.C:94 FFT.C:95 FFT.C:96 FFT.C:97 FFT.C:98 FFT.C:99 FFT.C:100 FFT.C:101 FFT.C:102 FFT.C:103 FFT.C:104 FFT.C:105 FFT.C:106 FFT.C:107 FFT.C:108 FFT.C:109 FFT.C:110 FFT.C:111 FFT.C:112 FFT.C:113 FFT.C:114 FFT.C:115 FFT.C:116 FFT.C:117 FFT.C:118 FFT.C:119 FFT.C:120 FFT.C:121 FFT.C:122 FFT.C:123 FFT.C:124 FFT.C:125 FFT.C:126 FFT.C:127 FFT.C:128 FFT.C:129 FFT.C:130 FFT.C:131 FFT.C:132 FFT.C:133 FFT.C:134 FFT.C:135 FFT.C:136 FFT.C:137 FFT.C:138 FFT.C:139 FFT.C:140 FFT.C:141 FFT.C:142 FFT.C:143 FFT.C:144 FFT.C:145 FFT.C:146 FFT.C:147 FFT.C:148 FFT.C:149 FFT.C:150 FFT.C:151 FFT.C:152 FFT.C:153 FFT.C:154 FFT.C:155 FFT.C:156 FFT.C:157 FFT.C:158 FFT.C:159 FFT.C:160 FFT.C:161 FFT.C:162 FFT.C:163 FFT.C:164 FFT.C:165 FFT.C:166 FFT.C:167 FFT.C:168 FFT.C:169 FFT.C:170 FFT.C:171 FFT.C:172 FFT.C:173 FFT.C:174 FFT.C:175 FFT.C:176 FFT.C:177 FFT.C:178 FFT.C:179 FFT.C:180 FFT.C:181 FFT.C:182 FFT.C:183 FFT.C:184 FFT.C:185 FFT.C:186 FFT.C:187 FFT.C:188 FFT.C:189 FFT.C:190 FFT.C:191 FFT.C:192 FFT.C:193 FFT.C:194 FFT.C:195 FFT.C:196 FFT.C:197 FFT.C:198 FFT.C:199 FFT.C:200 FFT.C:201 FFT.C:202 FFT.C:203 FFT.C:204 FFT.C:205 FFT.C:206 FFT.C:207 FFT.C:208 FFT.C:209 FFT.C:210 FFT.C:211 FFT.C:212 FFT.C:213 FFT.C:214 FFT.C:215 FFT.C:216 FFT.C:217 |
|