Belle II Software development
flavorTaggerVertexingValidation.py
1#!/usr/bin/env python
2
3
10
11
29
30import basf2 as b2
31import modularAnalysis as ma
32import flavorTagger as ft
33from dft import DeepFlavorTagger
34import vertex as vx
35import variables.collections as vc
36import variables.utils as vu
37from ROOT import Belle2
38import argparse
39import os
40
41
42def getCommandLineOptions():
43 """ Parses the command line options for the CPV validation and returns the corresponding arguments. """
44
45 parser = argparse.ArgumentParser(description='Script for the validation of CPV tools:\
46 it defines the procedure to sample the training set, train and test the flavor tagger\
47 as well as to reconstruct the vertices of B0-> J/psi K_S0 and of the tag-side B0\
48 using the tagV module.\n\
49 Usage: basf2 -i inputMDST.root flavorTaggerVertexingValidation.py -- -m Sampler -dc JPsiKs')
50
51 parser.add_argument('-bob2', '--belleOrBelle2Flag', dest='belleOrBelle2Flag',
52 type=str, default='Belle2', choices=['Belle', 'Belle2'],
53 help='Choose Belle for converted Belle data or MC, otherwise choose Belle2.')
54 parser.add_argument('-m', '--mode', dest='mode', type=str, required=True,
55 choices=['Sampler', 'Teacher', 'Expert'],
56 help='Working mode of the flavor tagger. Choose Sampler, Teacher or Expert.')
57 parser.add_argument('-trc', '--decayChannelTrainedOn', dest='decayChannelTrainedOn',
58 type=str, default='nunubar',
59 help='Decay channel of the weight files. Official samples available are JPsiKs or nunubar.')
60 parser.add_argument('-dc', '--decayChannel', dest='decayChannel', type=str, required=True,
61 choices=['JPsiKs', 'nunubar'], help='Decay channel that will be reconstructed. Choose JPsiKs or nunubar.')
62 parser.add_argument('-mct', '--mcType', dest='mcType', type=str, default='BGx1',
63 choices=['BGx0', 'BGx1'], help='Type of files. Choose BGx0 for background free Belle II MC. \n' +
64 'Otherwise choose BGx1 for BelleII MC with bkg. or for converted Belle data or MC.')
65 parser.add_argument('-fn', '--fileNumber', dest='fileNumber', type=str, default='',
66 help='A file number (when sampling in parallel).')
67 parser.add_argument('-wd', '--workingDirectory', dest='workingDirectory', type=str, default='.',
68 help='Path where the training samples and the weight files are saved.')
69 parser.add_argument('-sd', '--savingDirectory', dest='savingDirectory', type=str, default='.',
70 help='Path where the analyzed output files are saved.')
71 parser.add_argument('-dv', '--doVertex', dest='doVertex', type=bool, default=False,
72 help='Reconstruct B vertices True or False')
73 parser.add_argument('-bd', '--belleData', dest='belleData', type=str, default='',
74 choices=['', 'BelleDataConv'], help='Choose BelleDataConv only for Belle Data in Expert mode.')
75 args = parser.parse_args()
76
77 if args.belleData == "BelleDataConv":
78 if args.belleOrBelle2Flag != "Belle":
79 b2.B2FATAL("BelleDataConv only for Belle Data.")
80 if args.mode != "Expert":
81 b2.B2FATAL("BelleDataConv only in Expert mode.")
82 if args.mcType != "BGx1":
83 b2.B2FATAL("When using BelleDataConv, mcType must be set to BGx1.")
84
85 return args
86
87
88def setEnvironment(belleOrBelle2Flag="Belle2"):
89 """
90 Sets the environment to analyse the mdst files for validation.'
91 @param belleOrBelle2Flag Default is 'Belle2' but 'Belle' is possible.
92 """
93
94 environmentType = "default"
95
96 if belleOrBelle2Flag == "Belle":
97
98 from b2biiConversion import convertBelleMdstToBelleIIMdst
99
100 os.environ['BELLE_POSTGRES_SERVER'] = 'can51'
101 os.environ['USE_GRAND_REPROCESS_DATA'] = '1'
102
103 environmentType = "Belle"
104
105 inputFileList = []
106 for iFile in Belle2.Environment.Instance().getInputFilesOverride():
107 inputFileList.append(str(iFile))
108
109 convertBelleMdstToBelleIIMdst(inputBelleMDSTFile=inputFileList, path=cp_val_path)
110
111 else:
112 ma.inputMdstList(environmentType=environmentType, filelist=[], path=cp_val_path)
113
114
115def reconstructB2JpsiKs_mu(belleOrBelle2Flag='Belle2'):
116 """
117 Defines the reconstruction procedure for the benchmark channel 'B0 -> J/psi K_S0'
118
119 @param belleOrBelle2Flag Default is 'Belle2' but 'Belle' is possible.
120 """
121
122 # reconstruct J/psi -> mu+ mu- decay using standard muon list and perform MC association
123 ma.fillParticleList(decayString='mu+:all', cut='', path=cp_val_path)
124 ma.reconstructDecay(decayString='J/psi:mumu -> mu+:all mu-:all', cut='abs(dM) < 0.11', path=cp_val_path)
125 ma.matchMCTruth(list_name='J/psi:mumu', path=cp_val_path)
126
127 if belleOrBelle2Flag == "Belle":
128
129 # use the existent K_S0:mdst list
130 ma.matchMCTruth(list_name='K_S0:mdst', path=cp_val_path)
131
132 # reconstruct B0 -> J/psi Ks decay
133 ma.reconstructDecay(decayString='B0:sig -> J/psi:mumu K_S0:mdst', cut='Mbc > 5.2 and abs(deltaE) < 0.15', path=cp_val_path)
134
135 if belleOrBelle2Flag == "Belle2":
136
137 # reconstruct Ks from standard pi+ particle list
138 ma.fillParticleList(decayString='pi+:all', cut='', path=cp_val_path)
139 ma.reconstructDecay(decayString='K_S0:pipi -> pi+:all pi-:all', cut='abs(dM) < 0.25', path=cp_val_path)
140
141 # reconstruct B0 -> J/psi Ks decay
142 ma.reconstructDecay(decayString='B0:sig -> J/psi:mumu K_S0:pipi', cut='Mbc > 5.2 and abs(deltaE) < 0.15', path=cp_val_path)
143
144
145def reconstructB2nunubar():
146 """
147 Defines the procedure to create a B0 list for the benchmark channel 'B0 -> nu_tau anti-nu_tau'
148 """
149
150 ma.fillParticleListFromMC('nu_tau:MC', '', path=cp_val_path)
151 ma.reconstructMCDecay('B0:sig -> nu_tau:MC anti-nu_tau:MC', '', writeOut=True, path=cp_val_path)
152
153
154def mcMatchAndBuildROE(belleOrBelle2Flag='Belle2'):
155 """
156 Runs the mc matching and creates the rest of event for the signal particle list.'
157
158 @param belleOrBelle2Flag Default is 'Belle2' but 'Belle' is possible.
159 """
160
161 # perform MC matching (MC truth association). Always before TagV
162 ma.matchMCTruth(list_name='B0:sig', path=cp_val_path)
163
164 # build the rest of the event associated to the B0
165 ma.buildRestOfEvent(target_list_name='B0:sig', path=cp_val_path)
166
167
168def applyCPVTools(mode='Expert'):
169 """
170 Defines the procedure to use the flavor tagger and tagV on the signal 'B0:sig' list.
171 It saves also all variables to nTuples needed for evaluation of the performance
172
173 @param mode Default is 'Expert' but also needed for 'Sampler' mode.
174 """
175
176 if mode == 'Sampler':
177
178 ft.flavorTagger(
179 particleLists=['B0:sig'],
180 mode=mode,
181 weightFiles='B2' + decayChannelTrainedOn + mcType,
182 combinerMethods=['TMVA-FBDT', 'FANN-MLP'],
183 useOnlyLocalWeightFiles=True,
184 downloadFromDatabaseIfNotFound=False,
185 workingDirectory=workingDirectory,
186 samplerFileId=str(fileNumber),
187 path=cp_val_path)
188
189 if mode == 'Expert':
190
191 ft.flavorTagger(
192 particleLists=['B0:sig'],
193 combinerMethods=['TMVA-FBDT', 'FANN-MLP'],
194 weightFiles='B2' + decayChannelTrainedOn + mcType,
195 useOnlyLocalWeightFiles=True,
196 downloadFromDatabaseIfNotFound=False,
197 workingDirectory=workingDirectory,
198 samplerFileId=str(fileNumber),
199 path=cp_val_path)
200
201 # # Preliminarily, DNN Identifier has to be set by hand when validating
202 # # The standard name should be however
203 # This is temporary till the DNN gets retrained.
204 dnnIdentifier = "FlavorTagger_" + belleOrBelle2Flag + "_B2nunubarBGx1OptimizedForDataDNN"
205 if belleOrBelle2Flag == "Belle":
206 dnnIdentifier = "FlavorTagger_" + belleOrBelle2Flag + "_B2nunubarBGx1DNN"
207 b2.conditions.append_globaltag("analysis_tools_release-04-00")
208 DeepFlavorTagger.DeepFlavorTagger('B0:sig',
209 mode='expert',
210 working_dir='',
211 uniqueIdentifier=dnnIdentifier,
212 path=cp_val_path)
213
214 if doVertex or mode == 'Expert':
215
216 if doVertex:
217 if decayChannel == "JPsiKs":
218 # vx.kFit(list_name='B0:sig', conf_level=0.0, decay_string='B0:sig -> [J/psi:mumu -> ^mu+ ^mu-] K_S0',
219 # constraint='', path=cp_val_path)
220 vx.treeFit(list_name='B0:sig', conf_level=-2, path=cp_val_path)
221 vx.TagV(list_name='B0:sig', MCassociation='breco', path=cp_val_path)
222 print("TagV will be used")
223
224 # Select variables that will be stored to ntuple
225 fs_vars = vc.pid + vc.track + vc.track_hits + vc.mc_truth
226 jpsiandk0s_vars = vc.mc_truth
227 vertex_vars = vc.vertex + vc.mc_vertex + vc.kinematics + vc.mc_kinematics
228 bvars = vc.reco_stats + \
229 vc.deltae_mbc + \
230 vc.mc_truth + \
231 vc.roe_multiplicities + \
232 vc.tag_vertex + \
233 vc.mc_tag_vertex + \
234 vertex_vars
235
236 if decayChannel == "JPsiKs":
237 bvars = bvars + \
238 vu.create_aliases_for_selected(list_of_variables=fs_vars,
239 decay_string='B0 -> [J/psi -> ^mu+ ^mu-] [K_S0 -> ^pi+ ^pi-]') + \
240 vu.create_aliases_for_selected(list_of_variables=jpsiandk0s_vars,
241 decay_string='B0 -> [^J/psi -> mu+ mu-] [^K_S0 -> pi+ pi-]') + \
242 vu.create_aliases_for_selected(list_of_variables=vertex_vars,
243 decay_string='B0 -> [^J/psi -> ^mu+ ^mu-] [^K_S0 -> ^pi+ ^pi-]')
244 if mode == 'Expert':
245 bvars += ft.flavor_tagging + ['DNN_qrCombined', 'extraInfo(dnn_output)']
246 else:
247 vu._variablemanager.addAlias('qrMC', 'isRelatedRestOfEventB0Flavor')
248 bvars += ['qrMC']
249
250 # Saving variables to ntuple
251 ma.variablesToNtuple(decayString='B0:sig',
252 variables=bvars,
253 filename=savingDirectory + '/' + 'B2A801-FlavorTagger' +
254 mode + str(fileNumber) + belleOrBelle2Flag + mcType + belleData + '.root',
255 treename='B0tree',
256 path=cp_val_path)
257
258 ma.summaryOfLists(particleLists=['B0:sig'], path=cp_val_path)
259
260
261if __name__ == '__main__':
262
263 args = getCommandLineOptions()
264
265 belleOrBelle2Flag = args.belleOrBelle2Flag
266 mode = args.mode
267 decayChannelTrainedOn = args.decayChannelTrainedOn
268 decayChannel = args.decayChannel
269 mcType = args.mcType
270 fileNumber = args.fileNumber
271 workingDirectory = args.workingDirectory
272 savingDirectory = args.savingDirectory
273 doVertex = args.doVertex
274 belleData = args.belleData
275
276 if decayChannelTrainedOn == 'JPsiKs':
277 decayChannelTrainedOn = 'JpsiKs_mu'
278
279 cp_val_path = b2.Path()
280
281 if mode == "Sampler" or mode == "Expert":
282
283 setEnvironment(belleOrBelle2Flag=belleOrBelle2Flag)
284
285 if decayChannel == "nunubar":
286 reconstructB2nunubar()
287
288 elif decayChannel == "JPsiKs":
289 reconstructB2JpsiKs_mu(belleOrBelle2Flag=belleOrBelle2Flag)
290
291 mcMatchAndBuildROE(belleOrBelle2Flag=belleOrBelle2Flag)
292 applyCPVTools(mode=mode)
293 b2.process(cp_val_path)
294 print(b2.statistics)
295
296 if mode == "Teacher":
297
298 ft.flavorTagger(
299 particleLists=[],
300 mode='Teacher',
301 weightFiles='B2' + decayChannelTrainedOn + mcType,
302 combinerMethods=['TMVA-FBDT', 'FANN-MLP'],
303 useOnlyLocalWeightFiles=True,
304 downloadFromDatabaseIfNotFound=False,
305 uploadToDatabaseAfterTraining=True,
306 workingDirectory=workingDirectory,
307 path=cp_val_path)
308
static Environment & Instance()
Static method to get a reference to the Environment instance.
Definition: Environment.cc:28