Belle II Software development
inputVariablesPlots.py
1#!/usr/bin/env python3
2
3
10
11
23
24import os
25import glob
26import sys
27from matplotlib.ticker import FormatStrFormatter
28import matplotlib.pyplot as plt
29import ROOT
30from ROOT import Belle2
31import basf2 as b2
32import flavorTagger as ft
33from defaultEvaluationParameters import categories
34
35import numpy as np
36import matplotlib as mpl
37mpl.use('Agg')
38mpl.rcParams.update({'font.size': 22})
39mpl.rcParams['text.usetex'] = True
40mpl.rcParams['text.latex.preamble'] = [r"\usepackage{amsmath}"]
41
42ROOT.gROOT.SetBatch(True)
43
44if len(sys.argv) != 5:
45 sys.exit("Must provide 4 arguments: [Belle or Belle2] [BGx0 or BGx1] [training] [workingDirectory]"
46 )
47
48belleOrBelle2 = sys.argv[1]
49MCtype = str(sys.argv[2])
50decayChannelTrainedOn = str(sys.argv[3]) # Decay channel of the weight files "JPsiKs" or "nunubar"
51workingDirectory = sys.argv[4]
52
53filesDirectory = workingDirectory + '/FlavorTagging/TrainedMethods'
54
55if decayChannelTrainedOn == 'JPsiKs':
56 decayChannelTrainedOn = 'JpsiKs_mu'
57
58weightFiles = 'B2' + decayChannelTrainedOn + MCtype
59
60
61ROOT.TH1.SetDefaultSumw2()
62
63allInputVariables = []
64
65belleOrBelle2Flag = belleOrBelle2
66
67identifiersExtraInfosDict = dict()
68identifiersExtraInfosKaonPion = []
69
70if belleOrBelle2 == "Belle":
71 unitImp = "cm"
72
73dBw = 50
74
75pBins = 50
76fBins = 100
77
78unitImp = "mm"
79
80variablesPlotParamsDict = {
81 'useCMSFrame(p)': ['useCMSFrame__bop__bc', pBins, 0, 3, r'$p^*\ [{\rm GeV}/c]$', r"{\rm GeV}/c\, "],
82 'useCMSFrame(pt)': ['useCMSFrame__bopt__bc', pBins, 0, 3, r'$p_{\rm t}^*\ [{\rm GeV}/c]$', r"{\rm GeV}/c\, "],
83 'p': ['p', pBins, 0, 3, r'$p\ [{\rm GeV}/c]$', r"{\rm GeV}/c\, "],
84 'pt': ['pt', pBins, 0, 3, r'$p_{\rm t}\ [{\rm GeV}/c]$', r"{\rm GeV}/c\, "],
85 'cosTheta': ['cosTheta', dBw, -1, 1.01, r'$\cos{\theta}$', ""],
86 ft.eId[ft.getBelleOrBelle2()]: [Belle2.MakeROOTCompatible.makeROOTCompatible(ft.eId[ft.getBelleOrBelle2()]),
87 dBw, 0, 1.01, r'$\mathcal{L}_{e}$', ""],
88 'eid_dEdx': ['eid_dEdx', dBw, 0, 1.01, r'$\mathcal{L}_{e}^{{\rm d}E/{\rm d}x}$', ""],
89 'eid_TOP': ['eid_TOP', dBw, 0, 1.01, r'$\mathcal{L}_{e}^{\rm TOP}$', ""],
90 'eid_ARICH': ['eid_ARICH', dBw, 0, 1.01, r'$\mathcal{L}_{e}^{\rm ARICH}$', ""],
91 'eid_ECL': ['eid_ECL', dBw, 0, 1.01, r'$\mathcal{L}_{e}^{\rm ECL}$', ""],
92 'BtagToWBosonVariables(recoilMassSqrd)': ['BtagToWBosonVariables__borecoilMassSqrd__bc', fBins,
93 0, 100, r'$M_{\rm rec}^2\ [{\rm GeV}^2/c^4]$', r"{\rm GeV}^2/c^4"],
94 'BtagToWBosonVariables(pMissCMS)': [
95 'BtagToWBosonVariables__bopMissCMS__bc', 60, 0, 3.6,
96 r'$p^*_{\rm miss}\ [{\rm GeV}/c]$', r"{\rm GeV}/c\, "],
97 'BtagToWBosonVariables(cosThetaMissCMS)': ['BtagToWBosonVariables__bocosThetaMissCMS__bc',
98 dBw, -1, 1.01, r'$\cos{\theta^*_{\rm miss}}$', ""],
99 'BtagToWBosonVariables(EW90)': ['BtagToWBosonVariables__boEW90__bc',
100 dBw, 0, 4, r'$E_{90}^{W}\ [{\rm GeV}]$', r"{\rm GeV}\, "],
101 'BtagToWBosonVariables(recoilMass)': ['sqrt(abs(BtagToWBosonVariables__borecoilMassSqrd__bc))',
102 dBw, 0, 12, r'$M_{\rm rec}\ [{\rm GeV}/c^2]$', r"{\rm GeV}/c^2\, "],
103 'cosTPTO': ['cosTPTO', dBw, 0, 1.01, r'$\vert\cos{\theta^*_{\rm T}}\vert$', ""],
104 'ImpactXY': ['ImpactXY', dBw, 0, 0.5, r'$d_0\ [{\rm ' + unitImp + '}]$', r"{\rm " + unitImp + r"}\, "],
105 'z0': ['z0', dBw, 0, 1.0, r'$z_0\ [{\rm ' + unitImp + '}]$', r"{\rm " + unitImp + r"}\, "],
106 'y': ['y', dBw, -0.15, 0.15, r'$y_0\ [{\rm ' + unitImp + '}]$', r"{\rm " + unitImp + r"}\, "],
107 'OBoost': ['OBoost', dBw, -0.15, 0.15, r'$d_0^\prime\ [{\rm ' + unitImp + '}]$', r"{\rm " + unitImp + r"}\, "],
108 'distance': ['distance', dBw, 0, 1.5, r'$\xi_0\ [{\rm ' + unitImp + '}]$', r"{\rm " + unitImp + r"}\, "],
109 'chiProb': ['chiProb', dBw, 0, 1.01, r'$p$-${\rm value}$', ""],
110 ft.muId[ft.getBelleOrBelle2()]: [Belle2.MakeROOTCompatible.makeROOTCompatible(ft.muId[ft.getBelleOrBelle2()]),
111 dBw, 0, 1.01, r'$\mathcal{L}_{\mu}$', ""],
112 'muid_dEdx': ['muid_dEdx', dBw, 0, 1.01, r'$\mathcal{L}_{\mu}^{{\rm d}E/{\rm d}x}$', ""],
113 'muid_TOP': ['muid_TOP', dBw, 0, 1.01, r'$\mathcal{L}_{\mu}^{\rm TOP}$', ""],
114 'muid_ARICH': ['muid_ARICH', dBw, 0, 1.01, r'$\mathcal{L}_{\mu}^{\rm ARICH}$', ""],
115 'muid_KLM': ['muid_KLM', dBw, 0, 1.01, r'$\mathcal{L}_{\mu}^{\rm KLM}$', ""],
116 ft.KId[ft.getBelleOrBelle2()]: [Belle2.MakeROOTCompatible.makeROOTCompatible(ft.KId[ft.getBelleOrBelle2()]),
117 dBw, 0, 1.01, r'$\mathcal{L}_{K}$', ""],
118 'Kid_dEdx': ['Kid_dEdx', dBw, 0, 1.01, r'$\mathcal{L}_{K}^{{\rm d}E/{\rm d}x}$', ""],
119 'Kid_TOP': ['Kid_TOP', dBw, 0, 1.01, r'$\mathcal{L}_{K}^{\rm TOP}$', ""],
120 'Kid_ARICH': ['Kid_ARICH', dBw, 0, 1.01, r'$\mathcal{L}_{K}^{\rm ARICH}$', ""],
121 'NumberOfKShortsInRoe': ['NumberOfKShortsInRoe', dBw, 0, 12, r'$n_{K^0_S}$', ""],
122 'ptTracksRoe': ['ptTracksRoe', fBins, 0, 6, r'$\Sigma\, p_{\rm t}^2\ [{\rm GeV^2}/c^2]$',
123 r"{\rm GeV^2}/c^2"],
124 'extraInfo(isRightCategory(Kaon))': ['extraInfo__boisRightCategory__boKaon__bc__bc',
125 dBw, 0, 1.01, r"$y_{\rm Kaon}$", ""],
126 'HighestProbInCat(pi+:inRoe, isRightCategory(SlowPion))': [
127 'HighestProbInCat__bopi__pl__clinRoe__cm__spisRightCategory__boSlowPion__bc__bc',
128 dBw, 0, 1.01, r"$y_{\rm SlowPion}$", ""],
129 'KaonPionVariables(cosKaonPion)': ['KaonPionVariables__bocosKaonPion__bc',
130 dBw, -1, 1.01, r'$\cos{\theta^*_{K\pi}}$', ""],
131 'KaonPionVariables(HaveOpositeCharges)': ['KaonPionVariables__boHaveOpositeCharges__bc',
132 dBw, 0, 1.01, r'$\frac{1 - q_{K} \cdot q_\pi}{2}$', ""],
133 'pionID': ['pionID', dBw, 0, 1.01, r'$\mathcal{L}_{\pi}$', ""],
134 'piid_dEdx': ['piid_dEdx', dBw, 0, 1.01, r'$\mathcal{L}_{\pi}^{{\rm d}E/{\rm d}x}$', ""],
135 'piid_TOP': ['piid_TOP', dBw, 0, 1.01, r'$\mathcal{L}_{\pi}^{\rm TOP}$', ""],
136 'piid_ARICH': ['piid_ARICH', dBw, 0, 1.01, r'$\mathcal{L}_{\pi}^{\rm ARICH}$', ""],
137 'pi_vs_edEdxid': ['pi_vs_edEdxid', dBw, 0, 1.01, r'$\mathcal{L}_{\pi/e}^{{\rm d}E/{\rm d}x}$', ""],
138 'FSCVariables(pFastCMS)': ['FSCVariables__bopFastCMS__bc', pBins, 0, 3, r'$p^*_{\rm Fast}\ [{\rm GeV}/c]$', r"{\rm GeV}/c\, "],
139 'FSCVariables(cosSlowFast)': ['FSCVariables__bocosSlowFast__bc', dBw, -1, 1.01, r'$\cos{\theta^*_{\rm SlowFast}}$', ''],
140 'FSCVariables(cosTPTOFast)': ['FSCVariables__bocosTPTOFast__bc', dBw, 0, 1.01, r'$\vert\cos{\theta^*_{\rm T, Fast}}\vert$', ''],
141 'FSCVariables(SlowFastHaveOpositeCharges)': ['FSCVariables__boSlowFastHaveOpositeCharges__bc',
142 dBw, 0, 1.01, r'$\frac{1 - q_{\rm Slow} \cdot q_{\rm Fast}}{2}$', ""],
143 'lambdaFlavor': ['lambdaFlavor', dBw, -1, 1.01, r'$q_{\Lambda}$', ""],
144 'M': ['M', dBw, 1.08, 1.22, r'$M_{\Lambda}\ [{\rm GeV}/c^2]$', r"{\rm MeV}/c^2\, "],
145 'cosAngleBetweenMomentumAndVertexVector': ['cosAngleBetweenMomentumAndVertexVector',
146 dBw, -1, 1.01,
147 r'$\cos{\theta_{\boldsymbol{x}_{\Lambda},\boldsymbol{p}_{\Lambda}}}$', ""],
148 'lambdaZError': ['lambdaZError', dBw, 0, 0.05, r'$\sigma_{\Lambda}^{zz}$', r"{\rm mm}\, "],
149 'daughter(0,p)': ['daughter__bo0__cmp__bc', dBw, 0, 1, r'$p_{\pi}\ [{\rm GeV}/c]$', r"{\rm GeV}/c\, "],
150 'daughter(0,useCMSFrame(p))': ['daughter__bo0__cmuseCMSFrame__bop__bc__bc',
151 dBw, 0, 1, r'$p^*_{\pi}\ [{\rm GeV}/c]$', r"{\rm GeV}/c\, "],
152 'daughter(1,p)': ['daughter__bo1__cmp__bc', dBw, 0, 2, r'$p_{p}\ [{\rm GeV}/c]$', r"{\rm GeV}/c"],
153 'daughter(1,useCMSFrame(p))': ['daughter__bo1__cmuseCMSFrame__bop__bc__bc',
154 dBw, 0, 2, r'$p^*_{p}\ [{\rm GeV}/c]$', r"{\rm GeV}/c\, "],
155 'daughter(1,protonID)': ['daughter__bo1__cmprotonID__bc', dBw, 0, 1.01, r'$\mathcal{L}_{p}$', ""],
156 'daughter(0,pionID)': ['daughter__bo0__cmpionID__bc', dBw, 0, 1.01, r'$\mathcal{L}_{\pi}$', ""]}
157
158if not b2.find_file('InputVariablesPlots', silent=True):
159 os.mkdir('./InputVariablesPlots')
160
161
162def plotInputVariablesOfFlavorTagger():
163 """
164 Makes plots of the distribution of the input variables of the flavor tagger
165 for each category distinguishing between the target particles of the category (signal)
166 and all the other (bkg.)
167 """
168
169 for (particleList, category, _) in ft.getEventLevelParticleLists(categories):
170
171 # if category != "SlowPion":
172 # continue
173
174 if not b2.find_file('InputVariablesPlots/' + category, silent=True):
175 os.mkdir('./InputVariablesPlots/' + category)
176
177 if particleList not in identifiersExtraInfosDict and category != 'KaonPion':
178 identifiersExtraInfosDict[particleList] = []
179
180 methodPrefixEventLevel = "FlavorTagger_" + belleOrBelle2Flag + "_" + weightFiles + 'EventLevel' + category + 'FBDT'
181 treeName = methodPrefixEventLevel + "_tree"
182 targetVariable = 'isRightCategory(' + category + ')'
183
184 tree = ROOT.TChain(treeName)
185
186 workingFiles = glob.glob(filesDirectory + '/' + methodPrefixEventLevel + 'sampled*.root')
187 # print("workingFiles = ", workingFiles)
188 # workingFiles = glob.glob(filesDirectory + '/' + methodPrefixEventLevel + 'sampled1?.root')
189
190 for iFile in workingFiles:
191 tree.AddFile(iFile)
192
193 categoryInputVariables = []
194 trulyUsedInputVariables = []
195 for iVariable in tree.GetListOfBranches():
196
197 managerVariableName = str(Belle2.MakeROOTCompatible.invertMakeROOTCompatible(iVariable.GetName()))
198
199 if managerVariableName in ft.getTrainingVariables(category) or managerVariableName == 'distance' or \
200 managerVariableName == 'z0' or managerVariableName == 'ImpactXY' or \
201 managerVariableName == 'y' or managerVariableName == 'OBoost':
202 if managerVariableName in categoryInputVariables:
203 continue
204
205 categoryInputVariables.append(managerVariableName)
206 if managerVariableName in ft.getTrainingVariables(category):
207 allInputVariables.append((category, managerVariableName))
208 trulyUsedInputVariables.append((category, managerVariableName))
209
210 if managerVariableName not in identifiersExtraInfosDict[particleList] and category != 'KaonPion':
211 identifiersExtraInfosDict[particleList].append(managerVariableName)
212
213 elif category == 'KaonPion' and managerVariableName not in identifiersExtraInfosKaonPion:
214 identifiersExtraInfosKaonPion.append(managerVariableName)
215
216 # if managerVariableName not in variablesPlotParamsDict:
217 # variablesPlotParamsDict[managerVariableName] =
218 # [iVariable.GetName(), 100, 0, 2, iVariable.GetName(), "unit"]
219
220 print("The number of variables used in " + category + " is = ", len(trulyUsedInputVariables))
221
222 if category != 'KaonPion' and category != 'FSC' and category != 'MaximumPstar' and \
223 category != 'FastHadron' and category != 'Lambda':
224 categoryInputVariables.append('BtagToWBosonVariables(recoilMass)')
225
226 for inputVariable in categoryInputVariables:
227
228 print(inputVariable)
229
230 nBins = variablesPlotParamsDict[inputVariable][1]
231 limXmin = variablesPlotParamsDict[inputVariable][2]
232 limXmax = variablesPlotParamsDict[inputVariable][3]
233
234 if category == "SlowPion":
235 if inputVariable == 'p' or inputVariable == 'useCMSFrame(p)' or \
236 inputVariable == 'pt' or inputVariable == 'useCMSFrame(pt)':
237 nBins = 150
238 limXmax = 1.5
239
240 if inputVariable == 'distance':
241 nBins = 80
242 limXmax = 2.4
243
244 if inputVariable == 'ImpactXY':
245 nBins = 80
246 limXmax = 0.8
247
248 if category == "Lambda":
249 if inputVariable == 'distance':
250 # nBins = 25
251 limXmax = 10
252
253 if inputVariable == 'chiProb':
254 nBins = 25
255
256 signalHistogram = ROOT.TH1F("signal" + category + str(Belle2.MakeROOTCompatible.makeROOTCompatible(inputVariable)), "",
257 nBins,
258 limXmin,
259 limXmax)
260 backgroundHistogram = ROOT.TH1F("bkg" + category + str(Belle2.MakeROOTCompatible.makeROOTCompatible(inputVariable)), "",
261 nBins,
262 limXmin,
263 limXmax)
264
265 factorMultiplication = ''
266
267 if belleOrBelle2 == "Belle2" and ((category != "Lambda" and inputVariable == 'distance') or inputVariable ==
268 'z0' or inputVariable == 'ImpactXY' or inputVariable ==
269 'y' or inputVariable == 'OBoost'):
270 factorMultiplication = "*10 "
271
272 tree.Draw(variablesPlotParamsDict[inputVariable][0] + factorMultiplication + ">> signal" + category + str(
274 Belle2.MakeROOTCompatible.makeROOTCompatible(targetVariable) + " > 0")
275
276 tree.Draw(
277 variablesPlotParamsDict[inputVariable][0] +
278 factorMultiplication +
279 ">> bkg" +
280 category +
281 str(
284 " < 1")
285
286 signalScalingFactor = signalHistogram.Integral()
287 backgroundScalingFactor = backgroundHistogram.Integral()
288
289 if signalScalingFactor == 0:
290 signalScalingFactor = 1
291
292 if backgroundScalingFactor == 0:
293 backgroundScalingFactor = 1
294
295 signalHistogram.Scale(1 / signalScalingFactor)
296 backgroundHistogram.Scale(1 / backgroundScalingFactor)
297
298 signalArray = np.zeros((signalHistogram.GetNbinsX(), 2))
299 backgroundArray = np.zeros((backgroundHistogram.GetNbinsX(), 2))
300
301 for i in range(0, signalHistogram.GetNbinsX()):
302 signalArray[i] = np.array([signalHistogram.GetBinCenter(i + 1), signalHistogram.GetBinContent(i + 1)])
303 backgroundArray[i] = np.array([backgroundHistogram.GetBinCenter(i + 1), backgroundHistogram.GetBinContent(i + 1)])
304
305 fig1 = plt.figure(1, figsize=(11, 10))
306
307 # if inputVariable == 'Kid_dEdx' or inputVariable == 'muid_dEdx':
308 # ax1 = plt.axes([0.18, 0.17, 0.75, 0.8])
309 # if inputVariable == 'pi_vs_edEdxid':
310 # ax1 = plt.axes([0.18, 0.187, 0.75, 0.805])
311 # else:
312 ax1 = plt.axes([0.18, 0.2, 0.76, 0.705])
313
314 # print(signalArray.shape, signalHistogram.GetNbinsX(), )
315 # print(signalArray)
316 ax1.hist(
317 signalArray[:, 0], weights=signalArray[:, 1], bins=signalHistogram.GetNbinsX(),
318 histtype='step',
319 edgecolor='r',
320 linewidth=4,
321 alpha=0.9,
322 label=r'${\rm Signal}$')
323
324 ax1.hist(backgroundArray[:, 0], weights=backgroundArray[:, 1], bins=backgroundHistogram.GetNbinsX(),
325 histtype='step',
326 edgecolor='b', linewidth=4.5, linestyle='dashed', label=r'${\rm Background}$') # hatch='.',
327
328 p1, = ax1.plot([], label=r'${\rm Signal}$', linewidth=5, linestyle='solid', alpha=0.9, c='r')
329 p2, = ax1.plot([], label=r'${\rm Background}$', linewidth=5.5, linestyle='dashed', c='b')
330
331 binWidth = signalHistogram.GetBinWidth(2)
332
333 if inputVariable == 'lambdaZError': # or inputVariable == 'ImpactXY' or\
334 # (category != "Lambda" and inputVariable == 'distance'):
335 binWidth = binWidth * 10
336
337 if inputVariable == 'M':
338 binWidth = binWidth * 1000
339
340 if category == "Lambda" and inputVariable == 'distance':
341 variablesPlotParamsDict[inputVariable][5] = r"{\rm cm}\, "
342
343 binWidth = f'{binWidth:8.2f}'
344
345 xLabel = variablesPlotParamsDict[inputVariable][4]
346 legendLocation = 1
347
348 if category == "FSC":
349 if inputVariable == 'cosTPTO':
350 xLabel = r'$\vert\cos{\theta^*_{\rm T, Slow}}\vert$'
351 if inputVariable == 'useCMSFrame(p)':
352 xLabel = r'$p^*_{\rm Slow}\ [{\rm GeV}/c]$'
353 if category == 'Lambda':
354 if inputVariable == 'useCMSFrame(p)':
355 xLabel = r'$p^*_{\Lambda}\ [{\rm GeV}/c]$'
356 if inputVariable == 'p':
357 xLabel = r'$p_{\Lambda}\ [{\rm GeV}/c]$'
358
359 ax1.set_ylabel(r'${\rm Fraction\hspace{0.25em} of\hspace{0.25em} Events}\, /\, (\, ' + binWidth + r'\, ' +
360 variablesPlotParamsDict[inputVariable][5] + r')$', fontsize=46)
361 ax1.set_xlabel(xLabel, fontsize=65)
362 # plt.xticks([-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1],
363 # [r'$-1$', r'', r'$-0.5$', r'', r'$0$', r'', r'$0.5$', r'', r'$1$'], rotation=0, size=40)
364 if inputVariable == 'extraInfo(isRightCategory(Kaon))' or \
365 inputVariable == 'HighestProbInCat(pi+:inRoe, isRightCategory(SlowPion))':
366 legendLocation = 3
367 ax1.set_yscale('log', nonposy='clip')
368 else:
369 ax1.yaxis.set_major_formatter(FormatStrFormatter(r'$%.2f$'))
370
371 ax1.tick_params(axis='x', labelsize=50)
372 ax1.tick_params(axis='y', labelsize=40)
373
374 if inputVariable == 'pi_vs_edEdxid':
375 ax1.xaxis.labelpad = 5
376 else:
377 ax1.xaxis.labelpad = 15
378
379 if inputVariable.find('ARICH') != -1 or inputVariable.find('TOP') != -1 or \
380 inputVariable == 'cosTPTO' or inputVariable.find('KLM') != -1 or \
381 inputVariable == 'cosTheta' or inputVariable == 'FSCVariables(cosTPTOFast)' or \
382 inputVariable == 'KaonPionVariables(cosKaonPion)' or \
383 inputVariable == 'BtagToWBosonVariables(recoilMass)':
384 legendLocation = 2
385
386 elif inputVariable == 'FSCVariables(SlowFastHaveOpositeCharges)' or \
387 inputVariable == 'KaonPionVariables(HaveOpositeCharges)' or inputVariable == "eid_ECL" or \
388 inputVariable.find('ID') != -1 or inputVariable.find('dEdx') != -1:
389 legendLocation = 9
390
391 if inputVariable == 'muid_dEdx':
392 if category != 'KinLepton':
393 legendLocation = 8
394
395 ax1.legend([p1, p2], [r'${\rm Signal}$', r'${\rm Bkgr.}$'], prop={
396 'size': 50}, loc=legendLocation, numpoints=1, handlelength=1)
397 ax1.grid(True)
398 # ax1.set_ylim(0, 1.4)
399 ax1.set_xlim(limXmin, limXmax)
400 plt.savefig('./InputVariablesPlots/' + category + '/' + category +
401 "_" + str(Belle2.MakeROOTCompatible.makeROOTCompatible(inputVariable)) + '.pdf')
402 fig1.clear()
403
404 signalHistogram.Delete()
405 backgroundHistogram.Delete()
406
407
408if __name__ == '__main__':
409
410 plotInputVariablesOfFlavorTagger()
411
412 totalNumberOfVariables = 0
413
414 for category in ft.AvailableCategories:
415 totalNumberOfVariables += len(ft.getTrainingVariables(category))
416
417 print("Total number of variables = ", totalNumberOfVariables)
418
419 totalNumberOfCalculatedVariables = len(identifiersExtraInfosKaonPion)
420
421 print("Calculations for Kaon-Pion Category = ", totalNumberOfCalculatedVariables)
422
423 print("Variables per particle list:")
424 for particleList in identifiersExtraInfosDict:
425 print(particleList)
426 print(identifiersExtraInfosDict[particleList])
427 totalNumberOfCalculatedVariables += len(identifiersExtraInfosDict[particleList])
428
429 print("Total number of calculated variables = ", totalNumberOfCalculatedVariables)
static std::string makeROOTCompatible(std::string str)
Remove special characters that ROOT dislikes in branch names, e.g.
static std::string invertMakeROOTCompatible(std::string str)
Invert makeROOTCompatible operation.