Пример #1
0
//                     DOFF do fit fft   1=fit   2=fft+fit
//   fit cointains: baselineshift; fft; 
//
void ro_readwav(char* fname , int start=0, int stop=0, int DOFF=0,char *OPT="WWN0Q", char *clerun="run"){

  FILE *f;
  int i,j=0;
  Short_t ssample[10];
  UShort_t buffer[2200]; // usually 600

  //============ OPEN FILE========== READ 1st word
  f=fopen( fname , "r" );
  fread( ssample, sizeof(Short_t), 1 , f );
  printf("i ... sample size = %d ... one integer is %d  bytes\n",
	 ssample[0] , sizeof(Short_t)  );
  // read the rest =================== 1st sample 
  fread( buffer, sizeof(Short_t), ssample[0]-1, f );
  for (i=0;i<ssample[0];i++){buffer[i]=0;} // clean buffer
  printf("%s\n", "buffer clean");


  //----------------- DECLARATIONS #2
  TH1F *hch[8]; // channel histograms: 0-7 FW
  for (i=0;i<8;i++){hch[i]=NULL;}
  TH1F *hchf[8]; // chan fit 
  for (i=0;i<8;i++){hchf[i]=NULL;}
  TH1F *htime[8]; // I cannot Fill time histo !?
  for (i=0;i<8;i++){htime[i]=NULL;}
  TH2F* bidim[8];  // slope vs ene
  for (i=0;i<8;i++){bidim[i]=NULL;}
  //  TH2F* ede=new TH2F("ede","E x dE matrix",400,0,8000,400,0,8000);



  
  TH1F *h; // WAVE HISTOGRAM ============ MAIN HISTOGRAM
  
  char hname[20];   // histo channels
  int result;    
  int sizeOfStr=16; // SIZE OF struct with b,ch,t,E
  // ---- structure data:
  Short_t b,ch, evnt, ene ;  // board channel energy
  unsigned long long time=0;
  // tets differences
  unsigned long long timelast=0;
  Short_t extr;
  float avg=0.0;
  // fit parameters:
  double* pars;
  

    //==============================FILE  TTREE ================
    struct Tdata{
      ULong64_t t;   //l  time 
      Int_t n;       // i  event number
      Int_t ch;      // i   channel
      Int_t e;       //i    energy
      Float_t efit;  //F    energy from fit
      Float_t xi;    //F    Xi2 from  fit
      Float_t s;     //F    s - slope from fit
     //-------------------COINCIDENCES from NOW -----------
      Int_t e0;      // COINC CASE    E0
      Int_t e1;      // COINC CASE    E0
      Int_t dt;      //I   +-

      Int_t efit0;
      Int_t efit1;
      Int_t s0;
      Int_t s1;
      
    } event;
      
    char outname[300];   // OUT =   infile.root
    char wc[100];int wci=0;
    //    sprintf(outname,"%s_%06d_%06d.root", fname , start, stop );
    sprintf(outname,"%s_%06d_%06d.root" , clerun, start, stop );
    
    TFile *fo=new TFile(  outname ,"recreate");
    TTree *to=new TTree("pha","dpp_pha_data");
    to->Branch("time",&event.t,"t/l");
    to->Branch("data",&event.n,"n/i:ch/i:e/i:efit/F:xi/F:s/F");
    to->Branch("coin",&event.e0,"e0/i:e1/i:dt/I:efit0/I:efit1/I:s0/I:s1/I");


    MyCoinc *mc=new MyCoinc(0,1);  // guard channels  0 + 1 
//
    //
    //

    //#####################################  LOOP #####################
    int JMIN=start;
    int JMAX=stop;
    if (stop==0){JMAX=999999999;}
    //  JMAX=111;    // limit for test
    for (j=0;j<=JMAX;j++){
    
    event.n=j;
    event.e=0;
    event.efit=0;
    event.xi=0;
    event.s=0;

    event.efit0=0;
    event.efit1=0;
    event.s0=0;
    event.s1=0;

    // ch  t 
    
    result=fread( buffer,sizeof(Short_t) , sizeOfStr, f );
    if (result<sizeOfStr) break;
    //---------------- FW header decode
    b=buffer[0];
    ch=buffer[1];
    evnt=buffer[2];
    //[8]-[11] ... time
    //--------------- Time decode
    time=0;
    time=buffer[11];      time=time<<16;
    time=time+buffer[10]; time=time<<16;
    time=time+buffer[9]; time=time<<16;
    time=time+buffer[8];
    timelast=time;
    
    ene=buffer[12];
    extr=buffer[13];
    //    printf( "ch/evnt/ene   %3d   %3d  %3d  E=%3d  %3d\n", ch, evnt, ene, extr );
    //    printf("%lld  =======  %3d  \n", time, ene);

    event.t=time;
    event.e=ene;
    event.ch=ch;

    
    //================ FILL ENERGY HISTO
    if (hch[ ch ]==NULL){
      sprintf(hname,"hifw_%02d", ch);
      hch[ ch ]= new TH1F( hname,hname,16000,0,16000);
    }
    //  printf("%s\n", "J loop hifw ok");
    hch[ch]->Fill( ene );

    //================ FILL TIME HISTO
    if (htime[ch]==NULL){
      sprintf(hname,"hitime_%02d", ch); 
      //      htime[ch]= new TH1F( hname,"timeprofile;[seconds]",1000000,0,100);
      int seconds=1000;
      htime[ch]= new TH1F( hname,"hname",seconds*100,0,seconds);
      printf("defined  %d. htime\n",ch);
    }
    htime[ch]->Fill( float(time/100000000.) );

    if (j%1000==0){printf( "j=%d ...\n", j );}

    
    //    if ( j>= start){ //=======PARALLEL LOOP===============
    //===============================================LOAD WAVEFORM
    result = fread( buffer,sizeof(Short_t) , ssample[0], f );
    if (result< ssample[0]) break;

    
   


    
    // ============ FIT / ANALYZE ================
    int makefit=0;
    if ((j>=start)&&(j<stop) ){ makefit=1;}

    
    if (DOFF==0){ makefit=0;} //no reason, but ok
    if (makefit==1){
      //====CREATE HISTOGRAM wave ==>>> VARIANT:create/analyze/root it/delete
      //      if (j-start<100){
	sprintf(hname,"wave_%06d", j); // here I keep the channel
	h=new TH1F( hname,hname, ssample[0],0,ssample[0] );
     //      }// create only when #<100;  then REUSE "h"

      //====== prepare ZERO (one analyze parameter now)
      avg=0.0;
      for (i=0;i<50;i++){avg=avg+buffer[i];}
      avg=avg/(50.);


      // HISTOGRAM IS FILLED  HERE:
      // ### ======= Fill SHIFTED buffer TO ZERO histogram
      for (i=0;i<ssample[0];i++){    // i add ch 0/1 to the end!
	h->SetBinContent( i+1, buffer[i] - avg ); // 0-1 is #1
      }

      // ### FFT HERE //
      if (DOFF==2){  //====================++FFT BEGIN =============
      int n=ssample[0];
	TH1 *hmsm =0;
	TH1 *hpsm =0;
	hmsm=h->FFT(hmsm,"MAG");
	hpsm=h->FFT(hpsm,"PH");
	TVirtualFFT *fft = TVirtualFFT::GetCurrentTransform();
	Double_t *re_full = new Double_t[ssample[0]];
	Double_t *im_full = new Double_t[ssample[0]];
	fft->GetPointsComplex(re_full,im_full);
	for (int j=0;j<ssample[0]/2; j++){
	  hmsm->SetBinContent( j,  re_full[j]   );
	  hpsm->SetBinContent( j,  im_full[j]   );
	}
	//	for (int j=16;j>11;j--){
	hmsm->Smooth(2);
	hpsm->Smooth(2);
	for (int j=16;j>5;j--){
	  hmsm->SetBinContent( j,  0.8*re_full[j]   );
	  hpsm->SetBinContent( j,  0.8*im_full[j]   );
	}
	hmsm->Smooth(2);
	hpsm->Smooth(2);

	for (int j=0;j<ssample[0]/2;j++){
	  re_full[j]=hmsm->GetBinContent(j);
	  im_full[j]=hpsm->GetBinContent(j);
	}
 	TVirtualFFT *fft_back = TVirtualFFT::FFT(1, &n, "C2R M K");
	fft_back->SetPointsComplex(re_full,im_full);
	fft_back->Transform();
	TH1 *hb = 0;
	hb = TH1::TransformHisto(fft_back,hb,"Re");
	double mx= mx=hb->GetMaximum();
	double omax= h->GetMaximum();
	hb->Scale( omax/mx );
	delete fft_back;
	delete [] re_full;
	delete [] im_full;
	if (gPad!=NULL){
	  h->Draw();
	  hb->Draw("same");hb->SetLineColor(3);
	  gPad->Modified(); gPad->Update();
	}
	for (int j=0;j<ssample[0];j++){
	  h->SetBinContent( j, hb->GetBinContent(j) );
	}
	delete hb;
	delete hmsm;
	delete hpsm;
	//	sleep(1);
	//	h->Draw(); gPad->Modified(); gPad->Update();

      }// ========================================= FFT HERE  END



      
      // ### ===========     fit 1 ==========
      pars=fit1( ssample[0],  h , OPT ); // FIT 400 points in a sample
      printf("%06d/ %6.1f %5.2f    %5.2f  \n", j, pars[0], pars[1] ,pars[2]  );
      if ( bidim[ch]==NULL ){
	sprintf(hname,"bishape_%02d", ch);
	bidim[ch]=new TH2F( hname,"shapes;Energy;slope in channels", 2500,0,2500,450,2,45);
      }
      bidim[ch]->Fill( pars[0], pars[1] );
      //      sleep(1);
      
      //##### DEBUG HERE".....................
      // # pars[1]===S
      // # pars[0]==E
      //      if ( (ch==0)&&(pars[0]>960.) ){
      /*
      if ( (ch==0)&&(pars[1]>100.) ){
	printf("S problem @ %d chan %d S=%f\n",j,ch, pars[1]);
	sleep(5);
      }
      */
      //================ FILL ENERGY FIT HISTO
      if (hchf[ ch ]==NULL){
	sprintf(hname,"hifit_%02d", ch);
	hchf[ ch ]= new TH1F( hname,hname,16000,0,16000);
      }
      hchf[ch]->Fill( pars[0] );

      event.efit=pars[0];
      event.s=10*pars[1];
      event.xi=10*pars[2];
      if ( strstr(OPT,"WWN0Q")!=NULL)  {
	delete h;
	//       	printf("%s %s\n","...DELEING histogram ", OPT);
      }else{
	h->Write();
	printf("%s","...writing histogram to file\n");
      } //write to tree if not N0Q
    } // fit ---------------------------------------------END--
   // =========== FIT / ANALYZE  ============= END  ===========
    if ( event.efit>16000){
      event.efit=0;
      event.s=0;
      event.xi=0;
    }

    event.e0=0;
    event.e1=0;
    event.dt=0;


    //=================COINCIDENCES ========== BEGIN ======
    //  and if result == 1 : coincidence was found....
    if (1==mc->add( ch, event.t, event.e, event.efit, event.xi,event.s) ){
                                    // event.efit
      event.e0=mc->getlastC0();
      event.e1=mc->getlastC1();
      event.efit0=mc->getlastC0fit();
      event.efit1=mc->getlastC1fit();
      event.s0=mc->getlastC0s();
      event.s1=mc->getlastC1s();
      event.dt=-mc->getlastDT();
      if ( (event.dt>400)||(event.dt<-400)){
	printf("%4d mc ============================\n", event.dt);
      }
    } //============================ COINCIDENCES END =====
    


    
    if (makefit==1){ delete pars; } // no pars if no fit
    //    if (h!=NULL){delete h;}   // delete  WAVE HISTOGRAM

    //==========SAVE TTREE======
    //    if (makefit==1){
      to->Fill();
      //    }
    //    } // ===========PARALLEL LOOP ===========
    
  } //------- j < JMAX ------=====================================END




    fclose(f);
    
    if (j>=JMAX){  // i dont create thousands of th1f anymore
      printf("!... limit in number of histograms reached....%d.  STOP \n", j);
    }else{
      printf("!... total number of histograms  == %d \n", j);
      }     
    if ( (gPad!=NULL)&&(bidim[0]!=NULL)){    bidim[0]->Draw("col"); }
    double dlt=(timelast/100/1000);
    printf("%7.3f s =last time\n", dlt/1000.);

    //====SAVE==============================
    for (ch=0;ch<8;ch++){
      //      printf("ch == %d\n", ch);
      if (hch[ch]!=NULL){ hch[ch]->Write();}
      if (htime[ch]!=NULL){ htime[ch]->Write();}
      if (bidim[ch]!=NULL){ bidim[ch]->Write();}
    }

    //  ede->Write();
    // ttree:=====================
    //    mc->print();
    TH2F* mcbi=(TH2F*) mc->getbidim();  // this is coincidences stored in [mc]
    TH2F* mcbifi=(TH2F*) mc->getfitbidim();  // this is fit coincidences stored in [mc]
    TH1F* mchidt=(TH1F*) mc->gethidt();
    mcbi->Write();
    mcbifi->Write();
    mchidt->Write();
 
    to->Print();
    to->Write();
    fo->Close();

} //######################################################## END ##############
Пример #2
0
void analysis() {
    Int_t nbins = 800;
    Int_t j;
    char name[20];
    char title[100];
    TH1F *HistoEvent[2214];
    for (Int_t z=0;z<2214;z++) {
        sprintf(name,"HistoEvent%d",z-1);
        sprintf(title,"Event%d Histo", z-1);
        HistoEvent[z] = new TH1F(name,title,nbins, -0.1, 159.9);
    }
    TH1F *NewHistoEvent[2214];
    for (Int_t z=0;z<2214;z++) {
        sprintf(name,"NewHistoEvent%d",z-1);
        sprintf(title,"Event%d Histo", z-1);
        NewHistoEvent[z] = new TH1F(name,title,nbins, -0.1, 159.9);
    }
    TH1F *NewHistoEventFFT[2214];
    for (Int_t z=0;z<2214;z++) {
        sprintf(name,"NewHistoEventFFT%d",z-1);
        sprintf(title,"Event%d Histo", z-1);
        NewHistoEventFFT[z] = new TH1F(name,title,nbins, 0, 5);
    }
    Double_t mean;
    Double_t rms;
    Double_t meansum = 0;
    Double_t count = 0;
    Double_t meanrms = 0;
	TFile f("/home/marko/H4Analysis/ntuples/analysis_4443.root"); //ntuple generated by H4Analysis tool
	TFile f1("/home/marko/H4Analysis/ntuples/analysis_3905.root");
    TFile f2("/home/marko/Desktop/TB Timing Res/NormalizedSignalNoise.root", "read");
    TH1F* BestSignal = (TH1F*) f2.Get("BetterSignal");
    TFile outputfile("myoutput.root", "recreate");
    TCanvas* TimeandFreq = new TCanvas("TimeandFreq","Time and Frequency",1500,900);
    TCanvas* Freq = new TCanvas("Freq","Frequency",800,1200);
    TCanvas* TimeSignal = new TCanvas("TimeSignal","Pure Signal",800,1200);
	TimeandFreq->Divide(2,2);
	TTree* h4 = (TTree*) f.Get("h4");
    TTree* h4_2 = (TTree*) f1.Get("h4");
    TString plot;
    TString cut;
	TH2F* WavePulse = new TH2F ("WavePulse", "Wave Pulse", nbins, -0.1, 159.9, 850, -50, 800);
    TH2F* NoisePulse = new TH2F ("NoisePulse", "Noise", nbins, -0.1, 159.9, 100, -50, 50);
    TH1F* PulseTime = new TH1F ("PulseTime", "Original Wave Pulse", nbins, -0.1, 159.9); //nanoseconds
    TH2F* TempHisto = new TH2F ("TempHisto", "Temp Histo", nbins, -0.1, 159.9, 1000, -15, 15); //nanoseconds
	h4->Draw("WF_val:WF_time>>WavePulse", "WF_ch==2 && event==1 && spill==1");
    h4_2->Draw("WF_val:WF_time>>NoisePulse","WF_ch==APD1 && amp_max[APD3]<25 && b_rms[APD3]<5. && charge_tot[APD3]<20000 &&  amp_max[APD5]<25 && b_rms[APD5]<5. &&  amp_max[APD6]<25 && b_rms[APD6]<5. &&  amp_max[APD4]<25 && b_rms[APD4]<5. && amp_max[SiPM1]<20 && amp_max[SiPM2]<20 && amp_max[APD1]<40 && amp_max[APD2]<40 && b_rms[APD1]<5. && b_rms[APD2]<5. && WF_time<160");
    for (Int_t i=0; i<nbins; i++) {
		for (Int_t k=0; k<4096; k++) {
			if (WavePulse->GetBinContent(i+1, k) != 0) {
				PulseTime->SetBinContent(i+1,k-50);
			}
		}
	}
    TH1F *NoiseTime = new TH1F ("NoiseTime", "Noise", nbins, -0.1, 159.9);
    for (Int_t i=0; i<nbins; i++) {
        for (Int_t k=0; k<4096; k++) {
            if (NoisePulse->GetBinContent(i+1, k) != 0) {
                NoiseTime->SetBinContent(i+1,k-62.9087);
            }
        }
    }
    //TH1F* NormNoiseFFT = new TH1F ("NormNoiseFFT", "Normalized Noise FFT", nbins, 0, 5);
    //TStopwatch t;
    //t.Start(); //1 hour runtime
    //for (j=10;j<20;j++) {
    //    plot = "WF_val:WF_time>>TempHisto";
    //    cut = "WF_ch==APD1 && amp_max[APD3]<25 && b_rms[APD3]<5. && charge_tot[APD3]<20000 &&  amp_max[APD5]<25 && b_rms[APD5]<5. &&  amp_max[APD6]<25 && b_rms[APD6]<5. &&  amp_max[APD4]<25 && b_rms[APD4]<5. && amp_max[SiPM1]<20 && amp_max[SiPM2]<20 && amp_max[APD1]<40 && amp_max[APD2]<40 && b_rms[APD1]<5. && b_rms[APD2]<5. && WF_time<160 && event==";
    //    cut += j;
    //    h4_2->Draw(plot, cut, "goff");
    //    if (TempHisto->GetMaximum() == 0) {
    //        delete HistoEvent[j+1];
    //        continue;
    //    }
    //    for (Int_t i=0; i<nbins; i++) {
    //        for (Int_t k=0; k<1000; k++) {
    //            if (TempHisto->GetBinContent(i+1, k) != 0) {
    //                HistoEvent[j+1]->SetBinContent(i+1,k*0.03-15);
    //            }
    //        }
    //    }
    //    mean = TempHisto->GetMean(2);
    //    rms = TempHisto->GetRMS(2);
    //    for (Int_t q=0;q<nbins;q++) {
    //        NewHistoEvent[j+1]->SetBinContent(q+1, HistoEvent[j+1]->GetBinContent(q+1)-mean);
    //    }
    //    NewHistoEvent[j+1]->Scale(1/rms);
    //    NewHistoEvent[j+1]->FFT(NewHistoEventFFT[j+1], "MAG");
    //    NormNoiseFFT->Add(NormNoiseFFT, NewHistoEventFFT[j+1]);
    //    TempHisto->Write();
    //    NewHistoEvent[j+1]->Write();
    //    NewHistoEventFFT[j+1]->Write();
    //    cout << "Event " << j << ", Mean = " << mean << ", RMS = " << rms << endl;
    //    count += 1;
    //}
    //NormNoiseFFT->Scale(1/count);
    //NormNoiseFFT->Write();
    //t.Stop();
    //t.Print();
	new TFile("/home/marko/H4Analysis/ntuples/analysis_4443.root"); // ignore this reloading of the same file, it is required or else the plots do not show up (when I tried)
    TimeandFreq->cd(1);
    PulseTime->GetXaxis()->SetTitle("Time (ns)");
    PulseTime->GetYaxis()->SetTitle("Amplitude");
    PulseTime->DrawClone(); //Wave Pulse in Time domain
    TimeandFreq->cd(2);
    TH1F* PulseFreq = new TH1F ("PulseFreq", "Pulse FFT", nbins, 0, 5);
    TH1F* PulsePhase = new TH1F ("PulsePhase", "Pulse Phase", nbins, -0.1, 799.9);
    PulseTime->FFT(PulseFreq, "MAG");
    PulseTime->FFT(PulsePhase, "PH");
    PulseFreq->SetLineColor(kRed);
    PulseFreq->GetXaxis()->SetTitle("Frequency (GHz)");
    PulseFreq->GetYaxis()->SetTitle("Amplitude");
    PulseFreq->DrawClone(); //Wave Pulse in Frequency domain
    gPad->SetLogy();
    TimeandFreq->cd(3);
    NoiseTime->GetXaxis()->SetTitle("Time (ns)");
    NoiseTime->GetYaxis()->SetTitle("Amplitude");
    NoiseTime->DrawClone(); // Noise from pedestal in Time domain
    TimeandFreq->cd(4);
    TH1F* NoiseFreq = new TH1F ("NoiseFreq", "Noise FFT", nbins, 0, 5);
    NoiseTime->FFT(NoiseFreq, "MAG");
    NoiseFreq->GetXaxis()->SetTitle("Frequency (GHz)");
    NoiseFreq->GetYaxis()->SetTitle("Amplitude");
    NoiseFreq->Draw(); // Noise from pedestal in Frequency domain
    gPad->SetLogy();
    Freq->Divide(1,3);
    Freq->cd(1);
    PulseFreq->DrawClone();
    gPad->SetLogy();
    Freq->cd(2);
    NoiseFreq->DrawClone();
    gPad->SetLogy();
    Freq->cd(3);
    PulseFreq->SetTitle("Pulse and Noise FFT Comparison");
    PulseFreq->Draw();
    NoiseFreq->Draw("same");
    gPad->SetLogy();
    TH1F* UnscaledSignalFreq = new TH1F ("UnscaledSignalFreq", "Unscaled Signal Frequency", nbins, -0.1, 799.9);
    for (Int_t l=0; l<nbins; l++) {
        UnscaledSignalFreq->SetBinContent(l+1, (PulseFreq->GetBinContent(l+1)-NoiseFreq->GetBinContent(l+1))/PulseFreq->GetBinContent(l+1));
    }
    TH1F* SignalFreq = new TH1F ("SignalFreq", "Signal Frequency", nbins, 0, 799.9);
    for (Int_t m=0; m<nbins; m++) {
        SignalFreq->SetBinContent(m+1, UnscaledSignalFreq->GetBinContent(m+1)*PulseFreq->GetBinContent(m+1));
    }
    Double_t *re_full = new Double_t[nbins];
    Double_t *im_full = new Double_t[nbins];
    for (Int_t n=0; n<nbins; n++) {
        (re_full)[n]=(SignalFreq->GetBinContent(n+1)*cos(PulsePhase->GetBinContent(n+1)));
        (im_full)[n]=(SignalFreq->GetBinContent(n+1)*sin(PulsePhase->GetBinContent(n+1)));
    }
    TVirtualFFT *invFFT = TVirtualFFT::FFT(1, &nbins, "C2R M K");
    invFFT->SetPointsComplex(re_full, im_full);
    invFFT->Transform();
    TH1 *Signal = 0;
    Signal = TH1::TransformHisto(invFFT,Signal,"Re");
    Signal->SetTitle("Recovered Signal 'S'");
    TH1F* BetterSignal = new TH1F ("BetterSignal", "Recovered Signal", nbins, -0.1, 159.9);
    for (Int_t p=0; p<nbins; p++) {
        BetterSignal->SetBinContent(p+1, Signal->GetBinContent(p+1)/nbins);
    }
    TimeSignal->Divide(1,2);
    TimeSignal->cd(1);
    PulseTime->DrawClone(); //Original Wave Pulse
    TimeSignal->cd(2);
    BetterSignal->GetXaxis()->SetTitle("Time (ns)");
    BetterSignal->GetYaxis()->SetTitle("Amplitude");
    BetterSignal->SetLineColor(kRed);
    //BetterSignal->Draw(); // Recovered Wave Pulse with decreased contribution from background noise
    BestSignal->SetLineColor(kGreen);
    BestSignal->DrawClone("same");
    PulseTime->DrawClone("same");
}
Пример #3
0
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", "exp(-(x-679.)/40.0)*TMath::Erfc(-(1/sqrt(2))*((x-679.)/2.0 + 0.05))", 0, 1023);
   TF1 *model = new TF1("model", "[0]*exp(-(x-[1])/[2])*TMath::Erfc(-(1/sqrt(2))*((x-[1])/[3] + [3]/[2]))", 0, 1023);
   model->SetParameter( 0, 1. );
   model->SetParameter( 1, 679. );
   model->SetParameter( 2, 40. );
   model->SetParameter( 3, 2. );
   model->SetLineColor( kViolet );
   
   TF1 *model2 = new TF1("model2", "[0]*exp(-(x-[1])/[2])*TMath::Erfc(-(1/sqrt(2))*((x-[1])/[3] + [3]/[2])) + [4]*sin(2*TMath::Pi()*[5]*x)", 0, 1023);
   model2->SetParameter( 0, 1. );
   model2->SetParameter( 1, 679. );
   model2->SetParameter( 2, 40. );
   model2->SetParameter( 3, 2. );
   model2->SetParameter( 4, 0.05 );
   model2->SetParameter( 5, 2. );
   model2->SetLineColor( kViolet );
   //fsin->Draw();
   
   Int_t n=1024;
   TH1D *hsin = new TH1D("hsin", "hsin", n+1, 0, 1023);
   Double_t x;
   //hsin->Fit( model,"MLR" );
   //Fill the histogram with function values
   for (Int_t i=0; i<=n; i++){
     /*
     if( i >= n/2 )
       {
	 x = (Double_t(i-(n/2+1))/n)*(160*TMath::Pi());
       }
     else
       {
	 x = -80*TMath::Pi()+(Double_t(i)/n)*(160*TMath::Pi());
       }
     */
     x = (Double_t(i)/n)*(1024);
     //std::cout << "n: " << i << " x: " << x << std::endl;
     hsin->SetBinContent(i+1, fsin->Eval(x));
   }
   
   hsin->Fit( model2,"MLR" );
   //TFile* fn = new TFile("/Users/cmorgoth/Software/git/TimingAna_New/CIT_Laser_022015_69_ana.root", "READ");
   TFile* fn = new TFile("/Users/cmorgoth/Work/data/LaserDataAtCaltech/02282015/CIT_Laser_022015_69_ana.root", "READ");
   TH1F* pulse = (TH1F*)fn->Get("CH2pulse");
   //hsin->Draw("same");
   hsin->SetLineColor(kGreen-4);
   hsin->Draw();
   model->Draw("same");
   //pulse->SetAxisRange(650, 780, "X");
   pulse->Scale(22.0);
   pulse->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 = pulse->FFT(hm, "MAG");
   hm->SetTitle("Magnitude of the 1st transform");
   //hm->Draw();
   double sf = 5e3;//to go from sample to picosecons and also from Hz to MHz
   double range = sf*(double)n/(1023.);
   int n_bin_fft = hm->GetNbinsX();
   TH1F* hmr = new TH1F( "hmr" ,"Magnitude of the 1st transform Rescaled", n_bin_fft, 0, range);
   for( int i = 1; i <= n_bin_fft; i++)
     {
       double bc = hm->GetBinContent( i )/sqrt( n );
       hmr->SetBinContent( i, bc );
     }
   hmr->SetXTitle("f (MHz)");
   hmr->Draw();
   //Transfor to the theoretical function
   TH1 *hm2 =0;
   TVirtualFFT::SetTransform(0);
   hm2 = hsin->FFT(hm2, "MAG");
   hm2->SetLineColor(2);
   //hm2->Draw("same");
   TH1F* hmr2 = new TH1F( "hmr2" ,"Magnitude of the 1st transform Rescaled", n_bin_fft, 0, range);
   for( int i = 1; i <= n_bin_fft; i++)
     {
       double bc = hm2->GetBinContent( i )/sqrt( n );
       hmr2->SetBinContent( i, bc );
     }
   hmr2->SetLineColor( kRed );
   hmr2->Draw("same");
   //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;
}