Belle II Software development
LambdaSelector.py
1
8
9import modularAnalysis as ma
10import variables
11from variables import utils
12from basf2 import B2INFO, B2ERROR
13import basf2_mva
14# import torch as torch
15# Check if GPU is available
16# device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
17# print("Device is:",device)
18
19
20def add_default_lambda_Selector_aliases():
21 """
22 This function is used to set up variables aliases for lambda Selector variables.
23 """
24 variables.variables.addAlias('daughtersDeltaZ', 'daughterDiffOf(0, 1, dz)')
25 variables.variables.addAlias('cosVertexMomentum', 'cosAngleBetweenMomentumAndVertexVector')
26 variables.variables.addAlias('pro_nPXDHits', 'daughter(0,nPXDHits)')
27 variables.variables.addAlias('pin_nPXDHits', 'daughter(1,nPXDHits)')
28 variables.variables.addAlias('pro_nSVDHits', 'daughter(0,nSVDHits)')
29 variables.variables.addAlias('pin_nSVDHits', 'daughter(1,nSVDHits)')
30 variables.variables.addAlias('daughterAngleDiffInMother', 'useRestFrame(daughterAngle(0, 1))')
31 variables.variables.addAlias('pro_p', 'daughter(0,p)')
32 variables.variables.addAlias('pin_p', 'daughter(1,p)')
33 variables.variables.addAlias('pro_pt', 'daughter(0,pt)')
34 variables.variables.addAlias('pin_pt', 'daughter(1,pt)')
35 variables.variables.addAlias('pro_dr', 'daughter(0,dr)')
36 variables.variables.addAlias('pin_dr', 'daughter(1,dr)')
37 variables.variables.addAlias('pro_cosTheta', 'daughter(0,cosTheta)')
38 variables.variables.addAlias('pin_cosTheta', 'daughter(1,cosTheta)')
39 variables.variables.addAlias('pro_protonID', 'daughter(0,protonID)')
40 variables.variables.addAlias('pin_protonID', 'daughter(1,protonID)')
41 variables.variables.addAlias('proPDG', 'daughter(0,mcPDG)')
42 variables.variables.addAlias('pinPDG', 'daughter(1,mcPDG)')
43 variables.variables.addAlias("Mks_Hypo", "useAlternativeDaughterHypothesis(M, 0:pi+)")
44
45
46def add_variable_collection():
47 """
48 Call this function to add variable collection for lambdaSelector.
49 """
50 add_default_lambda_Selector_aliases()
51 inputVariablesList = [
52 'cosVertexMomentum',
53 'flightDistance',
54 'flightDistanceErr',
55 'significanceOfDistance',
56 'cosHelicityAngleMomentum',
57 'ImpactXY',
58 'decayAngle(0)',
59 'decayAngle(1)',
60 'daughterAngleDiffInMother',
61 'daughtersDeltaZ',
62 'pro_nSVDHits', 'pro_nPXDHits',
63 'pin_nSVDHits', 'pin_nPXDHits',
64 'pro_dr', 'pin_dr',
65 'pro_protonID', 'pin_protonID',
66 'pro_p', 'pin_p',
67 'pro_pt', 'pin_pt',
68 'pro_cosTheta', 'pin_cosTheta',
69 'pinPDG', 'proPDG',
70 'ArmenterosDaughter1Qt',
71 'ArmenterosDaughter2Qt',
72 'Mks_Hypo'
73 ]
74 utils.add_collection(inputVariablesList, 'lambda_selector_info')
75
76
77def V0Selector_Training(
78 train_data,
79 tree_name="tree",
80 mva_identifier="MVA_LightGBM_V0Selector.root",
81 target_variable="isSignal",
82 parameters={},
83 ):
84 """
85 Defines the configuration of V0Selector Training.
86 The training data should contain Lambda0 and misreconstructed Lambda0 without KS0.
87
88 @param train_data Root file containing Lambda information to be trained.
89 @param tree_name Tree name for variables.
90 @param mva_identifier Name for output MVA weight file.
91 @param target_variable Target variable for MVA training.
92 @param parameters hyperparameter for LGBM
93 """
94
95 # Create The GeneralOptions object as always
96 trainVars = [
97 'cosVertexMomentum',
98 'flightDistance',
99 'significanceOfDistance',
100 'cosHelicityAngleMomentum',
101 'ImpactXY',
102 'decayAngle(0)',
103 'decayAngle(1)',
104 'daughterAngleDiffInMother',
105 'daughtersDeltaZ',
106 'pro_nSVDHits', 'pro_nPXDHits',
107 'pin_nSVDHits', 'pin_nPXDHits',
108 'pro_dr', 'pin_dr',
109 ]
110
111 general_options = basf2_mva.GeneralOptions()
112 general_options.m_datafiles = basf2_mva.vector(train_data)
113 general_options.m_treename = tree_name
114 general_options.m_identifier = mva_identifier
115 general_options.m_variables = basf2_mva.vector(*trainVars)
116 general_options.m_target_variable = target_variable
117
118 python_options = basf2_mva.PythonOptions()
119
120 python_options.m_framework = "lightgbm"
121 python_options.m_steering_file = ""
122
123 import json
124 param = {'num_leaves': 256,
125 'objective': 'cross_entropy',
126 'learning_rate': 0.1,
127 'device_type': "cpu",
128 'deterministic': True,
129 'metric': 'auc',
130 'num_round': 100,
131 # 'stop_round' : 30, mute this in case too early stop
132 'path': mva_identifier+'.txt',
133 'min_data_in_leaf': 1000,
134 'max_depth': 8,
135 'max_bin': 250,
136 'boosting': 'gbdt',
137 'trainFraction': 0.8,
138 }
139 if isinstance(parameters, dict):
140 param.update(parameters)
141 config_string = json.dumps(param)
142 print("The json config string", config_string)
143 python_options.m_config = config_string
144
145 python_options.m_training_fraction = 1
146 python_options.m_normalize = False
147 python_options.m_nIterations = 1
148 python_options.m_mini_batch_size = 0
149
150 basf2_mva.teacher(general_options, python_options)
151
152
153def KsVeto_Training(
154 train_data,
155 tree_name="tree",
156 mva_identifier="MVA_LightGBM_KsVeto.root",
157 target_variable="isSignal",
158 parameters={},
159):
160 """
161 Defines the configuration of KsVeto Training.
162 The training data should contain only Lambda and Ks.
163
164 @param train_data Root file containing Ks information to be trained.
165 @param tree_name Tree name for variables.
166 @param mva_identifier Name for output MVA weight file.
167 @param target_variable Target variable for MVA training.
168 @param parameters hyperparameter for LGBM
169 """
170
171 # Create The GeneralOptions object as always
172 trainVars = [
173 'pro_protonID',
174 'pin_protonID',
175 'ArmenterosDaughter1Qt',
176 'ArmenterosDaughter2Qt',
177 'pro_cosTheta',
178 'pin_cosTheta',
179 'Mks_Hypo',
180 'ArmenterosLongitudinalMomentumAsymmetry',
181 ]
182
183 general_options = basf2_mva.GeneralOptions()
184 general_options.m_datafiles = basf2_mva.vector(train_data)
185 general_options.m_treename = tree_name
186 general_options.m_identifier = mva_identifier
187 general_options.m_variables = basf2_mva.vector(*trainVars)
188 general_options.m_target_variable = target_variable
189
190 python_options = basf2_mva.PythonOptions()
191
192 python_options.m_framework = "lightgbm"
193 python_options.m_steering_file = ""
194
195 import json
196 param = {'num_leaves': 256,
197 'learning_rate': 0.05,
198 'device_type': "cpu",
199 'deterministic': True,
200 'metric': 'auc',
201 'num_round': 100,
202 # 'stop_round' : 10,
203 'path': mva_identifier+'.txt',
204 'max_bin': 250,
205 'boosting': 'gbdt',
206 'max_depth': 8,
207 'trainFraction': 0.8,
208 'min_data_in_leaf': 300,
209 'objective': 'cross_entropy',
210 }
211 if isinstance(parameters, dict):
212 param.update(parameters)
213 config_string = json.dumps(param)
214 print("The json config string", config_string)
215 python_options.m_config = config_string
216
217 python_options.m_normalize = False # we do it inside MVA torch
218
219 python_options.m_nIterations = 1
220 python_options.m_mini_batch_size = 0
221 basf2_mva.teacher(general_options, python_options)
222
223# ****************************************
224# Lambda Selector MAIN FUNCTION
225# ****************************************
226
227
229 particleListName,
230 identifier_Lambda="Lambda_LGBM_V0Selector",
231 identifier_vKs="Lambda_LGBM_KsVeto",
232 output_label_name='',
233 extraInfoName_V0Selector='LambdaSelector_V0Selector',
234 extraInfoName_KsVeto='LambdaSelector_KsVeto',
235 useCustomThreshold=False,
236 threshold_V0Selector=0.72,
237 threshold_KsVeto=0.27,
238 path=None
239):
240 """
241 This function will apply Lambda0 selection MVA on the given particleList.
242 By default this function appends MVA output as a extraInfo for the given particleList.
243 You can apply preset cut or custom cut by giving parameters. In this case,
244 a new particleList is created from the original particleList applying cuts on the MVA output.
245
246 @param particleListName Reconstructed Lambda0 -> p+ pi- list.
247 @param output_label_name Label of the returned Lambda particleList.
248 When empty '', no cut is applied and new particleList is not created.
249 When custom name, the custom threshold is used, and useCustomThreshold
250 must be True.
251 When 'standard', 'tight', or 'loose', a cut with Ks efficiency
252 90%, 95%, and 85% is applied.
253 @param extraInfoName_V0Selector Variable name for V0Selector MVA output.
254 @param extraInfoName_KsVeto Variable name for KsVeto MVA output.
255 @param identifier_Lambda Identifier name for V0Selector weight file.
256 @param identifier_vKs Identifier name for KsVeto weight file.
257 @param useCustomThreshold Flag whether threshold_V0Selector and threshold_KsVeto are used.
258 @param threshold_V0Selector Threshold for V0Selector.
259 @param threshold_KsVeto Threshold for KsVeto.
260 @param path Basf2 path to execute.
261
262 """
263
264 add_default_lambda_Selector_aliases()
265
266 path.add_module('MVAMultipleExperts',
267 listNames=[particleListName],
268 extraInfoNames=[extraInfoName_V0Selector, extraInfoName_KsVeto],
269 identifiers=[identifier_Lambda, identifier_vKs])
270
271 _effnames = ['standard', 'tight', 'loose']
272 outputListName = ''
273
274 if useCustomThreshold:
275 if output_label_name in _effnames:
276 B2ERROR('LambdaSelector: Specify label name except for \'standard\', \'tight\', and \'loose\' '
277 'when you use custom threshold.')
278 elif output_label_name == '':
279 B2ERROR('LambdaSelector: Specify label name when you use custom threshold.')
280 else:
281 outputListName = particleListName.split(':')[0] + ':' + output_label_name
282 B2INFO('LambdaSelector: Custom Cut is applied on '+outputListName+'.')
283 V0_thr = threshold_V0Selector
284 Ks_thr = threshold_KsVeto
285 B2INFO('LambdaSelector: Threshold is (' + str(V0_thr) + ', ' + str(Ks_thr) + ')')
286 cut_string = 'extraInfo('+extraInfoName_V0Selector+')>'+str(V0_thr) + \
287 ' and extraInfo('+extraInfoName_KsVeto+')>'+str(Ks_thr)
288 ma.cutAndCopyLists(outputListName, particleListName, cut=cut_string, path=path)
289 else:
290 if output_label_name in _effnames:
291 outputListName = particleListName.split(':')[0] + ':' + output_label_name
292 V0_thr = 0
293 Ks_thr = 0
294 if output_label_name == 'standard':
295 B2INFO('LambdaSelector: Standard Cut is applied on '+outputListName+'.')
296 V0_thr = 0.72
297 Ks_thr = 0.27
298 elif output_label_name == 'tight':
299 B2INFO('LambdaSelector: Tight Cut is applied on '+outputListName+'.')
300 V0_thr = 0.88
301 Ks_thr = 0.63
302 elif output_label_name == 'loose':
303 B2INFO('LambdaSelector: Loose Cut is applied on '+outputListName+'.')
304 V0_thr = 0.25
305 Ks_thr = 0.11
306 B2INFO('LambdaSelector: Threshold is (' + str(V0_thr) + ', ' + str(Ks_thr) + ')')
307 cut_string = 'extraInfo('+extraInfoName_V0Selector+')>'+str(V0_thr) + \
308 ' and extraInfo('+extraInfoName_KsVeto+')>'+str(Ks_thr)
309 ma.cutAndCopyLists(outputListName, particleListName, cut=cut_string, path=path)
310 elif output_label_name == '':
311 outputListName = particleListName
312 else:
313 B2ERROR('LambdaSelector: Label should be \'\', \'standard\', \'tight\', or \'loose\' if you do'
314 'not apply custom threshold')
315
316 B2INFO('LambdaSelector: ParticleList '+outputListName+' is returned.')