Belle II Software development
2_analysis_pi0.py
1#!/usr/bin/env python3
2
3
10
11"""
12<header>
13 <input>../GenericB_GENSIMRECtoDST.dst.root</input>
14 <output>Pi0_Validation.root</output>
15 <contact>Mario Merola (mario.merola@na.infn.it)</contact>
16 <description>
17 Check the calibration of the ECL in the MC by determining the measured pi0 invariant mass.
18 </description>
19</header>
20"""
21
22import basf2
23import ROOT
24from modularAnalysis import cutAndCopyList, inputMdst
25from stdPi0s import stdPi0s
26from validation_tools.metadata import create_validation_histograms
27from validation_tools.metadata import validation_metadata_update
28from variables import variables as vm
29
30INPUT_FILENAME = "../GenericB_GENSIMRECtoDST.dst.root"
31OUTPUT_FILENAME_reco = "Pi0_Validation_reco.root"
32OUTPUT_FILENAME_mc = "Pi0_Validation_mc.root"
33
34# main = basf2.Path()
35main = basf2.create_path()
36inputMdst(INPUT_FILENAME, path=main)
37
38stdPi0s('all', path=main)
39cutAndCopyList('pi0:rec', 'pi0:all', 'daughter(0, E)>0.05 and daughter(1, E)>0.05', path=main)
40cutAndCopyList('pi0:mc', 'pi0:all', 'mcErrors<1', path=main)
41
42vm.addAlias('Mreco', 'M')
43create_validation_histograms(
44 main, OUTPUT_FILENAME_reco, "pi0:rec",
45 variables_1d=[
46 (
47 "Mreco", 40, 0.08, 0.18,
48 "#pi^{0} reconstructed candidates, invariant mass",
49 "Eldar Ganiev <eldar.ganiev@desy.de>",
50 r"The $\pi^0$ invariant mass distribution with $E_{\gamma}>0.05\, \text{GeV}$",
51 r"Distribution should be peaking at the nominal $\pi^0$ mass.",
52 "M(#pi^{0}) [GeV/c^{2}]", "Candidates", "shifter"
53 ),
54 ],
55 description=r"$\pi^0$ reconstructed mass distribution"
56)
57
58vm.addAlias('Mmc', 'M')
59create_validation_histograms(
60 main, OUTPUT_FILENAME_mc, "pi0:mc",
61 variables_1d=[
62 (
63 "Mmc", 40, 0.08, 0.18,
64 "#pi^{0} MC candidates, invariant mass",
65 "Eldar Ganiev <eldar.ganiev@desy.de>",
66 r"The $\pi^0$ invariant mass distribution for truth matched candidates",
67 r"Distribution should be peaking at the nominal $\pi^0$ mass.",
68 "M(#pi^{0}) [GeV/c^{2}]", "Candidates", "shifter"
69 ),
70 ],
71 description=r"$\pi^0$ MC mass distribution"
72)
73
74main.add_module('Progress')
75basf2.process(main)
76
77
78f_reco = ROOT.TFile(OUTPUT_FILENAME_reco)
79Mrecohist = f_reco.Get('Mreco')
80f_mc = ROOT.TFile(OUTPUT_FILENAME_mc)
81Mmchist = f_mc.Get('Mmc')
82
83
84mass = ROOT.RooRealVar("recomass", "m_{#gamma#gamma} [GeV/c^{2}]", 0.11, 0.15)
85
86h_pi0_reco = ROOT.RooDataHist("h_pi0_reco", "h_pi0_reco", ROOT.RooArgList(mass), Mrecohist)
87h_pi0_mc = ROOT.RooDataHist("h_pi0_mc", "h_pi0_mc", ROOT.RooArgList(mass), Mmchist)
88
89
90# pi0 signal PDF is a Gaussian (Crystal Ball also listed in case we want to switch)
91mean = ROOT.RooRealVar("mean", "mean", 0.125, 0.11, 0.15)
92sig1 = ROOT.RooRealVar("#sigma", "sig", 0.007, 0.002, 0.1)
93gau1 = ROOT.RooGaussian("gau1", "gau1", mass, mean, sig1)
94
95alphacb = ROOT.RooRealVar("alphacb", "alpha", 1.5, 0.1, 1.9)
96ncb = ROOT.RooRealVar("ncb", "n", 8) # ,2.,15)
97sigcb = ROOT.RooCBShape("sigcb", "sigcb", mass, mean, sig1, alphacb, ncb)
98
99# pi0 background PDF is a 2nd order Chebyshev
100b1 = ROOT.RooRealVar("b1", "b1", 0.1, -1, 1)
101a1 = ROOT.RooRealVar("a1", "a1", 0.1, -1, 1)
102bList = ROOT.RooArgList(a1, b1)
103bkg = ROOT.RooChebychev("bkg", "bkg", mass, bList)
104
105
106nsig = ROOT.RooRealVar("nsig", "nsig", 3000, 0, 1000000)
107nbkg = ROOT.RooRealVar("nbkg", "nbkg", 12000, 0, 1000000)
108
109
110totalPdf = ROOT.RooAddPdf("totalpdf", "", ROOT.RooArgList(gau1, bkg), ROOT.RooArgList(nsig, nbkg))
111
112
113output = ROOT.TFile("Pi0_Validation_ntuple.root", "recreate")
114
115# Store pi0 mass fit results to a tuple for comparison of mean and width among releases.
116outputNtuple = ROOT.TNtuple(
117 "pi0_mass",
118 "Pi0 mass fit results",
119 "mean:meanerror:width:widtherror:mean_MC:meanerror_MC:width_MC:widtherror_MC")
120
121
122ROOT.gROOT.SetBatch(True)
123canvas = ROOT.TCanvas("canvas", "pi0 mass fit", 1000, 600)
124canvas.Divide(2, 1)
125canvas.cd(1)
126
127# Fit to the reco mass
128totalPdf.fitTo(h_pi0_reco, ROOT.RooFit.Extended(True), ROOT.RooFit.Minimizer("Minuit2", "Migrad"))
129frame1 = mass.frame()
130h_pi0_reco.plotOn(frame1, ROOT.RooFit.Name("Hist"))
131frame1.SetMaximum(frame1.GetMaximum())
132totalPdf.plotOn(frame1, ROOT.RooFit.Name("curve"))
133totalPdf.plotOn(frame1, ROOT.RooFit.Components("gau1"), ROOT.RooFit.LineStyle(ROOT.kDashed), ROOT.RooFit.LineColor(ROOT.kRed))
134totalPdf.plotOn(frame1, ROOT.RooFit.Components("bkg"), ROOT.RooFit.LineStyle(3), ROOT.RooFit.LineColor(ROOT.kBlue))
135frame1.SetMaximum(Mrecohist.GetMaximum() * 1.5)
136frame1.GetXaxis().SetTitleOffset(1.4)
137frame1.GetYaxis().SetTitleOffset(1.5)
138meanval = mean.getVal()
139meanerror = mean.getError()
140width = sig1.getVal()
141widtherror = sig1.getError()
142frame1.Draw("")
143
144canvas.cd(2)
145
146# ---------------------------
147# Fit to the truth matched mass.
148# The same signal parametrisation as for the reco mass but only a 1st order Chebyshev polynomial are used.
149# Re-initialize the fit parameters.
150mean.setVal(0.125)
151sig1.setVal(0.007)
152nsig.setVal(2200)
153nbkg.setVal(700)
154a1.setVal(-0.5)
155
156bkg = ROOT.RooChebychev("bkg1", "bkg", mass, a1)
157totalPdf = ROOT.RooAddPdf("totalpdfMC", "", ROOT.RooArgList(gau1, bkg), ROOT.RooArgList(nsig, nbkg))
158
159# Fit to the truth matched mass
160totalPdf.fitTo(h_pi0_mc, ROOT.RooFit.Extended(True), ROOT.RooFit.Minimizer("Minuit2", "Migrad"))
161frame2 = mass.frame()
162h_pi0_mc.plotOn(frame2, ROOT.RooFit.Name("Hist"))
163frame2.SetMaximum(frame2.GetMaximum())
164totalPdf.plotOn(frame2, ROOT.RooFit.Name("curve"))
165totalPdf.plotOn(frame2, ROOT.RooFit.Components("gau1"), ROOT.RooFit.LineStyle(ROOT.kDashed), ROOT.RooFit.LineColor(ROOT.kRed))
166totalPdf.plotOn(frame2, ROOT.RooFit.Components("bkg1"), ROOT.RooFit.LineStyle(3), ROOT.RooFit.LineColor(ROOT.kBlue))
167frame2.SetMaximum(Mmchist.GetMaximum() * 1.5)
168frame2.GetXaxis().SetTitleOffset(1.4)
169frame2.GetYaxis().SetTitleOffset(1.5)
170meanval_mc = mean.getVal()
171meanerror_mc = mean.getError()
172width_mc = sig1.getVal()
173widtherror_mc = sig1.getError()
174frame2.Draw("")
175
176canvas.Write()
177
178outputNtuple.Fill(meanval, meanerror, width, widtherror, meanval_mc, meanerror_mc, width_mc, widtherror_mc)
179
180outputNtuple.Write()
181
182validation_metadata_update(
183 output,
184 "pi0_mass",
185 title="Pi0 mass fit results",
186 contact="eldar.ganiev@desy.de",
187 description="Fit to the invariant mass of the reconstructed and truth matched pi0s",
188 check="Consistent numerical fit results. Stable mean and width.",
189 metaoptions="shifter")
190
191
192output.Close()
193f_reco.Close()
194f_mc.Close()