28 from matplotlib.ticker
import FormatStrFormatter
29 import matplotlib.pyplot
as plt
31 from ROOT
import Belle2
33 import flavorTagger
as ft
34 from defaultEvaluationParameters
import categories
37 import matplotlib
as mpl
39 mpl.rcParams.update({
'font.size': 22})
40 mpl.rcParams[
'text.usetex'] =
True
41 mpl.rcParams[
'text.latex.preamble'] = [
r"\usepackage{amsmath}"]
43 ROOT.gROOT.SetBatch(
True)
45 if len(sys.argv) != 5:
46 sys.exit(
"Must provide 4 arguments: [Belle or Belle2] [BGx0 or BGx1] [training] [workingDirectory]"
49 belleOrBelle2 = sys.argv[1]
50 MCtype = str(sys.argv[2])
51 decayChannelTrainedOn = str(sys.argv[3])
52 workingDirectory = sys.argv[4]
54 filesDirectory = workingDirectory +
'/FlavorTagging/TrainedMethods'
56 if decayChannelTrainedOn ==
'JPsiKs':
57 decayChannelTrainedOn =
'JpsiKs_mu'
59 weightFiles =
'B2' + decayChannelTrainedOn + MCtype
62 ROOT.TH1.SetDefaultSumw2()
64 allInputVariables = []
66 belleOrBelle2Flag = belleOrBelle2
68 identifiersExtraInfosDict = dict()
69 identifiersExtraInfosKaonPion = []
71 if belleOrBelle2 ==
"Belle":
81 variablesPlotParamsDict = {
82 'useCMSFrame(p)': [
'useCMSFrame__bop__bc', pBins, 0, 3,
r'$p^*\ [{\rm GeV}/c]$',
r"{\rm GeV}/c\, "],
83 'useCMSFrame(pt)': [
'useCMSFrame__bopt__bc', pBins, 0, 3,
r'$p_{\rm t}^*\ [{\rm GeV}/c]$',
r"{\rm GeV}/c\, "],
84 'p': [
'p', pBins, 0, 3,
r'$p\ [{\rm GeV}/c]$',
r"{\rm GeV}/c\, "],
85 'pt': [
'pt', pBins, 0, 3,
r'$p_{\rm t}\ [{\rm GeV}/c]$',
r"{\rm GeV}/c\, "],
86 'cosTheta': [
'cosTheta', dBw, -1, 1.01,
r'$\cos{\theta}$',
""],
88 dBw, 0, 1.01,
r'$\mathcal{L}_{e}$',
""],
89 'eid_dEdx': [
'eid_dEdx', dBw, 0, 1.01,
r'$\mathcal{L}_{e}^{{\rm d}E/{\rm d}x}$',
""],
90 'eid_TOP': [
'eid_TOP', dBw, 0, 1.01,
r'$\mathcal{L}_{e}^{\rm TOP}$',
""],
91 'eid_ARICH': [
'eid_ARICH', dBw, 0, 1.01,
r'$\mathcal{L}_{e}^{\rm ARICH}$',
""],
92 'eid_ECL': [
'eid_ECL', dBw, 0, 1.01,
r'$\mathcal{L}_{e}^{\rm ECL}$',
""],
93 'BtagToWBosonVariables(recoilMassSqrd)': [
'BtagToWBosonVariables__borecoilMassSqrd__bc', fBins,
94 0, 100,
r'$M_{\rm rec}^2\ [{\rm GeV}^2/c^4]$',
r"{\rm GeV}^2/c^4"],
95 'BtagToWBosonVariables(pMissCMS)': [
96 'BtagToWBosonVariables__bopMissCMS__bc', 60, 0, 3.6,
97 r'$p^*_{\rm miss}\ [{\rm GeV}/c]$',
r"{\rm GeV}/c\, "],
98 'BtagToWBosonVariables(cosThetaMissCMS)': [
'BtagToWBosonVariables__bocosThetaMissCMS__bc',
99 dBw, -1, 1.01,
r'$\cos{\theta^*_{\rm miss}}$',
""],
100 'BtagToWBosonVariables(EW90)': [
'BtagToWBosonVariables__boEW90__bc',
101 dBw, 0, 4,
r'$E_{90}^{W}\ [{\rm GeV}]$',
r"{\rm GeV}\, "],
102 'BtagToWBosonVariables(recoilMass)': [
'sqrt(abs(BtagToWBosonVariables__borecoilMassSqrd__bc))',
103 dBw, 0, 12,
r'$M_{\rm rec}\ [{\rm GeV}/c^2]$',
r"{\rm GeV}/c^2\, "],
104 'cosTPTO': [
'cosTPTO', dBw, 0, 1.01,
r'$\vert\cos{\theta^*_{\rm T}}\vert$',
""],
105 'ImpactXY': [
'ImpactXY', dBw, 0, 0.5,
r'$d_0\ [{\rm ' + unitImp +
'}]$',
r"{\rm " + unitImp +
r"}\, "],
106 'z0': [
'z0', dBw, 0, 1.0,
r'$z_0\ [{\rm ' + unitImp +
'}]$',
r"{\rm " + unitImp +
r"}\, "],
107 'y': [
'y', dBw, -0.15, 0.15,
r'$y_0\ [{\rm ' + unitImp +
'}]$',
r"{\rm " + unitImp +
r"}\, "],
108 'OBoost': [
'OBoost', dBw, -0.15, 0.15,
r'$d_0^\prime\ [{\rm ' + unitImp +
'}]$',
r"{\rm " + unitImp +
r"}\, "],
109 'distance': [
'distance', dBw, 0, 1.5,
r'$\xi_0\ [{\rm ' + unitImp +
'}]$',
r"{\rm " + unitImp +
r"}\, "],
110 'chiProb': [
'chiProb', dBw, 0, 1.01,
r'$p$-${\rm value}$',
""],
112 dBw, 0, 1.01,
r'$\mathcal{L}_{\mu}$',
""],
113 'muid_dEdx': [
'muid_dEdx', dBw, 0, 1.01,
r'$\mathcal{L}_{\mu}^{{\rm d}E/{\rm d}x}$',
""],
114 'muid_TOP': [
'muid_TOP', dBw, 0, 1.01,
r'$\mathcal{L}_{\mu}^{\rm TOP}$',
""],
115 'muid_ARICH': [
'muid_ARICH', dBw, 0, 1.01,
r'$\mathcal{L}_{\mu}^{\rm ARICH}$',
""],
116 'muid_KLM': [
'muid_KLM', dBw, 0, 1.01,
r'$\mathcal{L}_{\mu}^{\rm KLM}$',
""],
118 dBw, 0, 1.01,
r'$\mathcal{L}_{K}$',
""],
119 'Kid_dEdx': [
'Kid_dEdx', dBw, 0, 1.01,
r'$\mathcal{L}_{K}^{{\rm d}E/{\rm d}x}$',
""],
120 'Kid_TOP': [
'Kid_TOP', dBw, 0, 1.01,
r'$\mathcal{L}_{K}^{\rm TOP}$',
""],
121 'Kid_ARICH': [
'Kid_ARICH', dBw, 0, 1.01,
r'$\mathcal{L}_{K}^{\rm ARICH}$',
""],
122 'NumberOfKShortsInRoe': [
'NumberOfKShortsInRoe', dBw, 0, 12,
r'$n_{K^0_S}$',
""],
123 'ptTracksRoe': [
'ptTracksRoe', fBins, 0, 6,
r'$\Sigma\, p_{\rm t}^2\ [{\rm GeV^2}/c^2]$',
125 'extraInfo(isRightCategory(Kaon))': [
'extraInfo__boisRightCategory__boKaon__bc__bc',
126 dBw, 0, 1.01,
r"$y_{\rm Kaon}$",
""],
127 'HighestProbInCat(pi+:inRoe, isRightCategory(SlowPion))': [
128 'HighestProbInCat__bopi__pl__clinRoe__cm__spisRightCategory__boSlowPion__bc__bc',
129 dBw, 0, 1.01,
r"$y_{\rm SlowPion}$",
""],
130 'KaonPionVariables(cosKaonPion)': [
'KaonPionVariables__bocosKaonPion__bc',
131 dBw, -1, 1.01,
r'$\cos{\theta^*_{K\pi}}$',
""],
132 'KaonPionVariables(HaveOpositeCharges)': [
'KaonPionVariables__boHaveOpositeCharges__bc',
133 dBw, 0, 1.01,
r'$\frac{1 - q_{K} \cdot q_\pi}{2}$',
""],
134 'pionID': [
'pionID', dBw, 0, 1.01,
r'$\mathcal{L}_{\pi}$',
""],
135 'piid_dEdx': [
'piid_dEdx', dBw, 0, 1.01,
r'$\mathcal{L}_{\pi}^{{\rm d}E/{\rm d}x}$',
""],
136 'piid_TOP': [
'piid_TOP', dBw, 0, 1.01,
r'$\mathcal{L}_{\pi}^{\rm TOP}$',
""],
137 'piid_ARICH': [
'piid_ARICH', dBw, 0, 1.01,
r'$\mathcal{L}_{\pi}^{\rm ARICH}$',
""],
138 'pi_vs_edEdxid': [
'pi_vs_edEdxid', dBw, 0, 1.01,
r'$\mathcal{L}_{\pi/e}^{{\rm d}E/{\rm d}x}$',
""],
139 'FSCVariables(pFastCMS)': [
'FSCVariables__bopFastCMS__bc', pBins, 0, 3,
r'$p^*_{\rm Fast}\ [{\rm GeV}/c]$',
r"{\rm GeV}/c\, "],
140 'FSCVariables(cosSlowFast)': [
'FSCVariables__bocosSlowFast__bc', dBw, -1, 1.01,
r'$\cos{\theta^*_{\rm SlowFast}}$',
''],
141 'FSCVariables(cosTPTOFast)': [
'FSCVariables__bocosTPTOFast__bc', dBw, 0, 1.01,
r'$\vert\cos{\theta^*_{\rm T, Fast}}\vert$',
''],
142 'FSCVariables(SlowFastHaveOpositeCharges)': [
'FSCVariables__boSlowFastHaveOpositeCharges__bc',
143 dBw, 0, 1.01,
r'$\frac{1 - q_{\rm Slow} \cdot q_{\rm Fast}}{2}$',
""],
144 'lambdaFlavor': [
'lambdaFlavor', dBw, -1, 1.01,
r'$q_{\Lambda}$',
""],
145 'M': [
'M', dBw, 1.08, 1.22,
r'$M_{\Lambda}\ [{\rm GeV}/c^2]$',
r"{\rm MeV}/c^2\, "],
146 'cosAngleBetweenMomentumAndVertexVector': [
'cosAngleBetweenMomentumAndVertexVector',
148 r'$\cos{\theta_{\boldsymbol{x}_{\Lambda},\boldsymbol{p}_{\Lambda}}}$',
""],
149 'lambdaZError': [
'lambdaZError', dBw, 0, 0.05,
r'$\sigma_{\Lambda}^{zz}$',
r"{\rm mm}\, "],
150 'daughter(0,p)': [
'daughter__bo0__cmp__bc', dBw, 0, 1,
r'$p_{\pi}\ [{\rm GeV}/c]$',
r"{\rm GeV}/c\, "],
151 'daughter(0,useCMSFrame(p))': [
'daughter__bo0__cmuseCMSFrame__bop__bc__bc',
152 dBw, 0, 1,
r'$p^*_{\pi}\ [{\rm GeV}/c]$',
r"{\rm GeV}/c\, "],
153 'daughter(1,p)': [
'daughter__bo1__cmp__bc', dBw, 0, 2,
r'$p_{p}\ [{\rm GeV}/c]$',
r"{\rm GeV}/c"],
154 'daughter(1,useCMSFrame(p))': [
'daughter__bo1__cmuseCMSFrame__bop__bc__bc',
155 dBw, 0, 2,
r'$p^*_{p}\ [{\rm GeV}/c]$',
r"{\rm GeV}/c\, "],
156 'daughter(1,protonID)': [
'daughter__bo1__cmprotonID__bc', dBw, 0, 1.01,
r'$\mathcal{L}_{p}$',
""],
157 'daughter(0,pionID)': [
'daughter__bo0__cmpionID__bc', dBw, 0, 1.01,
r'$\mathcal{L}_{\pi}$',
""]}
159 if not b2.find_file(
'InputVariablesPlots', silent=
True):
160 os.mkdir(
'./InputVariablesPlots')
163 def plotInputVariablesOfFlavorTagger():
165 Makes plots of the distribution of the input variables of the flavor tagger
166 for each category distinguishing between the target particles of the category (signal)
167 and all the other (bkg.)
170 for (particleList, category, _)
in ft.getEventLevelParticleLists(categories):
175 if not b2.find_file(
'InputVariablesPlots/' + category, silent=
True):
176 os.mkdir(
'./InputVariablesPlots/' + category)
178 if particleList
not in identifiersExtraInfosDict
and category !=
'KaonPion':
179 identifiersExtraInfosDict[particleList] = []
181 methodPrefixEventLevel =
"FlavorTagger_" + belleOrBelle2Flag +
"_" + weightFiles +
'EventLevel' + category +
'FBDT'
182 treeName = methodPrefixEventLevel +
"_tree"
183 targetVariable =
'isRightCategory(' + category +
')'
185 tree = ROOT.TChain(treeName)
187 workingFiles = glob.glob(filesDirectory +
'/' + methodPrefixEventLevel +
'sampled*.root')
191 for iFile
in workingFiles:
194 categoryInputVariables = []
195 trulyUsedInputVariables = []
196 for iVariable
in tree.GetListOfBranches():
200 if managerVariableName
in ft.getTrainingVariables(category)
or managerVariableName ==
'distance' or \
201 managerVariableName ==
'z0' or managerVariableName ==
'ImpactXY' or \
202 managerVariableName ==
'y' or managerVariableName ==
'OBoost':
203 if managerVariableName
in categoryInputVariables:
206 categoryInputVariables.append(managerVariableName)
207 if managerVariableName
in ft.getTrainingVariables(category):
208 allInputVariables.append((category, managerVariableName))
209 trulyUsedInputVariables.append((category, managerVariableName))
211 if managerVariableName
not in identifiersExtraInfosDict[particleList]
and category !=
'KaonPion':
212 identifiersExtraInfosDict[particleList].append(managerVariableName)
214 elif category ==
'KaonPion' and managerVariableName
not in identifiersExtraInfosKaonPion:
215 identifiersExtraInfosKaonPion.append(managerVariableName)
221 print(
"The number of variables used in " + category +
" is = ", len(trulyUsedInputVariables))
223 if category !=
'KaonPion' and category !=
'FSC' and category !=
'MaximumPstar' and \
224 category !=
'FastHadron' and category !=
'Lambda':
225 categoryInputVariables.append(
'BtagToWBosonVariables(recoilMass)')
227 for inputVariable
in categoryInputVariables:
231 nBins = variablesPlotParamsDict[inputVariable][1]
232 limXmin = variablesPlotParamsDict[inputVariable][2]
233 limXmax = variablesPlotParamsDict[inputVariable][3]
235 if category ==
"SlowPion":
236 if inputVariable ==
'p' or inputVariable ==
'useCMSFrame(p)' or \
237 inputVariable ==
'pt' or inputVariable ==
'useCMSFrame(pt)':
241 if inputVariable ==
'distance':
245 if inputVariable ==
'ImpactXY':
249 if category ==
"Lambda":
250 if inputVariable ==
'distance':
254 if inputVariable ==
'chiProb':
266 factorMultiplication = str()
268 if belleOrBelle2 ==
"Belle2" and ((category !=
"Lambda" and inputVariable ==
'distance')
or inputVariable ==
269 'z0' or inputVariable ==
'ImpactXY' or inputVariable ==
270 'y' or inputVariable ==
'OBoost'):
271 factorMultiplication =
"*10 "
273 tree.Draw(variablesPlotParamsDict[inputVariable][0] + factorMultiplication +
">> signal" + category + str(
278 variablesPlotParamsDict[inputVariable][0] +
279 factorMultiplication +
287 signalScalingFactor = signalHistogram.Integral()
288 backgroundScalingFactor = backgroundHistogram.Integral()
290 if signalScalingFactor == 0:
291 signalScalingFactor = 1
293 if backgroundScalingFactor == 0:
294 backgroundScalingFactor = 1
296 signalHistogram.Scale(1 / signalScalingFactor)
297 backgroundHistogram.Scale(1 / backgroundScalingFactor)
299 signalArray = np.zeros((signalHistogram.GetNbinsX(), 2))
300 backgroundArray = np.zeros((backgroundHistogram.GetNbinsX(), 2))
302 for i
in range(0, signalHistogram.GetNbinsX()):
303 signalArray[i] = np.array([signalHistogram.GetBinCenter(i + 1), signalHistogram.GetBinContent(i + 1)])
304 backgroundArray[i] = np.array([backgroundHistogram.GetBinCenter(i + 1), backgroundHistogram.GetBinContent(i + 1)])
306 fig1 = plt.figure(1, figsize=(11, 10))
313 ax1 = plt.axes([0.18, 0.2, 0.76, 0.705])
318 signalArray[:, 0], weights=signalArray[:, 1], bins=signalHistogram.GetNbinsX(),
323 label=
r'${\rm Signal}$')
325 ax1.hist(backgroundArray[:, 0], weights=backgroundArray[:, 1], bins=backgroundHistogram.GetNbinsX(),
327 edgecolor=
'b', linewidth=4.5, linestyle=
'dashed', label=
r'${\rm Background}$')
329 p1, = ax1.plot([], label=
r'${\rm Signal}$', linewidth=5, linestyle=
'solid', alpha=0.9, c=
'r')
330 p2, = ax1.plot([], label=
r'${\rm Background}$', linewidth=5.5, linestyle=
'dashed', c=
'b')
332 binWidth = signalHistogram.GetBinWidth(2)
334 if inputVariable ==
'lambdaZError':
336 binWidth = binWidth * 10
338 if inputVariable ==
'M':
339 binWidth = binWidth * 1000
341 if category ==
"Lambda" and inputVariable ==
'distance':
342 variablesPlotParamsDict[inputVariable][5] =
r"{\rm cm}\, "
344 binWidth =
'{:8.2f}'.format(binWidth)
346 xLabel = variablesPlotParamsDict[inputVariable][4]
349 if category ==
"FSC":
350 if inputVariable ==
'cosTPTO':
351 xLabel =
r'$\vert\cos{\theta^*_{\rm T, Slow}}\vert$'
352 if inputVariable ==
'useCMSFrame(p)':
353 xLabel =
r'$p^*_{\rm Slow}\ [{\rm GeV}/c]$'
354 if category ==
'Lambda':
355 if inputVariable ==
'useCMSFrame(p)':
356 xLabel =
r'$p^*_{\Lambda}\ [{\rm GeV}/c]$'
357 if inputVariable ==
'p':
358 xLabel =
r'$p_{\Lambda}\ [{\rm GeV}/c]$'
360 ax1.set_ylabel(
r'${\rm Fraction\hspace{0.25em} of\hspace{0.25em} Events}\, /\, (\, ' + binWidth +
r'\, ' +
361 variablesPlotParamsDict[inputVariable][5] +
r')$', fontsize=46)
362 ax1.set_xlabel(xLabel, fontsize=65)
365 if inputVariable ==
'extraInfo(isRightCategory(Kaon))' or \
366 inputVariable ==
'HighestProbInCat(pi+:inRoe, isRightCategory(SlowPion))':
368 ax1.set_yscale(
'log', nonposy=
'clip')
370 ax1.yaxis.set_major_formatter(FormatStrFormatter(
r'$%.2f$'))
372 ax1.tick_params(axis=
'x', labelsize=50)
373 ax1.tick_params(axis=
'y', labelsize=40)
375 if inputVariable ==
'pi_vs_edEdxid':
376 ax1.xaxis.labelpad = 5
378 ax1.xaxis.labelpad = 15
380 if inputVariable.find(
'ARICH') != -1
or inputVariable.find(
'TOP') != -1
or \
381 inputVariable ==
'cosTPTO' or inputVariable.find(
'KLM') != -1
or \
382 inputVariable ==
'cosTheta' or inputVariable ==
'FSCVariables(cosTPTOFast)' or \
383 inputVariable ==
'KaonPionVariables(cosKaonPion)' or \
384 inputVariable ==
'BtagToWBosonVariables(recoilMass)':
387 elif inputVariable ==
'FSCVariables(SlowFastHaveOpositeCharges)' or \
388 inputVariable ==
'KaonPionVariables(HaveOpositeCharges)' or inputVariable ==
"eid_ECL" or \
389 inputVariable.find(
'ID') != -1
or inputVariable.find(
'dEdx') != -1:
392 if inputVariable ==
'muid_dEdx':
393 if category !=
'KinLepton':
396 ax1.legend([p1, p2], [
r'${\rm Signal}$',
r'${\rm Bkgr.}$'], prop={
397 'size': 50}, loc=legendLocation, numpoints=1, handlelength=1)
400 ax1.set_xlim(limXmin, limXmax)
401 plt.savefig(
'./InputVariablesPlots/' + category +
'/' + category +
405 signalHistogram.Delete()
406 backgroundHistogram.Delete()
409 if __name__ ==
'__main__':
411 plotInputVariablesOfFlavorTagger()
413 totalNumberOfVariables = 0
415 for category
in ft.AvailableCategories:
416 totalNumberOfVariables += len(ft.getTrainingVariables(category))
418 print(
"Total number of variables = ", totalNumberOfVariables)
420 totalNumberOfCalculatedVariables = len(identifiersExtraInfosKaonPion)
422 print(
"Calculations for Kaon-Pion Category = ", totalNumberOfCalculatedVariables)
424 print(
"Variables per particle list:")
425 for particleList
in identifiersExtraInfosDict:
427 print(identifiersExtraInfosDict[particleList])
428 totalNumberOfCalculatedVariables += len(identifiersExtraInfosDict[particleList])
430 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.