16from basf2
import B2INFO, B2FATAL, B2WARNING
19import modularAnalysis
as ma
21from variables
import utils
28def getBelleOrBelle2():
30 Gets the global ModeCode.
38def setInteractionWithDatabase(downloadFromDatabaseIfNotFound=False, uploadToDatabaseAfterTraining=False):
40 Sets the interaction with the database: download trained weight files or upload weight files after training.
46 downloadFlag = downloadFromDatabaseIfNotFound
47 uploadFlag = uploadToDatabaseAfterTraining
51flavor_tagging = [
'FBDT_qrCombined',
'FANN_qrCombined',
'qrMC',
'mcFlavorOfOtherB',
'qrGNN',
52 'qpElectron',
'hasTrueTargetElectron',
'isRightCategoryElectron',
53 'qpIntermediateElectron',
'hasTrueTargetIntermediateElectron',
'isRightCategoryIntermediateElectron',
54 'qpMuon',
'hasTrueTargetMuon',
'isRightCategoryMuon',
55 'qpIntermediateMuon',
'hasTrueTargetIntermediateMuon',
'isRightCategoryIntermediateMuon',
56 'qpKinLepton',
'hasTrueTargetKinLepton',
'isRightCategoryKinLepton',
57 'qpIntermediateKinLepton',
'hasTrueTargetIntermediateKinLepton',
'isRightCategoryIntermediateKinLepton',
58 'qpKaon',
'hasTrueTargetKaon',
'isRightCategoryKaon',
59 'qpSlowPion',
'hasTrueTargetSlowPion',
'isRightCategorySlowPion',
60 'qpFastHadron',
'hasTrueTargetFastHadron',
'isRightCategoryFastHadron',
61 'qpLambda',
'hasTrueTargetLambda',
'isRightCategoryLambda',
62 'qpFSC',
'hasTrueTargetFSC',
'isRightCategoryFSC',
63 'qpMaximumPstar',
'hasTrueTargetMaximumPstar',
'isRightCategoryMaximumPstar',
64 'qpKaonPion',
'hasTrueTargetKaonPion',
'isRightCategoryKaonPion']
67def add_default_FlavorTagger_aliases():
69 This function adds the default aliases for flavor tagging variables
70 and defines the collection of flavor tagging variables.
73 variables.variables.addAlias(
'FBDT_qrCombined',
'qrOutput(FBDT)')
74 variables.variables.addAlias(
'FANN_qrCombined',
'qrOutput(FANN)')
75 variables.variables.addAlias(
'qrMC',
'isRelatedRestOfEventB0Flavor')
77 variables.variables.addAlias(
'qrGNN',
'extraInfo(qrGNN)')
79 for iCategory
in AvailableCategories:
80 aliasForQp =
'qp' + iCategory
81 aliasForTrueTarget =
'hasTrueTarget' + iCategory
82 aliasForIsRightCategory =
'isRightCategory' + iCategory
83 variables.variables.addAlias(aliasForQp,
'qpCategory(' + iCategory +
')')
84 variables.variables.addAlias(aliasForTrueTarget,
'hasTrueTargets(' + iCategory +
')')
85 variables.variables.addAlias(aliasForIsRightCategory,
'isTrueFTCategory(' + iCategory +
')')
87 utils.add_collection(flavor_tagging,
'flavor_tagging')
90def set_FlavorTagger_pid_aliases():
92 This function adds the pid aliases needed by the flavor tagger.
94 variables.variables.addAlias(
'eid_TOP',
'pidPairProbabilityExpert(11, 211, TOP)')
95 variables.variables.addAlias(
'eid_ARICH',
'pidPairProbabilityExpert(11, 211, ARICH)')
96 variables.variables.addAlias(
'eid_ECL',
'pidPairProbabilityExpert(11, 211, ECL)')
98 variables.variables.addAlias(
'muid_TOP',
'pidPairProbabilityExpert(13, 211, TOP)')
99 variables.variables.addAlias(
'muid_ARICH',
'pidPairProbabilityExpert(13, 211, ARICH)')
100 variables.variables.addAlias(
'muid_KLM',
'pidPairProbabilityExpert(13, 211, KLM)')
102 variables.variables.addAlias(
'piid_TOP',
'pidPairProbabilityExpert(211, 321, TOP)')
103 variables.variables.addAlias(
'piid_ARICH',
'pidPairProbabilityExpert(211, 321, ARICH)')
105 variables.variables.addAlias(
'Kid_TOP',
'pidPairProbabilityExpert(321, 211, TOP)')
106 variables.variables.addAlias(
'Kid_ARICH',
'pidPairProbabilityExpert(321, 211, ARICH)')
108 if getBelleOrBelle2() ==
"Belle":
109 variables.variables.addAlias(
'eid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(11, 211, CDC, SVD), 0.5)')
110 variables.variables.addAlias(
'muid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(13, 211, CDC, SVD), 0.5)')
111 variables.variables.addAlias(
'piid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(211, 321, CDC, SVD), 0.5)')
112 variables.variables.addAlias(
'pi_vs_edEdxid',
'ifNANgiveX(pidPairProbabilityExpert(211, 11, CDC, SVD), 0.5)')
113 variables.variables.addAlias(
'Kid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(321, 211, CDC, SVD), 0.5)')
115 variables.variables.addAlias(
'eid_dEdx',
'pidPairProbabilityExpert(11, 211, CDC)')
116 variables.variables.addAlias(
'muid_dEdx',
'pidPairProbabilityExpert(13, 211, CDC)')
117 variables.variables.addAlias(
'piid_dEdx',
'pidPairProbabilityExpert(211, 321, CDC)')
118 variables.variables.addAlias(
'pi_vs_edEdxid',
'pidPairProbabilityExpert(211, 11, CDC)')
119 variables.variables.addAlias(
'Kid_dEdx',
'pidPairProbabilityExpert(321, 211, CDC)')
122def set_FlavorTagger_pid_aliases_legacy():
124 This function adds the pid aliases needed by the flavor tagger trained for MC13.
126 variables.variables.addAlias(
'eid_TOP',
'ifNANgiveX(pidPairProbabilityExpert(11, 211, TOP), 0.5)')
127 variables.variables.addAlias(
'eid_ARICH',
'ifNANgiveX(pidPairProbabilityExpert(11, 211, ARICH), 0.5)')
128 variables.variables.addAlias(
'eid_ECL',
'ifNANgiveX(pidPairProbabilityExpert(11, 211, ECL), 0.5)')
130 variables.variables.addAlias(
'muid_TOP',
'ifNANgiveX(pidPairProbabilityExpert(13, 211, TOP), 0.5)')
131 variables.variables.addAlias(
'muid_ARICH',
'ifNANgiveX(pidPairProbabilityExpert(13, 211, ARICH), 0.5)')
132 variables.variables.addAlias(
'muid_KLM',
'ifNANgiveX(pidPairProbabilityExpert(13, 211, KLM), 0.5)')
134 variables.variables.addAlias(
'piid_TOP',
'ifNANgiveX(pidPairProbabilityExpert(211, 321, TOP), 0.5)')
135 variables.variables.addAlias(
'piid_ARICH',
'ifNANgiveX(pidPairProbabilityExpert(211, 321, ARICH), 0.5)')
137 variables.variables.addAlias(
'Kid_TOP',
'ifNANgiveX(pidPairProbabilityExpert(321, 211, TOP), 0.5)')
138 variables.variables.addAlias(
'Kid_ARICH',
'ifNANgiveX(pidPairProbabilityExpert(321, 211, ARICH), 0.5)')
140 if getBelleOrBelle2() ==
"Belle":
141 variables.variables.addAlias(
'eid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(11, 211, CDC, SVD), 0.5)')
142 variables.variables.addAlias(
'muid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(13, 211, CDC, SVD), 0.5)')
143 variables.variables.addAlias(
'piid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(211, 321, CDC, SVD), 0.5)')
144 variables.variables.addAlias(
'pi_vs_edEdxid',
'ifNANgiveX(pidPairProbabilityExpert(211, 11, CDC, SVD), 0.5)')
145 variables.variables.addAlias(
'Kid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(321, 211, CDC, SVD), 0.5)')
148 variables.variables.addAlias(
'eid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(11, 211, CDC), 0.5)')
149 variables.variables.addAlias(
'muid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(13, 211, CDC), 0.5)')
150 variables.variables.addAlias(
'piid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(211, 321, CDC), 0.5)')
151 variables.variables.addAlias(
'pi_vs_edEdxid',
'ifNANgiveX(pidPairProbabilityExpert(211, 11, CDC), 0.5)')
152 variables.variables.addAlias(
'Kid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(321, 211, CDC), 0.5)')
155def set_GNNFlavorTagger_aliases(categories, usePIDNN):
157 This function adds aliases for the GNN-based flavor tagger.
161 variables.variables.addAlias(
'qrCombined_bit',
'(qrCombined+1)/2')
162 alias_list = [
'qrCombined_bit']
177 'electronID_c':
'electronIDNN*charge' if usePIDNN
else 'electronID*charge',
178 'muonID_c':
'muonIDNN*charge' if usePIDNN
else 'muonID*charge',
179 'pionID_c':
'pionIDNN*charge' if usePIDNN
else 'pionID*charge',
180 'kaonID_c':
'kaonIDNN*charge' if usePIDNN
else 'kaonID*charge',
181 'protonID_c':
'protonIDNN*charge' if usePIDNN
else 'protonID*charge',
182 'deuteronID_c':
'deuteronIDNN*charge' if usePIDNN
else 'deuteronID*charge',
183 'electronID_noSVD_noTOP_c':
'electronID_noSVD_noTOP*charge',
187 for rank
in range(1, 17):
189 for cat
in categories:
190 listName = AvailableCategories[cat].particleList
191 varName = f
'QpTrack({listName}, isRightCategory({cat}), isRightCategory({cat}))'
193 varWithRank = f
'ifNANgiveX(getVariableByRank(pi+:inRoe, FT_p, {varName}, {rank}), 0)'
194 aliasWithRank = f
'{cat}_rank{rank}'
196 variables.variables.addAlias(aliasWithRank, varWithRank)
197 alias_list.append(aliasWithRank)
199 for alias, var
in var_dict.items():
200 varWithRank = f
'ifNANgiveX(getVariableByRank(pi+:inRoe, FT_p, {var}, {rank}), 0)'
201 aliasWithRank = f
'{alias}_rank{rank}'
203 variables.variables.addAlias(aliasWithRank, varWithRank)
204 alias_list.append(aliasWithRank)
209def setInputVariablesWithMask(maskName='all'):
211 Set aliases for input variables with ROE mask.
213 variables.variables.addAlias(
'pMissTag_withMask',
'pMissTag('+maskName+
')')
214 variables.variables.addAlias(
'cosTPTO_withMask',
'cosTPTO('+maskName+
')')
215 variables.variables.addAlias(
'ptTracksRoe_withMask',
'ptTracksRoe('+maskName+
')')
216 variables.variables.addAlias(
'pt2TracksRoe_withMask',
'pt2TracksRoe('+maskName+
')')
217 variables.variables.addAlias(
'ptTracksRoe_withMask',
'ptTracksRoe('+maskName+
')')
220def getFastBDTCategories():
222 Helper function for getting the FastBDT categories.
223 It's necessary for removing top-level ROOT imports.
225 fastBDTCategories = basf2_mva.FastBDTOptions()
226 fastBDTCategories.m_nTrees = 500
227 fastBDTCategories.m_nCuts = 8
228 fastBDTCategories.m_nLevels = 3
229 fastBDTCategories.m_shrinkage = 0.10
230 fastBDTCategories.m_randRatio = 0.5
231 return fastBDTCategories
234def getFastBDTCombiner():
236 Helper function for getting the FastBDT combiner.
237 It's necessary for removing top-level ROOT imports.
239 fastBDTCombiner = basf2_mva.FastBDTOptions()
240 fastBDTCombiner.m_nTrees = 500
241 fastBDTCombiner.m_nCuts = 8
242 fastBDTCombiner.m_nLevels = 3
243 fastBDTCombiner.m_shrinkage = 0.10
244 fastBDTCombiner.m_randRatio = 0.5
245 return fastBDTCombiner
248def getMlpFANNCombiner():
250 Helper function for getting the MLP FANN combiner.
251 It's necessary for removing top-level ROOT imports.
253 mlpFANNCombiner = basf2_mva.FANNOptions()
254 mlpFANNCombiner.m_max_epochs = 10000
255 mlpFANNCombiner.m_hidden_layers_architecture =
"3*N"
256 mlpFANNCombiner.m_hidden_activiation_function =
"FANN_SIGMOID_SYMMETRIC"
257 mlpFANNCombiner.m_output_activiation_function =
"FANN_SIGMOID_SYMMETRIC"
258 mlpFANNCombiner.m_error_function =
"FANN_ERRORFUNC_LINEAR"
259 mlpFANNCombiner.m_training_method =
"FANN_TRAIN_RPROP"
260 mlpFANNCombiner.m_validation_fraction = 0.5
261 mlpFANNCombiner.m_random_seeds = 10
262 mlpFANNCombiner.m_test_rate = 500
263 mlpFANNCombiner.m_number_of_threads = 8
264 mlpFANNCombiner.m_scale_features =
True
265 mlpFANNCombiner.m_scale_target =
False
267 return mlpFANNCombiner
279FTCategoryParameters = collections.namedtuple(
'FTCategoryParameters',
280 [
'particleList',
'trackName',
'eventName',
'variableName',
'code'])
284AvailableCategories = {
286 FTCategoryParameters(
'e+:inRoe',
'Electron',
'Electron',
287 'QpOf(e+:inRoe, isRightCategory(Electron), isRightCategory(Electron))',
289 'IntermediateElectron':
290 FTCategoryParameters(
'e+:inRoe',
'IntermediateElectron',
'IntermediateElectron',
291 'QpOf(e+:inRoe, isRightCategory(IntermediateElectron), isRightCategory(IntermediateElectron))',
294 FTCategoryParameters(
'mu+:inRoe',
'Muon',
'Muon',
295 'QpOf(mu+:inRoe, isRightCategory(Muon), isRightCategory(Muon))',
298 FTCategoryParameters(
'mu+:inRoe',
'IntermediateMuon',
'IntermediateMuon',
299 'QpOf(mu+:inRoe, isRightCategory(IntermediateMuon), isRightCategory(IntermediateMuon))',
302 FTCategoryParameters(
'mu+:inRoe',
'KinLepton',
'KinLepton',
303 'QpOf(mu+:inRoe, isRightCategory(KinLepton), isRightCategory(KinLepton))',
305 'IntermediateKinLepton':
306 FTCategoryParameters(
'mu+:inRoe',
'IntermediateKinLepton',
'IntermediateKinLepton',
307 'QpOf(mu+:inRoe, isRightCategory(IntermediateKinLepton), isRightCategory(IntermediateKinLepton))',
310 FTCategoryParameters(
'K+:inRoe',
'Kaon',
'Kaon',
311 'weightedQpOf(K+:inRoe, isRightCategory(Kaon), isRightCategory(Kaon))',
314 FTCategoryParameters(
'pi+:inRoe',
'SlowPion',
'SlowPion',
315 'QpOf(pi+:inRoe, isRightCategory(SlowPion), isRightCategory(SlowPion))',
318 FTCategoryParameters(
'pi+:inRoe',
'FastHadron',
'FastHadron',
319 'QpOf(pi+:inRoe, isRightCategory(FastHadron), isRightCategory(FastHadron))',
322 FTCategoryParameters(
'Lambda0:inRoe',
'Lambda',
'Lambda',
323 'weightedQpOf(Lambda0:inRoe, isRightCategory(Lambda), isRightCategory(Lambda))',
326 FTCategoryParameters(
'pi+:inRoe',
'SlowPion',
'FSC',
327 'QpOf(pi+:inRoe, isRightCategory(FSC), isRightCategory(SlowPion))',
330 FTCategoryParameters(
'pi+:inRoe',
'MaximumPstar',
'MaximumPstar',
331 'QpOf(pi+:inRoe, isRightCategory(MaximumPstar), isRightCategory(MaximumPstar))',
334 FTCategoryParameters(
'K+:inRoe',
'Kaon',
'KaonPion',
335 'QpOf(K+:inRoe, isRightCategory(KaonPion), isRightCategory(Kaon))',
340def getTrainingVariables(category=None, usePIDNN=False):
342 Helper function to get training variables.
344 NOTE: This function is not called the Expert mode. It is not necessary to be consistent with variables list of weight files.
347 KId = {
'Belle':
'ifNANgiveX(atcPIDBelle(3,2), 0.5)',
'Belle2':
'kaonIDNN' if usePIDNN
else 'kaonID'}
348 muId = {
'Belle':
'muIDBelle',
'Belle2':
'muonIDNN' if usePIDNN
else 'muonID'}
349 eId = {
'Belle':
'eIDBelle',
'Belle2':
'electronIDNN' if usePIDNN
else 'electronID'}
352 if category ==
'Electron' or category ==
'IntermediateElectron':
353 variables = [
'useCMSFrame(p)',
358 eId[getBelleOrBelle2()],
362 'BtagToWBosonVariables(recoilMassSqrd)',
363 'BtagToWBosonVariables(pMissCMS)',
364 'BtagToWBosonVariables(cosThetaMissCMS)',
365 'BtagToWBosonVariables(EW90)',
369 if getBelleOrBelle2() ==
"Belle":
370 variables.append(
'eid_dEdx')
371 variables.append(
'ImpactXY')
372 variables.append(
'distance')
374 elif category ==
'Muon' or category ==
'IntermediateMuon':
375 variables = [
'useCMSFrame(p)',
380 muId[getBelleOrBelle2()],
384 'BtagToWBosonVariables(recoilMassSqrd)',
385 'BtagToWBosonVariables(pMissCMS)',
386 'BtagToWBosonVariables(cosThetaMissCMS)',
387 'BtagToWBosonVariables(EW90)',
390 if getBelleOrBelle2() ==
"Belle":
391 variables.append(
'muid_dEdx')
392 variables.append(
'ImpactXY')
393 variables.append(
'distance')
394 variables.append(
'chiProb')
396 elif category ==
'KinLepton' or category ==
'IntermediateKinLepton':
397 variables = [
'useCMSFrame(p)',
402 muId[getBelleOrBelle2()],
406 eId[getBelleOrBelle2()],
410 'BtagToWBosonVariables(recoilMassSqrd)',
411 'BtagToWBosonVariables(pMissCMS)',
412 'BtagToWBosonVariables(cosThetaMissCMS)',
413 'BtagToWBosonVariables(EW90)',
416 if getBelleOrBelle2() ==
"Belle":
417 variables.append(
'eid_dEdx')
418 variables.append(
'muid_dEdx')
419 variables.append(
'ImpactXY')
420 variables.append(
'distance')
421 variables.append(
'chiProb')
423 elif category ==
'Kaon':
424 variables = [
'useCMSFrame(p)',
429 KId[getBelleOrBelle2()],
433 'NumberOfKShortsInRoe',
435 'BtagToWBosonVariables(recoilMassSqrd)',
436 'BtagToWBosonVariables(pMissCMS)',
437 'BtagToWBosonVariables(cosThetaMissCMS)',
438 'BtagToWBosonVariables(EW90)',
442 if getBelleOrBelle2() ==
"Belle":
443 variables.append(
'ImpactXY')
444 variables.append(
'distance')
446 elif category ==
'SlowPion':
447 variables = [
'useCMSFrame(p)',
452 'pionIDNN' if usePIDNN
else 'pionID',
456 KId[getBelleOrBelle2()],
460 'NumberOfKShortsInRoe',
462 eId[getBelleOrBelle2()],
463 'BtagToWBosonVariables(recoilMassSqrd)',
464 'BtagToWBosonVariables(EW90)',
465 'BtagToWBosonVariables(cosThetaMissCMS)',
466 'BtagToWBosonVariables(pMissCMS)',
469 if getBelleOrBelle2() ==
"Belle":
470 variables.append(
'piid_dEdx')
471 variables.append(
'ImpactXY')
472 variables.append(
'distance')
473 variables.append(
'chiProb')
475 elif category ==
'FastHadron':
476 variables = [
'useCMSFrame(p)',
481 'pionIDNN' if usePIDNN
else 'pionID',
486 KId[getBelleOrBelle2()],
490 'NumberOfKShortsInRoe',
492 eId[getBelleOrBelle2()],
493 'BtagToWBosonVariables(recoilMassSqrd)',
494 'BtagToWBosonVariables(EW90)',
495 'BtagToWBosonVariables(cosThetaMissCMS)',
498 if getBelleOrBelle2() ==
"Belle":
499 variables.append(
'BtagToWBosonVariables(pMissCMS)')
500 variables.append(
'ImpactXY')
501 variables.append(
'distance')
502 variables.append(
'chiProb')
504 elif category ==
'Lambda':
505 variables = [
'lambdaFlavor',
506 'NumberOfKShortsInRoe',
508 'cosAngleBetweenMomentumAndVertexVector',
511 'daughter(0,useCMSFrame(p))',
513 'daughter(1,useCMSFrame(p))',
518 if getBelleOrBelle2() ==
"Belle2":
520 variables.append(
'daughter(1,protonIDNN)' if usePIDNN
else 'daughter(1,protonID)')
522 variables.append(
'daughter(0,pionIDNN)' if usePIDNN
else 'daughter(0,pionID)')
524 variables.append(
'distance')
526 elif category ==
'MaximumPstar':
527 variables = [
'useCMSFrame(p)',
533 if getBelleOrBelle2() ==
"Belle2":
534 variables.append(
'ImpactXY')
535 variables.append(
'distance')
537 elif category ==
'FSC':
538 variables = [
'useCMSFrame(p)',
540 KId[getBelleOrBelle2()],
541 'FSCVariables(pFastCMS)',
542 'FSCVariables(cosSlowFast)',
543 'FSCVariables(cosTPTOFast)',
544 'FSCVariables(SlowFastHaveOpositeCharges)',
546 elif category ==
'KaonPion':
547 variables = [
'extraInfo(isRightCategory(Kaon))',
548 'HighestProbInCat(pi+:inRoe, isRightCategory(SlowPion))',
549 'KaonPionVariables(cosKaonPion)',
550 'KaonPionVariables(HaveOpositeCharges)',
551 KId[getBelleOrBelle2()]
557def FillParticleLists(maskName='all', categories=None, path=None):
559 Fills the particle Lists for all categories.
562 from vertex
import kFit
563 readyParticleLists = []
565 if categories
is None:
568 trackCut =
'isInRestOfEvent > 0.5 and passesROEMask(' + maskName +
') > 0.5 and p >= 0'
570 for category
in categories:
571 particleList = AvailableCategories[category].particleList
573 if particleList
in readyParticleLists:
577 if particleList ==
'Lambda0:inRoe':
578 if 'pi+:inRoe' not in readyParticleLists:
579 ma.fillParticleList(
'pi+:inRoe', trackCut, path=path)
580 readyParticleLists.append(
'pi+:inRoe')
582 ma.fillParticleList(
'p+:inRoe', trackCut, path=path)
583 ma.reconstructDecay(particleList +
' -> pi-:inRoe p+:inRoe',
'1.00<=M<=1.23',
False, path=path)
584 kFit(particleList, 0.01, path=path)
585 ma.matchMCTruth(particleList, path=path)
586 readyParticleLists.append(particleList)
590 ma.fillParticleList(particleList, trackCut, path=path)
591 readyParticleLists.append(particleList)
594 if getBelleOrBelle2() ==
'Belle':
595 ma.cutAndCopyList(
'K_S0:inRoe',
'K_S0:mdst',
'extraInfo(ksnbStandard) == 1 and isInRestOfEvent == 1', path=path)
597 if 'pi+:inRoe' not in readyParticleLists:
598 ma.fillParticleList(
'pi+:inRoe', trackCut, path=path)
599 ma.reconstructDecay(
'K_S0:inRoe -> pi+:inRoe pi-:inRoe',
'0.40<=M<=0.60',
False, path=path)
600 kFit(
'K_S0:inRoe', 0.01, path=path)
603 if getBelleOrBelle2() ==
'Belle2':
604 default_list_for_lid_BDT = [
'e+:inRoe',
'mu+:inRoe']
605 list_for_lid_BDT = []
607 for particleList
in default_list_for_lid_BDT:
608 if particleList
in readyParticleLists:
609 list_for_lid_BDT.append(particleList)
612 ma.applyChargedPidMVA(particleLists=list_for_lid_BDT, path=path,
614 binaryHypoPDGCodes=(11, 211))
615 ma.applyChargedPidMVA(particleLists=list_for_lid_BDT, path=path,
617 binaryHypoPDGCodes=(13, 211))
618 ma.applyChargedPidMVA(particleLists=list_for_lid_BDT, path=path,
622def eventLevel(mode='Expert', weightFiles='B2JpsiKs_mu', categories=None, usePIDNN=False, path=None):
624 Samples data for training or tests all categories all categories at event level.
627 from basf2
import create_path
628 from basf2
import register_module
630 B2INFO(
'EVENT LEVEL')
635 identifiersExtraInfosDict = dict()
636 identifiersExtraInfosKaonPion = []
638 if categories
is None:
641 for category
in categories:
642 particleList = AvailableCategories[category].particleList
644 methodPrefixEventLevel =
"FlavorTagger_" + getBelleOrBelle2() +
"_" + weightFiles +
'EventLevel' + category +
'FBDT'
645 identifierEventLevel = methodPrefixEventLevel
646 targetVariable =
'isRightCategory(' + category +
')'
647 extraInfoName = targetVariable
651 if downloadFlag
or useOnlyLocalFlag:
652 identifierEventLevel = filesDirectory +
'/' + methodPrefixEventLevel +
'_1.root'
655 if not os.path.isfile(identifierEventLevel):
656 basf2_mva.download(methodPrefixEventLevel, identifierEventLevel)
657 if not os.path.isfile(identifierEventLevel):
658 B2FATAL(
'Flavor Tagger: Weight file ' + identifierEventLevel +
659 ' was not downloaded from Database. Please check the buildOrRevision name. Stopped')
662 if not os.path.isfile(identifierEventLevel):
663 B2FATAL(
'Flavor Tagger: ' + particleList +
' Eventlevel was not trained. Weight file ' +
664 identifierEventLevel +
' was not found. Stopped')
666 B2INFO(
'flavorTagger: MVAExpert ' + methodPrefixEventLevel +
' ready.')
668 elif mode ==
'Sampler':
670 identifierEventLevel = filesDirectory +
'/' + methodPrefixEventLevel +
'_1.root'
671 if os.path.isfile(identifierEventLevel):
672 B2INFO(
'flavorTagger: MVAExpert ' + methodPrefixEventLevel +
' ready.')
674 if 'KaonPion' in categories:
675 methodPrefixEventLevelKaonPion =
"FlavorTagger_" + getBelleOrBelle2() + \
676 "_" + weightFiles +
'EventLevelKaonPionFBDT'
677 identifierEventLevelKaonPion = filesDirectory +
'/' + methodPrefixEventLevelKaonPion +
'_1.root'
678 if not os.path.isfile(identifierEventLevelKaonPion):
681 if category !=
"SlowPion" and category !=
"Kaon":
684 if mode ==
'Expert' or (mode ==
'Sampler' and os.path.isfile(identifierEventLevel)):
686 B2INFO(
'flavorTagger: Applying MVAExpert ' + methodPrefixEventLevel +
'.')
688 if category ==
'KaonPion':
689 identifiersExtraInfosKaonPion.append((extraInfoName, identifierEventLevel))
690 elif particleList
not in identifiersExtraInfosDict:
691 identifiersExtraInfosDict[particleList] = [(extraInfoName, identifierEventLevel)]
693 identifiersExtraInfosDict[particleList].append((extraInfoName, identifierEventLevel))
698 for particleList
in identifiersExtraInfosDict:
699 eventLevelPath = create_path()
700 SkipEmptyParticleList = register_module(
"SkimFilter")
701 SkipEmptyParticleList.set_name(
'SkimFilter_EventLevel_' + particleList)
702 SkipEmptyParticleList.param(
'particleLists', particleList)
703 SkipEmptyParticleList.if_true(eventLevelPath, basf2.AfterConditionPath.CONTINUE)
704 path.add_module(SkipEmptyParticleList)
706 mvaMultipleExperts = register_module(
'MVAMultipleExperts')
707 mvaMultipleExperts.set_name(
'MVAMultipleExperts_EventLevel_' + particleList)
708 mvaMultipleExperts.param(
'listNames', [particleList])
709 mvaMultipleExperts.param(
'extraInfoNames', [row[0]
for row
in identifiersExtraInfosDict[particleList]])
710 mvaMultipleExperts.param(
'signalFraction', signalFraction)
711 mvaMultipleExperts.param(
'identifiers', [row[1]
for row
in identifiersExtraInfosDict[particleList]])
712 eventLevelPath.add_module(mvaMultipleExperts)
714 if 'KaonPion' in categories
and len(identifiersExtraInfosKaonPion) != 0:
715 eventLevelKaonPionPath = create_path()
716 SkipEmptyParticleList = register_module(
"SkimFilter")
717 SkipEmptyParticleList.set_name(
'SkimFilter_' +
'K+:inRoe')
718 SkipEmptyParticleList.param(
'particleLists',
'K+:inRoe')
719 SkipEmptyParticleList.if_true(eventLevelKaonPionPath, basf2.AfterConditionPath.CONTINUE)
720 path.add_module(SkipEmptyParticleList)
722 mvaExpertKaonPion = register_module(
"MVAExpert")
723 mvaExpertKaonPion.set_name(
'MVAExpert_KaonPion_' +
'K+:inRoe')
724 mvaExpertKaonPion.param(
'listNames', [
'K+:inRoe'])
725 mvaExpertKaonPion.param(
'extraInfoName', identifiersExtraInfosKaonPion[0][0])
726 mvaExpertKaonPion.param(
'signalFraction', signalFraction)
727 mvaExpertKaonPion.param(
'identifier', identifiersExtraInfosKaonPion[0][1])
729 eventLevelKaonPionPath.add_module(mvaExpertKaonPion)
731 if mode ==
'Sampler':
733 for category
in categories:
734 particleList = AvailableCategories[category].particleList
736 methodPrefixEventLevel =
"FlavorTagger_" + getBelleOrBelle2() +
"_" + weightFiles +
'EventLevel' + category +
'FBDT'
737 identifierEventLevel = filesDirectory +
'/' + methodPrefixEventLevel +
'_1.root'
738 targetVariable =
'isRightCategory(' + category +
')'
740 if not os.path.isfile(identifierEventLevel):
742 if category ==
'KaonPion':
743 methodPrefixEventLevelSlowPion =
"FlavorTagger_" + getBelleOrBelle2() + \
744 "_" + weightFiles +
'EventLevelSlowPionFBDT'
745 identifierEventLevelSlowPion = filesDirectory +
'/' + methodPrefixEventLevelSlowPion +
'_1.root'
746 if not os.path.isfile(identifierEventLevelSlowPion):
747 B2INFO(
"Flavor Tagger: event level weight file for the Slow Pion category is absent." +
748 "It is required to sample the training information for the KaonPion category." +
749 "An additional sampling step will be needed after the following training step.")
752 B2INFO(
'flavorTagger: file ' + filesDirectory +
'/' +
753 methodPrefixEventLevel +
"sampled" + fileId +
'.root will be saved.')
755 ma.applyCuts(particleList,
'isRightCategory(mcAssociated) > 0', path)
756 eventLevelpath = create_path()
757 SkipEmptyParticleList = register_module(
"SkimFilter")
758 SkipEmptyParticleList.set_name(
'SkimFilter_EventLevel' + category)
759 SkipEmptyParticleList.param(
'particleLists', particleList)
760 SkipEmptyParticleList.if_true(eventLevelpath, basf2.AfterConditionPath.CONTINUE)
761 path.add_module(SkipEmptyParticleList)
763 ntuple = register_module(
'VariablesToNtuple')
764 ntuple.param(
'fileName', filesDirectory +
'/' + methodPrefixEventLevel +
"sampled" + fileId +
".root")
765 ntuple.param(
'treeName', methodPrefixEventLevel +
"_tree")
766 variablesToBeSaved = getTrainingVariables(category, usePIDNN) + [
768 'ancestorHasWhichFlavor',
776 if category !=
'KaonPion' and category !=
'FSC':
777 variablesToBeSaved = variablesToBeSaved + \
778 [
'extraInfo(isRightTrack(' + category +
'))',
779 'hasHighestProbInCat(' + particleList +
', isRightTrack(' + category +
'))']
780 ntuple.param(
'variables', variablesToBeSaved)
781 ntuple.param(
'particleList', particleList)
782 eventLevelpath.add_module(ntuple)
784 if ReadyMethods != len(categories):
790def eventLevelTeacher(weightFiles='B2JpsiKs_mu', categories=None, usePIDNN=False):
792 Trains all categories at event level.
795 B2INFO(
'EVENT LEVEL TEACHER')
799 if categories
is None:
802 for category
in categories:
803 methodPrefixEventLevel =
"FlavorTagger_" + getBelleOrBelle2() +
"_" + weightFiles +
'EventLevel' + category +
'FBDT'
804 targetVariable =
'isRightCategory(' + category +
')'
805 weightFile = filesDirectory +
'/' + methodPrefixEventLevel +
"_1.root"
807 if os.path.isfile(weightFile):
811 sampledFilesList = glob.glob(filesDirectory +
'/' + methodPrefixEventLevel +
'sampled*.root')
812 if len(sampledFilesList) == 0:
813 B2INFO(
'flavorTagger: eventLevelTeacher did not find any ' + methodPrefixEventLevel +
814 ".root" +
' file. Please run the flavorTagger in "Sampler" mode afterwards.')
817 B2INFO(
'flavorTagger: MVA Teacher training' + methodPrefixEventLevel +
' .')
818 trainingOptionsEventLevel = basf2_mva.GeneralOptions()
819 trainingOptionsEventLevel.m_datafiles = basf2_mva.vector(*sampledFilesList)
820 trainingOptionsEventLevel.m_treename = methodPrefixEventLevel +
"_tree"
821 trainingOptionsEventLevel.m_identifier = weightFile
822 trainingOptionsEventLevel.m_variables = basf2_mva.vector(*getTrainingVariables(category, usePIDNN))
823 trainingOptionsEventLevel.m_target_variable = targetVariable
824 trainingOptionsEventLevel.m_max_events = maxEventsNumber
826 basf2_mva.teacher(trainingOptionsEventLevel, getFastBDTCategories())
829 basf2_mva.upload(weightFile, methodPrefixEventLevel)
831 if ReadyMethods != len(categories):
837def combinerLevel(mode='Expert', weightFiles='B2JpsiKs_mu', categories=None,
838 variablesCombinerLevel=None, categoriesCombinationCode=None, path=None):
840 Samples the input data or tests the combiner according to the selected categories.
843 B2INFO(
'COMBINER LEVEL')
845 if categories
is None:
847 if variablesCombinerLevel
is None:
848 variablesCombinerLevel = []
850 B2INFO(
"Flavor Tagger: Required Combiner for Categories:")
851 for category
in categories:
854 B2INFO(
"Flavor Tagger: which corresponds to a weight file with categories combination code " + categoriesCombinationCode)
856 methodPrefixCombinerLevel =
"FlavorTagger_" + getBelleOrBelle2() +
"_" + weightFiles +
'Combiner' \
857 + categoriesCombinationCode
859 if mode ==
'Sampler':
861 if os.path.isfile(filesDirectory +
'/' + methodPrefixCombinerLevel +
'FBDT' +
'_1.root')
or \
862 os.path.isfile(filesDirectory +
'/' + methodPrefixCombinerLevel +
'FANN' +
'_1.root'):
863 B2FATAL(
'flavorTagger: File' + methodPrefixCombinerLevel +
'FBDT' +
"_1.root" +
' or ' + methodPrefixCombinerLevel +
864 'FANN' +
'_1.root found. Please run the "Expert" mode or delete the file if a new sampling is desired.')
866 B2INFO(
'flavorTagger: Sampling Data on Combiner Level. File' +
867 methodPrefixCombinerLevel +
".root" +
' will be saved')
869 ntuple = basf2.register_module(
'VariablesToNtuple')
870 ntuple.param(
'fileName', filesDirectory +
'/' + methodPrefixCombinerLevel +
"sampled" + fileId +
".root")
871 ntuple.param(
'treeName', methodPrefixCombinerLevel +
'FBDT' +
"_tree")
872 ntuple.param(
'variables', variablesCombinerLevel + [
'qrCombined'])
873 ntuple.param(
'particleList',
"")
874 path.add_module(ntuple)
880 identifierFBDT = methodPrefixCombinerLevel +
'FBDT'
881 if downloadFlag
or useOnlyLocalFlag:
882 identifierFBDT = filesDirectory +
'/' + methodPrefixCombinerLevel +
'FBDT' +
'_1.root'
885 if not os.path.isfile(identifierFBDT):
886 basf2_mva.download(methodPrefixCombinerLevel +
'FBDT', identifierFBDT)
887 if not os.path.isfile(identifierFBDT):
888 B2FATAL(
'Flavor Tagger: Weight file ' + identifierFBDT +
889 ' was not downloaded from Database. Please check the buildOrRevision name. Stopped')
892 if not os.path.isfile(identifierFBDT):
893 B2FATAL(
'flavorTagger: Combinerlevel FastBDT was not trained with this combination of categories.' +
894 ' Weight file ' + identifierFBDT +
' not found. Stopped')
896 B2INFO(
'flavorTagger: Ready to be used with weightFile ' + methodPrefixCombinerLevel +
'FBDT' +
'_1.root')
899 identifierFANN = methodPrefixCombinerLevel +
'FANN'
900 if downloadFlag
or useOnlyLocalFlag:
901 identifierFANN = filesDirectory +
'/' + methodPrefixCombinerLevel +
'FANN' +
'_1.root'
904 if not os.path.isfile(identifierFANN):
905 basf2_mva.download(methodPrefixCombinerLevel +
'FANN', identifierFANN)
906 if not os.path.isfile(identifierFANN):
907 B2FATAL(
'Flavor Tagger: Weight file ' + identifierFANN +
908 ' was not downloaded from Database. Please check the buildOrRevision name. Stopped')
910 if not os.path.isfile(identifierFANN):
911 B2FATAL(
'flavorTagger: Combinerlevel FANNMLP was not trained with this combination of categories. ' +
912 ' Weight file ' + identifierFANN +
' not found. Stopped')
914 B2INFO(
'flavorTagger: Ready to be used with weightFile ' + methodPrefixCombinerLevel +
'FANN' +
'_1.root')
918 if TMVAfbdt
and not FANNmlp:
919 B2INFO(
'flavorTagger: Apply FBDTMethod ' + methodPrefixCombinerLevel +
'FBDT')
920 path.add_module(
'MVAExpert', listNames=[], extraInfoName=
'qrCombined' +
'FBDT', signalFraction=signalFraction,
921 identifier=identifierFBDT)
923 if FANNmlp
and not TMVAfbdt:
924 B2INFO(
'flavorTagger: Apply FANNMethod on combiner level')
925 path.add_module(
'MVAExpert', listNames=[], extraInfoName=
'qrCombined' +
'FANN', signalFraction=signalFraction,
926 identifier=identifierFANN)
928 if FANNmlp
and TMVAfbdt:
929 B2INFO(
'flavorTagger: Apply FANNMethod and FBDTMethod on combiner level')
930 mvaMultipleExperts = basf2.register_module(
'MVAMultipleExperts')
931 mvaMultipleExperts.set_name(
'MVAMultipleExperts_Combiners')
932 mvaMultipleExperts.param(
'listNames', [])
933 mvaMultipleExperts.param(
'extraInfoNames', [
'qrCombined' +
'FBDT',
'qrCombined' +
'FANN'])
934 mvaMultipleExperts.param(
'signalFraction', signalFraction)
935 mvaMultipleExperts.param(
'identifiers', [identifierFBDT, identifierFANN])
936 path.add_module(mvaMultipleExperts)
939def combinerLevelTeacher(weightFiles='B2JpsiKs_mu', variablesCombinerLevel=None,
940 categoriesCombinationCode=None):
942 Trains the combiner according to the selected categories.
945 B2INFO(
'COMBINER LEVEL TEACHER')
947 if variablesCombinerLevel
is None:
948 variablesCombinerLevel = []
950 methodPrefixCombinerLevel =
"FlavorTagger_" + getBelleOrBelle2() +
"_" + weightFiles +
'Combiner' \
951 + categoriesCombinationCode
953 sampledFilesList = glob.glob(filesDirectory +
'/' + methodPrefixCombinerLevel +
'sampled*.root')
954 if len(sampledFilesList) == 0:
955 B2FATAL(
'FlavorTagger: combinerLevelTeacher did not find any ' +
956 methodPrefixCombinerLevel +
'sampled*.root file. Please run the flavorTagger in "Sampler" mode.')
960 if not os.path.isfile(filesDirectory +
'/' + methodPrefixCombinerLevel +
'FBDT' +
'_1.root'):
962 B2INFO(
'flavorTagger: MVA Teacher training a FastBDT on Combiner Level')
964 trainingOptionsCombinerLevel = basf2_mva.GeneralOptions()
965 trainingOptionsCombinerLevel.m_datafiles = basf2_mva.vector(*sampledFilesList)
966 trainingOptionsCombinerLevel.m_treename = methodPrefixCombinerLevel +
'FBDT' +
"_tree"
967 trainingOptionsCombinerLevel.m_identifier = filesDirectory +
'/' + methodPrefixCombinerLevel +
'FBDT' +
"_1.root"
968 trainingOptionsCombinerLevel.m_variables = basf2_mva.vector(*variablesCombinerLevel)
969 trainingOptionsCombinerLevel.m_target_variable =
'qrCombined'
970 trainingOptionsCombinerLevel.m_max_events = maxEventsNumber
972 basf2_mva.teacher(trainingOptionsCombinerLevel, getFastBDTCombiner())
975 basf2_mva.upload(filesDirectory +
'/' + methodPrefixCombinerLevel +
976 'FBDT' +
"_1.root", methodPrefixCombinerLevel +
'FBDT')
978 elif FANNmlp
and not os.path.isfile(filesDirectory +
'/' + methodPrefixCombinerLevel +
'FANN' +
'_1.root'):
980 B2INFO(
'flavorTagger: Combinerlevel FBDT was already trained with this combination of categories. Weight file ' +
981 methodPrefixCombinerLevel +
'FBDT' +
'_1.root has been found.')
984 B2FATAL(
'flavorTagger: Combinerlevel was already trained with this combination of categories. Weight files ' +
985 methodPrefixCombinerLevel +
'FBDT' +
'_1.root and ' +
986 methodPrefixCombinerLevel +
'FANN' +
'_1.root has been found. Please use the "Expert" mode')
990 if not os.path.isfile(filesDirectory +
'/' + methodPrefixCombinerLevel +
'FANN' +
'_1.root'):
992 B2INFO(
'flavorTagger: MVA Teacher training a FANN MLP on Combiner Level')
994 trainingOptionsCombinerLevel = basf2_mva.GeneralOptions()
995 trainingOptionsCombinerLevel.m_datafiles = basf2_mva.vector(*sampledFilesList)
996 trainingOptionsCombinerLevel.m_treename = methodPrefixCombinerLevel +
'FBDT' +
"_tree"
997 trainingOptionsCombinerLevel.m_identifier = filesDirectory +
'/' + methodPrefixCombinerLevel +
'FANN' +
"_1.root"
998 trainingOptionsCombinerLevel.m_variables = basf2_mva.vector(*variablesCombinerLevel)
999 trainingOptionsCombinerLevel.m_target_variable =
'qrCombined'
1000 trainingOptionsCombinerLevel.m_max_events = maxEventsNumber
1002 basf2_mva.teacher(trainingOptionsCombinerLevel, getMlpFANNCombiner())
1005 basf2_mva.upload(filesDirectory +
'/' + methodPrefixCombinerLevel +
1006 'FANN' +
"_1.root", methodPrefixCombinerLevel +
'FANN')
1008 elif TMVAfbdt
and not os.path.isfile(filesDirectory +
'/' + methodPrefixCombinerLevel +
'FBDT' +
'_1.root'):
1010 B2INFO(
'flavorTagger: Combinerlevel FBDT was already trained with this combination of categories. Weight file ' +
1011 methodPrefixCombinerLevel +
'FANN' +
'_1.config has been found.')
1014 B2FATAL(
'flavorTagger: Combinerlevel was already trained with this combination of categories. Weight files ' +
1015 methodPrefixCombinerLevel +
'FBDT' +
'_1.root and ' +
1016 methodPrefixCombinerLevel +
'FANN' +
'_1.root has been found. Please use the "Expert" mode')
1019def getEventLevelParticleLists(categories=None):
1021 if categories
is None:
1024 eventLevelParticleLists = []
1026 for category
in categories:
1027 ftCategory = AvailableCategories[category]
1028 event_tuple = (ftCategory.particleList, ftCategory.eventName, ftCategory.variableName)
1030 if event_tuple
not in eventLevelParticleLists:
1031 eventLevelParticleLists.append(event_tuple)
1033 B2FATAL(
'Flavor Tagger: ' + category +
' has been already given')
1035 return eventLevelParticleLists
1041 weightFiles='B2nunubarBGx1',
1042 workingDirectory='.',
1043 combinerMethods=['TMVA-FBDT'],
1046 'IntermediateElectron',
1050 'IntermediateKinLepton',
1058 maskName='FTDefaultMask',
1059 saveCategoriesInfo=True,
1060 useOnlyLocalWeightFiles=False,
1061 downloadFromDatabaseIfNotFound=False,
1062 uploadToDatabaseAfterTraining=False,
1064 prefix='MC16rd_light-2501-betelgeuse',
1066 identifierGNN='GFlaT_MC16rd_light-2501-betelgeuse_tensorflow',
1071 Defines the whole flavor tagging process for each selected Rest of Event (ROE) built in the steering file.
1072 The flavor is predicted by Multivariate Methods trained with Variables and MetaVariables which use
1073 Tracks, ECL- and KLMClusters from the corresponding RestOfEvent dataobject.
1074 This module can be used to sample the training information, to train and/or to test the flavorTagger.
1076 @param particleLists The ROEs for flavor tagging are selected from the given particle lists.
1077 @param mode The available modes are
1078 ``Expert`` (default), ``Sampler``, and ``Teacher``. In the ``Expert`` mode
1079 Flavor Tagging is applied to the analysis. In the ``Sampler`` mode you save
1080 the variables for training. In the ``Teacher`` mode the FlavorTagger is
1081 trained, for this step you do not reconstruct any particle or do any analysis,
1082 you just run the flavorTagger alone.
1083 @param weightFiles Weight files name. Default=
1084 ``B2nunubarBGx1`` (official weight files). If the user wants to train the
1085 FlavorTagger themselves, the weightfiles name should correspond to the
1086 analyzed CP channel in order to avoid confusions. The default name
1087 ``B2nunubarBGx1`` corresponds to
1088 :math:`B^0_{\\rm sig}\\to \\nu \\overline{\\nu}`.
1089 and ``B2JpsiKs_muBGx1`` to
1090 :math:`B^0_{\\rm sig}\\to J/\\psi (\\to \\mu^+ \\mu^-) K_s (\\to \\pi^+ \\pi^-)`.
1091 BGx1 stands for events simulated with background.
1092 @param workingDirectory Path to the directory containing the FlavorTagging/ folder.
1093 @param combinerMethods MVAs for the combiner: ``TMVA-FBDT` (default).
1094 ``FANN-MLP`` is available only with ``prefix=''`` (MC13 weight files).
1095 @param categories Categories used for flavor tagging. By default all are used.
1096 @param maskName Gets ROE particles from a specified ROE mask.
1097 ``FTDefaultMask`` (default): tentative mask definition that will be created
1098 automatically. The definition is as follows:
1100 - Track (pion): thetaInCDCAcceptance and dr<1 and abs(dz)<3
1101 - ECL-cluster (gamma): thetaInCDCAcceptance and clusterNHits>1.5 and \
1102 [[clusterReg==1 and E>0.08] or [clusterReg==2 and E>0.03] or \
1103 [clusterReg==3 and E>0.06]] \
1104 (Same as gamma:pi0eff30_May2020 and gamma:pi0eff40_May2020)
1106 ``all``: all ROE particles are used.
1107 Or one can give any mask name defined before calling this function.
1108 @param saveCategoriesInfo Sets to save information of individual categories.
1109 @param useOnlyLocalWeightFiles [Expert] Uses only locally saved weight files.
1110 @param downloadFromDatabaseIfNotFound [Expert] Weight files are downloaded from
1111 the conditions database if not available in workingDirectory.
1112 @param uploadToDatabaseAfterTraining [Expert] For librarians only: uploads weight files to localdb after training.
1113 @param samplerFileId Identifier to parallelize
1114 sampling. Only used in ``Sampler`` mode. If you are training by yourself and
1115 want to parallelize the sampling, you can run several sampling scripts in
1116 parallel. By changing this parameter you will not overwrite an older sample.
1117 @param prefix Prefix of weight files.
1118 ``MC16rd_light-2501-betelgeuse`` (default): Weight files trained for MC16rd samples.
1119 ``MC15ri_light-2207-bengal_0``: Weight files trained for MC15ri samples.
1120 ``''``: Weight files trained for MC13 samples.
1121 @param useGNN Use GNN-based Flavor Tagger in addition with FastBDT-based one.
1122 Please specify the weight file with the option ``identifierGNN``.
1123 [Expert] In the sampler mode,
1124 training files for GNN-based Flavor Tagger are produced.
1125 @param identifierGNN The name of weight file of the GNN-based Flavor Tagger.
1126 [Expert] Multiple identifiers can be given with list(str).
1127 @param usePIDNN If True, PID probabilities calculated from PID neural network are used
1128 (default is False). Prefix and identifierGNN must be set accordingly.
1129 @param path Modules are added to this path
1133 if (
not isinstance(particleLists, list)):
1134 particleLists = [particleLists]
1136 if mode !=
'Sampler' and mode !=
'Teacher' and mode !=
'Expert':
1137 B2FATAL(
'flavorTagger: Wrong mode given: The available modes are "Sampler", "Teacher" or "Expert"')
1139 if len(categories) != len(set(categories)):
1140 dup = [cat
for cat
in set(categories)
if categories.count(cat) > 1]
1141 B2WARNING(
'Flavor Tagger: There are duplicate elements in the given categories list. '
1142 <<
'The following duplicate elements are removed; ' <<
', '.join(dup))
1143 categories = list(set(categories))
1145 if len(categories) < 2:
1146 B2FATAL(
'Flavor Tagger: Invalid amount of categories. At least two are needed.')
1148 'Flavor Tagger: Possible categories are "Electron", "IntermediateElectron", "Muon", "IntermediateMuon", '
1149 '"KinLepton", "IntermediateKinLepton", "Kaon", "SlowPion", "FastHadron",'
1150 '"Lambda", "FSC", "MaximumPstar" or "KaonPion" ')
1152 for category
in categories:
1153 if category
not in AvailableCategories:
1154 B2FATAL(
'Flavor Tagger: ' + category +
' is not a valid category name given')
1155 B2FATAL(
'Flavor Tagger: Available categories are "Electron", "IntermediateElectron", '
1156 '"Muon", "IntermediateMuon", "KinLepton", "IntermediateKinLepton", "Kaon", "SlowPion", "FastHadron", '
1157 '"Lambda", "FSC", "MaximumPstar" or "KaonPion" ')
1159 if mode ==
'Expert' and useGNN
and identifierGNN ==
'':
1160 B2FATAL(
'Please specify the name of the weight file with ``identifierGNN``')
1165 basf2.find_file(workingDirectory)
1167 global filesDirectory
1168 filesDirectory = workingDirectory +
'/FlavorTagging/TrainedMethods'
1170 if mode ==
'Sampler' or (mode ==
'Expert' and downloadFromDatabaseIfNotFound):
1171 if not basf2.find_file(workingDirectory +
'/FlavorTagging', silent=
True):
1172 os.mkdir(workingDirectory +
'/FlavorTagging')
1173 os.mkdir(workingDirectory +
'/FlavorTagging/TrainedMethods')
1174 elif not basf2.find_file(workingDirectory +
'/FlavorTagging/TrainedMethods', silent=
True):
1175 os.mkdir(workingDirectory +
'/FlavorTagging/TrainedMethods')
1176 filesDirectory = workingDirectory +
'/FlavorTagging/TrainedMethods'
1178 if len(combinerMethods) < 1
or len(combinerMethods) > 2:
1179 B2FATAL(
'flavorTagger: Invalid list of combinerMethods. The available methods are "TMVA-FBDT" and "FANN-MLP"')
1187 for method
in combinerMethods:
1188 if method ==
'TMVA-FBDT':
1190 elif method ==
'FANN-MLP':
1193 B2FATAL(
'flavorTagger: Invalid list of combinerMethods. The available methods are "TMVA-FBDT" and "FANN-MLP"')
1196 fileId = samplerFileId
1198 global useOnlyLocalFlag
1199 useOnlyLocalFlag = useOnlyLocalWeightFiles
1201 B2INFO(
'*** FLAVOR TAGGING ***')
1203 B2INFO(
' Working directory is: ' + filesDirectory)
1206 setInteractionWithDatabase(downloadFromDatabaseIfNotFound, uploadToDatabaseAfterTraining)
1209 set_FlavorTagger_pid_aliases_legacy()
1211 set_FlavorTagger_pid_aliases()
1213 alias_list_for_GNN = []
1215 alias_list_for_GNN = set_GNNFlavorTagger_aliases(categories, usePIDNN)
1217 setInputVariablesWithMask()
1219 weightFiles = prefix +
'_' + weightFiles
1222 trackLevelParticleLists = []
1223 eventLevelParticleLists = []
1224 variablesCombinerLevel = []
1225 categoriesCombination = []
1226 categoriesCombinationCode =
'CatCode'
1227 for category
in categories:
1228 ftCategory = AvailableCategories[category]
1230 track_tuple = (ftCategory.particleList, ftCategory.trackName)
1231 event_tuple = (ftCategory.particleList, ftCategory.eventName, ftCategory.variableName)
1233 if track_tuple
not in trackLevelParticleLists
and category !=
'MaximumPstar':
1234 trackLevelParticleLists.append(track_tuple)
1236 if event_tuple
not in eventLevelParticleLists:
1237 eventLevelParticleLists.append(event_tuple)
1238 variablesCombinerLevel.append(ftCategory.variableName)
1239 categoriesCombination.append(ftCategory.code)
1241 B2FATAL(
'Flavor Tagger: ' + category +
' has been already given')
1243 for code
in sorted(categoriesCombination):
1244 categoriesCombinationCode = categoriesCombinationCode + f
'{int(code):02}'
1247 if maskName ==
'FTDefaultMask':
1250 'thetaInCDCAcceptance and dr<1 and abs(dz)<3',
1251 'thetaInCDCAcceptance and clusterNHits>1.5 and [[E>0.08 and clusterReg==1] or [E>0.03 and clusterReg==2] or \
1252 [E>0.06 and clusterReg==3]]')
1253 for name
in particleLists:
1254 ma.appendROEMasks(list_name=name, mask_tuples=[FTDefaultMask], path=path)
1257 roe_path = basf2.create_path()
1258 deadEndPath = basf2.create_path()
1260 if mode ==
'Sampler':
1262 ma.signalSideParticleListsFilter(
1264 'nROE_Charged(' + maskName +
', 0) > 0 and abs(qrCombined) == 1',
1268 FillParticleLists(maskName, categories, roe_path)
1271 if eventLevel(
'Expert', weightFiles, categories, usePIDNN, roe_path):
1273 ma.rankByHighest(
'pi+:inRoe',
'p', numBest=0, allowMultiRank=
False,
1274 outputVariable=
'FT_p_rank', overwriteRank=
True, path=roe_path)
1275 ma.fillParticleListFromDummy(
'vpho:dummy', path=roe_path)
1276 ma.variablesToNtuple(
'vpho:dummy',
1279 filename=f
'{filesDirectory}/FlavorTagger_GNN_sampled{fileId}.root',
1280 signalSideParticleList=particleLists[0],
1284 if eventLevel(mode, weightFiles, categories, usePIDNN, roe_path):
1285 combinerLevel(mode, weightFiles, categories, variablesCombinerLevel, categoriesCombinationCode, roe_path)
1287 path.for_each(
'RestOfEvent',
'RestOfEvents', roe_path)
1289 elif mode ==
'Expert':
1292 ma.signalSideParticleListsFilter(particleLists,
'nROE_Charged(' + maskName +
', 0) > 0', roe_path, deadEndPath)
1295 flavorTaggerInfoBuilder = basf2.register_module(
'FlavorTaggerInfoBuilder')
1296 path.add_module(flavorTaggerInfoBuilder)
1298 FillParticleLists(maskName, categories, roe_path)
1300 if eventLevel(mode, weightFiles, categories, usePIDNN, roe_path):
1301 combinerLevel(mode, weightFiles, categories, variablesCombinerLevel, categoriesCombinationCode, roe_path)
1303 flavorTaggerInfoFiller = basf2.register_module(
'FlavorTaggerInfoFiller')
1304 flavorTaggerInfoFiller.param(
'trackLevelParticleLists', trackLevelParticleLists)
1305 flavorTaggerInfoFiller.param(
'eventLevelParticleLists', eventLevelParticleLists)
1306 flavorTaggerInfoFiller.param(
'TMVAfbdt', TMVAfbdt)
1307 flavorTaggerInfoFiller.param(
'FANNmlp', FANNmlp)
1308 flavorTaggerInfoFiller.param(
'qpCategories', saveCategoriesInfo)
1309 flavorTaggerInfoFiller.param(
'istrueCategories', saveCategoriesInfo)
1310 flavorTaggerInfoFiller.param(
'targetProb',
False)
1311 flavorTaggerInfoFiller.param(
'trackPointers',
False)
1312 roe_path.add_module(flavorTaggerInfoFiller)
1313 add_default_FlavorTagger_aliases()
1316 ma.rankByHighest(
'pi+:inRoe',
'p', numBest=0, allowMultiRank=
False,
1317 outputVariable=
'FT_p_rank', overwriteRank=
True, path=roe_path)
1318 ma.fillParticleListFromDummy(
'vpho:dummy', path=roe_path)
1320 if isinstance(identifierGNN, str):
1321 roe_path.add_module(
'MVAExpert',
1322 listNames=
'vpho:dummy',
1323 extraInfoName=
'qrGNN_raw',
1324 identifier=identifierGNN)
1326 ma.variableToSignalSideExtraInfo(
'vpho:dummy', {
'extraInfo(qrGNN_raw)*2-1':
'qrGNN'},
1329 elif isinstance(identifierGNN, list):
1330 identifierGNN = list(set(identifierGNN))
1332 extraInfoNames = [f
'qrGNN_{i_id}' for i_id
in identifierGNN]
1333 roe_path.add_module(
'MVAMultipleExperts',
1334 listNames=
'vpho:dummy',
1335 extraInfoNames=extraInfoNames,
1336 identifiers=identifierGNN)
1339 for extraInfoName
in extraInfoNames:
1340 extraInfoDict[f
'extraInfo({extraInfoName})*2-1'] = extraInfoName
1341 variables.variables.addAlias(extraInfoName, f
'extraInfo({extraInfoName})')
1343 ma.variableToSignalSideExtraInfo(
'vpho:dummy', extraInfoDict,
1346 path.for_each(
'RestOfEvent',
'RestOfEvents', roe_path)
1348 elif mode ==
'Teacher':
1349 if eventLevelTeacher(weightFiles, categories, usePIDNN):
1350 combinerLevelTeacher(weightFiles, variablesCombinerLevel, categoriesCombinationCode)
1353if __name__ ==
'__main__':
1355 pretty_print_module(__name__,
"flavorTagger")