Belle II Software  release-08-01-10
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), Andrea Selce (selce@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 
22 import basf2
23 import ROOT
24 from modularAnalysis import cutAndCopyList, inputMdst
25 from validation_tools.metadata import create_validation_histograms
26 from validation_tools.metadata import validation_metadata_update
27 from variables import variables as vm
28 
29 INPUT_FILENAME = "../GenericB_GENSIMRECtoDST.dst.root"
30 OUTPUT_FILENAME = "Pi0_Validation.root"
31 
32 main = basf2.Path()
33 inputMdst(INPUT_FILENAME, path=main)
34 
35 cutAndCopyList('pi0:rec', 'pi0:all', 'daughter(0, E)>0.05 and daughter(1, E)>0.05', path=main)
36 cutAndCopyList('pi0:mc', 'pi0:all', 'mcErrors<1', path=main)
37 
38 vm.addAlias('Mreco', 'M')
39 
40 
41 create_validation_histograms(
42  main, OUTPUT_FILENAME, "pi0:rec",
43  variables_1d=[
44  (
45  "Mreco", 40, 0.08, 0.18,
46  "#pi^{0} reconstructed candidates, invariant mass",
47  "Andrea Selce <selce@infn.it>",
48  r"The $\pi^0$ invariant mass distribution with $E_{\gamma}>0.05\, \text{GeV}$",
49  r"Distribution should be peaking at the nominal $\pi^0$ mass.",
50  "M(#pi^{0}) [GeV/c^{2}]", "Candidates", "shifter"
51  ),
52  ],
53  description=r"$\pi^0$ reconstructed mass distribution",
54 )
55 
56 
57 vm.addAlias('Mmc', 'M')
58 
59 create_validation_histograms(
60  main, OUTPUT_FILENAME, "pi0:mc",
61  variables_1d=[
62  (
63  "Mmc", 40, 0.08, 0.18,
64  "#pi^{0} MC candidates, invariant mass",
65  "Andrea Selce <selce@infn.it>",
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 
74 main.add_module('Progress')
75 basf2.process(main)
76 print(basf2.statistics)
77 
78 
79 f = ROOT.TFile(OUTPUT_FILENAME)
80 Mrecohist = f.Get('Mreco')
81 Mmchist = f.Get('Mmc')
82 
83 
84 mass = ROOT.RooRealVar("recomass", "m_{#gamma#gamma} [GeV/c^{2}]", 0.11, 0.15)
85 
86 h_pi0_reco = ROOT.RooDataHist("h_pi0_reco", "h_pi0_reco", ROOT.RooArgList(mass), Mrecohist)
87 h_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)
91 mean = ROOT.RooRealVar("mean", "mean", 0.125, 0.11, 0.15)
92 sig1 = ROOT.RooRealVar("#sigma", "sig", 0.007, 0.002, 0.1)
93 gau1 = ROOT.RooGaussian("gau1", "gau1", mass, mean, sig1)
94 
95 alphacb = ROOT.RooRealVar("alphacb", "alpha", 1.5, 0.1, 1.9)
96 ncb = ROOT.RooRealVar("ncb", "n", 8) # ,2.,15)
97 sigcb = ROOT.RooCBShape("sigcb", "sigcb", mass, mean, sig1, alphacb, ncb)
98 
99 # pi0 background PDF is a 2nd order Chebyshev
100 b1 = ROOT.RooRealVar("b1", "b1", 0.1, -1, 1)
101 a1 = ROOT.RooRealVar("a1", "a1", 0.1, -1, 1)
102 bList = ROOT.RooArgList(a1, b1)
103 bkg = ROOT.RooChebychev("bkg", "bkg", mass, bList)
104 
105 
106 nsig = ROOT.RooRealVar("nsig", "nsig", 3000, 0, 1000000)
107 nbkg = ROOT.RooRealVar("nbkg", "nbkg", 12000, 0, 1000000)
108 
109 
110 totalPdf = ROOT.RooAddPdf("totalpdf", "", ROOT.RooArgList(gau1, bkg), ROOT.RooArgList(nsig, nbkg))
111 
112 
113 output = 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.
116 outputNtuple = 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 
122 ROOT.gROOT.SetBatch(True)
123 canvas = ROOT.TCanvas("canvas", "pi0 mass fit", 1000, 600)
124 canvas.Divide(2, 1)
125 canvas.cd(1)
126 
127 # Fit to the reco mass
128 totalPdf.fitTo(h_pi0_reco, ROOT.RooFit.Extended(True), ROOT.RooFit.Minimizer("Minuit2", "Migrad"))
129 frame1 = mass.frame()
130 h_pi0_reco.plotOn(frame1, ROOT.RooFit.Name("Hist"))
131 frame1.SetMaximum(frame1.GetMaximum())
132 totalPdf.plotOn(frame1, ROOT.RooFit.Name("curve"))
133 totalPdf.plotOn(frame1, ROOT.RooFit.Components("gau1"), ROOT.RooFit.LineStyle(ROOT.kDashed), ROOT.RooFit.LineColor(ROOT.kRed))
134 totalPdf.plotOn(frame1, ROOT.RooFit.Components("bkg"), ROOT.RooFit.LineStyle(3), ROOT.RooFit.LineColor(ROOT.kBlue))
135 frame1.SetMaximum(Mrecohist.GetMaximum() * 1.5)
136 frame1.GetXaxis().SetTitleOffset(1.4)
137 frame1.GetYaxis().SetTitleOffset(1.5)
138 meanval = mean.getVal()
139 meanerror = mean.getError()
140 width = sig1.getVal()
141 widtherror = sig1.getError()
142 frame1.Draw("")
143 
144 canvas.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.
150 mean.setVal(0.125)
151 sig1.setVal(0.007)
152 nsig.setVal(2200)
153 nbkg.setVal(700)
154 a1.setVal(-0.5)
155 
156 bkg = ROOT.RooChebychev("bkg1", "bkg", mass, a1)
157 totalPdf = ROOT.RooAddPdf("totalpdfMC", "", ROOT.RooArgList(gau1, bkg), ROOT.RooArgList(nsig, nbkg))
158 
159 # Fit to the truth matched mass
160 totalPdf.fitTo(h_pi0_mc, ROOT.RooFit.Extended(True), ROOT.RooFit.Minimizer("Minuit2", "Migrad"))
161 frame2 = mass.frame()
162 h_pi0_mc.plotOn(frame2, ROOT.RooFit.Name("Hist"))
163 frame2.SetMaximum(frame2.GetMaximum())
164 totalPdf.plotOn(frame2, ROOT.RooFit.Name("curve"))
165 totalPdf.plotOn(frame2, ROOT.RooFit.Components("gau1"), ROOT.RooFit.LineStyle(ROOT.kDashed), ROOT.RooFit.LineColor(ROOT.kRed))
166 totalPdf.plotOn(frame2, ROOT.RooFit.Components("bkg1"), ROOT.RooFit.LineStyle(3), ROOT.RooFit.LineColor(ROOT.kBlue))
167 frame2.SetMaximum(Mmchist.GetMaximum() * 1.5)
168 frame2.GetXaxis().SetTitleOffset(1.4)
169 frame2.GetYaxis().SetTitleOffset(1.5)
170 meanval_mc = mean.getVal()
171 meanerror_mc = mean.getError()
172 width_mc = sig1.getVal()
173 widtherror_mc = sig1.getError()
174 frame2.Draw("")
175 
176 canvas.Write()
177 
178 outputNtuple.Fill(meanval, meanerror, width, widtherror, meanval_mc, meanerror_mc, width_mc, widtherror_mc)
179 
180 outputNtuple.Write()
181 
182 validation_metadata_update(
183  output,
184  "pi0_mass",
185  title="Pi0 mass fit results",
186  contact="selce@infn.it",
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 
192 output.Close()