Belle II Software  light-2403-persian
test6_CPVFlavorTaggerEfficiency.py
1 #!/usr/bin/env python3
2 
3 
10 
11 """
12 <header>
13  <input>CPVToolsOutput.root</input>
14  <output>test6_CPVFlavorTaggerEfficiency.root</output>
15  <contact>Yo Sato; yosato@post.kek.jp</contact>
16  <description>This file calculates the effective efficiency of the category based flavor tagger considering the two
17  standard combiners and the individual categories. Validation plots are also produced. </description>
18 </header>
19 """
20 
21 import ROOT
22 from array import array
23 
24 ROOT.gROOT.SetBatch(True)
25 
26 workingFiles = ["../CPVToolsOutput.root"]
27 treeName = "B0tree"
28 
29 
30 workingDirectory = '.'
31 
32 #
33 # *******************************************
34 # DETERMINATION OF TOTAL EFFECTIVE EFFICIENCY
35 # *******************************************
36 #
37 
38 r_subsample = array('d', [
39  0.0,
40  0.1,
41  0.25,
42  0.5,
43  0.625,
44  0.75,
45  0.875,
46  1.0])
47 r_size = len(r_subsample)
48 average_eff = 0
49 
50 # All possible Categories
51 categories = [
52  'Electron',
53  'IntermediateElectron',
54  'Muon',
55  'IntermediateMuon',
56  'KinLepton',
57  'IntermediateKinLepton',
58  'Kaon',
59  'KaonPion',
60  'SlowPion',
61  'FSC',
62  'MaximumPstar',
63  'FastHadron',
64  'Lambda']
65 
66 
67 methods = []
68 
69 
70 class Quiet:
71  """Context handler class to quiet errors in a 'with' statement"""
72 
73  def __init__(self, level=ROOT.kInfo + 1):
74  """Class constructor"""
75 
76  self.levellevel = level
77 
78  def __enter__(self):
79  """Enter the context"""
80 
81  self.oldleveloldlevel = ROOT.gErrorIgnoreLevel
82  ROOT.gErrorIgnoreLevel = self.levellevel
83 
84  def __exit__(self, type, value, traceback):
85  """Exit the context"""
86  ROOT.gErrorIgnoreLevel = self.oldleveloldlevel
87 
88 
89 tree = ROOT.TChain(treeName)
90 
91 mcstatus = array('d', [-511.5, 0.0, 511.5])
92 ROOT.TH1.SetDefaultSumw2()
93 
94 for iFile in workingFiles:
95  tree.AddFile(iFile)
96 
97 totalBranches = []
98 for branch in tree.GetListOfBranches():
99  totalBranches.append(branch.GetName())
100 
101 if 'FBDT_qrCombined' in totalBranches:
102  methods.append("FBDT")
103 
104 usedCategories = []
105 for cat in categories:
106  catBranch = 'qp' + cat
107  if catBranch in totalBranches:
108  usedCategories.append(cat)
109 
110 categoriesNtupleList = ''
111 for category in usedCategories:
112  categoriesNtupleList = categoriesNtupleList + f"Eff_{category}:"
113 
114 
115 # Output Validation file
116 outputFile = ROOT.TFile("test6_CPVFlavorTaggerEfficiency.root", "RECREATE")
117 
118 # Values to be watched
119 outputNtuple = ROOT.TNtuple(
120  "FT_Efficiencies",
121  "Effective efficiencies of the flavor tagger combiners as well as of the individual tagging categories.",
122  "Eff_FBDT:DeltaEff_FBDT:" + categoriesNtupleList)
123 
124 outputNtuple.SetAlias('Description', "These are the effective efficiencies of the flavor tagger combiners as well as of " +
125  "the individual tagging efficiencies.")
126 outputNtuple.SetAlias(
127  'Check',
128  "These values should not change drastically. Since the nightly reconstruction validation runs" +
129  "on the same input file (which changes only from release to release), the values between builds should be the same.")
130 outputNtuple.SetAlias('Contact', "yosato@post.kek.jp")
131 
132 efficienciesForNtuple = []
133 
134 YmaxForQrPlot = 0
135 
136 for method in methods:
137  # histogram contains the average r in each of 7 bins -> calculation see below
138  histo_avr_r = ROOT.TH1F('Average_r', 'Average r in each of 7 bins (B0 and B0bar)', 7,
139  r_subsample)
140  histo_avr_rB0 = ROOT.TH1F('Average_rB0', 'Average r in each of 7 bins (B0)', 7,
141  r_subsample)
142  histo_avr_rB0bar = ROOT.TH1F('Average_rB0bar', 'Average r in each of 7 bins (B0bar)', 7,
143  r_subsample)
144  # histogram with number of entries in for each bin
145  histo_entries_per_bin = ROOT.TH1F(
146  'entries_per_bin',
147  'Events binned in r_subsample according to their r-value for B0 and B0bar prob',
148  7,
149  r_subsample)
150  histo_entries_per_binB0 = ROOT.TH1F('entries_per_binB0', 'Events binned in r_subsample according '
151  'to their r-value for B0 prob', 7, r_subsample)
152  histo_entries_per_binB0bar = ROOT.TH1F('entries_per_binB0bar',
153  'Events binned in r_subsample according to their r-value '
154  'for B0bar prob', 7, r_subsample)
155  # histogram network output (not qr and not r) for true B0 (signal) - not necessary
156  histo_Cnet_output_B0 = ROOT.TH1F('Comb_Net_Output_B0', 'Combiner network output [not equal to r] '
157  'for true B0 (binning 100)', 100, 0.0, 1.0)
158  # histogram network output (not qr and not r) for true B0bar (background) - not necessary
159  histo_Cnet_output_B0bar = ROOT.TH1F('Comb_Net_Output_B0bar', 'Combiner network output [not equal to r] '
160  'for true B0bar (binning 100)', 100, 0.0, 1.0)
161  # histogram containing the belle paper plot (qr-tagger output for true B0)
162  histo_belleplotB0 = ROOT.TH1F('qr_' + method + '_B0',
163  'BellePlot for true B0 (binning 50)', 50,
164  -1.0, 1.0)
165  # histogram containing the belle paper plot (qr-tagger output for true B0bar)
166  histo_belleplotB0bar = ROOT.TH1F('qr_' + method + '_B0Bar',
167  'BellePlot for true B0Bar (binning 50)',
168  50, -1.0, 1.0)
169 
170  # histogram containing the qr plot (qr-tagger output)
171  histo_belleplotBoth = ROOT.TH1F('qr_' + method + '_B0Both',
172  'qr-tagger output (binning 50)',
173  50, -1.0, 1.0)
174  # calibration plot for B0. If we get a linear line our MC is fine, than the assumption r ~ 1- 2w is reasonable
175  # expectation is, that for B0 calibration plot: qr=0 half B0 and half B0bar, qr = 1 only B0 and qr = -1
176  # no B0. Inverse for B0bar calibration plot
177  histo_calib_B0 = ROOT.TH1F('Calibration_' + method + '_B0', 'CalibrationPlot for true B0', 100, -1.0, 1.0)
178  # calibration plot for B0bar calibration plot
179  histo_calib_B0bar = ROOT.TH1F('Calibration_' + method + '_B0Bar',
180  'CalibrationPlot for true B0Bar', 100, -1.0,
181  1.0)
182  # belle plot with true B0 and B0bars
183  hallo12 = ROOT.TH1F('BellePlot_NoCut', 'BellePlot_NoCut (binning 100)',
184  100, -1.0, 1.0)
185 
186 
187  diag = ROOT.TF1('diag', 'pol1', -1, 1)
188 
189 
190  # histograms for the efficiency calculation in wrong way
191  histo_m0 = ROOT.TH1F('BellePlot_B0_m0',
192  'BellePlot_m for true B0 (binning 50)', 50, -1.0, 1.0)
193  histo_m1 = ROOT.TH1F('BellePlot_B0_m1',
194  'BellePlot_m for true B0 (binning 50)', 50, -1.0, 1.0)
195  histo_m2 = ROOT.TH1F('BellePlot_B0_m2',
196  'BellePlot_m for true B0Bar (binning 50)', 50, -1.0,
197  1.0)
198 
199  # filling the histograms
200 
201  tree.Draw(method + '_qrCombined>>qr_' + method + '_B0', 'qrMC == 1')
202  tree.Draw(method + '_qrCombined>>qr_' + method + '_B0Bar', 'qrMC == -1')
203  tree.Draw(method + '_qrCombined>>BellePlot_NoCut', 'abs(qrMC) == 1')
204  tree.Draw(method + '_qrCombined>>qr_' + method + '_B0Both', 'abs(qrMC) == 1')
205 
206  tree.Draw(method + '_qrCombined>>Calibration_' + method + '_B0', 'qrMC == 1')
207  tree.Draw(method + '_qrCombined>>Calibration_' + method + '_B0Bar', 'qrMC == -1')
208 
209  # filling histograms wrong efficiency calculation
210  tree.Draw(method + '_qrCombined>>BellePlot_B0_m0',
211  'qrMC == 1 && ' + method + '_qrCombined>0')
212  tree.Draw(method + '_qrCombined>>BellePlot_B0_m1',
213  'qrMC == 1 && ' + method + '_qrCombined<0')
214  tree.Draw(method + '_qrCombined>>BellePlot_B0_m2',
215  'qrMC == -1 && ' + method + '_qrCombined>0 ')
216 
217  # filling with abs(qr) in one of 7 bins with its weight
218  # separate calculation for B0 and B0bar
219 
220  tree.Project('Average_r', 'abs(' + method + '_qrCombined)',
221  'abs(' + method + '_qrCombined)')
222  tree.Project('Average_rB0', 'abs(' + method + '_qrCombined)', 'abs(' + method + '_qrCombined)*(qrMC==1)')
223  tree.Project('Average_rB0bar', 'abs(' + method + '_qrCombined)', 'abs(' + method + '_qrCombined)*(qrMC==-1)')
224 
225  # filling with abs(qr) in one of 7 bins
226  tree.Project('entries_per_bin', 'abs(' + method + '_qrCombined)', 'abs(qrMC) == 1')
227  tree.Project('entries_per_binB0', 'abs(' + method + '_qrCombined)', 'qrMC == 1')
228  tree.Project('entries_per_binB0bar', 'abs(' + method + '_qrCombined)', 'qrMC == -1')
229 
230  # producing the average r histograms
231  histo_avr_r.Divide(histo_entries_per_bin)
232  histo_avr_rB0.Divide(histo_entries_per_binB0)
233  histo_avr_rB0bar.Divide(histo_entries_per_binB0bar)
234 
235  # producing the calibration plots
236  # Errors ok
237  histo_calib_B0.Divide(hallo12)
238  histo_calib_B0bar.Divide(hallo12)
239 
240  # Fit for calibration plot
241  print(' ')
242  print('****************** CALIBRATION CHECK FOR COMBINER USING ' + method + ' ***************************************')
243  print(' ')
244  print('Fit polynomial of first order to the calibration plot. Expected value ~0.5')
245  print(' ')
246  histo_calib_B0.Fit(diag, 'TEST')
247  print(' ')
248  print('****************** MEASURED EFFECTIVE EFFICIENCY FOR COMBINER USING ' + method + ' ***************************')
249  print('* *')
250  # get total number of entries
251  total_entries = histo_entries_per_bin.GetEntries()
252  total_entries_B0 = histo_entries_per_binB0.GetEntries()
253  total_entries_B0bar = histo_entries_per_binB0bar.GetEntries()
254  tot_eff_effB0 = 0
255  tot_eff_effB0bar = 0
256  event_fractionB0 = array('f', [0] * r_size)
257  event_fractionB0bar = array('f', [0] * r_size)
258  event_fractionTotal = array('f', [0] * r_size)
259  event_fractionDiff = array('f', [0] * r_size)
260  rvalueB0 = array('f', [0] * r_size)
261  rvalueB0bar = array('f', [0] * r_size)
262  rvalueB0Average = array('f', [0] * r_size)
263  wvalue = array('f', [0] * r_size)
264  wvalueB0 = array('f', [0] * r_size)
265  wvalueB0bar = array('f', [0] * r_size)
266  wvalueDiff = array('f', [0] * r_size)
267  entries = array('f', [0] * r_size)
268  entriesB0 = array('f', [0] * r_size)
269  entriesB0bar = array('f', [0] * r_size)
270  iEffEfficiency = array('f', [0] * r_size)
271  iDeltaEffEfficiency = array('f', [0] * r_size)
272  # intervallEff = array('f', [0] * r_size)
273  performance = []
274  for i in range(1, r_size):
275  # get the average r-value
276  rvalueB0[i] = histo_avr_rB0.GetBinContent(i)
277  rvalueB0bar[i] = histo_avr_rB0bar.GetBinContent(i)
278  rvalueB0Average[i] = (rvalueB0[i] + rvalueB0bar[i]) / 2
279  # calculate the wrong tag fraction (only true if MC data good)
280  wvalue[i] = (1 - rvalueB0Average[i]) / 2
281  wvalueB0[i] = (1 - rvalueB0[i]) / 2
282  wvalueB0bar[i] = (1 - rvalueB0bar[i]) / 2
283  wvalueDiff[i] = wvalueB0[i] - wvalueB0bar[i]
284  entries[i] = histo_entries_per_bin.GetBinContent(i)
285  entriesB0[i] = histo_entries_per_binB0.GetBinContent(i)
286  entriesB0bar[i] = histo_entries_per_binB0bar.GetBinContent(i)
287  # fraction of events/all events
288  event_fractionTotal[i] = (entriesB0[i] + entriesB0bar[i]) / total_entries
289  event_fractionDiff[i] = (entriesB0[i] - entriesB0bar[i]) / total_entries
290  event_fractionB0[i] = entriesB0[i] / total_entries_B0
291  event_fractionB0bar[i] = entriesB0bar[i] / total_entries_B0bar
292  iEffEfficiency[i] = (event_fractionB0[i] * rvalueB0[i] * rvalueB0[i] +
293  event_fractionB0bar[i] * rvalueB0bar[i] * rvalueB0bar[i]) / 2
294  iDeltaEffEfficiency[i] = event_fractionB0[i] * rvalueB0[i] * \
295  rvalueB0[i] - event_fractionB0bar[i] * rvalueB0bar[i] * rvalueB0bar[i]
296  # finally calculating the total effective efficiency
297  tot_eff_effB0 = tot_eff_effB0 + event_fractionB0[i] * rvalueB0[i] * rvalueB0[i]
298  tot_eff_effB0bar = tot_eff_effB0bar + event_fractionB0bar[i] * rvalueB0bar[i] * rvalueB0bar[i]
299 
300  average_eff = (tot_eff_effB0 + tot_eff_effB0bar) / 2
301  diff_eff = tot_eff_effB0 - tot_eff_effB0bar
302  print('* ------------------------------------------------------------------------------------------------ *')
303  print('* *')
304  print('* __________________________________________________________________________________________ *')
305  print('* | | *')
306  print('* | TOTAL NUMBER OF TAGGED EVENTS = ' +
307  f"{f'{total_entries:.0f}':<24}" + f"{'| *':>36}")
308  print('* | | *')
309  print('* | TOTAL AVERAGE EFFECTIVE EFFICIENCY (q=+-1)= ' + f'{average_eff * 100:.2f}' +
310  ' % | *')
311  print('* | | *')
312  print('* | B0-TAGGER TOTAL EFFECTIVE EFFICIENCIES: ' +
313  f'{tot_eff_effB0 * 100:.2f}' + ' % (q=+1) ' +
314  f'{tot_eff_effB0bar * 100:.2f}' + ' % (q=-1) EffDiff=' +
315  f'{diff_eff * 100:^5.2f}' + ' % | *')
316  print('* | | *')
317  print('* | FLAVOR PERCENTAGE (MC): ' +
318  f'{total_entries_B0 / total_entries * 100:.2f}' + ' % (q=+1) ' +
319  f'{total_entries_B0bar / total_entries * 100:.2f}' + ' % (q=-1) Diff=' +
320  f'{(total_entries_B0 - total_entries_B0bar) / total_entries * 100:^5.2f}' + ' % | *')
321  print('* |__________________________________________________________________________________________| *')
322  print('* *')
323  print('****************************************************************************************************')
324  print('* *')
325 
326  efficienciesForNtuple.append(float(average_eff * 100))
327  efficienciesForNtuple.append(float(diff_eff * 100))
328 
329  maxB0 = histo_belleplotB0.GetBinContent(histo_belleplotB0.GetMaximumBin())
330  maxB0bar = histo_belleplotB0bar.GetBinContent(histo_belleplotB0bar.GetMaximumBin())
331  maxB0Both = histo_belleplotBoth.GetBinContent(histo_belleplotBoth.GetMaximumBin())
332 
333  Ymax = max(maxB0, maxB0bar, maxB0Both)
334  Ymax = Ymax + Ymax / 12
335 
336  if YmaxForQrPlot < Ymax:
337  YmaxForQrPlot = Ymax
338 
339  # produce a pdf
340  ROOT.gStyle.SetOptStat(0)
341  with Quiet(ROOT.kError):
342  Canvas1 = ROOT.TCanvas('Bla', 'Final Output', 1200, 800)
343  Canvas1.cd() # activate
344  Canvas1.SetLeftMargin(0.13)
345  Canvas1.SetRightMargin(0.04)
346  Canvas1.SetTopMargin(0.03)
347  Canvas1.SetBottomMargin(0.14)
348  histo_belleplotB0.SetFillColorAlpha(ROOT.kBlue, 0.2)
349  histo_belleplotB0.SetFillStyle(1001)
350  histo_belleplotB0.GetXaxis().SetLabelSize(0.04)
351  histo_belleplotB0.GetYaxis().SetLabelSize(0.04)
352  histo_belleplotB0.GetYaxis().SetTitleOffset(0.9)
353  histo_belleplotB0.GetXaxis().SetTitleSize(0.06)
354  histo_belleplotB0.GetYaxis().SetTitleSize(0.06)
355  histo_belleplotB0.GetYaxis().SetLimits(0, YmaxForQrPlot)
356  histo_belleplotB0.SetLineColor(ROOT.kBlue)
357  histo_belleplotB0bar.SetFillColorAlpha(ROOT.kRed, 1.0)
358  histo_belleplotB0bar.SetFillStyle(3005)
359  histo_belleplotB0bar.SetLineColor(ROOT.kRed)
360  # SetLabelSize etc SetTitle
361 
362  histo_belleplotB0.SetTitle('; #it{qr}_{' + method + '} ; Events (Total = ' + f"{f'{total_entries:.0f}':<1}" + ')'
363  )
364  histo_belleplotB0.SetMinimum(0)
365  histo_belleplotB0.SetMaximum(YmaxForQrPlot)
366  histo_belleplotB0.Draw('hist')
367  histo_belleplotB0bar.Draw('hist same')
368 
369  leg = ROOT.TLegend(0.2, 0.7, 0.9, 0.95)
370  leg.AddEntry(
371  histo_belleplotB0,
372  'true B^{0} ' +
373  ' #varepsilon_{eff}(B^{0}) = ' +
374  f'{tot_eff_effB0 * 100:.2f}' +
375  '% #frac{n_{B^{0}}}{n} = ' +
376  f'{total_entries_B0 / total_entries * 100:.2f}' +
377  '%')
378  leg.AddEntry(
379  histo_belleplotB0bar,
380  'true #bar{B}^{0} ' +
381  ' #varepsilon_{eff}(#bar{B}^{0}) = ' +
382  f'{tot_eff_effB0bar * 100:.2f}' +
383  '% #frac{n_{#bar{B}^{0}}}{n} = ' +
384  f'{total_entries_B0bar / total_entries * 100:.2f}' +
385  '%')
386  leg.AddEntry("", "Avrg. #bf{ #varepsilon_{eff} = " + f'{average_eff * 100:.2f}' +
387  '%} #Delta#varepsilon_{eff} = ' + f'{diff_eff * 100:^5.2f}' + '%')
388  leg.SetTextSize(0.045)
389  leg.Draw()
390 
391  Canvas1.Update()
392 
393  with Quiet(ROOT.kError):
394  Canvas1.SaveAs(workingDirectory + '/' + 'test6_CPVFTqr' + method + '_both.pdf')
395 
396  # Validation Plot 1
397  histo_belleplotBoth.GetXaxis().SetLabelSize(0.04)
398  histo_belleplotBoth.GetYaxis().SetLabelSize(0.04)
399  histo_belleplotBoth.GetYaxis().SetTitleOffset(0.7)
400  histo_belleplotBoth.GetXaxis().SetTitleOffset(0.7)
401  histo_belleplotBoth.GetXaxis().SetTitleSize(0.06)
402  histo_belleplotBoth.GetYaxis().SetTitleSize(0.06)
403 
404  histo_belleplotBoth.GetListOfFunctions().Add(ROOT.TNamed('MetaOptions', 'nostats'))
405  histo_belleplotBoth.GetListOfFunctions().Add(ROOT.TNamed('Description', 'Output of the flavor tagger combiner ' + method))
406  histo_belleplotBoth.GetListOfFunctions().Add(
407  ROOT.TNamed(
408  'Check',
409  'Shape should not change drastically. E.g. Warning if the peak at 0 increases or if the peaks at +-1 decrease.'))
410  histo_belleplotBoth.GetListOfFunctions().Add(ROOT.TNamed('Contact', 'yosato@post.kek.jp'))
411 
412  histo_belleplotBoth.SetTitle(
413  'Flavor tagger output for combiner ' +
414  method +
415  '; #it{qr}_{' +
416  method +
417  '} ; Events (Total = ' +
418  f"{f'{total_entries:.0f}':<1}" +
419  ')')
420  histo_belleplotBoth.SetMinimum(0)
421  histo_belleplotBoth.SetMaximum(YmaxForQrPlot)
422  histo_belleplotBoth.SetStats(False)
423  histo_belleplotBoth.Write()
424 
425  # Validation Plot 2
426  histo_belleplotB0.GetYaxis().SetTitleOffset(0.7)
427  histo_belleplotB0.GetXaxis().SetTitleOffset(0.7)
428  histo_belleplotB0.SetLineColor(ROOT.kBlue + 2)
429  histo_belleplotB0.SetTitle(
430  'Flavor tagger output for combiner ' +
431  method +
432  ' for true B^{0}s; #it{qr}_{' +
433  method +
434  '} ; Events (Total = ' +
435  f"{f'{histo_belleplotB0.GetEntries():.0f}':<1}" +
436  ')')
437  histo_belleplotB0.SetStats(False)
438 
439  histo_belleplotB0.GetListOfFunctions().Add(ROOT.TNamed('MetaOptions', 'nostats'))
440  histo_belleplotB0.GetListOfFunctions().Add(
441  ROOT.TNamed('Description', 'Output of the flavor tagger combiner ' + method + ' for true B0s'))
442  histo_belleplotB0.GetListOfFunctions().Add(
443  ROOT.TNamed(
444  'Check',
445  'Shape should not change drastically. E.g. Warning if the peak at 0 increases or if the peak at +1 decreases.'))
446  histo_belleplotB0.GetListOfFunctions().Add(ROOT.TNamed('Contact', 'yosato@post.kek.jp'))
447  histo_belleplotB0.Write()
448 
449  # Validation Plot 3
450  histo_belleplotB0bar.GetXaxis().SetLabelSize(0.04)
451  histo_belleplotB0bar.GetYaxis().SetLabelSize(0.04)
452  histo_belleplotB0bar.GetYaxis().SetTitleOffset(0.7)
453  histo_belleplotB0bar.GetXaxis().SetTitleOffset(0.7)
454  histo_belleplotB0bar.GetXaxis().SetTitleSize(0.06)
455  histo_belleplotB0bar.GetYaxis().SetTitleSize(0.06)
456  histo_belleplotB0bar.SetLineColor(ROOT.kBlue + 2)
457  histo_belleplotB0bar.SetTitle(
458  'Flavor tagger output for combiner ' +
459  method +
460  ' for true #bar{B}^{0}s; #it{qr}_{' +
461  method +
462  '} ; Events (Total = ' +
463  f"{f'{histo_belleplotB0bar.GetEntries():.0f}':<1}" +
464  ')')
465  histo_belleplotB0bar.SetMinimum(0)
466  histo_belleplotB0bar.SetMaximum(YmaxForQrPlot)
467  histo_belleplotB0bar.SetStats(False)
468 
469  histo_belleplotB0bar.GetListOfFunctions().Add(ROOT.TNamed('MetaOptions', 'nostats'))
470  histo_belleplotB0bar.GetListOfFunctions().Add(
471  ROOT.TNamed(
472  'Description',
473  'Output of the flavor tagger combiner ' +
474  method +
475  ' for true B0bars'))
476  histo_belleplotB0bar.GetListOfFunctions().Add(ROOT.TNamed(
477  'Check', 'Shape should not change drastically. E.g. Warning if the peak at 0 increases or if the peak at -1 decreases.'))
478  histo_belleplotB0bar.GetListOfFunctions().Add(ROOT.TNamed('Contact', 'yosato@post.kek.jp'))
479  histo_belleplotB0bar.Write()
480 
481  # IPython.embed()
482 
483  # produce the nice calibration plot
484  with Quiet(ROOT.kError):
485  Canvas2 = ROOT.TCanvas('Bla2', 'Calibration plot for true B0', 1200, 800)
486  Canvas2.cd() # activate
487  Canvas2.SetLeftMargin(0.13)
488  Canvas2.SetRightMargin(0.04)
489  Canvas2.SetTopMargin(0.03)
490  Canvas2.SetBottomMargin(0.14)
491  histo_calib_B0.GetXaxis().SetLabelSize(0.04)
492  histo_calib_B0.GetYaxis().SetLabelSize(0.04)
493  histo_calib_B0.GetYaxis().SetTitleOffset(0.9)
494  histo_calib_B0.GetXaxis().SetTitleSize(0.06)
495  histo_calib_B0.GetYaxis().SetTitleSize(0.06)
496  histo_calib_B0.SetFillColorAlpha(ROOT.kBlue, 0.2)
497  histo_calib_B0.SetFillStyle(1001)
498  histo_calib_B0.GetYaxis().SetTitleOffset(0.9)
499  histo_calib_B0.SetLineColor(ROOT.kBlue)
500 
501  histo_calib_B0.SetTitle('; #it{qr}_{' + method + '} ; Calibration '
502  )
503  histo_calib_B0.Draw('hist')
504  diag.Draw('SAME')
505 
506  leg2 = ROOT.TLegend(0.2, 0.75, 0.63, 0.93)
507  leg2.SetHeader(" y = #it{m}#it{x} + #it{c}", "")
508  leg2.GetListOfPrimitives().First().SetTextAlign(22)
509  leg2.AddEntry(
510  diag,
511  "#it{m} = " +
512  f"{diag.GetParameter('p1'):.2f}" +
513  " #it{c} = " +
514  f"{diag.GetParameter('p0'):.2f}")
515  leg2.SetTextSize(0.05)
516  leg2.Draw()
517 
518  Canvas2.Update()
519  with Quiet(ROOT.kError):
520  Canvas2.SaveAs(workingDirectory + '/' + 'test6_CPVFTCalibration_' + method + '_B0.pdf')
521 
522  # Validation Plot 4
523 
524  histo_calib_B0.GetYaxis().SetTitleOffset(0.7)
525  histo_calib_B0.GetXaxis().SetTitleOffset(0.7)
526  histo_calib_B0.SetLineColor(ROOT.kBlue + 2)
527  histo_calib_B0.SetTitle('Calibration plot for the flavor tagger combiner ' +
528  method + ' ; #it{qr}_{' + method + '} ; Calibration')
529  histo_calib_B0.SetMinimum(-0.2)
530  histo_calib_B0.SetMaximum(+1.2)
531  histo_calib_B0.SetStats(False)
532 
533  histo_calib_B0.GetListOfFunctions().Add(ROOT.TNamed('MetaOptions', 'nostats'))
534  histo_calib_B0.GetListOfFunctions().Add(
535  ROOT.TNamed(
536  'Description',
537  'Calibration plot for the flavor tagger combiner ' +
538  method +
539  ' for true B0s'))
540  histo_calib_B0.GetListOfFunctions().Add(
541  ROOT.TNamed('Check', 'Shape should not change drastically. E.g. warning if the shape stops being linear.'))
542  histo_calib_B0.GetListOfFunctions().Add(ROOT.TNamed('Contact', 'yosato@post.kek.jp'))
543  histo_calib_B0.Write()
544 
545  histo_belleplotBoth.Delete()
546  histo_avr_r.Delete()
547  histo_avr_rB0.Delete()
548  histo_avr_rB0bar.Delete()
549  histo_entries_per_bin.Delete()
550  histo_entries_per_binB0.Delete()
551  histo_entries_per_binB0bar.Delete()
552  histo_Cnet_output_B0.Delete()
553  histo_Cnet_output_B0bar.Delete()
554  histo_belleplotB0.Delete()
555  histo_belleplotB0bar.Delete()
556  histo_calib_B0.Delete()
557  histo_calib_B0bar.Delete()
558  hallo12.Delete()
559  histo_m0.Delete()
560  histo_m1.Delete()
561  histo_m2.Delete()
562  Canvas1.Clear()
563  Canvas2.Clear()
564 
565 
566 # **********************************************
567 # DETERMINATION OF INDIVIDUAL EFFECTIVE EFFICIENCY
568 # **********************************************
569 
570 print('************************* MEASURED EFFECTIVE EFFICIENCY FOR INDIVIDUAL CATEGORIES *********************************')
571 print('* *')
572 # input: Classifier input from event-level. Output of event-level is recalculated for input on combiner-level.
573 # but is re-evaluated under combiner target. Signal is B0, background is B0Bar.
574 
575 for category in usedCategories:
576  # histogram of input variable (only signal) - not yet a probability! It's a classifier plot!
577  hist_signal = ROOT.TH1F('Signal_' + category, 'Input Signal (B0)' +
578  category + ' (binning 50)', 50, -1.0, 1.0)
579  # histogram of input variable (only background) - not yet a probability! It's a classifier plot!
580  hist_background = ROOT.TH1F('Background_' + category, 'Input Background (B0bar)' +
581  category + ' (binning 50)', 50, -1.0, 1.0)
582  hist_both = ROOT.TH1F('qp_' + category, 'Input Background (B0bar)' +
583  category + ' (binning 50)', 100, -1, 1)
584 
585  # per definition that input is not comparable to the network output, this has to be transformed.
586  # probability output from 0 to 1 (corresponds to net output probability) -> calculation below
587  hist_probB0 = ROOT.TH1F('ProbabilityB0_' + category,
588  'Transformed to probability (B0) (' + category + ')',
589  50, 0.0, 1.0)
590  hist_probB0bar = ROOT.TH1F('ProbabilityB0bar_' + category,
591  'Transformed to probability (B0bar) (' + category + ')',
592  50, 0.0, 1.0)
593  # qp output from -1 to 1 -> transformation below
594  hist_qpB0 = ROOT.TH1F('QRB0_' + category, 'Transformed to qp (B0)(' +
595  category + ')', 50, -1.0, 1.0)
596  hist_qpB0bar = ROOT.TH1F('QRB0bar_' + category, 'Transformed to qp (B0bar) (' +
597  category + ')', 50, -1.0, 1.0)
598  # histogram for abs(qp), i.e. this histogram contains the r-values -> transformation below
599  # also used to get the number of entries, sorted into 7 bins
600  hist_absqpB0 = ROOT.TH1F('AbsQRB0_' + category, 'Abs(qp)(B0) (' + category + ')', 7, r_subsample)
601  hist_absqpB0bar = ROOT.TH1F('AbsQRB0bar_' + category, 'Abs(qp) (B0bar) (' + category + ')', 7, r_subsample)
602  # histogram contains at the end the average r values -> calculation below
603  # sorted into 7 bins
604  hist_aver_rB0 = ROOT.TH1F('AverageRB0_' + category, 'A good one (B0)' +
605  category, 7, r_subsample)
606  hist_aver_rB0bar = ROOT.TH1F('AverageRB0bar_' + category, 'A good one (B0bar)' +
607  category, 7, r_subsample)
608  # ****** TEST OF CALIBRATION ******
609  # for calibration plot we want to have
610  hist_all = ROOT.TH1F('All_' + category, 'Input Signal (B0) and Background (B0Bar)' +
611  category + ' (binning 50)', 50, 0.0, 1.0)
612  tree.Draw('qp' + category + '>>All_' + category, 'qrMC!=0')
613  hist_calib_B0 = ROOT.TH1F('Calib_B0_' + category, 'Calibration Plot for true B0' +
614  category + ' (binning 50)', 50, 0.0, 1.0)
615  tree.Draw('qp' + category + '>>Calib_B0_' + category, 'qrMC == 1.0')
616  hist_calib_B0.Divide(hist_all)
617 
618  # fill signal
619  tree.Draw('qp' + category + '>>Signal_' + category, 'qrMC == 1.0')
620  # fill background
621  tree.Draw('qp' + category + '>>Background_' + category, 'qrMC == -1.0'
622  )
623  # fill both
624  tree.Draw('qp' + category + '>>qp_' + category, 'abs(qrMC) == 1.0'
625  )
626 
627  # ***** TEST OF CALIBRATION ******
628 
629  # initialize some arrays
630  purityB0 = array('d', [0] * 51)
631  dilutionB02 = array('d', [0] * 51)
632  purityB0bar = array('d', [0] * 51)
633  dilutionB0bar2 = array('d', [0] * 51)
634  signal = array('d', [0] * 51)
635  back = array('d', [0] * 51)
636  weight = array('d', [0] * 51)
637 
638  for i in range(1, 51):
639  # doing the transformation to probabilities
640  signal[i] = hist_signal.GetBinContent(i)
641  back[i] = hist_background.GetBinContent(i)
642 
643  weight[i] = signal[i] + back[i]
644 
645  # avoid dividing by zero
646  if signal[i] + back[i] == 0:
647  purityB0[i] = 0
648  dilutionB02[i] = 0
649  purityB0bar[i] = 0
650  dilutionB0bar2[i] = 0
651  else:
652  purityB0[i] = signal[i] / (signal[i] + back[i])
653  dilutionB02[i] = -1 + 2 * signal[i] / (signal[i] + back[i])
654 
655  purityB0bar[i] = back[i] / (signal[i] + back[i])
656  dilutionB0bar2[i] = -1 + 2 * back[i] / (signal[i] + back[i])
657 
658  # filling histogram with probability from 0 to 1
659  hist_probB0.Fill(purityB0[i], signal[i])
660  hist_probB0bar.Fill(purityB0bar[i], back[i])
661 
662  # filling histogram with qp from -1 to 1
663  hist_qpB0.Fill(dilutionB02[i], signal[i])
664  hist_qpB0bar.Fill(dilutionB0bar2[i], back[i])
665 
666  # filling histogram with abs(qp), i.e. this histogram contains the r-values (not qp)
667  hist_absqpB0.Fill(abs(dilutionB02[i]), signal[i])
668  hist_absqpB0bar.Fill(abs(dilutionB0bar2[i]), back[i])
669  # filling histogram with abs(qp) special weighted - needed for average r calculation
670  hist_aver_rB0.Fill(abs(dilutionB02[i]), abs(dilutionB02[i]) * signal[i])
671  hist_aver_rB0bar.Fill(abs(dilutionB0bar2[i]), abs(dilutionB0bar2[i]) * back[i])
672 
673  # hist_aver_rB0bar contains now the average r-value
674  hist_aver_rB0.Divide(hist_absqpB0)
675  hist_aver_rB0bar.Divide(hist_absqpB0bar)
676  # now calculating the efficiency
677 
678  # calculating number of events
679  tot_entriesB0 = 0
680  tot_entriesB0bar = 0
681  for i in range(1, r_size):
682  tot_entriesB0 = tot_entriesB0 + hist_absqpB0.GetBinContent(i)
683  tot_entriesB0bar = tot_entriesB0bar + hist_absqpB0bar.GetBinContent(i)
684  # initializing some arrays
685  tot_eff_effB0 = 0
686  tot_eff_effB0bar = 0
687  event_fractionB0 = array('f', [0] * r_size)
688  event_fractionB0bar = array('f', [0] * r_size)
689  rvalueB0 = array('f', [0] * r_size)
690  rvalueB0bar = array('f', [0] * r_size)
691  # wvalue = array('f', [0] * r_size)
692  entriesB0 = array('f', [0] * r_size)
693  entriesB0bar = array('f', [0] * r_size)
694 
695  for i in range(1, r_size):
696  rvalueB0[i] = hist_aver_rB0.GetBinContent(i)
697  rvalueB0bar[i] = hist_aver_rB0bar.GetBinContent(i)
698  # wvalue[i] = (1 - rvalueB0[i]) / 2
699  entriesB0[i] = hist_absqpB0.GetBinContent(i)
700  entriesB0bar[i] = hist_absqpB0bar.GetBinContent(i)
701  event_fractionB0[i] = entriesB0[i] / tot_entriesB0
702  event_fractionB0bar[i] = entriesB0bar[i] / tot_entriesB0bar
703  # print '* Bin ' + str(i) + ' r-value: ' + str(rvalueB0[i]), 'entriesB0: ' +
704  # str(event_fractionB0[i] * 100) + ' % (' + str(entriesB0[i]) + '/' +
705  # str(tot_entriesB0) + ')'
706  tot_eff_effB0 = tot_eff_effB0 + event_fractionB0[i] * rvalueB0[i] \
707  * rvalueB0[i]
708  tot_eff_effB0bar = tot_eff_effB0bar + event_fractionB0bar[i] * rvalueB0bar[i] \
709  * rvalueB0bar[i]
710  effDiff = tot_eff_effB0 - tot_eff_effB0bar
711  effAverage = (tot_eff_effB0 + tot_eff_effB0bar) / 2
712 
713  print(
714  f"{'* ' + category:<25}" +
715  ' B0-Eff=' +
716  f'{tot_eff_effB0 * 100: 8.2f}' +
717  ' %' +
718  ' B0bar-Eff=' +
719  f'{tot_eff_effB0bar * 100: 8.2f}' +
720  ' %' +
721  ' EffAverage=' +
722  f'{effAverage * 100: 8.2f}' + ' %' +
723  ' EffDiff=' +
724  f'{effDiff * 100: 8.2f}' + ' % *')
725 
726  # ****** produce the input plots from combiner level ******
727 
728  efficienciesForNtuple.append(float(effAverage * 100))
729 
730  maxSignal = hist_signal.GetBinContent(hist_signal.GetMaximumBin())
731  maxBackground = hist_background.GetBinContent(hist_background.GetMaximumBin())
732 
733  Ymax = max(maxSignal, maxBackground)
734  Ymax = Ymax + Ymax / 12
735 
736  ROOT.gStyle.SetOptStat(0)
737  with Quiet(ROOT.kError):
738  Canvas = ROOT.TCanvas('Bla', 'TITEL BLA', 1200, 800)
739  Canvas.cd() # activate
740  Canvas.SetLogy()
741  Canvas.SetLeftMargin(0.13)
742  Canvas.SetRightMargin(0.04)
743  Canvas.SetTopMargin(0.03)
744  Canvas.SetBottomMargin(0.14)
745  hist_signal.SetFillColorAlpha(ROOT.kBlue, 0.2)
746  hist_signal.SetFillStyle(1001)
747  hist_signal.SetTitleSize(0.1)
748  hist_signal.GetXaxis().SetLabelSize(0.04)
749  hist_signal.GetYaxis().SetLabelSize(0.04)
750  hist_signal.GetXaxis().SetTitleSize(0.06)
751  hist_signal.GetYaxis().SetTitleSize(0.06)
752  hist_signal.GetXaxis().SetLabelSize(0.04)
753  hist_signal.GetYaxis().SetLabelSize(0.04)
754  hist_signal.GetXaxis().SetTitleSize(0.05)
755  hist_signal.GetYaxis().SetTitleSize(0.05)
756  hist_signal.GetXaxis().SetTitleOffset(0.95)
757  hist_signal.GetYaxis().SetTitleOffset(1.1)
758  hist_signal.GetXaxis().SetTitleOffset(1.15)
759  hist_signal.GetYaxis().SetLimits(0, Ymax)
760  hist_signal.SetLineColor(ROOT.kBlue)
761  hist_background.SetFillColorAlpha(ROOT.kRed, 1.0)
762  hist_background.SetFillStyle(3005)
763  hist_background.GetYaxis().SetLimits(0, Ymax)
764  hist_background.SetLineColor(ROOT.kRed)
765 
766  catName = category
767  if category == 'MaximumPstar':
768  catName = 'MaximumP*'
769 
770  hist_signal.SetTitle('; (#it{qp})^{' + catName + '} ; Events')
771  # hist_signal.SetMinimum(0)
772  hist_signal.SetMaximum(Ymax)
773  # hist_background.SetMinimum(0)
774  hist_background.SetMaximum(Ymax)
775 
776  hist_signal.Draw('hist')
777  hist_background.Draw('hist same')
778 
779  l0 = ROOT.TLegend(0.13, 0.65, 0.33, 0.97)
780  l0.SetFillColorAlpha(ROOT.kWhite, 0)
781  l0.AddEntry(hist_signal, ' #varepsilon_{eff}(B^{0}) = ' + f'{tot_eff_effB0 * 100:.2f}' + "%")
782  l0.AddEntry(hist_background, ' #varepsilon_{eff}(#bar{B}^{0}) = ' + f'{tot_eff_effB0bar * 100:.2f}' + "%")
783  l0.AddEntry("", "#bf{#varepsilon_{eff} = " + f'{effAverage * 100:.2f}' + '%}')
784  l0.AddEntry("", '#Delta#varepsilon_{eff} = ' + f'{effDiff * 100:^5.2f}' + '%')
785  l0.SetBorderSize(0)
786  l0.SetTextSize(0.045)
787  l0.Draw()
788 
789  l1 = ROOT.TLegend(0.85, 0.7, 0.96, 0.97)
790  l1.SetFillColorAlpha(ROOT.kWhite, 0.35)
791  l1.AddEntry(hist_signal, 'B^{0}_{MC}')
792  l1.AddEntry(hist_background, '#bar{B}^{0}_{MC}')
793  l1.SetTextSize(0.045)
794  l1.Draw()
795 
796  Canvas.Update()
797  with Quiet(ROOT.kError):
798  Canvas.SaveAs(workingDirectory + '/' + 'test6_CPVFTqp_' + category + '_both.pdf')
799 
800  # Validation Plot 4
801  hist_both.GetXaxis().SetLabelSize(0.04)
802  hist_both.GetYaxis().SetLabelSize(0.04)
803  hist_both.GetYaxis().SetTitleOffset(0.7)
804  hist_both.GetXaxis().SetTitleOffset(0.7)
805  hist_both.GetXaxis().SetTitleSize(0.06)
806  hist_both.GetYaxis().SetTitleSize(0.06)
807 
808  hist_both.GetListOfFunctions().Add(ROOT.TNamed('MetaOptions', 'nostats, logy'))
809  hist_both.GetListOfFunctions().Add(ROOT.TNamed('Description', 'Output of the flavor tagger category ' + catName))
810  hist_both.GetListOfFunctions().Add(
811  ROOT.TNamed('Check', 'Shape should not change drastically. E.g. Warning if there is only a peak at 0.'))
812  hist_both.GetListOfFunctions().Add(ROOT.TNamed('Contact', 'yosato@post.kek.jp'))
813 
814  hist_both.SetTitle(
815  'Flavor tagger output of the category ' +
816  catName +
817  '; #it{qp}_{' +
818  catName +
819  '} ; Events (Total = ' +
820  f"{f'{hist_both.GetEntries():.0f}':<1}" +
821  ')')
822  # hist_both.SetStats(False)
823  hist_both.Write()
824 
825  Canvas.Clear()
826 
827 outputNtuple.Fill(array('f', efficienciesForNtuple))
828 outputNtuple.Write()
829 outputFile.Close()
830 
831 print('* *')
832 print('*******************************************************************************************************************')
oldlevel
the previously set level to be ignored