25 import modularAnalysis
as ma
26 import flavorTagger
as ft
27 from dft
import DeepFlavorTagger
31 from ROOT
import Belle2
37 def getCommandLineOptions():
38 """ Parses the command line options for the CPV validation and returns the corresponding arguments. """
40 parser = argparse.ArgumentParser(description=
'Script for the validation of CPV tools:\
41 it defines the procedure to sample the training set, train and test the flavor tagger\
42 as well as to reconstruct the vertices of B0-> J/psi K_S0 and of the tag-side B0\
43 using the tagV module.\n\
44 Usage: basf2 -i inputMDST.root flavorTaggerVertexingValidation.py -- -m Sampler -dc JPsiKs')
46 parser.add_argument(
'-bob2',
'--belleOrBelle2Flag', dest=
'belleOrBelle2Flag',
47 type=str, default=
'Belle2', choices=[
'Belle',
'Belle2'],
48 help=
'Choose Belle for converted Belle data or MC, otherwise choose Belle2.')
49 parser.add_argument(
'-m',
'--mode', dest=
'mode', type=str, required=
True,
50 choices=[
'Sampler',
'Teacher',
'Expert'],
51 help=
'Working mode of the flavor tagger. Choose Sampler, Teacher or Expert.')
52 parser.add_argument(
'-trc',
'--decayChannelTrainedOn', dest=
'decayChannelTrainedOn',
53 type=str, default=
'nunubar',
54 help=
'Decay channel of the weight files. Official samples available are JPsiKs or nunubar.')
55 parser.add_argument(
'-dc',
'--decayChannel', dest=
'decayChannel', type=str, required=
True,
56 choices=[
'JPsiKs',
'nunubar'], help=
'Decay channel that will be reconstructed. Choose JPsiKs or nunubar.')
57 parser.add_argument(
'-mct',
'--mcType', dest=
'mcType', type=str, default=
'BGx1',
58 choices=[
'BGx0',
'BGx1'], help=
'Type of files. Choose BGx0 for background free Belle II MC. \n' +
59 'Otherwise choose BGx1 for BelleII MC with bkg. or for converted Belle data or MC.')
60 parser.add_argument(
'-fn',
'--fileNumber', dest=
'fileNumber', type=str, default=
'',
61 help=
'A file number (when sampling in parallel).')
62 parser.add_argument(
'-wd',
'--workingDirectory', dest=
'workingDirectory', type=str, default=
'.',
63 help=
'Path where the training samples and the weight files are saved.')
64 parser.add_argument(
'-sd',
'--savingDirectory', dest=
'savingDirectory', type=str, default=
'.',
65 help=
'Path where the analyzed output files are saved.')
66 parser.add_argument(
'-dv',
'--doVertex', dest=
'doVertex', type=bool, default=
False,
67 help=
'Reconstruct B vertices True or False')
68 parser.add_argument(
'-bd',
'--belleData', dest=
'belleData', type=str, default=
'',
69 choices=[
'',
'BelleDataConv'], help=
'Choose BelleDataConv only for Belle Data in Expert mode.')
70 args = parser.parse_args()
72 if args.belleData ==
"BelleDataConv":
73 if args.belleOrBelle2Flag !=
"Belle":
74 B2FATAL(
"BelleDataConv only for Belle Data.")
75 if args.mode !=
"Expert":
76 B2FATAL(
"BelleDataConv only in Expert mode.")
77 if args.mcType !=
"BGx1":
78 B2FATAL(
"When using BelleDataConv, mcType must be set to BGx1.")
83 def setEnvironment(belleOrBelle2Flag="Belle2"):
85 Sets the environment to analyse the mdst files for validation.'
87 @param belleOrBelle2Flag Default is 'Belle2' but 'Belle' is possible.
90 environmentType =
"default"
92 if belleOrBelle2Flag ==
"Belle":
94 from b2biiConversion
import convertBelleMdstToBelleIIMdst
96 os.environ[
'BELLE_POSTGRES_SERVER'] =
'can51'
97 os.environ[
'USE_GRAND_REPROCESS_DATA'] =
'1'
99 environmentType =
"Belle"
103 inputFileList.append(str(iFile))
105 convertBelleMdstToBelleIIMdst(inputBelleMDSTFile=inputFileList, path=cp_val_path)
108 ma.inputMdstList(environmentType=environmentType, filelist=[], path=cp_val_path)
111 def reconstructB2JpsiKs_mu(belleOrBelle2Flag='Belle2'):
113 Defines the reconstruction procedure for the benchmark channel 'B0 -> J/psi K_S0'
115 @param belleOrBelle2Flag Default is 'Belle2' but 'Belle' is possible.
119 ma.fillParticleList(decayString=
'mu+:all', cut=
'', path=cp_val_path)
120 ma.reconstructDecay(decayString=
'J/psi:mumu -> mu+:all mu-:all', cut=
'dM<0.11', path=cp_val_path)
121 ma.matchMCTruth(list_name=
'J/psi:mumu', path=cp_val_path)
123 if belleOrBelle2Flag ==
"Belle":
126 ma.matchMCTruth(list_name=
'K_S0:mdst', path=cp_val_path)
129 ma.reconstructDecay(decayString=
'B0:sig -> J/psi:mumu K_S0:mdst', cut=
'Mbc > 5.2 and abs(deltaE)<0.15', path=cp_val_path)
131 if belleOrBelle2Flag ==
"Belle2":
134 ma.fillParticleList(decayString=
'pi+:all', cut=
'', path=cp_val_path)
135 ma.reconstructDecay(decayString=
'K_S0:pipi -> pi+:all pi-:all', cut=
'dM<0.25', path=cp_val_path)
138 ma.reconstructDecay(decayString=
'B0:sig -> J/psi:mumu K_S0:pipi', cut=
'Mbc > 5.2 and abs(deltaE)<0.15', path=cp_val_path)
141 def reconstructB2nunubar():
143 Defines the procedure to create a B0 list for the benchmark channel 'B0 -> nu_tau anti-nu_tau'
146 ma.findMCDecay(list_name=
'B0:sig', decay=
'B0 -> nu_tau anti-nu_tau', writeOut=
True, path=cp_val_path)
149 def mcMatchAndBuildROE(belleOrBelle2Flag='Belle2'):
151 Runs the mc matching and creates the rest of event for the signal particle list.'
153 @param belleOrBelle2Flag Default is 'Belle2' but 'Belle' is possible.
157 ma.matchMCTruth(list_name=
'B0:sig', path=cp_val_path)
160 if belleOrBelle2Flag ==
"Belle":
161 target_list_name =
'B0:sig'
162 ma.fillParticleList(
'pi+:mdst',
'', path=cp_val_path)
163 ma.fillParticleList(
'gamma:mdst',
'', path=cp_val_path)
165 inputParticlelists = [
'pi+:mdst',
'gamma:mdst']
166 roeBuilder = b2.register_module(
'RestOfEventBuilder')
167 roeBuilder.set_name(
'ROEBuilder_' + target_list_name)
168 roeBuilder.param(
'particleList', target_list_name)
169 roeBuilder.param(
'particleListsInput', inputParticlelists)
170 cp_val_path.add_module(roeBuilder)
172 if belleOrBelle2Flag ==
"Belle2":
173 ma.buildRestOfEvent(target_list_name=
'B0:sig', inputParticlelists=[], path=cp_val_path)
176 def applyCPVTools(mode='Expert'):
178 Defines the procedure to use the flavor tagger and tagV on the signal 'B0:sig' list.
179 It saves also all variables to nTuples needed for evaluation of the performance
181 @param mode Default is 'Expert' but also needed for 'Sampler' mode.
184 if mode ==
'Sampler':
187 particleLists=[
'B0:sig'],
189 weightFiles=
'B2' + decayChannelTrainedOn + mcType,
190 combinerMethods=[
'TMVA-FBDT',
'FANN-MLP'],
191 useOnlyLocalWeightFiles=
True,
192 downloadFromDatabaseIfNotFound=
False,
193 workingDirectory=workingDirectory,
194 samplerFileId=str(fileNumber),
200 particleLists=[
'B0:sig'],
201 combinerMethods=[
'TMVA-FBDT',
'FANN-MLP'],
202 weightFiles=
'B2' + decayChannelTrainedOn + mcType,
203 useOnlyLocalWeightFiles=
True,
204 downloadFromDatabaseIfNotFound=
False,
205 workingDirectory=workingDirectory,
206 samplerFileId=str(fileNumber),
212 dnnIdentifier =
"FlavorTagger_" + belleOrBelle2Flag +
"_B2nunubarBGx1OptimizedForDataDNN"
213 if belleOrBelle2Flag ==
"Belle":
214 dnnIdentifier =
"FlavorTagger_" + belleOrBelle2Flag +
"_B2nunubarBGx1DNN"
215 b2.conditions.append_globaltag(
"analysis_tools_release-03-02-00")
216 DeepFlavorTagger.DeepFlavorTagger(
'B0:sig',
219 uniqueIdentifier=dnnIdentifier,
222 if doVertex
or mode ==
'Expert':
225 if decayChannel ==
"JPsiKs":
228 vx.treeFit(list_name=
'B0:sig', conf_level=-2, path=cp_val_path)
229 vx.TagV(list_name=
'B0:sig', MCassociation=
'breco', path=cp_val_path)
230 print(
"TagV will be used")
233 fs_vars = vc.pid + vc.track + vc.track_hits + vc.mc_truth
234 jpsiandk0s_vars = vc.mc_truth
235 vertex_vars = vc.vertex + vc.mc_vertex + vc.kinematics + vc.mc_kinematics
236 bvars = vc.reco_stats + \
239 vc.roe_multiplicities + \
244 if decayChannel ==
"JPsiKs":
246 vu.create_aliases_for_selected(list_of_variables=fs_vars,
247 decay_string=
'B0 -> [J/psi -> ^mu+ ^mu-] [K_S0 -> ^pi+ ^pi-]') + \
248 vu.create_aliases_for_selected(list_of_variables=jpsiandk0s_vars,
249 decay_string=
'B0 -> [^J/psi -> mu+ mu-] [^K_S0 -> pi+ pi-]') + \
250 vu.create_aliases_for_selected(list_of_variables=vertex_vars,
251 decay_string=
'B0 -> [^J/psi -> ^mu+ ^mu-] [^K_S0 -> ^pi+ ^pi-]')
253 bvars += ft.flavor_tagging + [
'DNN_qrCombined',
'extraInfo(dnn_output)']
255 vu._variablemanager.addAlias(
'qrMC',
'isRelatedRestOfEventB0Flavor')
259 ma.variablesToNtuple(decayString=
'B0:sig',
261 filename=savingDirectory +
'/' +
'B2A801-FlavorTagger' +
262 mode + str(fileNumber) + belleOrBelle2Flag + mcType + belleData +
'.root',
266 ma.summaryOfLists(particleLists=[
'B0:sig'], path=cp_val_path)
269 if __name__ ==
'__main__':
271 args = getCommandLineOptions()
273 belleOrBelle2Flag = args.belleOrBelle2Flag
275 decayChannelTrainedOn = args.decayChannelTrainedOn
276 decayChannel = args.decayChannel
278 fileNumber = args.fileNumber
279 workingDirectory = args.workingDirectory
280 savingDirectory = args.savingDirectory
281 doVertex = args.doVertex
282 belleData = args.belleData
284 if decayChannelTrainedOn ==
'JPsiKs':
285 decayChannelTrainedOn =
'JpsiKs_mu'
287 cp_val_path = b2.Path()
289 if mode ==
"Sampler" or mode ==
"Expert":
291 setEnvironment(belleOrBelle2Flag=belleOrBelle2Flag)
293 if decayChannel ==
"nunubar":
294 reconstructB2nunubar()
296 elif decayChannel ==
"JPsiKs":
297 reconstructB2JpsiKs_mu(belleOrBelle2Flag=belleOrBelle2Flag)
299 mcMatchAndBuildROE(belleOrBelle2Flag=belleOrBelle2Flag)
300 applyCPVTools(mode=mode)
301 b2.process(cp_val_path)
304 if mode ==
"Teacher":
309 weightFiles=
'B2' + decayChannelTrainedOn + mcType,
310 combinerMethods=[
'TMVA-FBDT',
'FANN-MLP'],
311 useOnlyLocalWeightFiles=
True,
312 downloadFromDatabaseIfNotFound=
False,
313 uploadToDatabaseAfterTraining=
True,
314 workingDirectory=workingDirectory,