16 from basf2
import B2INFO, B2FATAL, B2WARNING
20 import modularAnalysis
as ma
22 from variables
import utils
29 def getBelleOrBelle2():
31 Gets the global ModeCode.
39 def 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
52 flavor_tagging = [
'FBDT_qrCombined',
'FANN_qrCombined',
'qrMC',
'mcFlavorOfOtherB',
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']
68 def 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 for iCategory
in AvailableCategories:
79 aliasForQp =
'qp' + iCategory
80 aliasForTrueTarget =
'hasTrueTarget' + iCategory
81 aliasForIsRightCategory =
'isRightCategory' + iCategory
82 variables.variables.addAlias(aliasForQp,
'qpCategory(' + iCategory +
')')
83 variables.variables.addAlias(aliasForTrueTarget,
'hasTrueTargets(' + iCategory +
')')
84 variables.variables.addAlias(aliasForIsRightCategory,
'isTrueFTCategory(' + iCategory +
')')
86 utils.add_collection(flavor_tagging,
'flavor_tagging')
89 def set_FlavorTagger_pid_aliases():
91 This function adds the pid aliases needed by the flavor tagger.
93 variables.variables.addAlias(
'eid_TOP',
'pidPairProbabilityExpert(11, 211, TOP)')
94 variables.variables.addAlias(
'eid_ARICH',
'pidPairProbabilityExpert(11, 211, ARICH)')
95 variables.variables.addAlias(
'eid_ECL',
'pidPairProbabilityExpert(11, 211, ECL)')
97 variables.variables.addAlias(
'muid_TOP',
'pidPairProbabilityExpert(13, 211, TOP)')
98 variables.variables.addAlias(
'muid_ARICH',
'pidPairProbabilityExpert(13, 211, ARICH)')
99 variables.variables.addAlias(
'muid_KLM',
'pidPairProbabilityExpert(13, 211, KLM)')
101 variables.variables.addAlias(
'piid_TOP',
'pidPairProbabilityExpert(211, 321, TOP)')
102 variables.variables.addAlias(
'piid_ARICH',
'pidPairProbabilityExpert(211, 321, ARICH)')
104 variables.variables.addAlias(
'Kid_TOP',
'pidPairProbabilityExpert(321, 211, TOP)')
105 variables.variables.addAlias(
'Kid_ARICH',
'pidPairProbabilityExpert(321, 211, ARICH)')
107 if getBelleOrBelle2() ==
"Belle":
108 variables.variables.addAlias(
'eid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(11, 211, CDC, SVD), 0.5)')
109 variables.variables.addAlias(
'muid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(13, 211, CDC, SVD), 0.5)')
110 variables.variables.addAlias(
'piid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(211, 321, CDC, SVD), 0.5)')
111 variables.variables.addAlias(
'pi_vs_edEdxid',
'ifNANgiveX(pidPairProbabilityExpert(211, 11, CDC, SVD), 0.5)')
112 variables.variables.addAlias(
'Kid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(321, 211, CDC, SVD), 0.5)')
114 variables.variables.addAlias(
'eid_dEdx',
'pidPairProbabilityExpert(11, 211, CDC)')
115 variables.variables.addAlias(
'muid_dEdx',
'pidPairProbabilityExpert(13, 211, CDC)')
116 variables.variables.addAlias(
'piid_dEdx',
'pidPairProbabilityExpert(211, 321, CDC)')
117 variables.variables.addAlias(
'pi_vs_edEdxid',
'pidPairProbabilityExpert(211, 11, CDC)')
118 variables.variables.addAlias(
'Kid_dEdx',
'pidPairProbabilityExpert(321, 211, CDC)')
121 def set_FlavorTagger_pid_aliases_legacy():
123 This function adds the pid aliases needed by the flavor tagger trained for MC13.
125 variables.variables.addAlias(
'eid_TOP',
'ifNANgiveX(pidPairProbabilityExpert(11, 211, TOP), 0.5)')
126 variables.variables.addAlias(
'eid_ARICH',
'ifNANgiveX(pidPairProbabilityExpert(11, 211, ARICH), 0.5)')
127 variables.variables.addAlias(
'eid_ECL',
'ifNANgiveX(pidPairProbabilityExpert(11, 211, ECL), 0.5)')
129 variables.variables.addAlias(
'muid_TOP',
'ifNANgiveX(pidPairProbabilityExpert(13, 211, TOP), 0.5)')
130 variables.variables.addAlias(
'muid_ARICH',
'ifNANgiveX(pidPairProbabilityExpert(13, 211, ARICH), 0.5)')
131 variables.variables.addAlias(
'muid_KLM',
'ifNANgiveX(pidPairProbabilityExpert(13, 211, KLM), 0.5)')
133 variables.variables.addAlias(
'piid_TOP',
'ifNANgiveX(pidPairProbabilityExpert(211, 321, TOP), 0.5)')
134 variables.variables.addAlias(
'piid_ARICH',
'ifNANgiveX(pidPairProbabilityExpert(211, 321, ARICH), 0.5)')
136 variables.variables.addAlias(
'Kid_TOP',
'ifNANgiveX(pidPairProbabilityExpert(321, 211, TOP), 0.5)')
137 variables.variables.addAlias(
'Kid_ARICH',
'ifNANgiveX(pidPairProbabilityExpert(321, 211, ARICH), 0.5)')
139 if getBelleOrBelle2() ==
"Belle":
140 variables.variables.addAlias(
'eid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(11, 211, CDC, SVD), 0.5)')
141 variables.variables.addAlias(
'muid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(13, 211, CDC, SVD), 0.5)')
142 variables.variables.addAlias(
'piid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(211, 321, CDC, SVD), 0.5)')
143 variables.variables.addAlias(
'pi_vs_edEdxid',
'ifNANgiveX(pidPairProbabilityExpert(211, 11, CDC, SVD), 0.5)')
144 variables.variables.addAlias(
'Kid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(321, 211, CDC, SVD), 0.5)')
147 variables.variables.addAlias(
'eid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(11, 211, CDC), 0.5)')
148 variables.variables.addAlias(
'muid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(13, 211, CDC), 0.5)')
149 variables.variables.addAlias(
'piid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(211, 321, CDC), 0.5)')
150 variables.variables.addAlias(
'pi_vs_edEdxid',
'ifNANgiveX(pidPairProbabilityExpert(211, 11, CDC), 0.5)')
151 variables.variables.addAlias(
'Kid_dEdx',
'ifNANgiveX(pidPairProbabilityExpert(321, 211, CDC), 0.5)')
154 def setInputVariablesWithMask(maskName='all'):
156 Set aliases for input variables with ROE mask.
158 variables.variables.addAlias(
'pMissTag_withMask',
'pMissTag('+maskName+
')')
159 variables.variables.addAlias(
'cosTPTO_withMask',
'cosTPTO('+maskName+
')')
160 variables.variables.addAlias(
'ptTracksRoe_withMask',
'ptTracksRoe('+maskName+
')')
161 variables.variables.addAlias(
'pt2TracksRoe_withMask',
'pt2TracksRoe('+maskName+
')')
162 variables.variables.addAlias(
'ptTracksRoe_withMask',
'ptTracksRoe('+maskName+
')')
165 def getFastBDTCategories():
167 Helper function for getting the FastBDT categories.
168 It's necessary for removing top-level ROOT imports.
170 fastBDTCategories = basf2_mva.FastBDTOptions()
171 fastBDTCategories.m_nTrees = 500
172 fastBDTCategories.m_nCuts = 8
173 fastBDTCategories.m_nLevels = 3
174 fastBDTCategories.m_shrinkage = 0.10
175 fastBDTCategories.m_randRatio = 0.5
176 return fastBDTCategories
179 def getFastBDTCombiner():
181 Helper function for getting the FastBDT combiner.
182 It's necessary for removing top-level ROOT imports.
184 fastBDTCombiner = basf2_mva.FastBDTOptions()
185 fastBDTCombiner.m_nTrees = 500
186 fastBDTCombiner.m_nCuts = 8
187 fastBDTCombiner.m_nLevels = 3
188 fastBDTCombiner.m_shrinkage = 0.10
189 fastBDTCombiner.m_randRatio = 0.5
190 return fastBDTCombiner
193 def getMlpFANNCombiner():
195 Helper function for getting the MLP FANN combiner.
196 It's necessary for removing top-level ROOT imports.
198 mlpFANNCombiner = basf2_mva.FANNOptions()
199 mlpFANNCombiner.m_max_epochs = 10000
200 mlpFANNCombiner.m_hidden_layers_architecture =
"3*N"
201 mlpFANNCombiner.m_hidden_activiation_function =
"FANN_SIGMOID_SYMMETRIC"
202 mlpFANNCombiner.m_output_activiation_function =
"FANN_SIGMOID_SYMMETRIC"
203 mlpFANNCombiner.m_error_function =
"FANN_ERRORFUNC_LINEAR"
204 mlpFANNCombiner.m_training_method =
"FANN_TRAIN_RPROP"
205 mlpFANNCombiner.m_validation_fraction = 0.5
206 mlpFANNCombiner.m_random_seeds = 10
207 mlpFANNCombiner.m_test_rate = 500
208 mlpFANNCombiner.m_number_of_threads = 8
209 mlpFANNCombiner.m_scale_features =
True
210 mlpFANNCombiner.m_scale_target =
False
212 return mlpFANNCombiner
224 FTCategoryParameters = collections.namedtuple(
'FTCategoryParameters',
225 [
'particleList',
'trackName',
'eventName',
'variableName',
'code'])
229 AvailableCategories = {
231 FTCategoryParameters(
'e+:inRoe',
'Electron',
'Electron',
232 'QpOf(e+:inRoe, isRightCategory(Electron), isRightCategory(Electron))',
234 'IntermediateElectron':
235 FTCategoryParameters(
'e+:inRoe',
'IntermediateElectron',
'IntermediateElectron',
236 'QpOf(e+:inRoe, isRightCategory(IntermediateElectron), isRightCategory(IntermediateElectron))',
239 FTCategoryParameters(
'mu+:inRoe',
'Muon',
'Muon',
240 'QpOf(mu+:inRoe, isRightCategory(Muon), isRightCategory(Muon))',
243 FTCategoryParameters(
'mu+:inRoe',
'IntermediateMuon',
'IntermediateMuon',
244 'QpOf(mu+:inRoe, isRightCategory(IntermediateMuon), isRightCategory(IntermediateMuon))',
247 FTCategoryParameters(
'mu+:inRoe',
'KinLepton',
'KinLepton',
248 'QpOf(mu+:inRoe, isRightCategory(KinLepton), isRightCategory(KinLepton))',
250 'IntermediateKinLepton':
251 FTCategoryParameters(
'mu+:inRoe',
'IntermediateKinLepton',
'IntermediateKinLepton',
252 'QpOf(mu+:inRoe, isRightCategory(IntermediateKinLepton), isRightCategory(IntermediateKinLepton))',
255 FTCategoryParameters(
'K+:inRoe',
'Kaon',
'Kaon',
256 'weightedQpOf(K+:inRoe, isRightCategory(Kaon), isRightCategory(Kaon))',
259 FTCategoryParameters(
'pi+:inRoe',
'SlowPion',
'SlowPion',
260 'QpOf(pi+:inRoe, isRightCategory(SlowPion), isRightCategory(SlowPion))',
263 FTCategoryParameters(
'pi+:inRoe',
'FastHadron',
'FastHadron',
264 'QpOf(pi+:inRoe, isRightCategory(FastHadron), isRightCategory(FastHadron))',
267 FTCategoryParameters(
'Lambda0:inRoe',
'Lambda',
'Lambda',
268 'weightedQpOf(Lambda0:inRoe, isRightCategory(Lambda), isRightCategory(Lambda))',
271 FTCategoryParameters(
'pi+:inRoe',
'SlowPion',
'FSC',
272 'QpOf(pi+:inRoe, isRightCategory(FSC), isRightCategory(SlowPion))',
275 FTCategoryParameters(
'pi+:inRoe',
'MaximumPstar',
'MaximumPstar',
276 'QpOf(pi+:inRoe, isRightCategory(MaximumPstar), isRightCategory(MaximumPstar))',
279 FTCategoryParameters(
'K+:inRoe',
'Kaon',
'KaonPion',
280 'QpOf(K+:inRoe, isRightCategory(KaonPion), isRightCategory(Kaon))',
285 def getTrainingVariables(category=None):
287 Helper function to get training variables.
289 NOTE: This function is not called the Expert mode. It is not necessary to be consistent with variables list of weight files.
292 KId = {
'Belle':
'ifNANgiveX(atcPIDBelle(3,2), 0.5)',
'Belle2':
'kaonID'}
293 muId = {
'Belle':
'muIDBelle',
'Belle2':
'muonID'}
294 eId = {
'Belle':
'eIDBelle',
'Belle2':
'electronID'}
297 if category ==
'Electron' or category ==
'IntermediateElectron':
298 variables = [
'useCMSFrame(p)',
303 eId[getBelleOrBelle2()],
307 'BtagToWBosonVariables(recoilMassSqrd)',
308 'BtagToWBosonVariables(pMissCMS)',
309 'BtagToWBosonVariables(cosThetaMissCMS)',
310 'BtagToWBosonVariables(EW90)',
314 if getBelleOrBelle2() ==
"Belle":
315 variables.append(
'eid_dEdx')
316 variables.append(
'ImpactXY')
317 variables.append(
'distance')
319 elif category ==
'Muon' or category ==
'IntermediateMuon':
320 variables = [
'useCMSFrame(p)',
325 muId[getBelleOrBelle2()],
329 'BtagToWBosonVariables(recoilMassSqrd)',
330 'BtagToWBosonVariables(pMissCMS)',
331 'BtagToWBosonVariables(cosThetaMissCMS)',
332 'BtagToWBosonVariables(EW90)',
335 if getBelleOrBelle2() ==
"Belle":
336 variables.append(
'muid_dEdx')
337 variables.append(
'ImpactXY')
338 variables.append(
'distance')
339 variables.append(
'chiProb')
341 elif category ==
'KinLepton' or category ==
'IntermediateKinLepton':
342 variables = [
'useCMSFrame(p)',
347 muId[getBelleOrBelle2()],
351 eId[getBelleOrBelle2()],
355 'BtagToWBosonVariables(recoilMassSqrd)',
356 'BtagToWBosonVariables(pMissCMS)',
357 'BtagToWBosonVariables(cosThetaMissCMS)',
358 'BtagToWBosonVariables(EW90)',
361 if getBelleOrBelle2() ==
"Belle":
362 variables.append(
'eid_dEdx')
363 variables.append(
'muid_dEdx')
364 variables.append(
'ImpactXY')
365 variables.append(
'distance')
366 variables.append(
'chiProb')
368 elif category ==
'Kaon':
369 variables = [
'useCMSFrame(p)',
374 KId[getBelleOrBelle2()],
378 'NumberOfKShortsInRoe',
380 'BtagToWBosonVariables(recoilMassSqrd)',
381 'BtagToWBosonVariables(pMissCMS)',
382 'BtagToWBosonVariables(cosThetaMissCMS)',
383 'BtagToWBosonVariables(EW90)',
387 if getBelleOrBelle2() ==
"Belle":
388 variables.append(
'ImpactXY')
389 variables.append(
'distance')
391 elif category ==
'SlowPion':
392 variables = [
'useCMSFrame(p)',
401 KId[getBelleOrBelle2()],
405 'NumberOfKShortsInRoe',
407 eId[getBelleOrBelle2()],
408 'BtagToWBosonVariables(recoilMassSqrd)',
409 'BtagToWBosonVariables(EW90)',
410 'BtagToWBosonVariables(cosThetaMissCMS)',
411 'BtagToWBosonVariables(pMissCMS)',
414 if getBelleOrBelle2() ==
"Belle":
415 variables.append(
'piid_dEdx')
416 variables.append(
'ImpactXY')
417 variables.append(
'distance')
418 variables.append(
'chiProb')
420 elif category ==
'FastHadron':
421 variables = [
'useCMSFrame(p)',
431 KId[getBelleOrBelle2()],
435 'NumberOfKShortsInRoe',
437 eId[getBelleOrBelle2()],
438 'BtagToWBosonVariables(recoilMassSqrd)',
439 'BtagToWBosonVariables(EW90)',
440 'BtagToWBosonVariables(cosThetaMissCMS)',
443 if getBelleOrBelle2() ==
"Belle":
444 variables.append(
'BtagToWBosonVariables(pMissCMS)')
445 variables.append(
'ImpactXY')
446 variables.append(
'distance')
447 variables.append(
'chiProb')
449 elif category ==
'Lambda':
450 variables = [
'lambdaFlavor',
451 'NumberOfKShortsInRoe',
453 'cosAngleBetweenMomentumAndVertexVector',
456 'daughter(0,useCMSFrame(p))',
458 'daughter(1,useCMSFrame(p))',
463 if getBelleOrBelle2() ==
"Belle2":
464 variables.append(
'daughter(1,protonID)')
465 variables.append(
'daughter(0,pionID)')
467 variables.append(
'distance')
469 elif category ==
'MaximumPstar':
470 variables = [
'useCMSFrame(p)',
476 if getBelleOrBelle2() ==
"Belle2":
477 variables.append(
'ImpactXY')
478 variables.append(
'distance')
480 elif category ==
'FSC':
481 variables = [
'useCMSFrame(p)',
483 KId[getBelleOrBelle2()],
484 'FSCVariables(pFastCMS)',
485 'FSCVariables(cosSlowFast)',
486 'FSCVariables(cosTPTOFast)',
487 'FSCVariables(SlowFastHaveOpositeCharges)',
489 elif category ==
'KaonPion':
490 variables = [
'extraInfo(isRightCategory(Kaon))',
491 'HighestProbInCat(pi+:inRoe, isRightCategory(SlowPion))',
492 'KaonPionVariables(cosKaonPion)',
493 'KaonPionVariables(HaveOpositeCharges)',
494 KId[getBelleOrBelle2()]
500 def FillParticleLists(maskName='all', categories=None, path=None):
502 Fills the particle Lists for all categories.
505 from vertex
import kFit
506 readyParticleLists = []
508 if categories
is None:
511 trackCut =
'isInRestOfEvent > 0.5 and passesROEMask(' + maskName +
') > 0.5 and p >= 0'
513 for category
in categories:
514 particleList = AvailableCategories[category].particleList
516 if particleList
in readyParticleLists:
520 if particleList ==
'Lambda0:inRoe':
521 if 'pi+:inRoe' not in readyParticleLists:
522 ma.fillParticleList(
'pi+:inRoe', trackCut, path=path)
523 readyParticleLists.append(
'pi+:inRoe')
525 ma.fillParticleList(
'p+:inRoe', trackCut, path=path)
526 ma.reconstructDecay(particleList +
' -> pi-:inRoe p+:inRoe',
'1.00<=M<=1.23',
False, path=path)
527 kFit(particleList, 0.01, path=path)
528 ma.matchMCTruth(particleList, path=path)
529 readyParticleLists.append(particleList)
533 ma.fillParticleList(particleList, trackCut, path=path)
534 readyParticleLists.append(particleList)
537 if getBelleOrBelle2() ==
'Belle':
538 ma.cutAndCopyList(
'K_S0:inRoe',
'K_S0:mdst',
'extraInfo(ksnbStandard) == 1 and isInRestOfEvent == 1', path=path)
540 if 'pi+:inRoe' not in readyParticleLists:
541 ma.fillParticleList(
'pi+:inRoe', trackCut, path=path)
542 ma.reconstructDecay(
'K_S0:inRoe -> pi+:inRoe pi-:inRoe',
'0.40<=M<=0.60',
False, path=path)
543 kFit(
'K_S0:inRoe', 0.01, path=path)
546 if getBelleOrBelle2() ==
'Belle2':
547 default_list_for_lid_BDT = [
'e+:inRoe',
'mu+:inRoe']
548 list_for_lid_BDT = []
550 for particleList
in default_list_for_lid_BDT:
551 if particleList
in readyParticleLists:
552 list_for_lid_BDT.append(particleList)
555 ma.applyChargedPidMVA(particleLists=list_for_lid_BDT, path=path,
557 binaryHypoPDGCodes=(11, 211))
558 ma.applyChargedPidMVA(particleLists=list_for_lid_BDT, path=path,
560 binaryHypoPDGCodes=(13, 211))
561 ma.applyChargedPidMVA(particleLists=list_for_lid_BDT, path=path,
565 def eventLevel(mode='Expert', weightFiles='B2JpsiKs_mu', categories=None, path=None):
567 Samples data for training or tests all categories all categories at event level.
570 from basf2
import create_path
571 from basf2
import register_module
573 B2INFO(
'EVENT LEVEL')
578 identifiersExtraInfosDict = dict()
579 identifiersExtraInfosKaonPion = []
581 if categories
is None:
584 for category
in categories:
585 particleList = AvailableCategories[category].particleList
587 methodPrefixEventLevel =
"FlavorTagger_" + getBelleOrBelle2() +
"_" + weightFiles +
'EventLevel' + category +
'FBDT'
588 identifierEventLevel = methodPrefixEventLevel
589 targetVariable =
'isRightCategory(' + category +
')'
590 extraInfoName = targetVariable
594 if downloadFlag
or useOnlyLocalFlag:
595 identifierEventLevel = filesDirectory +
'/' + methodPrefixEventLevel +
'_1.root'
598 if not os.path.isfile(identifierEventLevel):
599 basf2_mva.download(methodPrefixEventLevel, identifierEventLevel)
600 if not os.path.isfile(identifierEventLevel):
601 B2FATAL(
'Flavor Tagger: Weight file ' + identifierEventLevel +
602 ' was not downloaded from Database. Please check the buildOrRevision name. Stopped')
605 if not os.path.isfile(identifierEventLevel):
606 B2FATAL(
'Flavor Tagger: ' + particleList +
' Eventlevel was not trained. Weight file ' +
607 identifierEventLevel +
' was not found. Stopped')
609 B2INFO(
'flavorTagger: MVAExpert ' + methodPrefixEventLevel +
' ready.')
611 elif mode ==
'Sampler':
613 identifierEventLevel = filesDirectory +
'/' + methodPrefixEventLevel +
'_1.root'
614 if os.path.isfile(identifierEventLevel):
615 B2INFO(
'flavorTagger: MVAExpert ' + methodPrefixEventLevel +
' ready.')
617 if 'KaonPion' in categories:
618 methodPrefixEventLevelKaonPion =
"FlavorTagger_" + getBelleOrBelle2() + \
619 "_" + weightFiles +
'EventLevelKaonPionFBDT'
620 identifierEventLevelKaonPion = filesDirectory +
'/' + methodPrefixEventLevelKaonPion +
'_1.root'
621 if not os.path.isfile(identifierEventLevelKaonPion):
624 if category !=
"SlowPion" and category !=
"Kaon":
627 if mode ==
'Expert' or (mode ==
'Sampler' and os.path.isfile(identifierEventLevel)):
629 B2INFO(
'flavorTagger: Applying MVAExpert ' + methodPrefixEventLevel +
'.')
631 if category ==
'KaonPion':
632 identifiersExtraInfosKaonPion.append((extraInfoName, identifierEventLevel))
633 elif particleList
not in identifiersExtraInfosDict:
634 identifiersExtraInfosDict[particleList] = [(extraInfoName, identifierEventLevel)]
636 identifiersExtraInfosDict[particleList].append((extraInfoName, identifierEventLevel))
641 for particleList
in identifiersExtraInfosDict:
642 eventLevelPath = create_path()
643 SkipEmptyParticleList = register_module(
"SkimFilter")
644 SkipEmptyParticleList.set_name(
'SkimFilter_EventLevel_' + particleList)
645 SkipEmptyParticleList.param(
'particleLists', particleList)
646 SkipEmptyParticleList.if_true(eventLevelPath, basf2.AfterConditionPath.CONTINUE)
647 path.add_module(SkipEmptyParticleList)
649 mvaMultipleExperts = register_module(
'MVAMultipleExperts')
650 mvaMultipleExperts.set_name(
'MVAMultipleExperts_EventLevel_' + particleList)
651 mvaMultipleExperts.param(
'listNames', [particleList])
652 mvaMultipleExperts.param(
'extraInfoNames', [row[0]
for row
in identifiersExtraInfosDict[particleList]])
653 mvaMultipleExperts.param(
'signalFraction', signalFraction)
654 mvaMultipleExperts.param(
'identifiers', [row[1]
for row
in identifiersExtraInfosDict[particleList]])
655 eventLevelPath.add_module(mvaMultipleExperts)
657 if 'KaonPion' in categories
and len(identifiersExtraInfosKaonPion) != 0:
658 eventLevelKaonPionPath = create_path()
659 SkipEmptyParticleList = register_module(
"SkimFilter")
660 SkipEmptyParticleList.set_name(
'SkimFilter_' +
'K+:inRoe')
661 SkipEmptyParticleList.param(
'particleLists',
'K+:inRoe')
662 SkipEmptyParticleList.if_true(eventLevelKaonPionPath, basf2.AfterConditionPath.CONTINUE)
663 path.add_module(SkipEmptyParticleList)
665 mvaExpertKaonPion = register_module(
"MVAExpert")
666 mvaExpertKaonPion.set_name(
'MVAExpert_KaonPion_' +
'K+:inRoe')
667 mvaExpertKaonPion.param(
'listNames', [
'K+:inRoe'])
668 mvaExpertKaonPion.param(
'extraInfoName', identifiersExtraInfosKaonPion[0][0])
669 mvaExpertKaonPion.param(
'signalFraction', signalFraction)
670 mvaExpertKaonPion.param(
'identifier', identifiersExtraInfosKaonPion[0][1])
672 eventLevelKaonPionPath.add_module(mvaExpertKaonPion)
674 if mode ==
'Sampler':
676 for category
in categories:
677 particleList = AvailableCategories[category].particleList
679 methodPrefixEventLevel =
"FlavorTagger_" + getBelleOrBelle2() +
"_" + weightFiles +
'EventLevel' + category +
'FBDT'
680 identifierEventLevel = filesDirectory +
'/' + methodPrefixEventLevel +
'_1.root'
681 targetVariable =
'isRightCategory(' + category +
')'
683 if not os.path.isfile(identifierEventLevel):
685 if category ==
'KaonPion':
686 methodPrefixEventLevelSlowPion =
"FlavorTagger_" + getBelleOrBelle2() + \
687 "_" + weightFiles +
'EventLevelSlowPionFBDT'
688 identifierEventLevelSlowPion = filesDirectory +
'/' + methodPrefixEventLevelSlowPion +
'_1.root'
689 if not os.path.isfile(identifierEventLevelSlowPion):
690 B2INFO(
"Flavor Tagger: event level weight file for the Slow Pion category is absent." +
691 "It is required to sample the training information for the KaonPion category." +
692 "An additional sampling step will be needed after the following training step.")
695 B2INFO(
'flavorTagger: file ' + filesDirectory +
'/' +
696 methodPrefixEventLevel +
"sampled" + fileId +
'.root will be saved.')
698 ma.applyCuts(particleList,
'isRightCategory(mcAssociated) > 0', path)
699 eventLevelpath = create_path()
700 SkipEmptyParticleList = register_module(
"SkimFilter")
701 SkipEmptyParticleList.set_name(
'SkimFilter_EventLevel' + category)
702 SkipEmptyParticleList.param(
'particleLists', particleList)
703 SkipEmptyParticleList.if_true(eventLevelpath, basf2.AfterConditionPath.CONTINUE)
704 path.add_module(SkipEmptyParticleList)
706 ntuple = register_module(
'VariablesToNtuple')
707 ntuple.param(
'fileName', filesDirectory +
'/' + methodPrefixEventLevel +
"sampled" + fileId +
".root")
708 ntuple.param(
'treeName', methodPrefixEventLevel +
"_tree")
709 variablesToBeSaved = getTrainingVariables(category) + [targetVariable,
'ancestorHasWhichFlavor',
710 'isSignal',
'mcPDG',
'mcErrors',
'genMotherPDG',
711 'nMCMatches',
'B0mcErrors']
712 if category !=
'KaonPion' and category !=
'FSC':
713 variablesToBeSaved = variablesToBeSaved + \
714 [
'extraInfo(isRightTrack(' + category +
'))',
715 'hasHighestProbInCat(' + particleList +
', isRightTrack(' + category +
'))']
716 ntuple.param(
'variables', variablesToBeSaved)
717 ntuple.param(
'particleList', particleList)
718 eventLevelpath.add_module(ntuple)
720 if ReadyMethods != len(categories):
726 def eventLevelTeacher(weightFiles='B2JpsiKs_mu', categories=None):
728 Trains all categories at event level.
731 B2INFO(
'EVENT LEVEL TEACHER')
735 if categories
is None:
738 for category
in categories:
739 methodPrefixEventLevel =
"FlavorTagger_" + getBelleOrBelle2() +
"_" + weightFiles +
'EventLevel' + category +
'FBDT'
740 targetVariable =
'isRightCategory(' + category +
')'
741 weightFile = filesDirectory +
'/' + methodPrefixEventLevel +
"_1.root"
743 if os.path.isfile(weightFile):
747 sampledFilesList = glob.glob(filesDirectory +
'/' + methodPrefixEventLevel +
'sampled*.root')
748 if len(sampledFilesList) == 0:
749 B2INFO(
'flavorTagger: eventLevelTeacher did not find any ' + methodPrefixEventLevel +
750 ".root" +
' file. Please run the flavorTagger in "Sampler" mode afterwards.')
753 B2INFO(
'flavorTagger: MVA Teacher training' + methodPrefixEventLevel +
' .')
754 trainingOptionsEventLevel = basf2_mva.GeneralOptions()
755 trainingOptionsEventLevel.m_datafiles = basf2_mva.vector(*sampledFilesList)
756 trainingOptionsEventLevel.m_treename = methodPrefixEventLevel +
"_tree"
757 trainingOptionsEventLevel.m_identifier = weightFile
758 trainingOptionsEventLevel.m_variables = basf2_mva.vector(*getTrainingVariables(category))
759 trainingOptionsEventLevel.m_target_variable = targetVariable
760 trainingOptionsEventLevel.m_max_events = maxEventsNumber
762 basf2_mva.teacher(trainingOptionsEventLevel, getFastBDTCategories())
765 basf2_mva.upload(weightFile, methodPrefixEventLevel)
767 if ReadyMethods != len(categories):
773 def combinerLevel(mode='Expert', weightFiles='B2JpsiKs_mu', categories=None,
774 variablesCombinerLevel=None, categoriesCombinationCode=None, path=None):
776 Samples the input data or tests the combiner according to the selected categories.
779 B2INFO(
'COMBINER LEVEL')
781 if categories
is None:
783 if variablesCombinerLevel
is None:
784 variablesCombinerLevel = []
786 B2INFO(
"Flavor Tagger: Required Combiner for Categories:")
787 for category
in categories:
790 B2INFO(
"Flavor Tagger: which corresponds to a weight file with categories combination code " + categoriesCombinationCode)
792 methodPrefixCombinerLevel =
"FlavorTagger_" + getBelleOrBelle2() +
"_" + weightFiles +
'Combiner' \
793 + categoriesCombinationCode
795 if mode ==
'Sampler':
797 if os.path.isfile(filesDirectory +
'/' + methodPrefixCombinerLevel +
'FBDT' +
'_1.root')
or \
798 os.path.isfile(filesDirectory +
'/' + methodPrefixCombinerLevel +
'FANN' +
'_1.root'):
799 B2FATAL(
'flavorTagger: File' + methodPrefixCombinerLevel +
'FBDT' +
"_1.root" +
' or ' + methodPrefixCombinerLevel +
800 'FANN' +
'_1.root found. Please run the "Expert" mode or delete the file if a new sampling is desired.')
802 B2INFO(
'flavorTagger: Sampling Data on Combiner Level. File' +
803 methodPrefixCombinerLevel +
".root" +
' will be saved')
805 ntuple = basf2.register_module(
'VariablesToNtuple')
806 ntuple.param(
'fileName', filesDirectory +
'/' + methodPrefixCombinerLevel +
"sampled" + fileId +
".root")
807 ntuple.param(
'treeName', methodPrefixCombinerLevel +
'FBDT' +
"_tree")
808 ntuple.param(
'variables', variablesCombinerLevel + [
'qrCombined'])
809 ntuple.param(
'particleList',
"")
810 path.add_module(ntuple)
816 identifierFBDT = methodPrefixCombinerLevel +
'FBDT'
817 if downloadFlag
or useOnlyLocalFlag:
818 identifierFBDT = filesDirectory +
'/' + methodPrefixCombinerLevel +
'FBDT' +
'_1.root'
821 if not os.path.isfile(identifierFBDT):
822 basf2_mva.download(methodPrefixCombinerLevel +
'FBDT', identifierFBDT)
823 if not os.path.isfile(identifierFBDT):
824 B2FATAL(
'Flavor Tagger: Weight file ' + identifierFBDT +
825 ' was not downloaded from Database. Please check the buildOrRevision name. Stopped')
828 if not os.path.isfile(identifierFBDT):
829 B2FATAL(
'flavorTagger: Combinerlevel FastBDT was not trained with this combination of categories.' +
830 ' Weight file ' + identifierFBDT +
' not found. Stopped')
832 B2INFO(
'flavorTagger: Ready to be used with weightFile ' + methodPrefixCombinerLevel +
'FBDT' +
'_1.root')
835 identifierFANN = methodPrefixCombinerLevel +
'FANN'
836 if downloadFlag
or useOnlyLocalFlag:
837 identifierFANN = filesDirectory +
'/' + methodPrefixCombinerLevel +
'FANN' +
'_1.root'
840 if not os.path.isfile(identifierFANN):
841 basf2_mva.download(methodPrefixCombinerLevel +
'FANN', identifierFANN)
842 if not os.path.isfile(identifierFANN):
843 B2FATAL(
'Flavor Tagger: Weight file ' + identifierFANN +
844 ' was not downloaded from Database. Please check the buildOrRevision name. Stopped')
846 if not os.path.isfile(identifierFANN):
847 B2FATAL(
'flavorTagger: Combinerlevel FANNMLP was not trained with this combination of categories. ' +
848 ' Weight file ' + identifierFANN +
' not found. Stopped')
850 B2INFO(
'flavorTagger: Ready to be used with weightFile ' + methodPrefixCombinerLevel +
'FANN' +
'_1.root')
854 if TMVAfbdt
and not FANNmlp:
855 B2INFO(
'flavorTagger: Apply FBDTMethod ' + methodPrefixCombinerLevel +
'FBDT')
856 path.add_module(
'MVAExpert', listNames=[], extraInfoName=
'qrCombined' +
'FBDT', signalFraction=signalFraction,
857 identifier=identifierFBDT)
859 if FANNmlp
and not TMVAfbdt:
860 B2INFO(
'flavorTagger: Apply FANNMethod on combiner level')
861 path.add_module(
'MVAExpert', listNames=[], extraInfoName=
'qrCombined' +
'FANN', signalFraction=signalFraction,
862 identifier=identifierFANN)
864 if FANNmlp
and TMVAfbdt:
865 B2INFO(
'flavorTagger: Apply FANNMethod and FBDTMethod on combiner level')
866 mvaMultipleExperts = basf2.register_module(
'MVAMultipleExperts')
867 mvaMultipleExperts.set_name(
'MVAMultipleExperts_Combiners')
868 mvaMultipleExperts.param(
'listNames', [])
869 mvaMultipleExperts.param(
'extraInfoNames', [
'qrCombined' +
'FBDT',
'qrCombined' +
'FANN'])
870 mvaMultipleExperts.param(
'signalFraction', signalFraction)
871 mvaMultipleExperts.param(
'identifiers', [identifierFBDT, identifierFANN])
872 path.add_module(mvaMultipleExperts)
875 def combinerLevelTeacher(weightFiles='B2JpsiKs_mu', variablesCombinerLevel=None,
876 categoriesCombinationCode=None):
878 Trains the combiner according to the selected categories.
881 B2INFO(
'COMBINER LEVEL TEACHER')
883 if variablesCombinerLevel
is None:
884 variablesCombinerLevel = []
886 methodPrefixCombinerLevel =
"FlavorTagger_" + getBelleOrBelle2() +
"_" + weightFiles +
'Combiner' \
887 + categoriesCombinationCode
889 sampledFilesList = glob.glob(filesDirectory +
'/' + methodPrefixCombinerLevel +
'sampled*.root')
890 if len(sampledFilesList) == 0:
891 B2FATAL(
'FlavorTagger: combinerLevelTeacher did not find any ' +
892 methodPrefixCombinerLevel +
'sampled*.root file. Please run the flavorTagger in "Sampler" mode.')
896 if not os.path.isfile(filesDirectory +
'/' + methodPrefixCombinerLevel +
'FBDT' +
'_1.root'):
898 B2INFO(
'flavorTagger: MVA Teacher training a FastBDT on Combiner Level')
900 trainingOptionsCombinerLevel = basf2_mva.GeneralOptions()
901 trainingOptionsCombinerLevel.m_datafiles = basf2_mva.vector(*sampledFilesList)
902 trainingOptionsCombinerLevel.m_treename = methodPrefixCombinerLevel +
'FBDT' +
"_tree"
903 trainingOptionsCombinerLevel.m_identifier = filesDirectory +
'/' + methodPrefixCombinerLevel +
'FBDT' +
"_1.root"
904 trainingOptionsCombinerLevel.m_variables = basf2_mva.vector(*variablesCombinerLevel)
905 trainingOptionsCombinerLevel.m_target_variable =
'qrCombined'
906 trainingOptionsCombinerLevel.m_max_events = maxEventsNumber
908 basf2_mva.teacher(trainingOptionsCombinerLevel, getFastBDTCombiner())
911 basf2_mva.upload(filesDirectory +
'/' + methodPrefixCombinerLevel +
912 'FBDT' +
"_1.root", methodPrefixCombinerLevel +
'FBDT')
914 elif FANNmlp
and not os.path.isfile(filesDirectory +
'/' + methodPrefixCombinerLevel +
'FANN' +
'_1.root'):
916 B2INFO(
'flavorTagger: Combinerlevel FBDT was already trained with this combination of categories. Weight file ' +
917 methodPrefixCombinerLevel +
'FBDT' +
'_1.root has been found.')
920 B2FATAL(
'flavorTagger: Combinerlevel was already trained with this combination of categories. Weight files ' +
921 methodPrefixCombinerLevel +
'FBDT' +
'_1.root and ' +
922 methodPrefixCombinerLevel +
'FANN' +
'_1.root has been found. Please use the "Expert" mode')
926 if not os.path.isfile(filesDirectory +
'/' + methodPrefixCombinerLevel +
'FANN' +
'_1.root'):
928 B2INFO(
'flavorTagger: MVA Teacher training a FANN MLP on Combiner Level')
930 trainingOptionsCombinerLevel = basf2_mva.GeneralOptions()
931 trainingOptionsCombinerLevel.m_datafiles = basf2_mva.vector(*sampledFilesList)
932 trainingOptionsCombinerLevel.m_treename = methodPrefixCombinerLevel +
'FBDT' +
"_tree"
933 trainingOptionsCombinerLevel.m_identifier = filesDirectory +
'/' + methodPrefixCombinerLevel +
'FANN' +
"_1.root"
934 trainingOptionsCombinerLevel.m_variables = basf2_mva.vector(*variablesCombinerLevel)
935 trainingOptionsCombinerLevel.m_target_variable =
'qrCombined'
936 trainingOptionsCombinerLevel.m_max_events = maxEventsNumber
938 basf2_mva.teacher(trainingOptionsCombinerLevel, getMlpFANNCombiner())
941 basf2_mva.upload(filesDirectory +
'/' + methodPrefixCombinerLevel +
942 'FANN' +
"_1.root", methodPrefixCombinerLevel +
'FANN')
944 elif TMVAfbdt
and not os.path.isfile(filesDirectory +
'/' + methodPrefixCombinerLevel +
'FBDT' +
'_1.root'):
946 B2INFO(
'flavorTagger: Combinerlevel FBDT was already trained with this combination of categories. Weight file ' +
947 methodPrefixCombinerLevel +
'FANN' +
'_1.config has been found.')
950 B2FATAL(
'flavorTagger: Combinerlevel was already trained with this combination of categories. Weight files ' +
951 methodPrefixCombinerLevel +
'FBDT' +
'_1.root and ' +
952 methodPrefixCombinerLevel +
'FANN' +
'_1.root has been found. Please use the "Expert" mode')
955 def getEventLevelParticleLists(categories=None):
957 if categories
is None:
960 eventLevelParticleLists = []
962 for category
in categories:
963 ftCategory = AvailableCategories[category]
964 event_tuple = (ftCategory.particleList, ftCategory.eventName, ftCategory.variableName)
966 if event_tuple
not in eventLevelParticleLists:
967 eventLevelParticleLists.append(event_tuple)
969 B2FATAL(
'Flavor Tagger: ' + category +
' has been already given')
971 return eventLevelParticleLists
977 weightFiles='B2nunubarBGx1',
978 workingDirectory='.',
979 combinerMethods=['TMVA-FBDT'],
982 'IntermediateElectron',
986 'IntermediateKinLepton',
994 maskName='FTDefaultMask',
995 saveCategoriesInfo=True,
996 useOnlyLocalWeightFiles=False,
997 downloadFromDatabaseIfNotFound=False,
998 uploadToDatabaseAfterTraining=False,
1000 prefix='MC15ri_light-2207-bengal_0',
1004 Defines the whole flavor tagging process for each selected Rest of Event (ROE) built in the steering file.
1005 The flavor is predicted by Multivariate Methods trained with Variables and MetaVariables which use
1006 Tracks, ECL- and KLMClusters from the corresponding RestOfEvent dataobject.
1007 This module can be used to sample the training information, to train and/or to test the flavorTagger.
1009 @param particleLists The ROEs for flavor tagging are selected from the given particle lists.
1010 @param mode The available modes are
1011 ``Expert`` (default), ``Sampler``, and ``Teacher``. In the ``Expert`` mode
1012 Flavor Tagging is applied to the analysis,. In the ``Sampler`` mode you save
1013 save the variables for training. In the ``Teacher`` mode the FlavorTagger is
1014 trained, for this step you do not reconstruct any particle or do any analysis,
1015 you just run the flavorTagger alone.
1016 @param weightFiles Weight files name. Default=
1017 ``B2nunubarBGx1`` (official weight files). If the user self
1018 wants to train the FlavorTagger, the weightfiles name should correspond to the
1019 analysed CP channel in order to avoid confusions. The default name
1020 ``B2nunubarBGx1`` corresponds to
1021 :math:`B^0_{\\rm sig}\\to \\nu \\overline{\\nu}`.
1022 and ``B2JpsiKs_muBGx1`` to
1023 :math:`B^0_{\\rm sig}\\to J/\\psi (\\to \\mu^+ \\mu^-) K_s (\\to \\pi^+ \\pi^-)`.
1024 BGx1 stays for events simulated with background.
1025 @param workingDirectory Path to the directory containing the FlavorTagging/ folder.
1026 @param combinerMethods MVAs for the combiner: ``TMVA-FBDT` (default).
1027 ``FANN-MLP`` is available only with ``prefix=''`` (MC13 weight files).
1028 @param categories Categories used for flavor tagging. By default all are used.
1029 @param maskName Gets ROE particles from a specified ROE mask.
1030 ``FTDefaultMask`` (default): tentative mask definition that will be created
1031 automatically. The definition is as follows:
1033 - Track (pion): thetaInCDCAcceptance and dr<1 and abs(dz)<3
1034 - ECL-cluster (gamma): thetaInCDCAcceptance and clusterNHits>1.5 and \
1035 [[clusterReg==1 and E>0.08] or [clusterReg==2 and E>0.03] or \
1036 [clusterReg==3 and E>0.06]] \
1037 (Same as gamma:pi0eff30_May2020 and gamma:pi0eff40_May2020)
1039 ``all``: all ROE particles are used.
1040 Or one can give any mask name defined before calling this function.
1041 @param saveCategoriesInfo Sets to save information of individual categories.
1042 @param useOnlyLocalWeightFiles [Expert] Uses only locally saved weight files.
1043 @param downloadFromDatabaseIfNotFound [Expert] Weight files are downloaded from
1044 the conditions database if not available in workingDirectory.
1045 @param uploadToDatabaseAfterTraining [Expert] For librarians only: uploads weight files to localdb after training.
1046 @param samplerFileId Identifier to paralellize
1047 sampling. Only used in ``Sampler`` mode. If you are training by yourself and
1048 want to parallelize the sampling, you can run several sampling scripts in
1049 parallel. By changing this parameter you will not overwrite an older sample.
1050 @param prefix Prefix of weight files.
1051 ``MC15ri_light-2207-bengal_0`` (default): Weight files trained for MC15ri samples.
1052 ``''``: Weight files trained for MC13 samples.
1053 @param path Modules are added to this path
1057 if (
not isinstance(particleLists, list)):
1058 particleLists = [particleLists]
1060 if mode !=
'Sampler' and mode !=
'Teacher' and mode !=
'Expert':
1061 B2FATAL(
'flavorTagger: Wrong mode given: The available modes are "Sampler", "Teacher" or "Expert"')
1063 if len(categories) != len(set(categories)):
1064 dup = [cat
for cat
in set(categories)
if categories.count(cat) > 1]
1065 B2WARNING(
'Flavor Tagger: There are duplicate elements in the given categories list. '
1066 <<
'The following duplicate elements are removed; ' <<
', '.join(dup))
1067 categories = list(set(categories))
1069 if len(categories) < 2:
1070 B2FATAL(
'Flavor Tagger: Invalid amount of categories. At least two are needed.')
1072 'Flavor Tagger: Possible categories are "Electron", "IntermediateElectron", "Muon", "IntermediateMuon", '
1073 '"KinLepton", "IntermediateKinLepton", "Kaon", "SlowPion", "FastHadron",'
1074 '"Lambda", "FSC", "MaximumPstar" or "KaonPion" ')
1076 for category
in categories:
1077 if category
not in AvailableCategories:
1078 B2FATAL(
'Flavor Tagger: ' + category +
' is not a valid category name given')
1079 B2FATAL(
'Flavor Tagger: Available categories are "Electron", "IntermediateElectron", '
1080 '"Muon", "IntermediateMuon", "KinLepton", "IntermediateKinLepton", "Kaon", "SlowPion", "FastHadron", '
1081 '"Lambda", "FSC", "MaximumPstar" or "KaonPion" ')
1086 basf2.find_file(workingDirectory)
1088 global filesDirectory
1089 filesDirectory = workingDirectory +
'/FlavorTagging/TrainedMethods'
1091 if mode ==
'Sampler' or (mode ==
'Expert' and downloadFromDatabaseIfNotFound):
1092 if not basf2.find_file(workingDirectory +
'/FlavorTagging', silent=
True):
1093 os.mkdir(workingDirectory +
'/FlavorTagging')
1094 os.mkdir(workingDirectory +
'/FlavorTagging/TrainedMethods')
1095 elif not basf2.find_file(workingDirectory +
'/FlavorTagging/TrainedMethods', silent=
True):
1096 os.mkdir(workingDirectory +
'/FlavorTagging/TrainedMethods')
1097 filesDirectory = workingDirectory +
'/FlavorTagging/TrainedMethods'
1099 if len(combinerMethods) < 1
or len(combinerMethods) > 2:
1100 B2FATAL(
'flavorTagger: Invalid list of combinerMethods. The available methods are "TMVA-FBDT" and "FANN-MLP"')
1108 for method
in combinerMethods:
1109 if method ==
'TMVA-FBDT':
1111 elif method ==
'FANN-MLP':
1114 B2FATAL(
'flavorTagger: Invalid list of combinerMethods. The available methods are "TMVA-FBDT" and "FANN-MLP"')
1117 fileId = samplerFileId
1119 global useOnlyLocalFlag
1120 useOnlyLocalFlag = useOnlyLocalWeightFiles
1122 B2INFO(
'*** FLAVOR TAGGING ***')
1124 B2INFO(
' Working directory is: ' + filesDirectory)
1127 setInteractionWithDatabase(downloadFromDatabaseIfNotFound, uploadToDatabaseAfterTraining)
1130 set_FlavorTagger_pid_aliases_legacy()
1132 set_FlavorTagger_pid_aliases()
1134 setInputVariablesWithMask()
1136 weightFiles = prefix +
'_' + weightFiles
1139 trackLevelParticleLists = []
1140 eventLevelParticleLists = []
1141 variablesCombinerLevel = []
1142 categoriesCombination = []
1143 categoriesCombinationCode =
'CatCode'
1144 for category
in categories:
1145 ftCategory = AvailableCategories[category]
1147 track_tuple = (ftCategory.particleList, ftCategory.trackName)
1148 event_tuple = (ftCategory.particleList, ftCategory.eventName, ftCategory.variableName)
1150 if track_tuple
not in trackLevelParticleLists
and category !=
'MaximumPstar':
1151 trackLevelParticleLists.append(track_tuple)
1153 if event_tuple
not in eventLevelParticleLists:
1154 eventLevelParticleLists.append(event_tuple)
1155 variablesCombinerLevel.append(ftCategory.variableName)
1156 categoriesCombination.append(ftCategory.code)
1158 B2FATAL(
'Flavor Tagger: ' + category +
' has been already given')
1160 for code
in sorted(categoriesCombination):
1161 categoriesCombinationCode = categoriesCombinationCode +
'%02d' % code
1164 if maskName ==
'FTDefaultMask':
1167 'thetaInCDCAcceptance and dr<1 and abs(dz)<3',
1168 'thetaInCDCAcceptance and clusterNHits>1.5 and [[E>0.08 and clusterReg==1] or [E>0.03 and clusterReg==2] or \
1169 [E>0.06 and clusterReg==3]]')
1170 for name
in particleLists:
1171 ma.appendROEMasks(list_name=name, mask_tuples=[FTDefaultMask], path=path)
1174 roe_path = basf2.create_path()
1175 deadEndPath = basf2.create_path()
1177 if mode ==
'Sampler':
1179 ma.signalSideParticleListsFilter(
1181 'nROE_Charged(' + maskName +
', 0) > 0 and abs(qrCombined) == 1',
1185 FillParticleLists(maskName, categories, roe_path)
1187 if eventLevel(mode, weightFiles, categories, roe_path):
1188 combinerLevel(mode, weightFiles, categories, variablesCombinerLevel, categoriesCombinationCode, roe_path)
1190 path.for_each(
'RestOfEvent',
'RestOfEvents', roe_path)
1192 elif mode ==
'Expert':
1195 ma.signalSideParticleListsFilter(particleLists,
'', roe_path, deadEndPath)
1196 ma.signalSideParticleListsFilter(particleLists,
'nROE_Charged(' + maskName +
', 0) > 0', roe_path, deadEndPath)
1199 flavorTaggerInfoBuilder = basf2.register_module(
'FlavorTaggerInfoBuilder')
1200 path.add_module(flavorTaggerInfoBuilder)
1202 FillParticleLists(maskName, categories, roe_path)
1204 if eventLevel(mode, weightFiles, categories, roe_path):
1205 combinerLevel(mode, weightFiles, categories, variablesCombinerLevel, categoriesCombinationCode, roe_path)
1207 flavorTaggerInfoFiller = basf2.register_module(
'FlavorTaggerInfoFiller')
1208 flavorTaggerInfoFiller.param(
'trackLevelParticleLists', trackLevelParticleLists)
1209 flavorTaggerInfoFiller.param(
'eventLevelParticleLists', eventLevelParticleLists)
1210 flavorTaggerInfoFiller.param(
'TMVAfbdt', TMVAfbdt)
1211 flavorTaggerInfoFiller.param(
'FANNmlp', FANNmlp)
1212 flavorTaggerInfoFiller.param(
'qpCategories', saveCategoriesInfo)
1213 flavorTaggerInfoFiller.param(
'istrueCategories', saveCategoriesInfo)
1214 flavorTaggerInfoFiller.param(
'targetProb',
False)
1215 flavorTaggerInfoFiller.param(
'trackPointers',
False)
1216 roe_path.add_module(flavorTaggerInfoFiller)
1217 add_default_FlavorTagger_aliases()
1219 path.for_each(
'RestOfEvent',
'RestOfEvents', roe_path)
1221 elif mode ==
'Teacher':
1222 if eventLevelTeacher(weightFiles, categories):
1223 combinerLevelTeacher(weightFiles, variablesCombinerLevel, categoriesCombinationCode)
1226 if __name__ ==
'__main__':
1230 function = globals()[
"flavorTagger"]
1231 signature = inspect.formatargspec(*inspect.getfullargspec(function))
1232 desc_list.append((function.__name__, signature +
'\n' + function.__doc__))
1234 from terminal_utils
import Pager
1235 from basf2.utils import pretty_print_description_list
1236 with Pager(
'Flavor Tagger function accepts the following arguments:'):
1237 pretty_print_description_list(desc_list)