16from basf2
import B2INFO, B2FATAL, B2WARNING
20import modularAnalysis
as ma
22from variables
import utils
29def getBelleOrBelle2():
31 Gets the global ModeCode.
39def setInteractionWithDatabase(downloadFromDatabaseIfNotFound=False, uploadToDatabaseAfterTraining=False):
41 Sets the interaction with the database: download trained weight files
or upload weight files after training.
47 downloadFlag = downloadFromDatabaseIfNotFound
48 uploadFlag = uploadToDatabaseAfterTraining
52flavor_tagging = [
'FBDT_qrCombined',
'FANN_qrCombined',
'qrMC',
'mcFlavorOfOtherB',
'qrGNN',
53 'qpElectron',
'hasTrueTargetElectron',
'isRightCategoryElectron',
54 'qpIntermediateElectron',
'hasTrueTargetIntermediateElectron',
'isRightCategoryIntermediateElectron',
55 'qpMuon',
'hasTrueTargetMuon',
'isRightCategoryMuon',
56 'qpIntermediateMuon',
'hasTrueTargetIntermediateMuon',
'isRightCategoryIntermediateMuon',
57 'qpKinLepton',
'hasTrueTargetKinLepton',
'isRightCategoryKinLepton',
58 'qpIntermediateKinLepton',
'hasTrueTargetIntermediateKinLepton',
'isRightCategoryIntermediateKinLepton',
59 'qpKaon',
'hasTrueTargetKaon',
'isRightCategoryKaon',
60 'qpSlowPion',
'hasTrueTargetSlowPion',
'isRightCategorySlowPion',
61 'qpFastHadron',
'hasTrueTargetFastHadron',
'isRightCategoryFastHadron',
62 'qpLambda',
'hasTrueTargetLambda',
'isRightCategoryLambda',
63 'qpFSC',
'hasTrueTargetFSC',
'isRightCategoryFSC',
64 'qpMaximumPstar',
'hasTrueTargetMaximumPstar',
'isRightCategoryMaximumPstar',
65 'qpKaonPion',
'hasTrueTargetKaonPion',
'isRightCategoryKaonPion']
68def add_default_FlavorTagger_aliases():
70 This function adds the default aliases for flavor tagging variables
71 and defines the collection of flavor tagging variables.
74 variables.variables.addAlias('FBDT_qrCombined',
'qrOutput(FBDT)')
75 variables.variables.addAlias(
'FANN_qrCombined',
'qrOutput(FANN)')
76 variables.variables.addAlias(
'qrMC',
'isRelatedRestOfEventB0Flavor')
78 variables.variables.addAlias(
'qrGNN',
'extraInfo(qrGNN)')
80 for iCategory
in AvailableCategories:
81 aliasForQp =
'qp' + iCategory
82 aliasForTrueTarget =
'hasTrueTarget' + iCategory
83 aliasForIsRightCategory =
'isRightCategory' + iCategory
84 variables.variables.addAlias(aliasForQp,
'qpCategory(' + iCategory +
')')
85 variables.variables.addAlias(aliasForTrueTarget,
'hasTrueTargets(' + iCategory +
')')
86 variables.variables.addAlias(aliasForIsRightCategory,
'isTrueFTCategory(' + iCategory +
')')
88 utils.add_collection(flavor_tagging,
'flavor_tagging')
91def set_FlavorTagger_pid_aliases():
93 This function adds the pid aliases needed by the flavor tagger.
95 variables.variables.addAlias('eid_TOP',
'pidPairProbabilityExpert(11, 211, TOP)')
96 variables.variables.addAlias(
'eid_ARICH',
'pidPairProbabilityExpert(11, 211, ARICH)')
97 variables.variables.addAlias(
'eid_ECL',
'pidPairProbabilityExpert(11, 211, ECL)')
99 variables.variables.addAlias(
'muid_TOP',
'pidPairProbabilityExpert(13, 211, TOP)')
100 variables.variables.addAlias(
'muid_ARICH',
'pidPairProbabilityExpert(13, 211, ARICH)')
101 variables.variables.addAlias(
'muid_KLM',
'pidPairProbabilityExpert(13, 211, KLM)')
103 variables.variables.addAlias(
'piid_TOP',
'pidPairProbabilityExpert(211, 321, TOP)')
104 variables.variables.addAlias(
'piid_ARICH',
'pidPairProbabilityExpert(211, 321, ARICH)')
106 variables.variables.addAlias(
'Kid_TOP',
'pidPairProbabilityExpert(321, 211, TOP)')
107 variables.variables.addAlias(
'Kid_ARICH',
'pidPairProbabilityExpert(321, 211, ARICH)')
109 if getBelleOrBelle2() ==
"Belle":
110 variables.variables.addAlias(
'eid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(11, 211, CDC, SVD), 0.5)')
111 variables.variables.addAlias(
'muid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(13, 211, CDC, SVD), 0.5)')
112 variables.variables.addAlias(
'piid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(211, 321, CDC, SVD), 0.5)')
113 variables.variables.addAlias(
'pi_vs_edEdxid',
'ifNANgiveX(pidPairProbabilityExpert(211, 11, CDC, SVD), 0.5)')
114 variables.variables.addAlias(
'Kid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(321, 211, CDC, SVD), 0.5)')
116 variables.variables.addAlias(
'eid_dEdx',
'pidPairProbabilityExpert(11, 211, CDC)')
117 variables.variables.addAlias(
'muid_dEdx',
'pidPairProbabilityExpert(13, 211, CDC)')
118 variables.variables.addAlias(
'piid_dEdx',
'pidPairProbabilityExpert(211, 321, CDC)')
119 variables.variables.addAlias(
'pi_vs_edEdxid',
'pidPairProbabilityExpert(211, 11, CDC)')
120 variables.variables.addAlias(
'Kid_dEdx',
'pidPairProbabilityExpert(321, 211, CDC)')
123def set_FlavorTagger_pid_aliases_legacy():
125 This function adds the pid aliases needed by the flavor tagger trained for MC13.
127 variables.variables.addAlias('eid_TOP',
'ifNANgiveX(pidPairProbabilityExpert(11, 211, TOP), 0.5)')
128 variables.variables.addAlias(
'eid_ARICH',
'ifNANgiveX(pidPairProbabilityExpert(11, 211, ARICH), 0.5)')
129 variables.variables.addAlias(
'eid_ECL',
'ifNANgiveX(pidPairProbabilityExpert(11, 211, ECL), 0.5)')
131 variables.variables.addAlias(
'muid_TOP',
'ifNANgiveX(pidPairProbabilityExpert(13, 211, TOP), 0.5)')
132 variables.variables.addAlias(
'muid_ARICH',
'ifNANgiveX(pidPairProbabilityExpert(13, 211, ARICH), 0.5)')
133 variables.variables.addAlias(
'muid_KLM',
'ifNANgiveX(pidPairProbabilityExpert(13, 211, KLM), 0.5)')
135 variables.variables.addAlias(
'piid_TOP',
'ifNANgiveX(pidPairProbabilityExpert(211, 321, TOP), 0.5)')
136 variables.variables.addAlias(
'piid_ARICH',
'ifNANgiveX(pidPairProbabilityExpert(211, 321, ARICH), 0.5)')
138 variables.variables.addAlias(
'Kid_TOP',
'ifNANgiveX(pidPairProbabilityExpert(321, 211, TOP), 0.5)')
139 variables.variables.addAlias(
'Kid_ARICH',
'ifNANgiveX(pidPairProbabilityExpert(321, 211, ARICH), 0.5)')
141 if getBelleOrBelle2() ==
"Belle":
142 variables.variables.addAlias(
'eid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(11, 211, CDC, SVD), 0.5)')
143 variables.variables.addAlias(
'muid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(13, 211, CDC, SVD), 0.5)')
144 variables.variables.addAlias(
'piid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(211, 321, CDC, SVD), 0.5)')
145 variables.variables.addAlias(
'pi_vs_edEdxid',
'ifNANgiveX(pidPairProbabilityExpert(211, 11, CDC, SVD), 0.5)')
146 variables.variables.addAlias(
'Kid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(321, 211, CDC, SVD), 0.5)')
149 variables.variables.addAlias(
'eid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(11, 211, CDC), 0.5)')
150 variables.variables.addAlias(
'muid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(13, 211, CDC), 0.5)')
151 variables.variables.addAlias(
'piid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(211, 321, CDC), 0.5)')
152 variables.variables.addAlias(
'pi_vs_edEdxid',
'ifNANgiveX(pidPairProbabilityExpert(211, 11, CDC), 0.5)')
153 variables.variables.addAlias(
'Kid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(321, 211, CDC), 0.5)')
156def set_GNNFlavorTagger_aliases(categories):
158 This function adds aliases for the GNN-based flavor tagger.
162 variables.variables.addAlias(
'qrCombined_bit',
'(qrCombined+1)/2')
163 alias_list = [
'qrCombined_bit']
178 'electronID_c':
'electronID*charge',
179 'muonID_c':
'muonID*charge',
180 'pionID_c':
'pionID*charge',
181 'kaonID_c':
'kaonID*charge',
182 'protonID_c':
'protonID*charge',
183 'deuteronID_c':
'deuteronID*charge',
184 'electronID_noSVD_noTOP_c':
'electronID_noSVD_noTOP*charge',
188 for rank
in range(1, 17):
190 for cat
in categories:
191 listName = AvailableCategories[cat].particleList
192 varName = f
'QpTrack({listName}, isRightCategory({cat}), isRightCategory({cat}))'
194 varWithRank = f
'ifNANgiveX(getVariableByRank(pi+:inRoe, FT_p, {varName}, {rank}), 0)'
195 aliasWithRank = f
'{cat}_rank{rank}'
197 variables.variables.addAlias(aliasWithRank, varWithRank)
198 alias_list.append(aliasWithRank)
200 for alias, var
in var_dict.items():
201 varWithRank = f
'ifNANgiveX(getVariableByRank(pi+:inRoe, FT_p, {var}, {rank}), 0)'
202 aliasWithRank = f
'{alias}_rank{rank}'
204 variables.variables.addAlias(aliasWithRank, varWithRank)
205 alias_list.append(aliasWithRank)
210def setInputVariablesWithMask(maskName='all'):
212 Set aliases for input variables
with ROE mask.
214 variables.variables.addAlias('pMissTag_withMask',
'pMissTag('+maskName+
')')
215 variables.variables.addAlias(
'cosTPTO_withMask',
'cosTPTO('+maskName+
')')
216 variables.variables.addAlias(
'ptTracksRoe_withMask',
'ptTracksRoe('+maskName+
')')
217 variables.variables.addAlias(
'pt2TracksRoe_withMask',
'pt2TracksRoe('+maskName+
')')
218 variables.variables.addAlias(
'ptTracksRoe_withMask',
'ptTracksRoe('+maskName+
')')
221def getFastBDTCategories():
223 Helper function for getting the FastBDT categories.
224 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):
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':
'kaonID'}
348 muId = {
'Belle':
'muIDBelle',
'Belle2':
'muonID'}
349 eId = {
'Belle':
'eIDBelle',
'Belle2':
'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)',
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)',
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":
519 variables.append(
'daughter(1,protonID)')
520 variables.append(
'daughter(0,pionID)')
522 variables.append(
'distance')
524 elif category ==
'MaximumPstar':
525 variables = [
'useCMSFrame(p)',
531 if getBelleOrBelle2() ==
"Belle2":
532 variables.append(
'ImpactXY')
533 variables.append(
'distance')
535 elif category ==
'FSC':
536 variables = [
'useCMSFrame(p)',
538 KId[getBelleOrBelle2()],
539 'FSCVariables(pFastCMS)',
540 'FSCVariables(cosSlowFast)',
541 'FSCVariables(cosTPTOFast)',
542 'FSCVariables(SlowFastHaveOpositeCharges)',
544 elif category ==
'KaonPion':
545 variables = [
'extraInfo(isRightCategory(Kaon))',
546 'HighestProbInCat(pi+:inRoe, isRightCategory(SlowPion))',
547 'KaonPionVariables(cosKaonPion)',
548 'KaonPionVariables(HaveOpositeCharges)',
549 KId[getBelleOrBelle2()]
555def FillParticleLists(maskName='all', categories=None, path=None):
557 Fills the particle Lists for all categories.
560 from vertex
import kFit
561 readyParticleLists = []
563 if categories
is None:
566 trackCut =
'isInRestOfEvent > 0.5 and passesROEMask(' + maskName +
') > 0.5 and p >= 0'
568 for category
in categories:
569 particleList = AvailableCategories[category].particleList
571 if particleList
in readyParticleLists:
575 if particleList ==
'Lambda0:inRoe':
576 if 'pi+:inRoe' not in readyParticleLists:
577 ma.fillParticleList(
'pi+:inRoe', trackCut, path=path)
578 readyParticleLists.append(
'pi+:inRoe')
580 ma.fillParticleList(
'p+:inRoe', trackCut, path=path)
581 ma.reconstructDecay(particleList +
' -> pi-:inRoe p+:inRoe',
'1.00<=M<=1.23',
False, path=path)
582 kFit(particleList, 0.01, path=path)
583 ma.matchMCTruth(particleList, path=path)
584 readyParticleLists.append(particleList)
588 ma.fillParticleList(particleList, trackCut, path=path)
589 readyParticleLists.append(particleList)
592 if getBelleOrBelle2() ==
'Belle':
593 ma.cutAndCopyList(
'K_S0:inRoe',
'K_S0:mdst',
'extraInfo(ksnbStandard) == 1 and isInRestOfEvent == 1', path=path)
595 if 'pi+:inRoe' not in readyParticleLists:
596 ma.fillParticleList(
'pi+:inRoe', trackCut, path=path)
597 ma.reconstructDecay(
'K_S0:inRoe -> pi+:inRoe pi-:inRoe',
'0.40<=M<=0.60',
False, path=path)
598 kFit(
'K_S0:inRoe', 0.01, path=path)
601 if getBelleOrBelle2() ==
'Belle2':
602 default_list_for_lid_BDT = [
'e+:inRoe',
'mu+:inRoe']
603 list_for_lid_BDT = []
605 for particleList
in default_list_for_lid_BDT:
606 if particleList
in readyParticleLists:
607 list_for_lid_BDT.append(particleList)
610 ma.applyChargedPidMVA(particleLists=list_for_lid_BDT, path=path,
612 binaryHypoPDGCodes=(11, 211))
613 ma.applyChargedPidMVA(particleLists=list_for_lid_BDT, path=path,
615 binaryHypoPDGCodes=(13, 211))
616 ma.applyChargedPidMVA(particleLists=list_for_lid_BDT, path=path,
620def eventLevel(mode='Expert', weightFiles='B2JpsiKs_mu', categories=None, path=None):
622 Samples data for training
or tests all categories all categories at event level.
625 from basf2
import create_path
626 from basf2
import register_module
628 B2INFO(
'EVENT LEVEL')
633 identifiersExtraInfosDict = dict()
634 identifiersExtraInfosKaonPion = []
636 if categories
is None:
639 for category
in categories:
640 particleList = AvailableCategories[category].particleList
642 methodPrefixEventLevel =
"FlavorTagger_" + getBelleOrBelle2() +
"_" + weightFiles +
'EventLevel' + category +
'FBDT'
643 identifierEventLevel = methodPrefixEventLevel
644 targetVariable =
'isRightCategory(' + category +
')'
645 extraInfoName = targetVariable
649 if downloadFlag
or useOnlyLocalFlag:
650 identifierEventLevel = filesDirectory +
'/' + methodPrefixEventLevel +
'_1.root'
653 if not os.path.isfile(identifierEventLevel):
654 basf2_mva.download(methodPrefixEventLevel, identifierEventLevel)
655 if not os.path.isfile(identifierEventLevel):
656 B2FATAL(
'Flavor Tagger: Weight file ' + identifierEventLevel +
657 ' was not downloaded from Database. Please check the buildOrRevision name. Stopped')
660 if not os.path.isfile(identifierEventLevel):
661 B2FATAL(
'Flavor Tagger: ' + particleList +
' Eventlevel was not trained. Weight file ' +
662 identifierEventLevel +
' was not found. Stopped')
664 B2INFO(
'flavorTagger: MVAExpert ' + methodPrefixEventLevel +
' ready.')
666 elif mode ==
'Sampler':
668 identifierEventLevel = filesDirectory +
'/' + methodPrefixEventLevel +
'_1.root'
669 if os.path.isfile(identifierEventLevel):
670 B2INFO(
'flavorTagger: MVAExpert ' + methodPrefixEventLevel +
' ready.')
672 if 'KaonPion' in categories:
673 methodPrefixEventLevelKaonPion =
"FlavorTagger_" + getBelleOrBelle2() + \
674 "_" + weightFiles +
'EventLevelKaonPionFBDT'
675 identifierEventLevelKaonPion = filesDirectory +
'/' + methodPrefixEventLevelKaonPion +
'_1.root'
676 if not os.path.isfile(identifierEventLevelKaonPion):
679 if category !=
"SlowPion" and category !=
"Kaon":
682 if mode ==
'Expert' or (mode ==
'Sampler' and os.path.isfile(identifierEventLevel)):
684 B2INFO(
'flavorTagger: Applying MVAExpert ' + methodPrefixEventLevel +
'.')
686 if category ==
'KaonPion':
687 identifiersExtraInfosKaonPion.append((extraInfoName, identifierEventLevel))
688 elif particleList
not in identifiersExtraInfosDict:
689 identifiersExtraInfosDict[particleList] = [(extraInfoName, identifierEventLevel)]
691 identifiersExtraInfosDict[particleList].append((extraInfoName, identifierEventLevel))
696 for particleList
in identifiersExtraInfosDict:
697 eventLevelPath = create_path()
698 SkipEmptyParticleList = register_module(
"SkimFilter")
699 SkipEmptyParticleList.set_name(
'SkimFilter_EventLevel_' + particleList)
700 SkipEmptyParticleList.param(
'particleLists', particleList)
701 SkipEmptyParticleList.if_true(eventLevelPath, basf2.AfterConditionPath.CONTINUE)
702 path.add_module(SkipEmptyParticleList)
704 mvaMultipleExperts = register_module(
'MVAMultipleExperts')
705 mvaMultipleExperts.set_name(
'MVAMultipleExperts_EventLevel_' + particleList)
706 mvaMultipleExperts.param(
'listNames', [particleList])
707 mvaMultipleExperts.param(
'extraInfoNames', [row[0]
for row
in identifiersExtraInfosDict[particleList]])
708 mvaMultipleExperts.param(
'signalFraction', signalFraction)
709 mvaMultipleExperts.param(
'identifiers', [row[1]
for row
in identifiersExtraInfosDict[particleList]])
710 eventLevelPath.add_module(mvaMultipleExperts)
712 if 'KaonPion' in categories
and len(identifiersExtraInfosKaonPion) != 0:
713 eventLevelKaonPionPath = create_path()
714 SkipEmptyParticleList = register_module(
"SkimFilter")
715 SkipEmptyParticleList.set_name(
'SkimFilter_' +
'K+:inRoe')
716 SkipEmptyParticleList.param(
'particleLists',
'K+:inRoe')
717 SkipEmptyParticleList.if_true(eventLevelKaonPionPath, basf2.AfterConditionPath.CONTINUE)
718 path.add_module(SkipEmptyParticleList)
720 mvaExpertKaonPion = register_module(
"MVAExpert")
721 mvaExpertKaonPion.set_name(
'MVAExpert_KaonPion_' +
'K+:inRoe')
722 mvaExpertKaonPion.param(
'listNames', [
'K+:inRoe'])
723 mvaExpertKaonPion.param(
'extraInfoName', identifiersExtraInfosKaonPion[0][0])
724 mvaExpertKaonPion.param(
'signalFraction', signalFraction)
725 mvaExpertKaonPion.param(
'identifier', identifiersExtraInfosKaonPion[0][1])
727 eventLevelKaonPionPath.add_module(mvaExpertKaonPion)
729 if mode ==
'Sampler':
731 for category
in categories:
732 particleList = AvailableCategories[category].particleList
734 methodPrefixEventLevel =
"FlavorTagger_" + getBelleOrBelle2() +
"_" + weightFiles +
'EventLevel' + category +
'FBDT'
735 identifierEventLevel = filesDirectory +
'/' + methodPrefixEventLevel +
'_1.root'
736 targetVariable =
'isRightCategory(' + category +
')'
738 if not os.path.isfile(identifierEventLevel):
740 if category ==
'KaonPion':
741 methodPrefixEventLevelSlowPion =
"FlavorTagger_" + getBelleOrBelle2() + \
742 "_" + weightFiles +
'EventLevelSlowPionFBDT'
743 identifierEventLevelSlowPion = filesDirectory +
'/' + methodPrefixEventLevelSlowPion +
'_1.root'
744 if not os.path.isfile(identifierEventLevelSlowPion):
745 B2INFO(
"Flavor Tagger: event level weight file for the Slow Pion category is absent." +
746 "It is required to sample the training information for the KaonPion category." +
747 "An additional sampling step will be needed after the following training step.")
750 B2INFO(
'flavorTagger: file ' + filesDirectory +
'/' +
751 methodPrefixEventLevel +
"sampled" + fileId +
'.root will be saved.')
753 ma.applyCuts(particleList,
'isRightCategory(mcAssociated) > 0', path)
754 eventLevelpath = create_path()
755 SkipEmptyParticleList = register_module(
"SkimFilter")
756 SkipEmptyParticleList.set_name(
'SkimFilter_EventLevel' + category)
757 SkipEmptyParticleList.param(
'particleLists', particleList)
758 SkipEmptyParticleList.if_true(eventLevelpath, basf2.AfterConditionPath.CONTINUE)
759 path.add_module(SkipEmptyParticleList)
761 ntuple = register_module(
'VariablesToNtuple')
762 ntuple.param(
'fileName', filesDirectory +
'/' + methodPrefixEventLevel +
"sampled" + fileId +
".root")
763 ntuple.param(
'treeName', methodPrefixEventLevel +
"_tree")
764 variablesToBeSaved = getTrainingVariables(category) + [targetVariable,
'ancestorHasWhichFlavor',
765 'isSignal',
'mcPDG',
'mcErrors',
'genMotherPDG',
766 'nMCMatches',
'B0mcErrors']
767 if category !=
'KaonPion' and category !=
'FSC':
768 variablesToBeSaved = variablesToBeSaved + \
769 [
'extraInfo(isRightTrack(' + category +
'))',
770 'hasHighestProbInCat(' + particleList +
', isRightTrack(' + category +
'))']
771 ntuple.param(
'variables', variablesToBeSaved)
772 ntuple.param(
'particleList', particleList)
773 eventLevelpath.add_module(ntuple)
775 if ReadyMethods != len(categories):
781def eventLevelTeacher(weightFiles='B2JpsiKs_mu', categories=None):
783 Trains all categories at event level.
786 B2INFO('EVENT LEVEL TEACHER')
790 if categories
is None:
793 for category
in categories:
794 methodPrefixEventLevel =
"FlavorTagger_" + getBelleOrBelle2() +
"_" + weightFiles +
'EventLevel' + category +
'FBDT'
795 targetVariable =
'isRightCategory(' + category +
')'
796 weightFile = filesDirectory +
'/' + methodPrefixEventLevel +
"_1.root"
798 if os.path.isfile(weightFile):
802 sampledFilesList = glob.glob(filesDirectory +
'/' + methodPrefixEventLevel +
'sampled*.root')
803 if len(sampledFilesList) == 0:
804 B2INFO(
'flavorTagger: eventLevelTeacher did not find any ' + methodPrefixEventLevel +
805 ".root" +
' file. Please run the flavorTagger in "Sampler" mode afterwards.')
808 B2INFO(
'flavorTagger: MVA Teacher training' + methodPrefixEventLevel +
' .')
809 trainingOptionsEventLevel = basf2_mva.GeneralOptions()
810 trainingOptionsEventLevel.m_datafiles = basf2_mva.vector(*sampledFilesList)
811 trainingOptionsEventLevel.m_treename = methodPrefixEventLevel +
"_tree"
812 trainingOptionsEventLevel.m_identifier = weightFile
813 trainingOptionsEventLevel.m_variables = basf2_mva.vector(*getTrainingVariables(category))
814 trainingOptionsEventLevel.m_target_variable = targetVariable
815 trainingOptionsEventLevel.m_max_events = maxEventsNumber
817 basf2_mva.teacher(trainingOptionsEventLevel, getFastBDTCategories())
820 basf2_mva.upload(weightFile, methodPrefixEventLevel)
822 if ReadyMethods != len(categories):
828def combinerLevel(mode='Expert', weightFiles='B2JpsiKs_mu', categories=None,
829 variablesCombinerLevel=None, categoriesCombinationCode=None, path=None):
831 Samples the input data or tests the combiner according to the selected categories.
834 B2INFO('COMBINER LEVEL')
836 if categories
is None:
838 if variablesCombinerLevel
is None:
839 variablesCombinerLevel = []
841 B2INFO(
"Flavor Tagger: Required Combiner for Categories:")
842 for category
in categories:
845 B2INFO(
"Flavor Tagger: which corresponds to a weight file with categories combination code " + categoriesCombinationCode)
847 methodPrefixCombinerLevel =
"FlavorTagger_" + getBelleOrBelle2() +
"_" + weightFiles +
'Combiner' \
848 + categoriesCombinationCode
850 if mode ==
'Sampler':
852 if os.path.isfile(filesDirectory +
'/' + methodPrefixCombinerLevel +
'FBDT' +
'_1.root')
or \
853 os.path.isfile(filesDirectory +
'/' + methodPrefixCombinerLevel +
'FANN' +
'_1.root'):
854 B2FATAL(
'flavorTagger: File' + methodPrefixCombinerLevel +
'FBDT' +
"_1.root" +
' or ' + methodPrefixCombinerLevel +
855 'FANN' +
'_1.root found. Please run the "Expert" mode or delete the file if a new sampling is desired.')
857 B2INFO(
'flavorTagger: Sampling Data on Combiner Level. File' +
858 methodPrefixCombinerLevel +
".root" +
' will be saved')
860 ntuple = basf2.register_module(
'VariablesToNtuple')
861 ntuple.param(
'fileName', filesDirectory +
'/' + methodPrefixCombinerLevel +
"sampled" + fileId +
".root")
862 ntuple.param(
'treeName', methodPrefixCombinerLevel +
'FBDT' +
"_tree")
863 ntuple.param(
'variables', variablesCombinerLevel + [
'qrCombined'])
864 ntuple.param(
'particleList',
"")
865 path.add_module(ntuple)
871 identifierFBDT = methodPrefixCombinerLevel +
'FBDT'
872 if downloadFlag
or useOnlyLocalFlag:
873 identifierFBDT = filesDirectory +
'/' + methodPrefixCombinerLevel +
'FBDT' +
'_1.root'
876 if not os.path.isfile(identifierFBDT):
877 basf2_mva.download(methodPrefixCombinerLevel +
'FBDT', identifierFBDT)
878 if not os.path.isfile(identifierFBDT):
879 B2FATAL(
'Flavor Tagger: Weight file ' + identifierFBDT +
880 ' was not downloaded from Database. Please check the buildOrRevision name. Stopped')
883 if not os.path.isfile(identifierFBDT):
884 B2FATAL(
'flavorTagger: Combinerlevel FastBDT was not trained with this combination of categories.' +
885 ' Weight file ' + identifierFBDT +
' not found. Stopped')
887 B2INFO(
'flavorTagger: Ready to be used with weightFile ' + methodPrefixCombinerLevel +
'FBDT' +
'_1.root')
890 identifierFANN = methodPrefixCombinerLevel +
'FANN'
891 if downloadFlag
or useOnlyLocalFlag:
892 identifierFANN = filesDirectory +
'/' + methodPrefixCombinerLevel +
'FANN' +
'_1.root'
895 if not os.path.isfile(identifierFANN):
896 basf2_mva.download(methodPrefixCombinerLevel +
'FANN', identifierFANN)
897 if not os.path.isfile(identifierFANN):
898 B2FATAL(
'Flavor Tagger: Weight file ' + identifierFANN +
899 ' was not downloaded from Database. Please check the buildOrRevision name. Stopped')
901 if not os.path.isfile(identifierFANN):
902 B2FATAL(
'flavorTagger: Combinerlevel FANNMLP was not trained with this combination of categories. ' +
903 ' Weight file ' + identifierFANN +
' not found. Stopped')
905 B2INFO(
'flavorTagger: Ready to be used with weightFile ' + methodPrefixCombinerLevel +
'FANN' +
'_1.root')
909 if TMVAfbdt
and not FANNmlp:
910 B2INFO(
'flavorTagger: Apply FBDTMethod ' + methodPrefixCombinerLevel +
'FBDT')
911 path.add_module(
'MVAExpert', listNames=[], extraInfoName=
'qrCombined' +
'FBDT', signalFraction=signalFraction,
912 identifier=identifierFBDT)
914 if FANNmlp
and not TMVAfbdt:
915 B2INFO(
'flavorTagger: Apply FANNMethod on combiner level')
916 path.add_module(
'MVAExpert', listNames=[], extraInfoName=
'qrCombined' +
'FANN', signalFraction=signalFraction,
917 identifier=identifierFANN)
919 if FANNmlp
and TMVAfbdt:
920 B2INFO(
'flavorTagger: Apply FANNMethod and FBDTMethod on combiner level')
921 mvaMultipleExperts = basf2.register_module(
'MVAMultipleExperts')
922 mvaMultipleExperts.set_name(
'MVAMultipleExperts_Combiners')
923 mvaMultipleExperts.param(
'listNames', [])
924 mvaMultipleExperts.param(
'extraInfoNames', [
'qrCombined' +
'FBDT',
'qrCombined' +
'FANN'])
925 mvaMultipleExperts.param(
'signalFraction', signalFraction)
926 mvaMultipleExperts.param(
'identifiers', [identifierFBDT, identifierFANN])
927 path.add_module(mvaMultipleExperts)
930def combinerLevelTeacher(weightFiles='B2JpsiKs_mu', variablesCombinerLevel=None,
931 categoriesCombinationCode=None):
933 Trains the combiner according to the selected categories.
936 B2INFO('COMBINER LEVEL TEACHER')
938 if variablesCombinerLevel
is None:
939 variablesCombinerLevel = []
941 methodPrefixCombinerLevel =
"FlavorTagger_" + getBelleOrBelle2() +
"_" + weightFiles +
'Combiner' \
942 + categoriesCombinationCode
944 sampledFilesList = glob.glob(filesDirectory +
'/' + methodPrefixCombinerLevel +
'sampled*.root')
945 if len(sampledFilesList) == 0:
946 B2FATAL(
'FlavorTagger: combinerLevelTeacher did not find any ' +
947 methodPrefixCombinerLevel +
'sampled*.root file. Please run the flavorTagger in "Sampler" mode.')
951 if not os.path.isfile(filesDirectory +
'/' + methodPrefixCombinerLevel +
'FBDT' +
'_1.root'):
953 B2INFO(
'flavorTagger: MVA Teacher training a FastBDT on Combiner Level')
955 trainingOptionsCombinerLevel = basf2_mva.GeneralOptions()
956 trainingOptionsCombinerLevel.m_datafiles = basf2_mva.vector(*sampledFilesList)
957 trainingOptionsCombinerLevel.m_treename = methodPrefixCombinerLevel +
'FBDT' +
"_tree"
958 trainingOptionsCombinerLevel.m_identifier = filesDirectory +
'/' + methodPrefixCombinerLevel +
'FBDT' +
"_1.root"
959 trainingOptionsCombinerLevel.m_variables = basf2_mva.vector(*variablesCombinerLevel)
960 trainingOptionsCombinerLevel.m_target_variable =
'qrCombined'
961 trainingOptionsCombinerLevel.m_max_events = maxEventsNumber
963 basf2_mva.teacher(trainingOptionsCombinerLevel, getFastBDTCombiner())
966 basf2_mva.upload(filesDirectory +
'/' + methodPrefixCombinerLevel +
967 'FBDT' +
"_1.root", methodPrefixCombinerLevel +
'FBDT')
969 elif FANNmlp
and not os.path.isfile(filesDirectory +
'/' + methodPrefixCombinerLevel +
'FANN' +
'_1.root'):
971 B2INFO(
'flavorTagger: Combinerlevel FBDT was already trained with this combination of categories. Weight file ' +
972 methodPrefixCombinerLevel +
'FBDT' +
'_1.root has been found.')
975 B2FATAL(
'flavorTagger: Combinerlevel was already trained with this combination of categories. Weight files ' +
976 methodPrefixCombinerLevel +
'FBDT' +
'_1.root and ' +
977 methodPrefixCombinerLevel +
'FANN' +
'_1.root has been found. Please use the "Expert" mode')
981 if not os.path.isfile(filesDirectory +
'/' + methodPrefixCombinerLevel +
'FANN' +
'_1.root'):
983 B2INFO(
'flavorTagger: MVA Teacher training a FANN MLP on Combiner Level')
985 trainingOptionsCombinerLevel = basf2_mva.GeneralOptions()
986 trainingOptionsCombinerLevel.m_datafiles = basf2_mva.vector(*sampledFilesList)
987 trainingOptionsCombinerLevel.m_treename = methodPrefixCombinerLevel +
'FBDT' +
"_tree"
988 trainingOptionsCombinerLevel.m_identifier = filesDirectory +
'/' + methodPrefixCombinerLevel +
'FANN' +
"_1.root"
989 trainingOptionsCombinerLevel.m_variables = basf2_mva.vector(*variablesCombinerLevel)
990 trainingOptionsCombinerLevel.m_target_variable =
'qrCombined'
991 trainingOptionsCombinerLevel.m_max_events = maxEventsNumber
993 basf2_mva.teacher(trainingOptionsCombinerLevel, getMlpFANNCombiner())
996 basf2_mva.upload(filesDirectory +
'/' + methodPrefixCombinerLevel +
997 'FANN' +
"_1.root", methodPrefixCombinerLevel +
'FANN')
999 elif TMVAfbdt
and not os.path.isfile(filesDirectory +
'/' + methodPrefixCombinerLevel +
'FBDT' +
'_1.root'):
1001 B2INFO(
'flavorTagger: Combinerlevel FBDT was already trained with this combination of categories. Weight file ' +
1002 methodPrefixCombinerLevel +
'FANN' +
'_1.config has been found.')
1005 B2FATAL(
'flavorTagger: Combinerlevel was already trained with this combination of categories. Weight files ' +
1006 methodPrefixCombinerLevel +
'FBDT' +
'_1.root and ' +
1007 methodPrefixCombinerLevel +
'FANN' +
'_1.root has been found. Please use the "Expert" mode')
1010def getEventLevelParticleLists(categories=None):
1012 if categories
is None:
1015 eventLevelParticleLists = []
1017 for category
in categories:
1018 ftCategory = AvailableCategories[category]
1019 event_tuple = (ftCategory.particleList, ftCategory.eventName, ftCategory.variableName)
1021 if event_tuple
not in eventLevelParticleLists:
1022 eventLevelParticleLists.append(event_tuple)
1024 B2FATAL(
'Flavor Tagger: ' + category +
' has been already given')
1026 return eventLevelParticleLists
1032 weightFiles='B2nunubarBGx1',
1033 workingDirectory='.',
1034 combinerMethods=['TMVA-FBDT'],
1037 'IntermediateElectron',
1041 'IntermediateKinLepton',
1049 maskName='FTDefaultMask',
1050 saveCategoriesInfo=True,
1051 useOnlyLocalWeightFiles=False,
1052 downloadFromDatabaseIfNotFound=False,
1053 uploadToDatabaseAfterTraining=False,
1055 prefix='MC15ri_light-2207-bengal_0',
1057 identifierGNN='GFlaT_MC15ri_light_2303_iriomote_0',
1061 Defines the whole flavor tagging process for each selected Rest of Event (ROE) built
in the steering file.
1062 The flavor
is predicted by Multivariate Methods trained
with Variables
and MetaVariables which use
1063 Tracks, ECL-
and KLMClusters
from the corresponding RestOfEvent dataobject.
1064 This module can be used to sample the training information, to train
and/
or to test the flavorTagger.
1066 @param particleLists The ROEs
for flavor tagging are selected
from the given particle lists.
1067 @param mode The available modes are
1068 ``Expert`` (default), ``Sampler``,
and ``Teacher``. In the ``Expert`` mode
1069 Flavor Tagging
is applied to the analysis,. In the ``Sampler`` mode you save
1070 save the variables
for training. In the ``Teacher`` mode the FlavorTagger
is
1071 trained,
for this step you do
not reconstruct any particle
or do any analysis,
1072 you just run the flavorTagger alone.
1073 @param weightFiles Weight files name. Default=
1074 ``B2nunubarBGx1`` (official weight files). If the user self
1075 wants to train the FlavorTagger, the weightfiles name should correspond to the
1076 analysed CP channel
in order to avoid confusions. The default name
1077 ``B2nunubarBGx1`` corresponds to
1078 :math:`B^0_{\\rm sig}\\to \\nu \\overline{\\nu}`.
1079 and ``B2JpsiKs_muBGx1`` to
1080 :math:`B^0_{\\rm sig}\\to J/\\psi (\\to \\mu^+ \\mu^-) K_s (\\to \\pi^+ \\pi^-)`.
1081 BGx1 stays
for events simulated
with background.
1082 @param workingDirectory Path to the directory containing the FlavorTagging/ folder.
1083 @param combinerMethods MVAs
for the combiner: ``TMVA-FBDT` (default).
1084 ``FANN-MLP``
is available only
with ``prefix=
''`` (MC13 weight files).
1085 @param categories Categories used
for flavor tagging. By default all are used.
1086 @param maskName Gets ROE particles
from a specified ROE mask.
1087 ``FTDefaultMask`` (default): tentative mask definition that will be created
1088 automatically. The definition
is as follows:
1090 - Track (pion): thetaInCDCAcceptance
and dr<1
and abs(dz)<3
1091 - ECL-cluster (gamma): thetaInCDCAcceptance
and clusterNHits>1.5
and \
1092 [[clusterReg==1
and E>0.08]
or [clusterReg==2
and E>0.03]
or \
1093 [clusterReg==3
and E>0.06]] \
1094 (Same
as gamma:pi0eff30_May2020
and gamma:pi0eff40_May2020)
1096 ``all``: all ROE particles are used.
1097 Or one can give any mask name defined before calling this function.
1098 @param saveCategoriesInfo Sets to save information of individual categories.
1099 @param useOnlyLocalWeightFiles [Expert] Uses only locally saved weight files.
1100 @param downloadFromDatabaseIfNotFound [Expert] Weight files are downloaded
from
1101 the conditions database
if not available
in workingDirectory.
1102 @param uploadToDatabaseAfterTraining [Expert] For librarians only: uploads weight files to localdb after training.
1103 @param samplerFileId Identifier to parallelize
1104 sampling. Only used
in ``Sampler`` mode. If you are training by yourself
and
1105 want to parallelize the sampling, you can run several sampling scripts
in
1106 parallel. By changing this parameter you will
not overwrite an older sample.
1107 @param prefix Prefix of weight files.
1108 ``MC15ri_light-2207-bengal_0`` (default): Weight files trained
for MC15ri samples.
1109 ``
''``: Weight files trained
for MC13 samples.
1110 @param useGNN Use GNN-based Flavor Tagger
in addition
with FastBDT-based one.
1111 Please specify the weight file
with the option ``identifierGNN``.
1112 [Expert] In the sampler mode, training files
for GNN-based Flavor Tagger
is produced.
1113 @param identifierGNN The name of weight file of the GNN-based Flavor Tagger.
1114 [Expert] Multiple identifiers can be given
with list(str).
1115 @param path Modules are added to this path
1119 if (
not isinstance(particleLists, list)):
1120 particleLists = [particleLists]
1122 if mode !=
'Sampler' and mode !=
'Teacher' and mode !=
'Expert':
1123 B2FATAL(
'flavorTagger: Wrong mode given: The available modes are "Sampler", "Teacher" or "Expert"')
1125 if len(categories) != len(set(categories)):
1126 dup = [cat
for cat
in set(categories)
if categories.count(cat) > 1]
1127 B2WARNING(
'Flavor Tagger: There are duplicate elements in the given categories list. '
1128 <<
'The following duplicate elements are removed; ' <<
', '.join(dup))
1129 categories = list(set(categories))
1131 if len(categories) < 2:
1132 B2FATAL(
'Flavor Tagger: Invalid amount of categories. At least two are needed.')
1134 'Flavor Tagger: Possible categories are "Electron", "IntermediateElectron", "Muon", "IntermediateMuon", '
1135 '"KinLepton", "IntermediateKinLepton", "Kaon", "SlowPion", "FastHadron",'
1136 '"Lambda", "FSC", "MaximumPstar" or "KaonPion" ')
1138 for category
in categories:
1139 if category
not in AvailableCategories:
1140 B2FATAL(
'Flavor Tagger: ' + category +
' is not a valid category name given')
1141 B2FATAL(
'Flavor Tagger: Available categories are "Electron", "IntermediateElectron", '
1142 '"Muon", "IntermediateMuon", "KinLepton", "IntermediateKinLepton", "Kaon", "SlowPion", "FastHadron", '
1143 '"Lambda", "FSC", "MaximumPstar" or "KaonPion" ')
1145 if mode ==
'Expert' and useGNN
and identifierGNN ==
'':
1146 B2FATAL(
'Please specify the name of the weight file with ``identifierGNN``')
1151 basf2.find_file(workingDirectory)
1153 global filesDirectory
1154 filesDirectory = workingDirectory +
'/FlavorTagging/TrainedMethods'
1156 if mode ==
'Sampler' or (mode ==
'Expert' and downloadFromDatabaseIfNotFound):
1157 if not basf2.find_file(workingDirectory +
'/FlavorTagging', silent=
True):
1158 os.mkdir(workingDirectory +
'/FlavorTagging')
1159 os.mkdir(workingDirectory +
'/FlavorTagging/TrainedMethods')
1160 elif not basf2.find_file(workingDirectory +
'/FlavorTagging/TrainedMethods', silent=
True):
1161 os.mkdir(workingDirectory +
'/FlavorTagging/TrainedMethods')
1162 filesDirectory = workingDirectory +
'/FlavorTagging/TrainedMethods'
1164 if len(combinerMethods) < 1
or len(combinerMethods) > 2:
1165 B2FATAL(
'flavorTagger: Invalid list of combinerMethods. The available methods are "TMVA-FBDT" and "FANN-MLP"')
1173 for method
in combinerMethods:
1174 if method ==
'TMVA-FBDT':
1176 elif method ==
'FANN-MLP':
1179 B2FATAL(
'flavorTagger: Invalid list of combinerMethods. The available methods are "TMVA-FBDT" and "FANN-MLP"')
1182 fileId = samplerFileId
1184 global useOnlyLocalFlag
1185 useOnlyLocalFlag = useOnlyLocalWeightFiles
1187 B2INFO(
'*** FLAVOR TAGGING ***')
1189 B2INFO(
' Working directory is: ' + filesDirectory)
1192 setInteractionWithDatabase(downloadFromDatabaseIfNotFound, uploadToDatabaseAfterTraining)
1195 set_FlavorTagger_pid_aliases_legacy()
1197 set_FlavorTagger_pid_aliases()
1199 alias_list_for_GNN = []
1201 alias_list_for_GNN = set_GNNFlavorTagger_aliases(categories)
1203 setInputVariablesWithMask()
1205 weightFiles = prefix +
'_' + weightFiles
1208 trackLevelParticleLists = []
1209 eventLevelParticleLists = []
1210 variablesCombinerLevel = []
1211 categoriesCombination = []
1212 categoriesCombinationCode =
'CatCode'
1213 for category
in categories:
1214 ftCategory = AvailableCategories[category]
1216 track_tuple = (ftCategory.particleList, ftCategory.trackName)
1217 event_tuple = (ftCategory.particleList, ftCategory.eventName, ftCategory.variableName)
1219 if track_tuple
not in trackLevelParticleLists
and category !=
'MaximumPstar':
1220 trackLevelParticleLists.append(track_tuple)
1222 if event_tuple
not in eventLevelParticleLists:
1223 eventLevelParticleLists.append(event_tuple)
1224 variablesCombinerLevel.append(ftCategory.variableName)
1225 categoriesCombination.append(ftCategory.code)
1227 B2FATAL(
'Flavor Tagger: ' + category +
' has been already given')
1229 for code
in sorted(categoriesCombination):
1230 categoriesCombinationCode = categoriesCombinationCode + f
'{int(code):02}'
1233 if maskName ==
'FTDefaultMask':
1236 'thetaInCDCAcceptance and dr<1 and abs(dz)<3',
1237 'thetaInCDCAcceptance and clusterNHits>1.5 and [[E>0.08 and clusterReg==1] or [E>0.03 and clusterReg==2] or \
1238 [E>0.06 and clusterReg==3]]')
1239 for name
in particleLists:
1240 ma.appendROEMasks(list_name=name, mask_tuples=[FTDefaultMask], path=path)
1243 roe_path = basf2.create_path()
1244 deadEndPath = basf2.create_path()
1246 if mode ==
'Sampler':
1248 ma.signalSideParticleListsFilter(
1250 'nROE_Charged(' + maskName +
', 0) > 0 and abs(qrCombined) == 1',
1254 FillParticleLists(maskName, categories, roe_path)
1257 if eventLevel(
'Expert', weightFiles, categories, roe_path):
1259 ma.rankByHighest(
'pi+:inRoe',
'p', numBest=0, allowMultiRank=
False,
1260 outputVariable=
'FT_p_rank', overwriteRank=
True, path=roe_path)
1261 ma.fillParticleListFromDummy(
'vpho:dummy', path=roe_path)
1262 ma.variablesToNtuple(
'vpho:dummy',
1265 filename=f
'{filesDirectory}/FlavorTagger_GNN_sampled{fileId}.root',
1266 signalSideParticleList=particleLists[0],
1270 if eventLevel(mode, weightFiles, categories, roe_path):
1271 combinerLevel(mode, weightFiles, categories, variablesCombinerLevel, categoriesCombinationCode, roe_path)
1273 path.for_each(
'RestOfEvent',
'RestOfEvents', roe_path)
1275 elif mode ==
'Expert':
1278 ma.signalSideParticleListsFilter(particleLists,
'nROE_Charged(' + maskName +
', 0) > 0', roe_path, deadEndPath)
1281 flavorTaggerInfoBuilder = basf2.register_module(
'FlavorTaggerInfoBuilder')
1282 path.add_module(flavorTaggerInfoBuilder)
1284 FillParticleLists(maskName, categories, roe_path)
1286 if eventLevel(mode, weightFiles, categories, roe_path):
1287 combinerLevel(mode, weightFiles, categories, variablesCombinerLevel, categoriesCombinationCode, roe_path)
1289 flavorTaggerInfoFiller = basf2.register_module(
'FlavorTaggerInfoFiller')
1290 flavorTaggerInfoFiller.param(
'trackLevelParticleLists', trackLevelParticleLists)
1291 flavorTaggerInfoFiller.param(
'eventLevelParticleLists', eventLevelParticleLists)
1292 flavorTaggerInfoFiller.param(
'TMVAfbdt', TMVAfbdt)
1293 flavorTaggerInfoFiller.param(
'FANNmlp', FANNmlp)
1294 flavorTaggerInfoFiller.param(
'qpCategories', saveCategoriesInfo)
1295 flavorTaggerInfoFiller.param(
'istrueCategories', saveCategoriesInfo)
1296 flavorTaggerInfoFiller.param(
'targetProb',
False)
1297 flavorTaggerInfoFiller.param(
'trackPointers',
False)
1298 roe_path.add_module(flavorTaggerInfoFiller)
1299 add_default_FlavorTagger_aliases()
1302 ma.rankByHighest(
'pi+:inRoe',
'p', numBest=0, allowMultiRank=
False,
1303 outputVariable=
'FT_p_rank', overwriteRank=
True, path=roe_path)
1304 ma.fillParticleListFromDummy(
'vpho:dummy', path=roe_path)
1306 if isinstance(identifierGNN, str):
1307 roe_path.add_module(
'MVAExpert',
1308 listNames=
'vpho:dummy',
1309 extraInfoName=
'qrGNN_raw',
1310 identifier=identifierGNN)
1312 ma.variableToSignalSideExtraInfo(
'vpho:dummy', {
'extraInfo(qrGNN_raw)*2-1':
'qrGNN'},
1315 elif isinstance(identifierGNN, list):
1316 identifierGNN = list(set(identifierGNN))
1318 extraInfoNames = [f
'qrGNN_{i_id}' for i_id
in identifierGNN]
1319 roe_path.add_module(
'MVAMultipleExperts',
1320 listNames=
'vpho:dummy',
1321 extraInfoNames=extraInfoNames,
1322 identifiers=identifierGNN)
1325 for extraInfoName
in extraInfoNames:
1326 extraInfoDict[f
'extraInfo({extraInfoName})*2-1'] = extraInfoName
1327 variables.variables.addAlias(extraInfoName, f
'extraInfo({extraInfoName})')
1329 ma.variableToSignalSideExtraInfo(
'vpho:dummy', extraInfoDict,
1332 path.for_each(
'RestOfEvent',
'RestOfEvents', roe_path)
1334 elif mode ==
'Teacher':
1335 if eventLevelTeacher(weightFiles, categories):
1336 combinerLevelTeacher(weightFiles, variablesCombinerLevel, categoriesCombinationCode)
1339if __name__ ==
'__main__':
1343 function = globals()[
"flavorTagger"]
1344 signature = inspect.formatargspec(*inspect.getfullargspec(function))
1345 desc_list.append((function.__name__, signature +
'\n' + function.__doc__))
1347 from terminal_utils
import Pager
1348 from basf2.utils import pretty_print_description_list
1349 with Pager(
'Flavor Tagger function accepts the following arguments:'):
1350 pretty_print_description_list(desc_list)