27 from matplotlib.ticker
import FormatStrFormatter
28 import matplotlib.pyplot
as plt
30 from ROOT
import Belle2
32 import flavorTagger
as ft
33 from defaultEvaluationParameters
import categories
36 import matplotlib
as mpl
38 mpl.rcParams.update({
'font.size': 22})
39 mpl.rcParams[
'text.usetex'] =
True
40 mpl.rcParams[
'text.latex.preamble'] = [
r"\usepackage{amsmath}"]
42 ROOT.gROOT.SetBatch(
True)
44 if len(sys.argv) != 5:
45 sys.exit(
"Must provide 4 arguments: [Belle or Belle2] [BGx0 or BGx1] [training] [workingDirectory]"
48 belleOrBelle2 = sys.argv[1]
49 MCtype = str(sys.argv[2])
50 decayChannelTrainedOn = str(sys.argv[3])
51 workingDirectory = sys.argv[4]
53 filesDirectory = workingDirectory +
'/FlavorTagging/TrainedMethods'
55 if decayChannelTrainedOn ==
'JPsiKs':
56 decayChannelTrainedOn =
'JpsiKs_mu'
58 weightFiles =
'B2' + decayChannelTrainedOn + MCtype
61 ROOT.TH1.SetDefaultSumw2()
63 allInputVariables = []
65 belleOrBelle2Flag = belleOrBelle2
67 identifiersExtraInfosDict = dict()
68 identifiersExtraInfosKaonPion = []
70 if belleOrBelle2 ==
"Belle":
80 variablesPlotParamsDict = {
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}$',
""],
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}$',
""],
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}$',
""],
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]$',
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',
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}$',
""]}
158 if not b2.find_file(
'InputVariablesPlots', silent=
True):
159 os.mkdir(
'./InputVariablesPlots')
162 def plotInputVariablesOfFlavorTagger():
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.)
169 for (particleList, category, _)
in ft.getEventLevelParticleLists(categories):
174 if not b2.find_file(
'InputVariablesPlots/' + category, silent=
True):
175 os.mkdir(
'./InputVariablesPlots/' + category)
177 if particleList
not in identifiersExtraInfosDict
and category !=
'KaonPion':
178 identifiersExtraInfosDict[particleList] = []
180 methodPrefixEventLevel =
"FlavorTagger_" + belleOrBelle2Flag +
"_" + weightFiles +
'EventLevel' + category +
'FBDT'
181 treeName = methodPrefixEventLevel +
"_tree"
182 targetVariable =
'isRightCategory(' + category +
')'
184 tree = ROOT.TChain(treeName)
186 workingFiles = glob.glob(filesDirectory +
'/' + methodPrefixEventLevel +
'sampled*.root')
190 for iFile
in workingFiles:
193 categoryInputVariables = []
194 trulyUsedInputVariables = []
195 for iVariable
in tree.GetListOfBranches():
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:
205 categoryInputVariables.append(managerVariableName)
206 if managerVariableName
in ft.getTrainingVariables(category):
207 allInputVariables.append((category, managerVariableName))
208 trulyUsedInputVariables.append((category, managerVariableName))
210 if managerVariableName
not in identifiersExtraInfosDict[particleList]
and category !=
'KaonPion':
211 identifiersExtraInfosDict[particleList].append(managerVariableName)
213 elif category ==
'KaonPion' and managerVariableName
not in identifiersExtraInfosKaonPion:
214 identifiersExtraInfosKaonPion.append(managerVariableName)
220 print(
"The number of variables used in " + category +
" is = ", len(trulyUsedInputVariables))
222 if category !=
'KaonPion' and category !=
'FSC' and category !=
'MaximumPstar' and \
223 category !=
'FastHadron' and category !=
'Lambda':
224 categoryInputVariables.append(
'BtagToWBosonVariables(recoilMass)')
226 for inputVariable
in categoryInputVariables:
230 nBins = variablesPlotParamsDict[inputVariable][1]
231 limXmin = variablesPlotParamsDict[inputVariable][2]
232 limXmax = variablesPlotParamsDict[inputVariable][3]
234 if category ==
"SlowPion":
235 if inputVariable ==
'p' or inputVariable ==
'useCMSFrame(p)' or \
236 inputVariable ==
'pt' or inputVariable ==
'useCMSFrame(pt)':
240 if inputVariable ==
'distance':
244 if inputVariable ==
'ImpactXY':
248 if category ==
"Lambda":
249 if inputVariable ==
'distance':
253 if inputVariable ==
'chiProb':
265 factorMultiplication =
''
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 "
272 tree.Draw(variablesPlotParamsDict[inputVariable][0] + factorMultiplication +
">> signal" + category + str(
277 variablesPlotParamsDict[inputVariable][0] +
278 factorMultiplication +
286 signalScalingFactor = signalHistogram.Integral()
287 backgroundScalingFactor = backgroundHistogram.Integral()
289 if signalScalingFactor == 0:
290 signalScalingFactor = 1
292 if backgroundScalingFactor == 0:
293 backgroundScalingFactor = 1
295 signalHistogram.Scale(1 / signalScalingFactor)
296 backgroundHistogram.Scale(1 / backgroundScalingFactor)
298 signalArray = np.zeros((signalHistogram.GetNbinsX(), 2))
299 backgroundArray = np.zeros((backgroundHistogram.GetNbinsX(), 2))
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)])
305 fig1 = plt.figure(1, figsize=(11, 10))
312 ax1 = plt.axes([0.18, 0.2, 0.76, 0.705])
317 signalArray[:, 0], weights=signalArray[:, 1], bins=signalHistogram.GetNbinsX(),
322 label=
r'${\rm Signal}$')
324 ax1.hist(backgroundArray[:, 0], weights=backgroundArray[:, 1], bins=backgroundHistogram.GetNbinsX(),
326 edgecolor=
'b', linewidth=4.5, linestyle=
'dashed', label=
r'${\rm Background}$')
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')
331 binWidth = signalHistogram.GetBinWidth(2)
333 if inputVariable ==
'lambdaZError':
335 binWidth = binWidth * 10
337 if inputVariable ==
'M':
338 binWidth = binWidth * 1000
340 if category ==
"Lambda" and inputVariable ==
'distance':
341 variablesPlotParamsDict[inputVariable][5] =
r"{\rm cm}\, "
343 binWidth =
'{:8.2f}'.format(binWidth)
345 xLabel = variablesPlotParamsDict[inputVariable][4]
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]$'
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)
364 if inputVariable ==
'extraInfo(isRightCategory(Kaon))' or \
365 inputVariable ==
'HighestProbInCat(pi+:inRoe, isRightCategory(SlowPion))':
367 ax1.set_yscale(
'log', nonposy=
'clip')
369 ax1.yaxis.set_major_formatter(FormatStrFormatter(
r'$%.2f$'))
371 ax1.tick_params(axis=
'x', labelsize=50)
372 ax1.tick_params(axis=
'y', labelsize=40)
374 if inputVariable ==
'pi_vs_edEdxid':
375 ax1.xaxis.labelpad = 5
377 ax1.xaxis.labelpad = 15
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)':
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:
391 if inputVariable ==
'muid_dEdx':
392 if category !=
'KinLepton':
395 ax1.legend([p1, p2], [
r'${\rm Signal}$',
r'${\rm Bkgr.}$'], prop={
396 'size': 50}, loc=legendLocation, numpoints=1, handlelength=1)
399 ax1.set_xlim(limXmin, limXmax)
400 plt.savefig(
'./InputVariablesPlots/' + category +
'/' + category +
404 signalHistogram.Delete()
405 backgroundHistogram.Delete()
408 if __name__ ==
'__main__':
410 plotInputVariablesOfFlavorTagger()
412 totalNumberOfVariables = 0
414 for category
in ft.AvailableCategories:
415 totalNumberOfVariables += len(ft.getTrainingVariables(category))
417 print(
"Total number of variables = ", totalNumberOfVariables)
419 totalNumberOfCalculatedVariables = len(identifiersExtraInfosKaonPion)
421 print(
"Calculations for Kaon-Pion Category = ", totalNumberOfCalculatedVariables)
423 print(
"Variables per particle list:")
424 for particleList
in identifiersExtraInfosDict:
426 print(identifiersExtraInfosDict[particleList])
427 totalNumberOfCalculatedVariables += len(identifiersExtraInfosDict[particleList])
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.