TVirtualFFT.cxx

Go to the documentation of this file.
00001 // @(#)root/base:$Id: TVirtualFFT.cxx 22967 2008-04-03 14:32:25Z rdm $
00002 // Author: Anna Kreshuk  10/04/2006
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //////////////////////////////////////////////////////////////////////////
00013 //
00014 // TVirtualFFT
00015 //
00016 // TVirtualFFT is an interface class for Fast Fourier Transforms.
00017 //
00018 //
00019 //
00020 // The default FFT library is FFTW. To use it, FFTW3 library should already
00021 // be installed, and ROOT should be have fftw3 module enabled, with the directories
00022 // of fftw3 include file and library specified (see installation instructions).
00023 // Function SetDefaultFFT() allows to change the default library.
00024 //
00025 // Available transform types:
00026 // FFT:
00027 // - "C2CFORWARD" - a complex input/output discrete Fourier transform (DFT)
00028 //                  in one or more dimensions, -1 in the exponent
00029 // - "C2CBACKWARD"- a complex input/output discrete Fourier transform (DFT)
00030 //                  in one or more dimensions, +1 in the exponent
00031 // - "R2C"        - a real-input/complex-output discrete Fourier transform (DFT)
00032 //                  in one or more dimensions,
00033 // - "C2R"        - inverse transforms to "R2C", taking complex input
00034 //                  (storing the non-redundant half of a logically Hermitian array)
00035 //                  to real output
00036 // - "R2HC"       - a real-input DFT with output in ¡Èhalfcomplex¡É format,
00037 //                  i.e. real and imaginary parts for a transform of size n stored as
00038 //                  r0, r1, r2, ..., rn/2, i(n+1)/2-1, ..., i2, i1
00039 // - "HC2R"       - computes the reverse of FFTW_R2HC, above
00040 // - "DHT"        - computes a discrete Hartley transform
00041 //
00042 // Sine/cosine transforms:
00043 // Different types of transforms are specified by parameter kind of the SineCosine() static
00044 // function. 4 different kinds of sine and cosine transforms are available
00045 //  DCT-I  (REDFT00 in FFTW3 notation)- kind=0
00046 //  DCT-II (REDFT10 in FFTW3 notation)- kind=1
00047 //  DCT-III(REDFT01 in FFTW3 notation)- kind=2
00048 //  DCT-IV (REDFT11 in FFTW3 notation)- kind=3
00049 //  DST-I  (RODFT00 in FFTW3 notation)- kind=4
00050 //  DST-II (RODFT10 in FFTW3 notation)- kind=5
00051 //  DST-III(RODFT01 in FFTW3 notation)- kind=6
00052 //  DST-IV (RODFT11 in FFTW3 notation)- kind=7
00053 // Formulas and detailed descriptions can be found in the chapter
00054 // "What FFTW really computes" of the FFTW manual
00055 //
00056 // NOTE: FFTW computes unnormalized transforms, so doing a transform, followed by its
00057 //       inverse will give the original array, multiplied by normalization constant
00058 //       (transform size(N) for FFT, 2*(N-1) for DCT-I, 2*(N+1) for DST-I, 2*N for
00059 //       other sine/cosine transforms)
00060 //
00061 // How to use it:
00062 // Call to the static function FFT returns a pointer to a fast fourier transform
00063 // with requested parameters. Call to the static function SineCosine returns a
00064 // pointer to a sine or cosine transform with requested parameters. Example:
00065 // {
00066 //    Int_t N = 10; Double_t *in = new Double_t[N];
00067 //    TVirtualFFT *fftr2c = TVirtualFFT::FFT(1, &N, "R2C");
00068 //    fftr2c->SetPoints(in);
00069 //    fftr2c->Transform();
00070 //    Double_t re, im;
00071 //    for (Int_t i=0; i<N; i++)
00072 //       fftr2c->GetPointComplex(i, re, im);
00073 //    ...
00074 //    fftr2c->SetPoints(in2);
00075 //    ...
00076 //    fftr2c->SetPoints(in3);
00077 //    ...
00078 // }
00079 // Different options are explained in the function comments
00080 //
00081 //
00082 //
00083 //
00084 //
00085 //////////////////////////////////////////////////////////////////////////
00086 
00087 #include "TROOT.h"
00088 #include "TVirtualFFT.h"
00089 #include "TPluginManager.h"
00090 #include "TEnv.h"
00091 #include "TError.h"
00092 
00093 TVirtualFFT *TVirtualFFT::fgFFT    = 0;
00094 TString      TVirtualFFT::fgDefault   = "";
00095 
00096 ClassImp(TVirtualFFT)
00097 
00098 //_____________________________________________________________________________
00099 TVirtualFFT::~TVirtualFFT()
00100 {
00101    //destructor
00102    if (this==fgFFT)
00103       fgFFT = 0;
00104 }
00105 
00106 //_____________________________________________________________________________
00107 TVirtualFFT* TVirtualFFT::FFT(Int_t ndim, Int_t *n, Option_t *option)
00108 {
00109 //Returns a pointer to the FFT of requested size and type.
00110 //Parameters:
00111 // -ndim : number of transform dimensions
00112 // -n    : sizes of each dimension (an array at least ndim long)
00113 // -option : consists of 3 parts - flag option and an option to create a new TVirtualFFT
00114 //         1) transform type option:
00115 //           Available transform types are:
00116 //           C2CForward, C2CBackward, C2R, R2C, R2HC, HC2R, DHT
00117 //           see class description for details
00118 //         2) flag option: choosing how much time should be spent in planning the transform:
00119 //           Possible options:
00120 //           "ES" (from "estimate") - no time in preparing the transform,
00121 //                                  but probably sub-optimal  performance
00122 //           "M"  (from "measure")  - some time spend in finding the optimal way
00123 //                                  to do the transform
00124 //           "P" (from "patient")   - more time spend in finding the optimal way
00125 //                                  to do the transform
00126 //           "EX" (from "exhaustive") - the most optimal way is found
00127 //           This option should be chosen depending on how many transforms of the
00128 //           same size and type are going to be done.
00129 //           Planning is only done once, for the first transform of this size and type.
00130 //         3) option allowing to choose between the global fgFFT and a new TVirtualFFT object
00131 //           ""  - default, changes and returns the global fgFFT variable
00132 //           "K" (from "keep")- without touching the global fgFFT,
00133 //           creates and returns a new TVirtualFFT*. User is then responsible for deleting it.
00134 // Examples of valid options: "R2C ES K", "C2CF M", "DHT P K", etc.
00135 
00136 
00137    Int_t inputtype=0, currenttype=0;
00138    TString opt = option;
00139    opt.ToUpper();
00140    //find the tranform flag
00141    Option_t *flag;
00142    flag = "ES";
00143    if (opt.Contains("ES")) flag = "ES";
00144    if (opt.Contains("M"))  flag = "M";
00145    if (opt.Contains("P"))  flag = "P";
00146    if (opt.Contains("EX")) flag = "EX";
00147 
00148    Int_t ndiff = 0;
00149 
00150    if (!opt.Contains("K")) {
00151       if (fgFFT){
00152          //if the global transform exists, check if it should be changed
00153          if (fgFFT->GetNdim()!=ndim)
00154             ndiff++;
00155          else {
00156             Int_t *ncurrent = fgFFT->GetN();
00157             for (Int_t i=0; i<ndim; i++){
00158                if (n[i]!=ncurrent[i])
00159                   ndiff++;
00160             }
00161          }
00162          Option_t *t = fgFFT->GetType();
00163          if (!opt.Contains(t)) {
00164             if (opt.Contains("HC") || opt.Contains("DHT"))
00165                inputtype = 1;
00166             if (strcmp(t,"R2HC")==0 || strcmp(t,"HC2R")==0 || strcmp(t,"DHT")==0)
00167                currenttype=1;
00168 
00169             if (!(inputtype==1 && currenttype==1))
00170                ndiff++;
00171          }
00172          if (ndiff>0){
00173             delete fgFFT;
00174             fgFFT = 0;
00175          }
00176       }
00177    }
00178 
00179    Int_t sign = 0;
00180    if (opt.Contains("C2CB") || opt.Contains("C2R"))
00181       sign = 1;
00182    if (opt.Contains("C2CF") || opt.Contains("R2C"))
00183       sign = -1;
00184 
00185    TVirtualFFT *fft = 0;
00186    if (opt.Contains("K") || !fgFFT) {
00187       TPluginHandler *h;
00188       TString pluginname;
00189       if (fgDefault.Length()==0) fgDefault="fftw";
00190       if (strcmp(fgDefault.Data(),"fftw")==0) {
00191          if (opt.Contains("C2C")) pluginname = "fftwc2c";
00192          if (opt.Contains("C2R")) pluginname = "fftwc2r";
00193          if (opt.Contains("R2C")) pluginname = "fftwr2c";
00194          if (opt.Contains("HC") || opt.Contains("DHT")) pluginname = "fftwr2r";
00195          if ((h=gROOT->GetPluginManager()->FindHandler("TVirtualFFT", pluginname))) {
00196             if (h->LoadPlugin()==-1) {
00197                ::Error("TVirtualFFT::FFT", "handler not found");
00198                return 0;
00199             }
00200             fft = (TVirtualFFT*)h->ExecPlugin(3, ndim, n, kFALSE);
00201             if (!fft) {
00202                ::Error("TVirtualFFT::FFT", "plugin failed to create TVirtualFFT object");
00203                return 0;
00204             }
00205             Int_t *kind = new Int_t[1];
00206             if (pluginname=="fftwr2r") {
00207                if (opt.Contains("R2HC")) kind[0] = 10;
00208                if (opt.Contains("HC2R")) kind[0] = 11;
00209                if (opt.Contains("DHT")) kind[0] = 12;
00210             }
00211             fft->Init(flag, sign, kind);
00212             if (!opt.Contains("K")) {
00213                fgFFT = fft;
00214             }
00215             delete [] kind;
00216             return fft;
00217          }
00218          else {
00219             ::Error("TVirtualFFT::FFT", "plugin not found");
00220             return 0;
00221          }
00222       }
00223    } else {
00224       //if the global transform already exists and just needs to be reinitialised
00225       //with different parameters
00226       if (fgFFT->GetSign()!=sign || !opt.Contains(fgFFT->GetTransformFlag()) || !opt.Contains(fgFFT->GetType())) {
00227          Int_t *kind = new Int_t[1];
00228          if (inputtype==1) {
00229             if (opt.Contains("R2HC")) kind[0] = 10;
00230             if (opt.Contains("HC2R")) kind[0] = 11;
00231             if (opt.Contains("DHT")) kind[0] = 12;
00232          }
00233          fgFFT->Init(flag, sign, kind);
00234          delete [] kind;
00235       }
00236    }
00237    return fgFFT;
00238 }
00239 
00240 //_____________________________________________________________________________
00241 TVirtualFFT* TVirtualFFT::SineCosine(Int_t ndim, Int_t *n, Int_t *r2rkind, Option_t *option)
00242 {
00243 //Returns a pointer to a sine or cosine transform of requested size and kind
00244 //
00245 //Parameters:
00246 // -ndim    : number of transform dimensions
00247 // -n       : sizes of each dimension (an array at least ndim long)
00248 // -r2rkind : transform kind for each dimension
00249 //     4 different kinds of sine and cosine transforms are available
00250 //     DCT-I    - kind=0
00251 //     DCT-II   - kind=1
00252 //     DCT-III  - kind=2
00253 //     DCT-IV   - kind=3
00254 //     DST-I    - kind=4
00255 //     DST-II   - kind=5
00256 //     DST-III  - kind=6
00257 //     DST-IV   - kind=7
00258 // -option : consists of 2 parts - flag option and an option to create a new TVirtualFFT
00259 //         - flag option: choosing how much time should be spent in planning the transform:
00260 //           Possible options:
00261 //           "ES" (from "estimate") - no time in preparing the transform,
00262 //                                  but probably sub-optimal  performance
00263 //           "M"  (from "measure")  - some time spend in finding the optimal way
00264 //                                  to do the transform
00265 //           "P" (from "patient")   - more time spend in finding the optimal way
00266 //                                  to do the transform
00267 //           "EX" (from "exhaustive") - the most optimal way is found
00268 //           This option should be chosen depending on how many transforms of the
00269 //           same size and type are going to be done.
00270 //           Planning is only done once, for the first transform of this size and type.
00271 //         - option allowing to choose between the global fgFFT and a new TVirtualFFT object
00272 //           ""  - default, changes and returns the global fgFFT variable
00273 //           "K" (from "keep")- without touching the global fgFFT,
00274 //           creates and returns a new TVirtualFFT*. User is then responsible for deleting it.
00275 // Examples of valid options: "ES K", "EX", etc
00276 
00277    TString opt = option;
00278    //find the tranform flag
00279    Option_t *flag;
00280    flag = "ES";
00281    if (opt.Contains("ES")) flag = "ES";
00282    if (opt.Contains("M"))  flag = "M";
00283    if (opt.Contains("P"))  flag = "P";
00284    if (opt.Contains("EX")) flag = "EX";
00285 
00286    if (!opt.Contains("K")) {
00287       if (fgFFT){
00288          Int_t ndiff = 0;
00289          if (fgFFT->GetNdim()!=ndim || strcmp(fgFFT->GetType(),"R2R")!=0)
00290             ndiff++;
00291          else {
00292             Int_t *ncurrent = fgFFT->GetN();
00293             for (Int_t i=0; i<ndim; i++) {
00294                if (n[i] != ncurrent[i])
00295                   ndiff++;
00296             }
00297 
00298          }
00299          if (ndiff>0) {
00300             delete fgFFT;
00301             fgFFT = 0;
00302          }
00303       }
00304    }
00305    TVirtualFFT *fft = 0;
00306    if (!fgFFT || opt.Contains("K")) {
00307       TPluginHandler *h;
00308       TString pluginname;
00309       if (fgDefault.Length()==0) fgDefault="fftw";
00310       if (strcmp(fgDefault.Data(),"fftw")==0) {
00311          pluginname = "fftwr2r";
00312          if ((h=gROOT->GetPluginManager()->FindHandler("TVirtualFFT", pluginname))) {
00313             if (h->LoadPlugin()==-1){
00314                ::Error("TVirtualFFT::SineCosine", "handler not found");
00315                return 0;
00316             }
00317             fft = (TVirtualFFT*)h->ExecPlugin(3, ndim, n, kFALSE);
00318             if (!fft) {
00319                ::Error("TVirtualFFT::SineCosine", "plugin failed to create TVirtualFFT object");
00320                return 0;
00321             }
00322             fft->Init(flag, 0, r2rkind);
00323             if (!opt.Contains("K"))
00324                fgFFT = fft;
00325             return fft;
00326          } else {
00327             ::Error("TVirtualFFT::SineCosine", "handler not found");
00328             return 0;
00329          }
00330       }
00331    }
00332 
00333    //if (fgFFT->GetTransformFlag()!=flag)
00334    fgFFT->Init(flag,0, r2rkind);
00335    return fgFFT;
00336 }
00337 
00338 //_____________________________________________________________________________
00339 TVirtualFFT* TVirtualFFT::GetCurrentTransform()
00340 {
00341 // static: return current fgFFT
00342 
00343    if (fgFFT)
00344       return fgFFT;
00345    else{
00346       ::Warning("TVirtualFFT::GetCurrentTransform", "fgFFT is not defined yet");
00347       return 0;
00348    }
00349 }
00350 
00351 //_____________________________________________________________________________
00352 void TVirtualFFT::SetTransform(TVirtualFFT* fft)
00353 {
00354 // static: set the current transfrom to parameter
00355 
00356    fgFFT = fft;
00357 }
00358 
00359 //_____________________________________________________________________________
00360 const char *TVirtualFFT::GetDefaultFFT()
00361 {
00362 // static: return the name of the default fft
00363 
00364    return fgDefault.Data();
00365 }
00366 
00367 //______________________________________________________________________________
00368 void TVirtualFFT::SetDefaultFFT(const char *name)
00369 {
00370    // static: set name of default fft
00371 
00372    if (fgDefault == name) return;
00373    delete fgFFT;
00374    fgFFT = 0;
00375    fgDefault = name;
00376 }

Generated on Tue Jul 5 14:11:24 2011 for ROOT_528-00b_version by  doxygen 1.5.1