ROOT logo
/////////////////////////////////////////////////////////////////////////
//
// 'ADDITION AND CONVOLUTION' RooFit tutorial macro #210
// 
// Convolution in cyclical angular observables theta, and 
// construction of p.d.f in terms of trasnformed angular
// coordinates, e.g. cos(theta), where the convolution
// is performed in theta rather than cos(theta)
//
// (require ROOT to be compiled with --enable-fftw3)
// 
// pdf(theta)    = T(theta)          (x) gauss(theta)
// pdf(cosTheta) = T(acos(cosTheta)) (x) gauss(acos(cosTheta))
// 
//
// 04/2009 - Wouter Verkerke 
//
/////////////////////////////////////////////////////////////////////////

#ifndef __CINT__
#include "RooGlobalFunc.h"
#endif
#include "RooRealVar.h"
#include "RooDataSet.h"
#include "RooGaussian.h"
#include "RooGenericPdf.h"
#include "RooFormulaVar.h"
#include "RooFFTConvPdf.h"
#include "RooPlot.h"
#include "TCanvas.h"
#include "TAxis.h"
#include "TH1.h"
using namespace RooFit ;



void rf210_angularconv()
{
  // S e t u p   c o m p o n e n t   p d f s 
  // ---------------------------------------

  // Define angle psi
  RooRealVar psi("psi","psi",0,3.14159268) ;  

  // Define physics p.d.f T(psi)
  RooGenericPdf Tpsi("Tpsi","1+sin(2*@0)",psi) ;

  // Define resolution R(psi)
  RooRealVar gbias("gbias","gbias",0.2,0.,1) ;
  RooRealVar greso("greso","greso",0.3,0.1,1.0) ;
  RooGaussian Rpsi("Rpsi","Rpsi",psi,gbias,greso) ;

  // Define cos(psi) and function psif that calculates psi from cos(psi)
  RooRealVar cpsi("cpsi","cos(psi)",-1,1) ;
  RooFormulaVar psif("psif","acos(cpsi)",cpsi) ;

  // Define physics p.d.f. also as function of cos(psi): T(psif(cpsi)) = T(cpsi) ;
  RooGenericPdf Tcpsi("T","1+sin(2*@0)",psif) ;



  // C o n s t r u c t   c o n v o l u t i o n   p d f  i n   p s i 
  // --------------------------------------------------------------

  // Define convoluted p.d.f. as function of psi: M=[T(x)R](psi) = M(psi)
  RooFFTConvPdf Mpsi("Mf","Mf",psi,Tpsi,Rpsi) ;

  // Set the buffer fraction to zero to obtain a true cyclical convolution
  Mpsi.setBufferFraction(0) ;



  // S a m p l e ,   f i t   a n d   p l o t   c o n v o l u t e d   p d f  ( p s i )  
  // --------------------------------------------------------------------------------

  // Generate some events in observable psi
  RooDataSet* data_psi = Mpsi.generate(psi,10000) ;

  // Fit convoluted model as function of angle psi
  Mpsi.fitTo(*data_psi) ;
  
  // Plot cos(psi) frame with Mf(cpsi)
  RooPlot* frame1 = psi.frame(Title("Cyclical convolution in angle psi")) ;
  data_psi->plotOn(frame1) ;
  Mpsi.plotOn(frame1) ;

  // Overlay comparison to unsmeared physics p.d.f T(psi)
  Tpsi.plotOn(frame1,LineColor(kRed)) ;



  // C o n s t r u c t   c o n v o l u t i o n   p d f   i n   c o s ( p s i ) 
  // --------------------------------------------------------------------------


  // Define convoluted p.d.f. as function of cos(psi): M=[T(x)R](psif(cpsi)) = M(cpsi)
  //
  // Need to give both observable psi here (for definition of convolution)
  // and function psif here (for definition of observables, ultimately in cpsi)
  RooFFTConvPdf Mcpsi("Mf","Mf",psif,psi,Tpsi,Rpsi) ;

  // Set the buffer fraction to zero to obtain a true cyclical convolution
  Mcpsi.setBufferFraction(0) ;


  // S a m p l e ,   f i t   a n d   p l o t   c o n v o l u t e d   p d f  ( c o s p s i )  
  // --------------------------------------------------------------------------------

  // Generate some events
  RooDataSet* data_cpsi = Mcpsi.generate(cpsi,10000) ;

  // Fit convoluted model as function of cos(psi)
  Mcpsi.fitTo(*data_cpsi) ;
  
  // Plot cos(psi) frame with Mf(cpsi)
  RooPlot* frame2 = cpsi.frame(Title("Same convolution in psi, expressed in cos(psi)")) ;
  data_cpsi->plotOn(frame2) ;
  Mcpsi.plotOn(frame2) ;

  // Overlay comparison to unsmeared physics p.d.f Tf(cpsi)
  Tcpsi.plotOn(frame2,LineColor(kRed)) ;



  // Draw frame on canvas
  TCanvas* c = new TCanvas("rf210_angularconv","rf210_angularconv",800,400) ;
  c->Divide(2) ;
  c->cd(1) ; gPad->SetLeftMargin(0.15) ; frame1->GetYaxis()->SetTitleOffset(1.4) ; frame1->Draw() ;
  c->cd(2) ; gPad->SetLeftMargin(0.15) ; frame2->GetYaxis()->SetTitleOffset(1.4) ; frame2->Draw() ;

}
 rf210_angularconv.C:1
 rf210_angularconv.C:2
 rf210_angularconv.C:3
 rf210_angularconv.C:4
 rf210_angularconv.C:5
 rf210_angularconv.C:6
 rf210_angularconv.C:7
 rf210_angularconv.C:8
 rf210_angularconv.C:9
 rf210_angularconv.C:10
 rf210_angularconv.C:11
 rf210_angularconv.C:12
 rf210_angularconv.C:13
 rf210_angularconv.C:14
 rf210_angularconv.C:15
 rf210_angularconv.C:16
 rf210_angularconv.C:17
 rf210_angularconv.C:18
 rf210_angularconv.C:19
 rf210_angularconv.C:20
 rf210_angularconv.C:21
 rf210_angularconv.C:22
 rf210_angularconv.C:23
 rf210_angularconv.C:24
 rf210_angularconv.C:25
 rf210_angularconv.C:26
 rf210_angularconv.C:27
 rf210_angularconv.C:28
 rf210_angularconv.C:29
 rf210_angularconv.C:30
 rf210_angularconv.C:31
 rf210_angularconv.C:32
 rf210_angularconv.C:33
 rf210_angularconv.C:34
 rf210_angularconv.C:35
 rf210_angularconv.C:36
 rf210_angularconv.C:37
 rf210_angularconv.C:38
 rf210_angularconv.C:39
 rf210_angularconv.C:40
 rf210_angularconv.C:41
 rf210_angularconv.C:42
 rf210_angularconv.C:43
 rf210_angularconv.C:44
 rf210_angularconv.C:45
 rf210_angularconv.C:46
 rf210_angularconv.C:47
 rf210_angularconv.C:48
 rf210_angularconv.C:49
 rf210_angularconv.C:50
 rf210_angularconv.C:51
 rf210_angularconv.C:52
 rf210_angularconv.C:53
 rf210_angularconv.C:54
 rf210_angularconv.C:55
 rf210_angularconv.C:56
 rf210_angularconv.C:57
 rf210_angularconv.C:58
 rf210_angularconv.C:59
 rf210_angularconv.C:60
 rf210_angularconv.C:61
 rf210_angularconv.C:62
 rf210_angularconv.C:63
 rf210_angularconv.C:64
 rf210_angularconv.C:65
 rf210_angularconv.C:66
 rf210_angularconv.C:67
 rf210_angularconv.C:68
 rf210_angularconv.C:69
 rf210_angularconv.C:70
 rf210_angularconv.C:71
 rf210_angularconv.C:72
 rf210_angularconv.C:73
 rf210_angularconv.C:74
 rf210_angularconv.C:75
 rf210_angularconv.C:76
 rf210_angularconv.C:77
 rf210_angularconv.C:78
 rf210_angularconv.C:79
 rf210_angularconv.C:80
 rf210_angularconv.C:81
 rf210_angularconv.C:82
 rf210_angularconv.C:83
 rf210_angularconv.C:84
 rf210_angularconv.C:85
 rf210_angularconv.C:86
 rf210_angularconv.C:87
 rf210_angularconv.C:88
 rf210_angularconv.C:89
 rf210_angularconv.C:90
 rf210_angularconv.C:91
 rf210_angularconv.C:92
 rf210_angularconv.C:93
 rf210_angularconv.C:94
 rf210_angularconv.C:95
 rf210_angularconv.C:96
 rf210_angularconv.C:97
 rf210_angularconv.C:98
 rf210_angularconv.C:99
 rf210_angularconv.C:100
 rf210_angularconv.C:101
 rf210_angularconv.C:102
 rf210_angularconv.C:103
 rf210_angularconv.C:104
 rf210_angularconv.C:105
 rf210_angularconv.C:106
 rf210_angularconv.C:107
 rf210_angularconv.C:108
 rf210_angularconv.C:109
 rf210_angularconv.C:110
 rf210_angularconv.C:111
 rf210_angularconv.C:112
 rf210_angularconv.C:113
 rf210_angularconv.C:114
 rf210_angularconv.C:115
 rf210_angularconv.C:116
 rf210_angularconv.C:117
 rf210_angularconv.C:118
 rf210_angularconv.C:119
 rf210_angularconv.C:120
 rf210_angularconv.C:121
 rf210_angularconv.C:122
 rf210_angularconv.C:123
 rf210_angularconv.C:124
 rf210_angularconv.C:125
 rf210_angularconv.C:126
 rf210_angularconv.C:127
 rf210_angularconv.C:128
 rf210_angularconv.C:129
 rf210_angularconv.C:130
 rf210_angularconv.C:131
 rf210_angularconv.C:132