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 = []
67 ft.WhichCategories(categories)
70 belleOrBelle2Flag = belleOrBelle2
72 identifiersExtraInfosDict = dict()
73 identifiersExtraInfosKaonPion = []
75 if belleOrBelle2 ==
"Belle":
85 variablesPlotParamsDict = {
86 'useCMSFrame(p)': [
'useCMSFrame__bop__bc', pBins, 0, 3,
r'$p^*\ [{\rm GeV}/c]$',
r"{\rm GeV}/c\, "],
87 'useCMSFrame(pt)': [
'useCMSFrame__bopt__bc', pBins, 0, 3,
r'$p_{\rm t}^*\ [{\rm GeV}/c]$',
r"{\rm GeV}/c\, "],
88 'p': [
'p', pBins, 0, 3,
r'$p\ [{\rm GeV}/c]$',
r"{\rm GeV}/c\, "],
89 'pt': [
'pt', pBins, 0, 3,
r'$p_{\rm t}\ [{\rm GeV}/c]$',
r"{\rm GeV}/c\, "],
90 'cosTheta': [
'cosTheta', dBw, -1, 1.01,
r'$\cos{\theta}$',
""],
92 dBw, 0, 1.01,
r'$\mathcal{L}_{e}$',
""],
93 'eid_dEdx': [
'eid_dEdx', dBw, 0, 1.01,
r'$\mathcal{L}_{e}^{{\rm d}E/{\rm d}x}$',
""],
94 'eid_TOP': [
'eid_TOP', dBw, 0, 1.01,
r'$\mathcal{L}_{e}^{\rm TOP}$',
""],
95 'eid_ARICH': [
'eid_ARICH', dBw, 0, 1.01,
r'$\mathcal{L}_{e}^{\rm ARICH}$',
""],
96 'eid_ECL': [
'eid_ECL', dBw, 0, 1.01,
r'$\mathcal{L}_{e}^{\rm ECL}$',
""],
97 'BtagToWBosonVariables(recoilMassSqrd)': [
'BtagToWBosonVariables__borecoilMassSqrd__bc', fBins,
98 0, 100,
r'$M_{\rm rec}^2\ [{\rm GeV}^2/c^4]$',
r"{\rm GeV}^2/c^4"],
99 'BtagToWBosonVariables(pMissCMS)': [
100 'BtagToWBosonVariables__bopMissCMS__bc', 60, 0, 3.6,
101 r'$p^*_{\rm miss}\ [{\rm GeV}/c]$',
r"{\rm GeV}/c\, "],
102 'BtagToWBosonVariables(cosThetaMissCMS)': [
'BtagToWBosonVariables__bocosThetaMissCMS__bc',
103 dBw, -1, 1.01,
r'$\cos{\theta^*_{\rm miss}}$',
""],
104 'BtagToWBosonVariables(EW90)': [
'BtagToWBosonVariables__boEW90__bc',
105 dBw, 0, 4,
r'$E_{90}^{W}\ [{\rm GeV}]$',
r"{\rm GeV}\, "],
106 'BtagToWBosonVariables(recoilMass)': [
'sqrt(abs(BtagToWBosonVariables__borecoilMassSqrd__bc))',
107 dBw, 0, 12,
r'$M_{\rm rec}\ [{\rm GeV}/c^2]$',
r"{\rm GeV}/c^2\, "],
108 'cosTPTO': [
'cosTPTO', dBw, 0, 1.01,
r'$\vert\cos{\theta^*_{\rm T}}\vert$',
""],
109 'ImpactXY': [
'ImpactXY', dBw, 0, 0.5,
r'$d_0\ [{\rm ' + unitImp +
'}]$',
r"{\rm " + unitImp +
r"}\, "],
110 'z0': [
'z0', dBw, 0, 1.0,
r'$z_0\ [{\rm ' + unitImp +
'}]$',
r"{\rm " + unitImp +
r"}\, "],
111 'y': [
'y', dBw, -0.15, 0.15,
r'$y_0\ [{\rm ' + unitImp +
'}]$',
r"{\rm " + unitImp +
r"}\, "],
112 'OBoost': [
'OBoost', dBw, -0.15, 0.15,
r'$d_0^\prime\ [{\rm ' + unitImp +
'}]$',
r"{\rm " + unitImp +
r"}\, "],
113 'distance': [
'distance', dBw, 0, 1.5,
r'$\xi_0\ [{\rm ' + unitImp +
'}]$',
r"{\rm " + unitImp +
r"}\, "],
114 'chiProb': [
'chiProb', dBw, 0, 1.01,
r'$p$-${\rm value}$',
""],
116 dBw, 0, 1.01,
r'$\mathcal{L}_{\mu}$',
""],
117 'muid_dEdx': [
'muid_dEdx', dBw, 0, 1.01,
r'$\mathcal{L}_{\mu}^{{\rm d}E/{\rm d}x}$',
""],
118 'muid_TOP': [
'muid_TOP', dBw, 0, 1.01,
r'$\mathcal{L}_{\mu}^{\rm TOP}$',
""],
119 'muid_ARICH': [
'muid_ARICH', dBw, 0, 1.01,
r'$\mathcal{L}_{\mu}^{\rm ARICH}$',
""],
120 'muid_KLM': [
'muid_KLM', dBw, 0, 1.01,
r'$\mathcal{L}_{\mu}^{\rm KLM}$',
""],
122 dBw, 0, 1.01,
r'$\mathcal{L}_{K}$',
""],
123 'Kid_dEdx': [
'Kid_dEdx', dBw, 0, 1.01,
r'$\mathcal{L}_{K}^{{\rm d}E/{\rm d}x}$',
""],
124 'Kid_TOP': [
'Kid_TOP', dBw, 0, 1.01,
r'$\mathcal{L}_{K}^{\rm TOP}$',
""],
125 'Kid_ARICH': [
'Kid_ARICH', dBw, 0, 1.01,
r'$\mathcal{L}_{K}^{\rm ARICH}$',
""],
126 'NumberOfKShortsInRoe': [
'NumberOfKShortsInRoe', dBw, 0, 12,
r'$n_{K^0_S}$',
""],
127 'ptTracksRoe': [
'ptTracksRoe', fBins, 0, 6,
r'$\Sigma\, p_{\rm t}^2\ [{\rm GeV^2}/c^2]$',
129 'extraInfo(isRightCategory(Kaon))': [
'extraInfo__boisRightCategory__boKaon__bc__bc',
130 dBw, 0, 1.01,
r"$y_{\rm Kaon}$",
""],
131 'HighestProbInCat(pi+:inRoe, isRightCategory(SlowPion))': [
132 'HighestProbInCat__bopi__pl__clinRoe__cm__spisRightCategory__boSlowPion__bc__bc',
133 dBw, 0, 1.01,
r"$y_{\rm SlowPion}$",
""],
134 'KaonPionVariables(cosKaonPion)': [
'KaonPionVariables__bocosKaonPion__bc',
135 dBw, -1, 1.01,
r'$\cos{\theta^*_{K\pi}}$',
""],
136 'KaonPionVariables(HaveOpositeCharges)': [
'KaonPionVariables__boHaveOpositeCharges__bc',
137 dBw, 0, 1.01,
r'$\frac{1 - q_{K} \cdot q_\pi}{2}$',
""],
138 'pionID': [
'pionID', dBw, 0, 1.01,
r'$\mathcal{L}_{\pi}$',
""],
139 'piid_dEdx': [
'piid_dEdx', dBw, 0, 1.01,
r'$\mathcal{L}_{\pi}^{{\rm d}E/{\rm d}x}$',
""],
140 'piid_TOP': [
'piid_TOP', dBw, 0, 1.01,
r'$\mathcal{L}_{\pi}^{\rm TOP}$',
""],
141 'piid_ARICH': [
'piid_ARICH', dBw, 0, 1.01,
r'$\mathcal{L}_{\pi}^{\rm ARICH}$',
""],
142 'pi_vs_edEdxid': [
'pi_vs_edEdxid', dBw, 0, 1.01,
r'$\mathcal{L}_{\pi/e}^{{\rm d}E/{\rm d}x}$',
""],
143 'FSCVariables(pFastCMS)': [
'FSCVariables__bopFastCMS__bc', pBins, 0, 3,
r'$p^*_{\rm Fast}\ [{\rm GeV}/c]$',
r"{\rm GeV}/c\, "],
144 'FSCVariables(cosSlowFast)': [
'FSCVariables__bocosSlowFast__bc', dBw, -1, 1.01,
r'$\cos{\theta^*_{\rm SlowFast}}$',
''],
145 'FSCVariables(cosTPTOFast)': [
'FSCVariables__bocosTPTOFast__bc', dBw, 0, 1.01,
r'$\vert\cos{\theta^*_{\rm T, Fast}}\vert$',
''],
146 'FSCVariables(SlowFastHaveOpositeCharges)': [
'FSCVariables__boSlowFastHaveOpositeCharges__bc',
147 dBw, 0, 1.01,
r'$\frac{1 - q_{\rm Slow} \cdot q_{\rm Fast}}{2}$',
""],
148 'lambdaFlavor': [
'lambdaFlavor', dBw, -1, 1.01,
r'$q_{\Lambda}$',
""],
149 'M': [
'M', dBw, 1.08, 1.22,
r'$M_{\Lambda}\ [{\rm GeV}/c^2]$',
r"{\rm MeV}/c^2\, "],
150 'cosAngleBetweenMomentumAndVertexVector': [
'cosAngleBetweenMomentumAndVertexVector',
152 r'$\cos{\theta_{\boldsymbol{x}_{\Lambda},\boldsymbol{p}_{\Lambda}}}$',
""],
153 'lambdaZError': [
'lambdaZError', dBw, 0, 0.05,
r'$\sigma_{\Lambda}^{zz}$',
r"{\rm mm}\, "],
154 'daughter(0,p)': [
'daughter__bo0__cmp__bc', dBw, 0, 1,
r'$p_{\pi}\ [{\rm GeV}/c]$',
r"{\rm GeV}/c\, "],
155 'daughter(0,useCMSFrame(p))': [
'daughter__bo0__cmuseCMSFrame__bop__bc__bc',
156 dBw, 0, 1,
r'$p^*_{\pi}\ [{\rm GeV}/c]$',
r"{\rm GeV}/c\, "],
157 'daughter(1,p)': [
'daughter__bo1__cmp__bc', dBw, 0, 2,
r'$p_{p}\ [{\rm GeV}/c]$',
r"{\rm GeV}/c"],
158 'daughter(1,useCMSFrame(p))': [
'daughter__bo1__cmuseCMSFrame__bop__bc__bc',
159 dBw, 0, 2,
r'$p^*_{p}\ [{\rm GeV}/c]$',
r"{\rm GeV}/c\, "],
160 'daughter(1,protonID)': [
'daughter__bo1__cmprotonID__bc', dBw, 0, 1.01,
r'$\mathcal{L}_{p}$',
""],
161 'daughter(0,pionID)': [
'daughter__bo0__cmpionID__bc', dBw, 0, 1.01,
r'$\mathcal{L}_{\pi}$',
""]}
163 if not b2.find_file(
'InputVariablesPlots', silent=
True):
164 os.mkdir(
'./InputVariablesPlots')
167 def plotInputVariablesOfFlavorTagger():
169 Makes plots of the distribution of the input variables of the flavor tagger
170 for each category distinguishing between the target particles of the category (signal)
171 and all the other (bkg.)
174 for (particleList, category, combinerVariable)
in ft.eventLevelParticleLists:
179 if not b2.find_file(
'InputVariablesPlots/' + category, silent=
True):
180 os.mkdir(
'./InputVariablesPlots/' + category)
182 if particleList
not in identifiersExtraInfosDict
and category !=
'KaonPion':
183 identifiersExtraInfosDict[particleList] = []
185 methodPrefixEventLevel =
"FlavorTagger_" + belleOrBelle2Flag +
"_" + weightFiles +
'EventLevel' + category +
'FBDT'
186 treeName = methodPrefixEventLevel +
"_tree"
187 targetVariable =
'isRightCategory(' + category +
')'
189 tree = ROOT.TChain(treeName)
191 workingFiles = glob.glob(filesDirectory +
'/' + methodPrefixEventLevel +
'sampled*.root')
195 for iFile
in workingFiles:
198 categoryInputVariables = []
199 trulyUsedInputVariables = []
200 for iVariable
in tree.GetListOfBranches():
204 if managerVariableName
in ft.variables[category]
or managerVariableName ==
'distance' or \
205 managerVariableName ==
'z0' or managerVariableName ==
'ImpactXY' or \
206 managerVariableName ==
'y' or managerVariableName ==
'OBoost':
207 if managerVariableName
in categoryInputVariables:
210 categoryInputVariables.append(managerVariableName)
211 if managerVariableName
in ft.variables[category]:
212 allInputVariables.append((category, managerVariableName))
213 trulyUsedInputVariables.append((category, managerVariableName))
215 if managerVariableName
not in identifiersExtraInfosDict[particleList]
and category !=
'KaonPion':
216 identifiersExtraInfosDict[particleList].append(managerVariableName)
218 elif category ==
'KaonPion' and managerVariableName
not in identifiersExtraInfosKaonPion:
219 identifiersExtraInfosKaonPion.append(managerVariableName)
225 print(
"The number of variables used in " + category +
" is = ", len(trulyUsedInputVariables))
227 if category !=
'KaonPion' and category !=
'FSC' and category !=
'MaximumPstar' and \
228 category !=
'FastHadron' and category !=
'Lambda':
229 categoryInputVariables.append(
'BtagToWBosonVariables(recoilMass)')
231 for inputVariable
in categoryInputVariables:
235 nBins = variablesPlotParamsDict[inputVariable][1]
236 limXmin = variablesPlotParamsDict[inputVariable][2]
237 limXmax = variablesPlotParamsDict[inputVariable][3]
239 if category ==
"SlowPion":
240 if inputVariable ==
'p' or inputVariable ==
'useCMSFrame(p)' or \
241 inputVariable ==
'pt' or inputVariable ==
'useCMSFrame(pt)':
245 if inputVariable ==
'distance':
249 if inputVariable ==
'ImpactXY':
253 if category ==
"Lambda":
254 if inputVariable ==
'distance':
258 if inputVariable ==
'chiProb':
270 factorMultiplication = str()
272 if belleOrBelle2 ==
"Belle2" and ((category !=
"Lambda" and inputVariable ==
'distance')
or inputVariable ==
273 'z0' or inputVariable ==
'ImpactXY' or inputVariable ==
274 'y' or inputVariable ==
'OBoost'):
275 factorMultiplication =
"*10 "
277 tree.Draw(variablesPlotParamsDict[inputVariable][0] + factorMultiplication +
">> signal" + category +
280 tree.Draw(variablesPlotParamsDict[inputVariable][0] + factorMultiplication +
">> bkg" + category +
283 signalScalingFactor = signalHistogram.Integral()
284 backgroundScalingFactor = backgroundHistogram.Integral()
286 if signalScalingFactor == 0:
287 signalScalingFactor = 1
289 if backgroundScalingFactor == 0:
290 backgroundScalingFactor = 1
292 signalHistogram.Scale(1 / signalScalingFactor)
293 backgroundHistogram.Scale(1 / backgroundScalingFactor)
295 signalArray = np.zeros((signalHistogram.GetNbinsX(), 2))
296 backgroundArray = np.zeros((backgroundHistogram.GetNbinsX(), 2))
298 for i
in range(0, signalHistogram.GetNbinsX()):
299 signalArray[i] = np.array([signalHistogram.GetBinCenter(i + 1), signalHistogram.GetBinContent(i + 1)])
300 backgroundArray[i] = np.array([backgroundHistogram.GetBinCenter(i + 1), backgroundHistogram.GetBinContent(i + 1)])
302 fig1 = plt.figure(1, figsize=(11, 10))
309 ax1 = plt.axes([0.18, 0.2, 0.76, 0.705])
314 signalArray[:, 0], weights=signalArray[:, 1], bins=signalHistogram.GetNbinsX(),
319 label=
r'${\rm Signal}$')
321 ax1.hist(backgroundArray[:, 0], weights=backgroundArray[:, 1], bins=backgroundHistogram.GetNbinsX(),
323 edgecolor=
'b', linewidth=4.5, linestyle=
'dashed', label=
r'${\rm Background}$')
325 p1, = ax1.plot([], label=
r'${\rm Signal}$', linewidth=5, linestyle=
'solid', alpha=0.9, c=
'r')
326 p2, = ax1.plot([], label=
r'${\rm Background}$', linewidth=5.5, linestyle=
'dashed', c=
'b')
328 binWidth = signalHistogram.GetBinWidth(2)
330 if inputVariable ==
'lambdaZError':
332 binWidth = binWidth * 10
334 if inputVariable ==
'M':
335 binWidth = binWidth * 1000
337 if category ==
"Lambda" and inputVariable ==
'distance':
338 variablesPlotParamsDict[inputVariable][5] =
r"{\rm cm}\, "
340 binWidth =
'{:8.2f}'.format(binWidth)
342 xLabel = variablesPlotParamsDict[inputVariable][4]
345 if category ==
"FSC":
346 if inputVariable ==
'cosTPTO':
347 xLabel =
r'$\vert\cos{\theta^*_{\rm T, Slow}}\vert$'
348 if inputVariable ==
'useCMSFrame(p)':
349 xLabel =
r'$p^*_{\rm Slow}\ [{\rm GeV}/c]$'
350 if category ==
'Lambda':
351 if inputVariable ==
'useCMSFrame(p)':
352 xLabel =
r'$p^*_{\Lambda}\ [{\rm GeV}/c]$'
353 if inputVariable ==
'p':
354 xLabel =
r'$p_{\Lambda}\ [{\rm GeV}/c]$'
356 ax1.set_ylabel(
r'${\rm Fraction\hspace{0.25em} of\hspace{0.25em} Events}\, /\, (\, ' + binWidth +
r'\, ' +
357 variablesPlotParamsDict[inputVariable][5] +
r')$', fontsize=46)
358 ax1.set_xlabel(xLabel, fontsize=65)
361 if inputVariable ==
'extraInfo(isRightCategory(Kaon))' or \
362 inputVariable ==
'HighestProbInCat(pi+:inRoe, isRightCategory(SlowPion))':
364 ax1.set_yscale(
'log', nonposy=
'clip')
366 ax1.yaxis.set_major_formatter(FormatStrFormatter(
r'$%.2f$'))
368 ax1.tick_params(axis=
'x', labelsize=50)
369 ax1.tick_params(axis=
'y', labelsize=40)
371 if inputVariable ==
'pi_vs_edEdxid':
372 ax1.xaxis.labelpad = 5
374 ax1.xaxis.labelpad = 15
376 if inputVariable.find(
'ARICH') != -1
or inputVariable.find(
'TOP') != -1
or \
377 inputVariable ==
'cosTPTO' or inputVariable.find(
'KLM') != -1
or \
378 inputVariable ==
'cosTheta' or inputVariable ==
'FSCVariables(cosTPTOFast)' or \
379 inputVariable ==
'KaonPionVariables(cosKaonPion)' or \
380 inputVariable ==
'BtagToWBosonVariables(recoilMass)':
383 elif inputVariable ==
'FSCVariables(SlowFastHaveOpositeCharges)' or \
384 inputVariable ==
'KaonPionVariables(HaveOpositeCharges)' or inputVariable ==
"eid_ECL" or \
385 inputVariable.find(
'ID') != -1
or inputVariable.find(
'dEdx') != -1:
388 if inputVariable ==
'muid_dEdx':
389 if category !=
'KinLepton':
392 ax1.legend([p1, p2], [
r'${\rm Signal}$',
r'${\rm Bkgr.}$'], prop={
393 'size': 50}, loc=legendLocation, numpoints=1, handlelength=1)
396 ax1.set_xlim(limXmin, limXmax)
397 plt.savefig(
'./InputVariablesPlots/' + category +
'/' + category +
401 signalHistogram.Delete()
402 backgroundHistogram.Delete()
405 if __name__ ==
'__main__':
407 plotInputVariablesOfFlavorTagger()
409 totalNumberOfVariables = 0
411 for category
in ft.variables:
412 totalNumberOfVariables += len(ft.variables[category])
414 print(
"Total number of variables = ", totalNumberOfVariables)
416 totalNumberOfCalculatedVariables = len(identifiersExtraInfosKaonPion)
418 print(
"Calculations for Kaon-Pion Category = ", totalNumberOfCalculatedVariables)
420 print(
"Variables per particle list:")
421 for particleList
in identifiersExtraInfosDict:
423 print(identifiersExtraInfosDict[particleList])
424 totalNumberOfCalculatedVariables += len(identifiersExtraInfosDict[particleList])
426 print(
"Total number of calculated variables = ", totalNumberOfCalculatedVariables)
std::string makeROOTCompatible(std::string str)
Remove special characters that ROOT dislikes in branch names, e.g.
std::string invertMakeROOTCompatible(std::string str)
Invert makeROOTCompatible operation.