## \file ## \ingroup tutorial_roofit ## \notebook ## Convolution in cyclical angular observables theta, and ## construction of p.d.f in terms of transformed angular ## coordinates, e.g. cos(theta), the convolution ## is performed in theta rather than cos(theta) ## ## (require ROOT to be compiled with --enable-fftw3) ## ## pdf(theta) = ROOT.T(theta) (x) gauss(theta) ## pdf(cosTheta) = ROOT.T(acos(cosTheta)) (x) gauss(acos(cosTheta)) ## ## \macro_image ## \macro_code ## \macro_output ## ## \date February 2018 ## \authors Clemens Lange, Wouter Verkerke (C version) import ROOT # Set up component pdfs # --------------------------------------- # Define angle psi psi = ROOT.RooRealVar("psi", "psi", 0, 3.14159268) # Define physics p.d.f T(psi) Tpsi = ROOT.RooGenericPdf("Tpsi", "1+sin(2*@0)", [psi]) # Define resolution R(psi) gbias = ROOT.RooRealVar("gbias", "gbias", 0.2, 0.0, 1) greso = ROOT.RooRealVar("greso", "greso", 0.3, 0.1, 1.0) Rpsi = ROOT.RooGaussian("Rpsi", "Rpsi", psi, gbias, greso) # Define cos(psi) and function psif that calculates psi from cos(psi) cpsi = ROOT.RooRealVar("cpsi", "cos(psi)", -1, 1) psif = ROOT.RooFormulaVar("psif", "acos(cpsi)", [cpsi]) # Define physics p.d.f. also as function of cos(psi): T(psif(cpsi)) = T(cpsi) Tcpsi = ROOT.RooGenericPdf("T", "1+sin(2*@0)", [psif]) # Construct convolution pdf in psi # -------------------------------------------------------------- # Define convoluted p.d.f. as function of psi: M=[T(x)R](psi) = M(psi) Mpsi = ROOT.RooFFTConvPdf("Mf", "Mf", psi, Tpsi, Rpsi) # Set the buffer fraction to zero to obtain a ROOT.True cyclical # convolution Mpsi.setBufferFraction(0) # Sample, fit and plot convoluted pdf (psi) # -------------------------------------------------------------------------------- # Generate some events in observable psi data_psi = Mpsi.generate({psi}, 10000) # Fit convoluted model as function of angle psi Mpsi.fitTo(data_psi, PrintLevel=-1) # Plot cos(psi) frame with Mf(cpsi) frame1 = psi.frame(Title="Cyclical convolution in angle psi") data_psi.plotOn(frame1) Mpsi.plotOn(frame1) # Overlay comparison to unsmeared physics p.d.f ROOT.T(psi) Tpsi.plotOn(frame1, LineColor="r") # Construct convolution pdf in cos(psi) # -------------------------------------------------------------------------- # 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, in cpsi) Mcpsi = ROOT.RooFFTConvPdf("Mf", "Mf", psif, psi, Tpsi, Rpsi) # Set the buffer fraction to zero to obtain a ROOT.True cyclical # convolution Mcpsi.setBufferFraction(0) # Sample, fit and plot convoluted pdf (cospsi) # -------------------------------------------------------------------------------- # Generate some events data_cpsi = Mcpsi.generate({cpsi}, 10000) # set psi constant to exclude to be a parameter of the fit psi.setConstant(True) # Fit convoluted model as function of cos(psi) Mcpsi.fitTo(data_cpsi, PrintLevel=-1) # Plot cos(psi) frame with Mf(cpsi) frame2 = cpsi.frame(Title="Same convolution in psi, in cos(psi)") data_cpsi.plotOn(frame2) Mcpsi.plotOn(frame2) # Overlay comparison to unsmeared physics p.d.f ROOT.Tf(cpsi) Tcpsi.plotOn(frame2, LineColor="r") # Draw frame on canvas c = ROOT.TCanvas("rf210_angularconv", "rf210_angularconv", 800, 400) c.Divide(2) c.cd(1) ROOT.gPad.SetLeftMargin(0.15) frame1.GetYaxis().SetTitleOffset(1.4) frame1.Draw() c.cd(2) ROOT.gPad.SetLeftMargin(0.15) frame2.GetYaxis().SetTitleOffset(1.4) frame2.Draw() c.SaveAs("rf210_angularconv.png")