Belle II Software development
default_channels.py
1#!/usr/bin/env python3
2
3
10
11"""
12 Contains some example configurations of the FEI
13 Mostly you want to use get_default_channels,
14 which can return the configuration for common use-cases
15 - Hadronic tagging (hadronic = True)
16 - Semileptonic tagging (semileptonic = True)
17 - B+/B- (chargedB = True)
18 - B0/anti-B0 (neutralB = True)
19 - running on Belle 1 MC/data (convertedFromBelle = True)
20 - running a specific FEI which is optimized for a signal selection and uses ROEs (specific = True)
21 - run without semileptonic D channels (removeSLD = True )
22 - B mesons with a strange quark in Y(5S) runs (strangeB = True)
23
24 Another interesting configuration is given by get_fr_channels,
25 which will return a configuration which is equivalent to the original Full Reconstruction algorithm used by Belle
26"""
27
28import b2bii
29from fei import Particle, MVAConfiguration, PreCutConfiguration, PostCutConfiguration
30from basf2 import B2FATAL, B2INFO
31
32
33def get_default_channels(
34 B_extra_cut=None,
35 hadronic=True,
36 semileptonic=True,
37 KLong=False,
38 baryonic=True,
39 chargedB=True,
40 neutralB=True,
41 specific=False,
42 removeSLD=False,
43 strangeB=False):
44 """
45 returns list of Particle objects with all default channels for running
46 FEI on Upsilon(4S). For a training with analysis-specific signal selection,
47 adding a cut on nRemainingTracksInRestOfEvent is recommended.
48 @param B_extra_cut Additional user cut on recombination of tag-B-mesons
49 @param hadronic whether to include hadronic B decays (default is True)
50 @param semileptonic whether to include semileptonic B decays (default is True)
51 @param KLong whether to include K_long decays into the training (default is False)
52 @param baryonic whether to include baryons into the training (default is True)
53 @param chargedB whether to recombine charged B mesons (default is True)
54 @param neutralB whether to recombine neutral B mesons (default is True)
55 @param specific if True, this adds isInRestOfEvent cut to all FSP
56 @param removeSLD if True, removes semileptonic D modes from semileptonic B lists (default is False)
57 @param strangeB if True, reconstruct B_s mesons in Upsilon5S decays (default is False)
58 """
59 if strangeB is True:
60 B2INFO('Running 5S FEI')
61 if chargedB is False and neutralB is False and strangeB is False:
62 B2FATAL('No B-Mesons will be recombined, since chargedB==False and neutralB==False and strangeB==False was selected!'
63 ' Please reconfigure the arguments of get_default_channels() accordingly')
64 if hadronic is False and semileptonic is False:
65 if KLong is False:
66 B2FATAL('No B-Mesons will be recombined, since hadronic==False, semileptonic==False, and KLong==False were selected.'
67 ' Please reconfigure the arguments of get_default_channels() accordingly')
68
69 convertedFromBelle = b2bii.isB2BII()
70
71 if convertedFromBelle:
72 # Using Belle specific Variables for e-ID, mu-ID and K-ID
73 # atcPIDBelle(3,2) is used as K-ID
74 # atcPIDBelle(4,2) and atcPIDBelle(4,3) are used as pr-ID
75
76 chargedVariables = ['eIDBelle',
77 'atcPIDBelle(3,2)',
78 'atcPIDBelle(4,2)', 'atcPIDBelle(4,3)',
79 'muIDBelle',
80 'p', 'pt', 'pz', 'dr', 'dz', 'chiProb', 'extraInfo(preCut_rank)']
81 else:
82 chargedVariables = ['electronID', 'kaonID', 'protonID', 'muonID',
83 'p', 'pt', 'pz', 'dr', 'dz', 'chiProb', 'extraInfo(preCut_rank)']
84
85 if specific:
86 charged_user_cut = '[dr < 2] and [abs(dz) < 4] and isInRestOfEvent > 0.5'
87 else:
88 charged_user_cut = '[dr < 2] and [abs(dz) < 4]'
89
90 pion = Particle('pi+',
91 MVAConfiguration(variables=chargedVariables,
92 target='isPrimarySignal'),
93 PreCutConfiguration(userCut=charged_user_cut,
94 bestCandidateMode='highest',
95 bestCandidateVariable='pionID' if not convertedFromBelle else 'atcPIDBelle(2,3)',
96 bestCandidateCut=20),
97 PostCutConfiguration(bestCandidateCut=10, value=0.01))
98 pion.addChannel(['pi+:FSP'])
99
100 kaon = Particle('K+',
101 MVAConfiguration(variables=chargedVariables,
102 target='isPrimarySignal'),
103 PreCutConfiguration(userCut=charged_user_cut,
104 bestCandidateMode='highest',
105 bestCandidateVariable='kaonID' if not convertedFromBelle else 'atcPIDBelle(3,2)',
106 bestCandidateCut=20),
107 PostCutConfiguration(bestCandidateCut=10, value=0.01))
108 kaon.addChannel(['K+:FSP'])
109
110 proton = Particle('p+',
111 MVAConfiguration(variables=chargedVariables,
112 target='isPrimarySignal'),
113 PreCutConfiguration(userCut=charged_user_cut,
114 bestCandidateMode='highest',
115 bestCandidateVariable='protonID' if not convertedFromBelle else 'atcPIDBelle(4,3)',
116 bestCandidateCut=20),
117 PostCutConfiguration(bestCandidateCut=10, value=0.01))
118 proton.addChannel(['p+:FSP'])
119
120 electron = Particle('e+',
121 MVAConfiguration(variables=chargedVariables,
122 target='isPrimarySignal'),
123 PreCutConfiguration(userCut=charged_user_cut,
124 bestCandidateMode='highest',
125 bestCandidateVariable='electronID' if not convertedFromBelle else 'eIDBelle',
126 bestCandidateCut=10),
127 PostCutConfiguration(bestCandidateCut=5, value=0.01))
128 electron.addChannel(['e+:FSP'])
129
130 muon = Particle('mu+',
131 MVAConfiguration(variables=chargedVariables,
132 target='isPrimarySignal'),
133 PreCutConfiguration(userCut=charged_user_cut,
134 bestCandidateMode='highest',
135 bestCandidateVariable='muonID' if not convertedFromBelle else 'muIDBelle',
136 bestCandidateCut=10),
137 PostCutConfiguration(bestCandidateCut=5, value=0.01))
138 muon.addChannel(['mu+:FSP'])
139
140 if convertedFromBelle:
141 gamma_cut = 'goodBelleGamma == 1 and clusterBelleQuality == 0'
142 else:
143 # Same as goodBelleGamma == 1
144 gamma_cut = '[[clusterReg == 1 and E > 0.10] or [clusterReg == 2 and E > 0.05] or [clusterReg == 3 and E > 0.15]]'
145 if specific:
146 gamma_cut += ' and isInRestOfEvent > 0.5'
147
148 gamma = Particle('gamma',
149 MVAConfiguration(variables=['clusterReg', 'clusterNHits', 'clusterTiming', 'extraInfo(preCut_rank)',
150 'clusterE9E25', 'pt', 'E', 'pz'],
151 target='isPrimarySignal'),
152 PreCutConfiguration(userCut=gamma_cut,
153 bestCandidateMode='highest',
154 bestCandidateVariable='E',
155 bestCandidateCut=40),
156 PostCutConfiguration(bestCandidateCut=20, value=0.01))
157 gamma.addChannel(['gamma:FSP'])
158 gamma.addChannel(['gamma:V0'],
159 MVAConfiguration(variables=['pt', 'E', 'pz', 'extraInfo(preCut_rank)'],
160 target='isPrimarySignal'),
161 PreCutConfiguration(userCut='',
162 bestCandidateMode='highest',
163 bestCandidateVariable='E',
164 bestCandidateCut=40))
165
166 if convertedFromBelle:
167
168 pi0_cut = '0.08 < InvM < 0.18'
169 if specific:
170 pi0_cut += ' and isInRestOfEvent > 0.5'
171
172 pi0 = Particle('pi0',
173 MVAConfiguration(variables=['InvM', 'extraInfo(preCut_rank)', 'chiProb', 'abs(BellePi0SigM)',
174 'daughterAngle(0,1)', 'pt', 'pz', 'E'],
175 target='isSignal'),
176 PreCutConfiguration(userCut=pi0_cut,
177 bestCandidateVariable='abs(BellePi0SigM)',
178 bestCandidateCut=20),
179 PostCutConfiguration(bestCandidateCut=10, value=0.01))
180 pi0.addChannel(['pi0:FSP'])
181
182 ks0_cut = '0.4 < M < 0.6'
183 if specific:
184 ks0_cut += ' and isInRestOfEvent > 0.5'
185
186 KS0 = Particle('K_S0',
187 MVAConfiguration(variables=['dr', 'dz', 'distance', 'significanceOfDistance', 'chiProb', 'M', 'abs(dM)',
188 'useCMSFrame(E)', 'daughterAngle(0,1)',
189 'cosAngleBetweenMomentumAndVertexVector',
190 'extraInfo(preCut_rank)', 'extraInfo(goodKs)', 'extraInfo(ksnbVLike)',
191 'extraInfo(ksnbNoLam)', 'extraInfo(ksnbStandard)'],
192 target='isSignal'),
193 PreCutConfiguration(userCut=ks0_cut,
194 bestCandidateVariable='abs(dM)',
195 bestCandidateCut=20),
196 PostCutConfiguration(bestCandidateCut=10, value=0.01))
197 KS0.addChannel(['K_S0:V0'])
198
199 Lam_cut = '0.9 < M < 1.3'
200 if specific:
201 Lam_cut += ' and isInRestOfEvent > 0.5'
202 L0 = Particle('Lambda0',
203 MVAConfiguration(variables=['dr', 'dz', 'distance', 'significanceOfDistance', 'chiProb', 'M', 'abs(dM)',
204 'useCMSFrame(E)', 'daughterAngle(0,1)',
205 'cosAngleBetweenMomentumAndVertexVector',
206 'extraInfo(preCut_rank)', 'extraInfo(goodLambda)', 'extraInfo(ksnbVLike)',
207 'extraInfo(ksnbNoLam)'],
208 target='isSignal'),
209 PreCutConfiguration(userCut=Lam_cut,
210 bestCandidateVariable='abs(dM)',
211 bestCandidateCut=20),
212 PostCutConfiguration(bestCandidateCut=10, value=0.01))
213 L0.addChannel(['Lambda0:V0'])
214
215 else:
216
217 pi0 = Particle('pi0',
218 MVAConfiguration(variables=['M', 'daughter({},extraInfo(SignalProbability))', 'extraInfo(preCut_rank)',
219 'daughterAngle(0,1)', 'pt', 'pz', 'E', 'abs(dM)'],
220 target='isSignal'),
221 PreCutConfiguration(userCut='0.08 < M < 0.18',
222 bestCandidateVariable='abs(dM)',
223 bestCandidateCut=20),
224 PostCutConfiguration(bestCandidateCut=10, value=0.01))
225 pi0.addChannel(['gamma', 'gamma'])
226
227 KS0 = Particle('K_S0',
228 MVAConfiguration(variables=['dr', 'dz', 'distance', 'significanceOfDistance', 'chiProb', 'M', 'abs(dM)',
229 'useCMSFrame(E)', 'daughterAngle(0,1)',
230 'daughter({},extraInfo(SignalProbability))',
231 'useRestFrame(daughter({}, p))', 'cosAngleBetweenMomentumAndVertexVector',
232 'daughter({}, dz)', 'daughter({}, dr)', 'extraInfo(preCut_rank)'],
233 target='isSignal'),
234 PreCutConfiguration(userCut='0.4 < M < 0.6',
235 bestCandidateVariable='abs(dM)',
236 bestCandidateCut=20),
237 PostCutConfiguration(bestCandidateCut=10, value=0.01))
238 KS0.addChannel(['pi+', 'pi-'])
239 KS0.addChannel(['pi0', 'pi0'])
240
241 ks0_cut = '0.4 < M < 0.6'
242 if specific:
243 ks0_cut += ' and isInRestOfEvent > 0.5'
244
245 KS0.addChannel(['K_S0:V0'],
246 MVAConfiguration(variables=['dr', 'dz', 'distance', 'significanceOfDistance', 'chiProb', 'M',
247 'useCMSFrame(E)', 'daughterAngle(0,1)', 'extraInfo(preCut_rank)', 'abs(dM)',
248 'useRestFrame(daughter({}, p))', 'cosAngleBetweenMomentumAndVertexVector',
249 'daughter({}, dz)', 'daughter({}, dr)'],
250 target='isSignal'),
251 PreCutConfiguration(userCut=ks0_cut,
252 bestCandidateVariable='abs(dM)',
253 bestCandidateCut=20))
254
255 L0 = Particle('Lambda0',
256 MVAConfiguration(variables=['dr', 'dz', 'distance', 'significanceOfDistance', 'chiProb', 'M', 'abs(dM)',
257 'useCMSFrame(E)', 'daughterAngle(0,1)',
258 'daughter({},extraInfo(SignalProbability))',
259 'useRestFrame(daughter({}, p))', 'cosAngleBetweenMomentumAndVertexVector',
260 'daughter({}, dz)', 'daughter({}, dr)', 'extraInfo(preCut_rank)'],
261 target='isSignal'),
262 PreCutConfiguration(userCut='0.9 < M < 1.3',
263 bestCandidateVariable='abs(dM)',
264 bestCandidateCut=20),
265 PostCutConfiguration(bestCandidateCut=10, value=0.01))
266 L0.addChannel(['p+', 'pi-'])
267
268 Lam_cut = '0.9 < M < 1.3'
269 if specific:
270 Lam_cut += ' and isInRestOfEvent > 0.5'
271
272 L0.addChannel(['Lambda0:V0'],
273 MVAConfiguration(variables=['dr', 'dz', 'distance', 'significanceOfDistance', 'chiProb', 'M',
274 'useCMSFrame(E)', 'daughterAngle(0,1)', 'extraInfo(preCut_rank)', 'abs(dM)',
275 'useRestFrame(daughter({}, p))', 'cosAngleBetweenMomentumAndVertexVector',
276 'daughter({}, dz)', 'daughter({}, dr)'],
277 target='isSignal'),
278 PreCutConfiguration(userCut=Lam_cut,
279 bestCandidateVariable='abs(dM)',
280 bestCandidateCut=20))
281 kl0_cut = ''
282 if specific:
283 kl0_cut += 'isInRestOfEvent > 0.5'
284
285 KL0 = Particle('K_L0',
286 MVAConfiguration(variables=['E', 'klmClusterTiming'],
287 target='isSignal'),
288 PreCutConfiguration(userCut=kl0_cut,
289 bestCandidateVariable='abs(dM)',
290 bestCandidateCut=20),
291 PostCutConfiguration(bestCandidateCut=10, value=0.01))
292 KL0.addChannel(['K_L0:FSP'])
293
294 SigmaP = Particle('Sigma+',
295 MVAConfiguration(variables=['dr', 'dz', 'distance', 'significanceOfDistance', 'chiProb', 'M', 'abs(dM)',
296 'useCMSFrame(E)', 'daughterAngle(0,1)',
297 'daughter({},extraInfo(SignalProbability))',
298 'useRestFrame(daughter({}, p))', 'cosAngleBetweenMomentumAndVertexVector',
299 'daughter({}, dz)', 'daughter({}, dr)', 'extraInfo(preCut_rank)'],
300 target='isSignal'),
301 PreCutConfiguration(userCut='1.0 < M < 1.4',
302 bestCandidateVariable='abs(dM)',
303 bestCandidateCut=20),
304 PostCutConfiguration(bestCandidateCut=10, value=0.01))
305 SigmaP.addChannel(['p+', 'pi0'])
306 # variables for D mesons and J/Psi
307 intermediate_vars = ['daughterProductOf(extraInfo(SignalProbability))', 'daughter({},extraInfo(SignalProbability))',
308 'chiProb', 'daughter({}, chiProb)', 'extraInfo(preCut_rank)', 'abs(dM)',
309 'useRestFrame(daughter({}, p))',
310 'useRestFrame(daughter({}, distance))',
311 'decayAngle({})', 'daughterAngle({},{})', 'cosAngleBetweenMomentumAndVertexVector',
312 'daughterInvariantMass({},{})', 'daughterInvariantMass({},{},{})', 'daughterInvariantMass({},{},{},{})',
313 'daughterInvariantMass({},{},{},{},{})', 'dQ', 'Q', 'dM', 'daughter({},extraInfo(decayModeID))']
314
315 # TODO if specific:
316 # We can not do this in the generic case (because this would heavily influence our performance on the unknown signal events
317 # but in the specific case this could work well
318 # intermediate_vars = ['nRemainingTracksInEvent']
319 LC = Particle('Lambda_c+',
320 MVAConfiguration(variables=intermediate_vars,
321 target='isSignal'),
322 PreCutConfiguration(userCut='2.2 < M < 2.4',
323 bestCandidateVariable='abs(dM)',
324 bestCandidateCut=20),
325 PostCutConfiguration(bestCandidateCut=10, value=0.001))
326 LC.addChannel(['p+', 'K-', 'pi+'])
327 LC.addChannel(['p+', 'pi-', 'pi+'])
328 LC.addChannel(['p+', 'K-', 'K+'])
329 LC.addChannel(['p+', 'K-', 'pi+', 'pi0'])
330 LC.addChannel(['p+', 'K-', 'pi+', 'pi0', 'pi0'])
331 LC.addChannel(['p+', 'pi+', 'pi+', 'pi-', 'pi-'])
332 LC.addChannel(['p+', 'K_S0'])
333 LC.addChannel(['p+', 'K_S0', 'pi0'])
334 LC.addChannel(['p+', 'K_S0', 'pi+', 'pi-'])
335 LC.addChannel(['Lambda0', 'pi+'])
336 LC.addChannel(['Lambda0', 'pi+', 'pi0'])
337 LC.addChannel(['Lambda0', 'pi+', 'pi-', 'pi+'])
338 LC.addChannel(['Lambda0', 'pi+', 'gamma'])
339 LC.addChannel(['Lambda0', 'pi+', 'pi0', 'gamma'])
340 LC.addChannel(['Lambda0', 'pi+', 'pi-', 'pi+', 'gamma'])
341 LC.addChannel(['Sigma+', 'pi+', 'pi-'])
342 LC.addChannel(['Sigma+', 'pi+', 'pi-', 'pi0'])
343 LC.addChannel(['Sigma+', 'pi0'])
344
345 D0 = Particle('D0',
346 MVAConfiguration(variables=intermediate_vars,
347 target='isSignal'),
348 PreCutConfiguration(userCut='1.7 < M < 1.95',
349 bestCandidateVariable='abs(dM)',
350 bestCandidateCut=20),
351 PostCutConfiguration(bestCandidateCut=10, value=0.001))
352 D0.addChannel(['K-', 'pi+'])
353 D0.addChannel(['K-', 'pi+', 'pi0'])
354 D0.addChannel(['K-', 'pi+', 'pi0', 'pi0'])
355 D0.addChannel(['K-', 'pi+', 'pi+', 'pi-'])
356 D0.addChannel(['K-', 'pi+', 'pi+', 'pi-', 'pi0'])
357 D0.addChannel(['pi-', 'pi+'])
358 D0.addChannel(['pi-', 'pi+', 'pi+', 'pi-'])
359 D0.addChannel(['pi-', 'pi+', 'pi0'])
360 D0.addChannel(['pi-', 'pi+', 'pi0', 'pi0'])
361 D0.addChannel(['K_S0', 'pi0'])
362 D0.addChannel(['K_S0', 'pi+', 'pi-'])
363 D0.addChannel(['K_S0', 'pi+', 'pi-', 'pi0'])
364 D0.addChannel(['K-', 'K+'])
365 D0.addChannel(['K-', 'K+', 'pi0'])
366 D0.addChannel(['K-', 'K+', 'K_S0'])
367
368 if not removeSLD and semileptonic:
369 D0_SL = Particle('D0:semileptonic',
370 MVAConfiguration(variables=intermediate_vars,
371 target='isSignalAcceptMissingNeutrino'),
372 PreCutConfiguration(userCut='',
373 bestCandidateMode='highest',
374 bestCandidateVariable='daughterProductOf(extraInfo(SignalProbability))',
375 bestCandidateCut=20),
376 PostCutConfiguration(bestCandidateCut=10, value=0.001))
377
378 D0_SL.addChannel(['K-', 'e+'])
379 D0_SL.addChannel(['K-', 'mu+'])
380 D0_SL.addChannel(['K-', 'pi0', 'e+'])
381 D0_SL.addChannel(['K-', 'pi0', 'mu+'])
382 D0_SL.addChannel(['K_S0', 'pi-', 'e+'])
383 D0_SL.addChannel(['K_S0', 'pi-', 'mu+'])
384
385 if KLong:
386 D0_KL = Particle('D0:KL',
387 MVAConfiguration(variables=intermediate_vars,
388 target='isSignal'),
389 PreCutConfiguration(userCut='',
390 bestCandidateMode='highest',
391 bestCandidateVariable='daughterProductOf(extraInfo(SignalProbability))',
392 bestCandidateCut=20),
393 PostCutConfiguration(bestCandidateCut=10, value=0.001))
394
395 D0_KL.addChannel(['K_L0', 'pi0'])
396 D0_KL.addChannel(['K_L0', 'pi+', 'pi-'])
397 D0_KL.addChannel(['K_L0', 'pi+', 'pi-', 'pi0'])
398 D0_KL.addChannel(['K-', 'K+', 'K_L0'])
399
400 DP = Particle('D+',
401 MVAConfiguration(variables=intermediate_vars,
402 target='isSignal'),
403 PreCutConfiguration(userCut='1.7 < M < 1.95',
404 bestCandidateVariable='abs(dM)',
405 bestCandidateCut=20),
406 PostCutConfiguration(bestCandidateCut=10, value=0.001))
407
408 DP.addChannel(['K-', 'pi+', 'pi+'])
409 DP.addChannel(['K-', 'pi+', 'pi+', 'pi0'])
410 DP.addChannel(['K-', 'K+', 'pi+'])
411 DP.addChannel(['K-', 'K+', 'pi+', 'pi0'])
412 DP.addChannel(['pi+', 'pi0'])
413 DP.addChannel(['pi+', 'pi+', 'pi-'])
414 DP.addChannel(['pi+', 'pi+', 'pi-', 'pi0'])
415 DP.addChannel(['K_S0', 'pi+'])
416 DP.addChannel(['K_S0', 'pi+', 'pi0'])
417 DP.addChannel(['K_S0', 'pi+', 'pi+', 'pi-'])
418 DP.addChannel(['K+', 'K_S0', 'K_S0'])
419
420 if not removeSLD and semileptonic:
421 DP_SL = Particle('D+:semileptonic',
422 MVAConfiguration(variables=intermediate_vars,
423 target='isSignalAcceptMissingNeutrino'),
424 PreCutConfiguration(userCut='',
425 bestCandidateMode='highest',
426 bestCandidateVariable='daughterProductOf(extraInfo(SignalProbability))',
427 bestCandidateCut=20),
428 PostCutConfiguration(bestCandidateCut=10, value=0.001))
429
430 DP_SL.addChannel(['K_S0', 'e+'])
431 DP_SL.addChannel(['K_S0', 'mu+'])
432 DP_SL.addChannel(['K-', 'pi+', 'e+'])
433 DP_SL.addChannel(['K-', 'pi+', 'mu+'])
434
435 if KLong:
436 DP_KL = Particle('D+:KL',
437 MVAConfiguration(variables=intermediate_vars,
438 target='isSignal'),
439 PreCutConfiguration(userCut='',
440 bestCandidateMode='highest',
441 bestCandidateVariable='daughterProductOf(extraInfo(SignalProbability))',
442 bestCandidateCut=20),
443 PostCutConfiguration(bestCandidateCut=10, value=0.001))
444
445 DP_KL.addChannel(['K_L0', 'pi+'])
446 DP_KL.addChannel(['K_L0', 'pi+', 'pi0'])
447 DP_KL.addChannel(['K_L0', 'pi+', 'pi+', 'pi-'])
448 DP_KL.addChannel(['K+', 'K_L0', 'K_S0'])
449 DP_KL.addChannel(['K+', 'K_L0', 'K_L0'])
450
451 Jpsi = Particle('J/psi',
452 MVAConfiguration(variables=intermediate_vars,
453 target='isSignal'),
454 PreCutConfiguration(userCut='2.6 < M < 3.7',
455 bestCandidateVariable='abs(dM)',
456 bestCandidateCut=20),
457 PostCutConfiguration(bestCandidateCut=10, value=0.001))
458
459 Jpsi.addChannel(['e+', 'e-'])
460 Jpsi.addChannel(['mu+', 'mu-'])
461
462 DSP = Particle('D*+',
463 MVAConfiguration(variables=intermediate_vars,
464 target='isSignal'),
465 PreCutConfiguration(userCut='0 < Q < 0.3',
466 bestCandidateVariable='abs(dQ)',
467 bestCandidateCut=20),
468 PostCutConfiguration(bestCandidateCut=10, value=0.001))
469
470 DSP.addChannel(['D0', 'pi+'])
471 DSP.addChannel(['D+', 'pi0'])
472 DSP.addChannel(['D+', 'gamma'])
473
474 if not removeSLD and semileptonic:
475 DSP_SL = Particle('D*+:semileptonic',
476 MVAConfiguration(variables=intermediate_vars,
477 target='isSignalAcceptMissingNeutrino'),
478 PreCutConfiguration(userCut='0 < Q < 0.3',
479 bestCandidateVariable='abs(dQ)',
480 bestCandidateCut=20),
481 PostCutConfiguration(bestCandidateCut=10, value=0.001))
482
483 DSP_SL.addChannel(['D0:semileptonic', 'pi+'])
484 DSP_SL.addChannel(['D+:semileptonic', 'pi0'])
485 DSP_SL.addChannel(['D+:semileptonic', 'gamma'])
486
487 if KLong:
488 DSP_KL = Particle('D*+:KL',
489 MVAConfiguration(variables=intermediate_vars,
490 target='isSignal'),
491 PreCutConfiguration(userCut='0 < Q < 0.3',
492 bestCandidateVariable='abs(dQ)',
493 bestCandidateCut=20),
494 PostCutConfiguration(bestCandidateCut=10, value=0.001))
495
496 DSP_KL.addChannel(['D0:KL', 'pi+'])
497 DSP_KL.addChannel(['D+:KL', 'pi0'])
498 DSP_KL.addChannel(['D+:KL', 'gamma'])
499
500 DS0 = Particle('D*0',
501 MVAConfiguration(variables=intermediate_vars,
502 target='isSignal'),
503 PreCutConfiguration(userCut='0 < Q < 0.3',
504 bestCandidateVariable='abs(dQ)',
505 bestCandidateCut=20),
506 PostCutConfiguration(bestCandidateCut=10, value=0.001))
507
508 DS0.addChannel(['D0', 'pi0'])
509 DS0.addChannel(['D0', 'gamma'])
510
511 if not removeSLD and semileptonic:
512 DS0_SL = Particle('D*0:semileptonic',
513 MVAConfiguration(variables=intermediate_vars,
514 target='isSignalAcceptMissingNeutrino'),
515 PreCutConfiguration(userCut='0 < Q < 0.3',
516 bestCandidateVariable='abs(dQ)',
517 bestCandidateCut=20),
518 PostCutConfiguration(bestCandidateCut=10, value=0.001))
519
520 DS0_SL.addChannel(['D0:semileptonic', 'pi0'])
521 DS0_SL.addChannel(['D0:semileptonic', 'gamma'])
522
523 if KLong:
524 DS0_KL = Particle('D*0:KL',
525 MVAConfiguration(variables=intermediate_vars,
526 target='isSignal'),
527 PreCutConfiguration(userCut='0 < Q < 0.3',
528 bestCandidateVariable='abs(dQ)',
529 bestCandidateCut=20),
530 PostCutConfiguration(bestCandidateCut=10, value=0.001))
531
532 DS0_KL.addChannel(['D0:KL', 'pi0'])
533 DS0_KL.addChannel(['D0:KL', 'gamma'])
534
535 DS = Particle('D_s+',
536 MVAConfiguration(variables=intermediate_vars,
537 target='isSignal'),
538 PreCutConfiguration(userCut='1.68 < M < 2.1',
539 bestCandidateVariable='abs(dM)',
540 bestCandidateCut=20),
541 PostCutConfiguration(bestCandidateCut=10, value=0.001))
542
543 DS.addChannel(['K+', 'K_S0'])
544 DS.addChannel(['K+', 'pi+', 'pi-'])
545 DS.addChannel(['K+', 'K-', 'pi+'])
546 DS.addChannel(['K+', 'K-', 'pi+', 'pi0'])
547 DS.addChannel(['K+', 'K_S0', 'pi+', 'pi-'])
548 DS.addChannel(['K-', 'K_S0', 'pi+', 'pi+'])
549 DS.addChannel(['K+', 'K-', 'pi+', 'pi+', 'pi-'])
550 DS.addChannel(['pi+', 'pi+', 'pi-'])
551 DS.addChannel(['K_S0', 'pi+'])
552 DS.addChannel(['K_S0', 'pi+', 'pi0'])
553
554 if KLong:
555 DS_KL = Particle('D_s+:KL',
556 MVAConfiguration(variables=intermediate_vars,
557 target='isSignal'),
558 PreCutConfiguration(userCut='',
559 bestCandidateMode='highest',
560 bestCandidateVariable='daughterProductOf(extraInfo(SignalProbability))',
561 bestCandidateCut=20),
562 PostCutConfiguration(bestCandidateCut=10, value=0.001))
563
564 DS_KL.addChannel(['K+', 'K_L0'])
565 DS_KL.addChannel(['K+', 'K_L0', 'pi+', 'pi-'])
566 DS_KL.addChannel(['K-', 'K_L0', 'pi+', 'pi+'])
567 DS_KL.addChannel(['K_L0', 'pi+'])
568 DS_KL.addChannel(['K_L0', 'pi+', 'pi0'])
569
570 DSS = Particle('D_s*+',
571 MVAConfiguration(variables=intermediate_vars,
572 target='isSignal'),
573 PreCutConfiguration(userCut='0.0 < Q < 0.3',
574 bestCandidateVariable='abs(dQ)',
575 bestCandidateCut=20),
576 PostCutConfiguration(bestCandidateCut=10, value=0.001))
577
578 DSS.addChannel(['D_s+', 'gamma'])
579 DSS.addChannel(['D_s+', 'pi0'])
580
581 if KLong:
582 DSS_KL = Particle('D_s*+:KL',
583 MVAConfiguration(variables=intermediate_vars,
584 target='isSignal'),
585 PreCutConfiguration(userCut='0.0 < Q < 0.3',
586 bestCandidateVariable='abs(dQ)',
587 bestCandidateCut=20),
588 PostCutConfiguration(bestCandidateCut=10, value=0.001))
589
590 DSS_KL.addChannel(['D_s+:KL', 'gamma'])
591 DSS_KL.addChannel(['D_s+:KL', 'pi0'])
592
593 # note: these should not be correlated to Mbc (weak correlation of deltaE is OK)
594 B_vars = ['daughterProductOf(extraInfo(SignalProbability))', 'daughter({},extraInfo(SignalProbability))',
595 'chiProb', 'daughter({}, chiProb)', 'extraInfo(preCut_rank)',
596 'useRestFrame(daughter({}, p))',
597 'useRestFrame(daughter({}, distance))',
598 'decayAngle({})', 'daughterAngle({},{})', 'cosAngleBetweenMomentumAndVertexVector',
599 'dr', 'dz', 'dx', 'dy', 'distance', 'significanceOfDistance', 'deltaE', 'daughter({},extraInfo(decayModeID))']
600
601 hadronic_user_cut = 'Mbc > 5.2 and abs(deltaE) < 0.5'
602 if B_extra_cut is not None:
603 hadronic_user_cut += ' and [' + B_extra_cut + ']'
604
605 BP = Particle('B+',
606 MVAConfiguration(variables=B_vars,
607 target='isSignal'),
608 PreCutConfiguration(userCut=hadronic_user_cut,
609 bestCandidateMode='highest',
610 bestCandidateVariable='daughterProductOf(extraInfo(SignalProbability))',
611 bestCandidateCut=20),
612 PostCutConfiguration(bestCandidateCut=20))
613
614 BP.addChannel(['anti-D0', 'pi+'])
615 BP.addChannel(['anti-D0', 'pi+', 'pi0'])
616 BP.addChannel(['anti-D0', 'pi+', 'pi0', 'pi0'])
617 BP.addChannel(['anti-D0', 'pi+', 'pi+', 'pi-'])
618 BP.addChannel(['anti-D0', 'pi+', 'pi+', 'pi-', 'pi0'])
619 BP.addChannel(['anti-D0', 'D+'])
620 BP.addChannel(['anti-D0', 'D+', 'K_S0'])
621 BP.addChannel(['anti-D*0', 'D+', 'K_S0'])
622 BP.addChannel(['anti-D0', 'D*+', 'K_S0'])
623 BP.addChannel(['anti-D*0', 'D*+', 'K_S0'])
624 BP.addChannel(['anti-D0', 'D0', 'K+'])
625 BP.addChannel(['anti-D*0', 'D0', 'K+'])
626 BP.addChannel(['anti-D0', 'D*0', 'K+'])
627 BP.addChannel(['anti-D*0', 'D*0', 'K+'])
628 BP.addChannel(['D_s+', 'anti-D0'])
629 BP.addChannel(['anti-D*0', 'pi+'])
630 BP.addChannel(['anti-D*0', 'pi+', 'pi0'])
631 BP.addChannel(['anti-D*0', 'pi+', 'pi0', 'pi0'])
632 BP.addChannel(['anti-D*0', 'pi+', 'pi+', 'pi-'])
633 BP.addChannel(['anti-D*0', 'pi+', 'pi+', 'pi-', 'pi0'])
634 BP.addChannel(['D_s*+', 'anti-D0'])
635 BP.addChannel(['D_s+', 'anti-D*0'])
636 BP.addChannel(['anti-D0', 'K+'])
637 BP.addChannel(['D-', 'pi+', 'pi+'])
638 BP.addChannel(['D-', 'pi+', 'pi+', 'pi0'])
639 BP.addChannel(['J/psi', 'K+'], preCutConfig=BP.preCutConfig._replace(noBackgroundSampling=True))
640 BP.addChannel(['J/psi', 'K+', 'pi+', 'pi-'])
641 BP.addChannel(['J/psi', 'K+', 'pi0'])
642 BP.addChannel(['J/psi', 'K_S0', 'pi+'])
643 if baryonic:
644 BP.addChannel(['anti-Lambda_c-', 'p+', 'pi+', 'pi0'])
645 BP.addChannel(['anti-Lambda_c-', 'p+', 'pi+', 'pi-', 'pi+'])
646 BP.addChannel(['anti-D0', 'p+', 'anti-p-', 'pi+'])
647 BP.addChannel(['anti-D*0', 'p+', 'anti-p-', 'pi+'])
648 BP.addChannel(['D+', 'p+', 'anti-p-', 'pi+', 'pi-'])
649 BP.addChannel(['D*+', 'p+', 'anti-p-', 'pi+', 'pi-'])
650 BP.addChannel(['anti-Lambda_c-', 'p+', 'pi+'])
651
652 B_SL_vars = ['daughterProductOf(extraInfo(SignalProbability))', 'daughter({},extraInfo(SignalProbability))',
653 'chiProb', 'daughter({}, chiProb)', 'extraInfo(preCut_rank)',
654 'useRestFrame(daughter({}, p))',
655 'useRestFrame(daughter({}, distance))',
656 'cosAngleBetweenMomentumAndVertexVector',
657 'dr', 'dz', 'dx', 'dy', 'distance', 'significanceOfDistance', 'daughter({},extraInfo(decayModeID))']
658
659 semileptonic_user_cut = ''
660 if B_extra_cut is not None:
661 semileptonic_user_cut += B_extra_cut
662
663 BP_SL = Particle('B+:semileptonic',
664 MVAConfiguration(variables=B_SL_vars,
665 target='isSignalAcceptMissingNeutrino'),
666 PreCutConfiguration(userCut=semileptonic_user_cut,
667 bestCandidateMode='highest',
668 bestCandidateVariable='daughterProductOf(extraInfo(SignalProbability))',
669 bestCandidateCut=20),
670 PostCutConfiguration(bestCandidateCut=20))
671 BP_SL.addChannel(['anti-D0', 'e+'])
672 BP_SL.addChannel(['anti-D0', 'mu+'])
673 BP_SL.addChannel(['anti-D*0', 'e+'])
674 BP_SL.addChannel(['anti-D*0', 'mu+'])
675 BP_SL.addChannel(['D-', 'pi+', 'e+'])
676 BP_SL.addChannel(['D-', 'pi+', 'mu+'])
677 BP_SL.addChannel(['D*-', 'pi+', 'e+'])
678 BP_SL.addChannel(['D*-', 'pi+', 'mu+'])
679
680 if not removeSLD and semileptonic:
681 BP_SL.addChannel(['anti-D0:semileptonic', 'pi+'])
682 BP_SL.addChannel(['anti-D0:semileptonic', 'pi+', 'pi0'])
683 BP_SL.addChannel(['anti-D0:semileptonic', 'pi+', 'pi0', 'pi0'])
684 BP_SL.addChannel(['anti-D0:semileptonic', 'pi+', 'pi+', 'pi-'])
685 BP_SL.addChannel(['anti-D0:semileptonic', 'pi+', 'pi+', 'pi-', 'pi0'])
686 BP_SL.addChannel(['anti-D0:semileptonic', 'D+'])
687 BP_SL.addChannel(['anti-D0:semileptonic', 'D+', 'K_S0'])
688 BP_SL.addChannel(['anti-D*0:semileptonic', 'D+', 'K_S0'])
689 BP_SL.addChannel(['anti-D0:semileptonic', 'D*+', 'K_S0'])
690 BP_SL.addChannel(['anti-D*0:semileptonic', 'D*+', 'K_S0'])
691 BP_SL.addChannel(['anti-D0:semileptonic', 'D0', 'K+'])
692 BP_SL.addChannel(['anti-D*0:semileptonic', 'D0', 'K+'])
693 BP_SL.addChannel(['anti-D0:semileptonic', 'D*0', 'K+'])
694 BP_SL.addChannel(['anti-D*0:semileptonic', 'D*0', 'K+'])
695 BP_SL.addChannel(['anti-D0', 'D+:semileptonic'])
696 BP_SL.addChannel(['anti-D0', 'D+:semileptonic', 'K_S0'])
697 BP_SL.addChannel(['anti-D*0', 'D+:semileptonic', 'K_S0'])
698 BP_SL.addChannel(['anti-D0', 'D*+:semileptonic', 'K_S0'])
699 BP_SL.addChannel(['anti-D*0', 'D*+:semileptonic', 'K_S0'])
700 BP_SL.addChannel(['anti-D0', 'D0:semileptonic', 'K+'])
701 BP_SL.addChannel(['anti-D*0', 'D0:semileptonic', 'K+'])
702 BP_SL.addChannel(['anti-D0', 'D*0:semileptonic', 'K+'])
703 BP_SL.addChannel(['anti-D*0', 'D*0:semileptonic', 'K+'])
704 BP_SL.addChannel(['D_s+', 'anti-D0:semileptonic'])
705 BP_SL.addChannel(['anti-D*0:semileptonic', 'pi+'])
706 BP_SL.addChannel(['anti-D*0:semileptonic', 'pi+', 'pi0'])
707 BP_SL.addChannel(['anti-D*0:semileptonic', 'pi+', 'pi0', 'pi0'])
708 BP_SL.addChannel(['anti-D*0:semileptonic', 'pi+', 'pi+', 'pi-'])
709 BP_SL.addChannel(['anti-D*0:semileptonic', 'pi+', 'pi+', 'pi-', 'pi0'])
710 BP_SL.addChannel(['D_s*+', 'anti-D0:semileptonic'])
711 BP_SL.addChannel(['D_s+', 'anti-D*0:semileptonic'])
712 BP_SL.addChannel(['anti-D0:semileptonic', 'K+'])
713 BP_SL.addChannel(['D-:semileptonic', 'pi+', 'pi+'])
714 BP_SL.addChannel(['D-:semileptonic', 'pi+', 'pi+', 'pi0'])
715
716 if KLong:
717 BP_KL = Particle('B+:KL',
718 MVAConfiguration(variables=B_vars,
719 target='isSignal'),
720 PreCutConfiguration(userCut=semileptonic_user_cut,
721 bestCandidateMode='highest',
722 bestCandidateVariable='daughterProductOf(extraInfo(SignalProbability))',
723 bestCandidateCut=20),
724 PostCutConfiguration(bestCandidateCut=20))
725 BP_KL.addChannel(['anti-D0:KL', 'pi+'])
726 BP_KL.addChannel(['anti-D0:KL', 'pi+', 'pi0'])
727 BP_KL.addChannel(['anti-D0:KL', 'pi+', 'pi0', 'pi0'])
728 BP_KL.addChannel(['anti-D0:KL', 'pi+', 'pi+', 'pi-'])
729 BP_KL.addChannel(['anti-D0:KL', 'pi+', 'pi+', 'pi-', 'pi0'])
730 BP_KL.addChannel(['anti-D0:KL', 'D+'])
731 BP_KL.addChannel(['anti-D0:KL', 'D+', 'K_S0'])
732 BP_KL.addChannel(['anti-D*0:KL', 'D+', 'K_S0'])
733 BP_KL.addChannel(['anti-D0:KL', 'D*+', 'K_S0'])
734 BP_KL.addChannel(['anti-D*0:KL', 'D*+', 'K_S0'])
735 BP_KL.addChannel(['anti-D0:KL', 'D0', 'K+'])
736 BP_KL.addChannel(['anti-D*0:KL', 'D0', 'K+'])
737 BP_KL.addChannel(['anti-D0:KL', 'D*0', 'K+'])
738 BP_KL.addChannel(['anti-D*0:KL', 'D*0', 'K+'])
739 BP_KL.addChannel(['anti-D0', 'D+:KL'])
740 BP_KL.addChannel(['anti-D0', 'D+:KL', 'K_S0'])
741 BP_KL.addChannel(['anti-D*0', 'D+:KL', 'K_S0'])
742 BP_KL.addChannel(['anti-D0', 'D*+:KL', 'K_S0'])
743 BP_KL.addChannel(['anti-D*0', 'D*+:KL', 'K_S0'])
744 BP_KL.addChannel(['anti-D0', 'D0:KL', 'K+'])
745 BP_KL.addChannel(['anti-D*0', 'D0:KL', 'K+'])
746 BP_KL.addChannel(['anti-D0', 'D*0:KL', 'K+'])
747 BP_KL.addChannel(['anti-D*0', 'D*0:KL', 'K+'])
748 BP_KL.addChannel(['D_s+', 'anti-D0:KL'])
749 BP_KL.addChannel(['D_s+:KL', 'anti-D0'])
750 BP_KL.addChannel(['anti-D*0:KL', 'pi+'])
751 BP_KL.addChannel(['anti-D*0:KL', 'pi+', 'pi0'])
752 BP_KL.addChannel(['anti-D*0:KL', 'pi+', 'pi0', 'pi0'])
753 BP_KL.addChannel(['anti-D*0:KL', 'pi+', 'pi+', 'pi-'])
754 BP_KL.addChannel(['anti-D*0:KL', 'pi+', 'pi+', 'pi-', 'pi0'])
755 BP_KL.addChannel(['D_s*+', 'anti-D0:KL'])
756 BP_KL.addChannel(['D_s+', 'anti-D*0:KL'])
757 BP_KL.addChannel(['D_s*+:KL', 'anti-D0'])
758 BP_KL.addChannel(['D_s+:KL', 'anti-D*0'])
759 BP_KL.addChannel(['anti-D0:KL', 'K+'])
760 BP_KL.addChannel(['D-:KL', 'pi+', 'pi+'])
761 BP_KL.addChannel(['D-:KL', 'pi+', 'pi+', 'pi0'])
762 BP_KL.addChannel(['anti-D0', 'D+', 'K_L0'])
763 BP_KL.addChannel(['anti-D*0', 'D+', 'K_L0'])
764 BP_KL.addChannel(['anti-D0', 'D*+', 'K_L0'])
765 BP_KL.addChannel(['anti-D*0', 'D*+', 'K_L0'])
766 BP_KL.addChannel(['J/psi', 'K_L0', 'pi+'])
767
768 B0 = Particle('B0',
769 MVAConfiguration(variables=B_vars,
770 target='isSignal'),
771 PreCutConfiguration(userCut=hadronic_user_cut,
772 bestCandidateMode='highest',
773 bestCandidateVariable='daughterProductOf(extraInfo(SignalProbability))',
774 bestCandidateCut=20),
775 PostCutConfiguration(bestCandidateCut=20))
776 B0.addChannel(['D-', 'pi+'])
777 B0.addChannel(['D-', 'pi+', 'pi0'])
778 B0.addChannel(['D-', 'pi+', 'pi0', 'pi0'])
779 B0.addChannel(['D-', 'pi+', 'pi+', 'pi-'])
780 B0.addChannel(['D-', 'pi+', 'pi+', 'pi-', 'pi0'])
781 B0.addChannel(['anti-D0', 'pi+', 'pi-'])
782 B0.addChannel(['D-', 'D0', 'K+'])
783 B0.addChannel(['D-', 'D*0', 'K+'])
784 B0.addChannel(['D*-', 'D0', 'K+'])
785 B0.addChannel(['D*-', 'D*0', 'K+'])
786 B0.addChannel(['D-', 'D+', 'K_S0'])
787 B0.addChannel(['D*-', 'D+', 'K_S0'])
788 B0.addChannel(['D-', 'D*+', 'K_S0'])
789 B0.addChannel(['D*-', 'D*+', 'K_S0'])
790 B0.addChannel(['D_s+', 'D-'])
791 B0.addChannel(['D*-', 'pi+'])
792 B0.addChannel(['D*-', 'pi+', 'pi0'])
793 B0.addChannel(['D*-', 'pi+', 'pi0', 'pi0'])
794 B0.addChannel(['D*-', 'pi+', 'pi+', 'pi-'])
795 B0.addChannel(['D*-', 'pi+', 'pi+', 'pi-', 'pi0'])
796 B0.addChannel(['D_s*+', 'D-'])
797 B0.addChannel(['D_s+', 'D*-'])
798 B0.addChannel(['D_s*+', 'D*-'])
799 B0.addChannel(['J/psi', 'K_S0'], preCutConfig=B0.preCutConfig._replace(noBackgroundSampling=True))
800 B0.addChannel(['J/psi', 'K+', 'pi-'])
801 B0.addChannel(['J/psi', 'K_S0', 'pi+', 'pi-'])
802 if baryonic:
803 B0.addChannel(['anti-Lambda_c-', 'p+', 'pi+', 'pi-'])
804 B0.addChannel(['anti-D0', 'p+', 'anti-p-'])
805 B0.addChannel(['D-', 'p+', 'anti-p-', 'pi+'])
806 B0.addChannel(['D*-', 'p+', 'anti-p-', 'pi+'])
807 B0.addChannel(['anti-D0', 'p+', 'anti-p-', 'pi+', 'pi-'])
808 B0.addChannel(['anti-D*0', 'p+', 'anti-p-', 'pi+', 'pi-'])
809
810 B0_SL = Particle('B0:semileptonic',
811 MVAConfiguration(variables=B_SL_vars,
812 target='isSignalAcceptMissingNeutrino'),
813 PreCutConfiguration(userCut=semileptonic_user_cut,
814 bestCandidateMode='highest',
815 bestCandidateVariable='daughterProductOf(extraInfo(SignalProbability))',
816 bestCandidateCut=20),
817 PostCutConfiguration(bestCandidateCut=20))
818 B0_SL.addChannel(['D-', 'e+'])
819 B0_SL.addChannel(['D-', 'mu+'])
820 B0_SL.addChannel(['D*-', 'e+'])
821 B0_SL.addChannel(['D*-', 'mu+'])
822 B0_SL.addChannel(['anti-D0', 'pi-', 'e+'])
823 B0_SL.addChannel(['anti-D0', 'pi-', 'mu+'])
824 B0_SL.addChannel(['anti-D*0', 'pi-', 'e+'])
825 B0_SL.addChannel(['anti-D*0', 'pi-', 'mu+'])
826
827 if not removeSLD and semileptonic:
828 B0_SL.addChannel(['D-:semileptonic', 'pi+'])
829 B0_SL.addChannel(['D-:semileptonic', 'pi+', 'pi0'])
830 B0_SL.addChannel(['D-:semileptonic', 'pi+', 'pi0', 'pi0'])
831 B0_SL.addChannel(['D-:semileptonic', 'pi+', 'pi+', 'pi-'])
832 B0_SL.addChannel(['D-:semileptonic', 'pi+', 'pi+', 'pi-', 'pi0'])
833 B0_SL.addChannel(['anti-D0:semileptonic', 'pi+', 'pi-'])
834 B0_SL.addChannel(['D-:semileptonic', 'D0', 'K+'])
835 B0_SL.addChannel(['D-:semileptonic', 'D*0', 'K+'])
836 B0_SL.addChannel(['D*-:semileptonic', 'D0', 'K+'])
837 B0_SL.addChannel(['D*-:semileptonic', 'D*0', 'K+'])
838 B0_SL.addChannel(['D-:semileptonic', 'D+', 'K_S0'])
839 B0_SL.addChannel(['D*-:semileptonic', 'D+', 'K_S0'])
840 B0_SL.addChannel(['D-:semileptonic', 'D*+', 'K_S0'])
841 B0_SL.addChannel(['D*-:semileptonic', 'D*+', 'K_S0'])
842 B0_SL.addChannel(['D-', 'D0:semileptonic', 'K+'])
843 B0_SL.addChannel(['D-', 'D*0:semileptonic', 'K+'])
844 B0_SL.addChannel(['D*-', 'D0:semileptonic', 'K+'])
845 B0_SL.addChannel(['D*-', 'D*0:semileptonic', 'K+'])
846 B0_SL.addChannel(['D-', 'D+:semileptonic', 'K_S0'])
847 B0_SL.addChannel(['D*-', 'D+:semileptonic', 'K_S0'])
848 B0_SL.addChannel(['D-', 'D*+:semileptonic', 'K_S0'])
849 B0_SL.addChannel(['D*-', 'D*+:semileptonic', 'K_S0'])
850 B0_SL.addChannel(['D_s+', 'D-:semileptonic'])
851 B0_SL.addChannel(['D*-:semileptonic', 'pi+'])
852 B0_SL.addChannel(['D*-:semileptonic', 'pi+', 'pi0'])
853 B0_SL.addChannel(['D*-:semileptonic', 'pi+', 'pi0', 'pi0'])
854 B0_SL.addChannel(['D*-:semileptonic', 'pi+', 'pi+', 'pi-'])
855 B0_SL.addChannel(['D*-:semileptonic', 'pi+', 'pi+', 'pi-', 'pi0'])
856 B0_SL.addChannel(['D_s*+', 'D-:semileptonic'])
857 B0_SL.addChannel(['D_s+', 'D*-:semileptonic'])
858 B0_SL.addChannel(['D_s*+', 'D*-:semileptonic'])
859
860 if KLong:
861 B0_KL = Particle('B0:KL',
862 MVAConfiguration(variables=B_vars,
863 target='isSignal'),
864 PreCutConfiguration(userCut=semileptonic_user_cut,
865 bestCandidateMode='highest',
866 bestCandidateVariable='daughterProductOf(extraInfo(SignalProbability))',
867 bestCandidateCut=20),
868 PostCutConfiguration(bestCandidateCut=20))
869 B0_KL.addChannel(['D-:KL', 'pi+'])
870 B0_KL.addChannel(['D-:KL', 'pi+', 'pi0'])
871 B0_KL.addChannel(['D-:KL', 'pi+', 'pi0', 'pi0'])
872 B0_KL.addChannel(['D-:KL', 'pi+', 'pi+', 'pi-'])
873 B0_KL.addChannel(['D-:KL', 'pi+', 'pi+', 'pi-', 'pi0'])
874 B0_KL.addChannel(['anti-D0:KL', 'pi+', 'pi-'])
875 B0_KL.addChannel(['D-:KL', 'D0', 'K+'])
876 B0_KL.addChannel(['D-:KL', 'D*0', 'K+'])
877 B0_KL.addChannel(['D*-:KL', 'D0', 'K+'])
878 B0_KL.addChannel(['D*-:KL', 'D*0', 'K+'])
879 B0_KL.addChannel(['D-:KL', 'D+', 'K_S0'])
880 B0_KL.addChannel(['D*-:KL', 'D+', 'K_S0'])
881 B0_KL.addChannel(['D-:KL', 'D*+', 'K_S0'])
882 B0_KL.addChannel(['D*-:KL', 'D*+', 'K_S0'])
883 B0_KL.addChannel(['D-', 'D0:KL', 'K+'])
884 B0_KL.addChannel(['D-', 'D*0:KL', 'K+'])
885 B0_KL.addChannel(['D*-', 'D0:KL', 'K+'])
886 B0_KL.addChannel(['D*-', 'D*0:KL', 'K+'])
887 B0_KL.addChannel(['D-', 'D+:KL', 'K_S0'])
888 B0_KL.addChannel(['D*-', 'D+:KL', 'K_S0'])
889 B0_KL.addChannel(['D-', 'D*+:KL', 'K_S0'])
890 B0_KL.addChannel(['D*-', 'D*+:KL', 'K_S0'])
891 B0_KL.addChannel(['D_s+', 'D-:KL'])
892 B0_KL.addChannel(['D_s+:KL', 'D-'])
893 B0_KL.addChannel(['D*-:KL', 'pi+'])
894 B0_KL.addChannel(['D*-:KL', 'pi+', 'pi0'])
895 B0_KL.addChannel(['D*-:KL', 'pi+', 'pi0', 'pi0'])
896 B0_KL.addChannel(['D*-:KL', 'pi+', 'pi+', 'pi-'])
897 B0_KL.addChannel(['D*-:KL', 'pi+', 'pi+', 'pi-', 'pi0'])
898 B0_KL.addChannel(['D_s*+', 'D-:KL'])
899 B0_KL.addChannel(['D_s+', 'D*-:KL'])
900 B0_KL.addChannel(['D_s*+', 'D*-:KL'])
901 B0_KL.addChannel(['D_s*+:KL', 'D-'])
902 B0_KL.addChannel(['D_s+:KL', 'D*-'])
903 B0_KL.addChannel(['D_s*+:KL', 'D*-'])
904 B0_KL.addChannel(['D-', 'D+', 'K_L0'])
905 B0_KL.addChannel(['D*-', 'D+', 'K_L0'])
906 B0_KL.addChannel(['D-', 'D*+', 'K_L0'])
907 B0_KL.addChannel(['D*-', 'D*+', 'K_L0'])
908 B0_KL.addChannel(['J/psi', 'K_L0'])
909 B0_KL.addChannel(['J/psi', 'K_L0', 'pi+', 'pi-'])
910
911 # Use deltaE + Mbc - m_(B_s) instead of deltaE since Bs has only one peak here (vs. 3 in deltaE)
912 Bs_vars = ['formula(deltaE+Mbc-5.3669)' if x == 'deltaE' else x for x in B_vars]
913
914 hadronic_bs_user_cut = 'Mbc > 5.3 and abs(formula(deltaE+Mbc-5.3669)) < 0.5'
915 if B_extra_cut is not None:
916 hadronic_bs_user_cut += ' and [' + B_extra_cut + ']'
917
918 BS = Particle('B_s0',
919 MVAConfiguration(variables=Bs_vars,
920 target='isSignal'),
921 PreCutConfiguration(userCut=hadronic_bs_user_cut,
922 bestCandidateMode='highest',
923 bestCandidateVariable='daughterProductOf(extraInfo(SignalProbability))',
924 bestCandidateCut=20),
925 PostCutConfiguration(bestCandidateCut=20))
926
927 # Override precut for some channels as this provides better performance
928 tight_precut = BS.preCutConfig._replace(userCut=hadronic_bs_user_cut + ' and abs(formula(deltaE+Mbc-5.3669)) < 0.1')
929
930 # D_s & D*
931 BS.addChannel(['D_s-', 'D_s+'], preCutConfig=tight_precut)
932 BS.addChannel(['D_s*+', 'D_s-'], preCutConfig=tight_precut)
933 BS.addChannel(['D_s*-', 'D_s+'], preCutConfig=tight_precut)
934 BS.addChannel(['D_s*+', 'D_s*-'], preCutConfig=tight_precut)
935 BS.addChannel(['D_s-', 'D+'], preCutConfig=tight_precut)
936 BS.addChannel(['D_s+', 'D*-'])
937 BS.addChannel(['D_s*+', 'D-'])
938 BS.addChannel(['D_s*+', 'D*-'])
939
940 # D_s
941 BS.addChannel(['D_s-', 'K+'])
942 BS.addChannel(['D_s+', 'K-'])
943 BS.addChannel(['D_s-', 'pi+'])
944 BS.addChannel(['D_s-', 'pi+', 'pi+', 'pi-'], preCutConfig=tight_precut)
945 BS.addChannel(['D_s-', 'D0', 'K+'], preCutConfig=tight_precut)
946 BS.addChannel(['D_s-', 'D+', 'K_S0'])
947 BS.addChannel(['D_s-', 'pi+', 'pi0'], preCutConfig=tight_precut) # rho+
948 BS.addChannel(['D_s-', 'D0', 'K+', 'pi0'], preCutConfig=tight_precut) # K*+
949 BS.addChannel(['D_s-', 'D0', 'K_S0', 'pi+']) # K*+
950 BS.addChannel(['D_s-', 'D+', 'K+', 'pi-']) # K*0
951 BS.addChannel(['D_s-', 'D+', 'K_S0', 'pi0']) # K*0
952 BS.addChannel(['D_s-', 'D*0', 'K+'], preCutConfig=tight_precut)
953 BS.addChannel(['D_s-', 'D*+', 'K_S0'])
954 BS.addChannel(['D_s-', 'D*0', 'K+', 'pi0']) # K*+
955 BS.addChannel(['D_s-', 'D*0', 'K_S0', 'pi+']) # K*+
956 BS.addChannel(['D_s-', 'D*+', 'K+', 'pi-']) # K*0
957 BS.addChannel(['D_s-', 'D*+', 'K_S0', 'pi0']) # K*0
958
959 # D_s*
960 BS.addChannel(['D_s*-', 'K+'])
961 BS.addChannel(['D_s*-', 'pi+'])
962 BS.addChannel(['D_s*-', 'D0', 'K+'], preCutConfig=tight_precut)
963 BS.addChannel(['D_s*-', 'D+', 'K_S0'])
964 BS.addChannel(['D_s*-', 'D*0', 'K+'], preCutConfig=tight_precut)
965 BS.addChannel(['D_s*-', 'D*+', 'K_S0'])
966 BS.addChannel(['D_s*-', 'pi+', 'pi+', 'pi-'], preCutConfig=tight_precut)
967 BS.addChannel(['D_s*-', 'pi+', 'pi0'], preCutConfig=tight_precut) # rho+
968 BS.addChannel(['D_s*-', 'D0', 'K+', 'pi0']) # K*+
969 BS.addChannel(['D_s*-', 'D0', 'K_S0', 'pi+']) # K*+
970 BS.addChannel(['D_s*-', 'D+', 'K+', 'pi-']) # K*0
971 BS.addChannel(['D_s*-', 'D+', 'K_S0', 'pi0']) # K*0
972 BS.addChannel(['D_s*-', 'D*0', 'K+', 'pi0']) # K*+
973 BS.addChannel(['D_s*-', 'D*0', 'K_S0', 'pi+']) # K*+
974 BS.addChannel(['D_s*-', 'D*+', 'K+', 'pi-']) # K*0
975 BS.addChannel(['D_s*-', 'D*+', 'K_S0', 'pi0']) # K*0
976
977 # J/Psi
978 BS.addChannel(['J/psi', 'K_S0'])
979 BS.addChannel(['J/psi', 'pi+', 'pi-'])
980 BS.addChannel(['J/psi', 'K+', 'K-'], preCutConfig=BS.preCutConfig._replace(noBackgroundSampling=True)) # Phi
981 BS.addChannel(['J/psi', 'K_S0', 'K-', 'pi+'])
982 BS.addChannel(['J/psi', 'K-', 'K+', 'pi0'])
983 BS.addChannel(['J/psi', 'pi-', 'pi+', 'pi0']) # Eta
984 BS.addChannel(['J/psi', 'pi+', 'pi-', 'pi-', 'pi+', 'pi0']) # Etaprime
985
986 # Other
987 BS.addChannel(['anti-D*0', 'K_S0'])
988 BS.addChannel(['anti-D0', 'K_S0'])
989 BS.addChannel(['anti-D0', 'K-', 'pi+'])
990
991 particles = []
992 particles.append(pion)
993 particles.append(kaon)
994 if baryonic:
995 particles.append(proton)
996 particles.append(muon)
997 particles.append(electron)
998 particles.append(gamma)
999
1000 particles.append(pi0)
1001 particles.append(KS0)
1002 if baryonic:
1003 particles.append(L0)
1004 particles.append(SigmaP)
1005 particles.append(Jpsi)
1006
1007 particles.append(D0)
1008 particles.append(DP)
1009 particles.append(DS)
1010 if baryonic:
1011 particles.append(LC)
1012
1013 particles.append(DS0)
1014 particles.append(DSP)
1015 particles.append(DSS)
1016
1017 if hadronic:
1018 if neutralB:
1019 particles.append(B0)
1020 if chargedB:
1021 particles.append(BP)
1022
1023 if KLong:
1024 particles.append(KL0)
1025 particles.append(D0_KL)
1026 particles.append(DP_KL)
1027 particles.append(DS_KL)
1028 particles.append(DS0_KL)
1029 particles.append(DSP_KL)
1030 particles.append(DSS_KL)
1031 if neutralB:
1032 particles.append(B0_KL)
1033 if chargedB:
1034 particles.append(BP_KL)
1035
1036 if semileptonic:
1037 if not removeSLD:
1038 particles.append(D0_SL)
1039 particles.append(DP_SL)
1040 particles.append(DS0_SL)
1041 particles.append(DSP_SL)
1042 if neutralB:
1043 particles.append(B0_SL)
1044 if chargedB:
1045 particles.append(BP_SL)
1046
1047 if strangeB:
1048 particles.append(BS)
1049
1050 return particles
1051
1052
1053def get_unittest_channels(specific=False):
1054 chargedVariables = ['electronID', 'extraInfo(preCut_rank)',
1055 'kaonID', 'protonID', 'muonID',
1056 'p', 'pt', 'pz', 'dr', 'dz', 'chiProb']
1057
1058 specific_cut = ''
1059 if specific:
1060 specific_cut = ' and isInRestOfEvent > 0.5'
1061
1062 pion = Particle('pi+',
1063 MVAConfiguration(variables=chargedVariables,
1064 target='isPrimarySignal'),
1065 PreCutConfiguration(userCut='[dr < 2] and [abs(dz) < 4]' + specific_cut,
1066 bestCandidateMode='highest',
1067 bestCandidateVariable='pionID',
1068 bestCandidateCut=20),
1069 PostCutConfiguration(bestCandidateCut=10, value=0.01))
1070 pion.addChannel(['pi+:FSP'])
1071
1072 kaon = Particle('K+',
1073 MVAConfiguration(variables=chargedVariables,
1074 target='isPrimarySignal'),
1075 PreCutConfiguration(userCut='[dr < 2] and [abs(dz) < 4]' + specific_cut,
1076 bestCandidateMode='highest',
1077 bestCandidateVariable='kaonID',
1078 bestCandidateCut=20),
1079 PostCutConfiguration(bestCandidateCut=10, value=0.01))
1080 kaon.addChannel(['K+:FSP'])
1081
1082 muon = Particle('mu+',
1083 MVAConfiguration(variables=chargedVariables,
1084 target='isPrimarySignal'),
1085 PreCutConfiguration(userCut='[dr < 2] and [abs(dz) < 4]' + specific_cut,
1086 bestCandidateVariable='muonID',
1087 bestCandidateMode='highest',
1088 bestCandidateCut=10),
1089 PostCutConfiguration(bestCandidateCut=5, value=0.01))
1090 muon.addChannel(['mu+:FSP'])
1091
1092 gamma = Particle('gamma',
1093 MVAConfiguration(variables=['clusterReg', 'clusterNHits', 'clusterTiming', 'clusterE9E25',
1094 'pt', 'E', 'pz', 'extraInfo(preCut_rank)'],
1095 target='isPrimarySignal'),
1096 PreCutConfiguration(userCut='E > 0.05' + specific_cut,
1097 bestCandidateMode='highest',
1098 bestCandidateVariable='E',
1099 bestCandidateCut=40),
1100 PostCutConfiguration(bestCandidateCut=20, value=0.01))
1101 gamma.addChannel(['gamma:FSP'])
1102 gamma.addChannel(['gamma:V0'],
1103 MVAConfiguration(variables=['pt', 'E', 'pz'],
1104 target='isPrimarySignal'))
1105
1106 pi0 = Particle('pi0',
1107 MVAConfiguration(variables=['M', 'daughter({},extraInfo(SignalProbability))', 'extraInfo(preCut_rank)',
1108 'daughterAngle(0,1)', 'pt', 'pz', 'E', 'abs(dM)'],
1109 target='isSignal'),
1110 PreCutConfiguration(userCut='0.08 < M < 0.18',
1111 bestCandidateVariable='abs(dM)',
1112 bestCandidateCut=20),
1113 PostCutConfiguration(bestCandidateCut=10, value=0.01))
1114 pi0.addChannel(['gamma', 'gamma'])
1115
1116 intermediate_vars = ['daughterProductOf(extraInfo(SignalProbability))', 'daughter({},extraInfo(SignalProbability))',
1117 'chiProb', 'daughter({}, chiProb)', 'extraInfo(preCut_rank)', 'abs(dM)',
1118 'useRestFrame(daughter({}, p))',
1119 'useRestFrame(daughter({}, distance))',
1120 'decayAngle({})', 'daughterAngle({},{})', 'cosAngleBetweenMomentumAndVertexVector',
1121 'daughterInvariantMass({},{})', 'daughterInvariantMass({},{},{})', 'daughterInvariantMass({},{},{},{})',
1122 'daughterInvariantMass({},{},{},{},{})', 'dQ', 'Q', 'dM', 'daughter({},extraInfo(decayModeID))']
1123
1124 D0 = Particle('D0',
1125 MVAConfiguration(variables=intermediate_vars,
1126 target='isSignal'),
1127 PreCutConfiguration(userCut='1.7 < M < 1.95',
1128 bestCandidateVariable='abs(dM)',
1129 bestCandidateCut=20),
1130 PostCutConfiguration(bestCandidateCut=10, value=0.001))
1131 D0.addChannel(['K-', 'pi+'])
1132 D0.addChannel(['K-', 'pi+', 'pi0'])
1133 D0.addChannel(['pi-', 'pi+'])
1134
1135 D0_SL = Particle('D0:semileptonic',
1136 MVAConfiguration(variables=intermediate_vars,
1137 target='isSignalAcceptMissingNeutrino'),
1138 PreCutConfiguration(userCut='',
1139 bestCandidateMode='highest',
1140 bestCandidateVariable='daughterProductOf(extraInfo(SignalProbability))',
1141 bestCandidateCut=20),
1142 PostCutConfiguration(bestCandidateCut=10, value=0.001))
1143
1144 D0_SL.addChannel(['K-', 'mu+'])
1145 D0_SL.addChannel(['K-', 'pi0', 'mu+'])
1146
1147 particles = [gamma, muon, pion, kaon, pi0, D0, D0_SL]
1148 return particles
1149
1150
1151def get_fr_channels(convertedFromBelle=False):
1152 """
1153 Get channels of original FR for comparison
1154 @param convertedFromBelle whether to use Belle variables which is necessary for b2bii converted data (default is False)
1155 """
1156
1157 if convertedFromBelle:
1158 # Using Belle specific Variables for e-ID, mu-ID and K-ID
1159 # atcPIDBelle(3,2) is used as K-ID
1160 # atcPIDBelle(4,2) and atcPIDBelle(4,3) are used as pr-ID
1161 chargedVariables = ['eIDBelle',
1162 'atcPIDBelle(3,2)',
1163 'atcPIDBelle(4,2)', 'atcPIDBelle(4,3)',
1164 'muIDBelle',
1165 'p', 'pt', 'pz', 'dr', 'dz', 'chiProb', 'extraInfo(preCut_rank)']
1166 else:
1167 chargedVariables = ['electronID', 'kaonID', 'protonID', 'muonID',
1168 'p', 'pt', 'pz', 'dr', 'dz', 'chiProb', 'extraInfo(preCut_rank)']
1169
1170 charged_user_cut = '[dr < 2] and [abs(dz) < 4]'
1171
1172 pion = Particle('pi+',
1173 MVAConfiguration(variables=chargedVariables,
1174 target='isPrimarySignal'),
1175 PreCutConfiguration(userCut=charged_user_cut,
1176 bestCandidateMode='highest',
1177 bestCandidateVariable='pionID' if not convertedFromBelle else 'atcPIDBelle(2,3)',
1178 bestCandidateCut=20),
1179 PostCutConfiguration(bestCandidateCut=10, value=0.01))
1180 pion.addChannel(['pi+:FSP'])
1181
1182 kaon = Particle('K+',
1183 MVAConfiguration(variables=chargedVariables,
1184 target='isPrimarySignal'),
1185 PreCutConfiguration(userCut=charged_user_cut,
1186 bestCandidateMode='highest',
1187 bestCandidateVariable='kaonID' if not convertedFromBelle else 'atcPIDBelle(3,2)',
1188 bestCandidateCut=20),
1189 PostCutConfiguration(bestCandidateCut=10, value=0.01))
1190 kaon.addChannel(['K+:FSP'])
1191
1192 electron = Particle('e+',
1193 MVAConfiguration(variables=chargedVariables,
1194 target='isPrimarySignal'),
1195 PreCutConfiguration(userCut=charged_user_cut,
1196 bestCandidateMode='highest',
1197 bestCandidateVariable='electronID' if not convertedFromBelle else 'eIDBelle',
1198 bestCandidateCut=10),
1199 PostCutConfiguration(bestCandidateCut=10, value=0.01))
1200 electron.addChannel(['e+:FSP'])
1201
1202 muon = Particle('mu+',
1203 MVAConfiguration(variables=chargedVariables,
1204 target='isPrimarySignal'),
1205 PreCutConfiguration(userCut=charged_user_cut,
1206 bestCandidateMode='highest',
1207 bestCandidateVariable='muonID' if not convertedFromBelle else 'muIDBelle',
1208 bestCandidateCut=10),
1209 PostCutConfiguration(bestCandidateCut=10, value=0.01))
1210 muon.addChannel(['mu+:FSP'])
1211
1212 high_energy_photon = '[[clusterReg == 1 and E > 0.10] or [clusterReg == 2 and E > 0.09] or [clusterReg == 3 and E > 0.16]]'
1213 gamma = Particle('gamma',
1214 MVAConfiguration(variables=['clusterReg', 'clusterNHits', 'clusterTiming', 'extraInfo(preCut_rank)',
1215 'clusterE9E25', 'pt', 'E', 'pz'],
1216 target='isPrimarySignal'),
1217 PreCutConfiguration(userCut=high_energy_photon if not convertedFromBelle else
1218 'goodBelleGamma == 1 and clusterBelleQuality == 0',
1219 bestCandidateMode='highest',
1220 bestCandidateVariable='E',
1221 bestCandidateCut=40),
1222 PostCutConfiguration(bestCandidateCut=20, value=0.01))
1223 gamma.addChannel(['gamma:FSP'])
1224 gamma.addChannel(['gamma:V0'],
1225 MVAConfiguration(variables=['pt', 'E', 'pz', 'extraInfo(preCut_rank)'],
1226 target='isPrimarySignal'),
1227 PreCutConfiguration(userCut='',
1228 bestCandidateMode='highest',
1229 bestCandidateVariable='E',
1230 bestCandidateCut=40))
1231
1232 if convertedFromBelle:
1233
1234 pi0 = Particle('pi0',
1235 MVAConfiguration(variables=['InvM', 'extraInfo(preCut_rank)', 'chiProb', 'abs(BellePi0SigM)',
1236 'daughterAngle(0,1)', 'pt', 'pz', 'E'],
1237 target='isSignal'),
1238 PreCutConfiguration(userCut='0.08 < InvM < 0.18',
1239 bestCandidateVariable='abs(BellePi0SigM)',
1240 bestCandidateCut=20),
1241 PostCutConfiguration(bestCandidateCut=10, value=0.01))
1242 pi0.addChannel(['pi0:FSP'])
1243
1244 KS0 = Particle('K_S0',
1245 MVAConfiguration(variables=['dr', 'dz', 'distance', 'significanceOfDistance', 'chiProb', 'M', 'abs(dM)',
1246 'useCMSFrame(E)', 'daughterAngle(0,1)',
1247 'cosAngleBetweenMomentumAndVertexVector',
1248 'extraInfo(preCut_rank)', 'extraInfo(goodKs)', 'extraInfo(ksnbVLike)',
1249 'extraInfo(ksnbNoLam)', 'extraInfo(ksnbStandard)'],
1250 target='isSignal'),
1251 PreCutConfiguration(userCut='0.4 < M < 0.6',
1252 bestCandidateVariable='abs(dM)',
1253 bestCandidateCut=20),
1254 PostCutConfiguration(bestCandidateCut=10, value=0.01))
1255 KS0.addChannel(['K_S0:V0'])
1256
1257 else:
1258
1259 pi0 = Particle('pi0',
1260 MVAConfiguration(variables=['M', 'daughter({},extraInfo(SignalProbability))', 'extraInfo(preCut_rank)',
1261 'daughterAngle(0,1)', 'pt', 'pz', 'E', 'abs(dM)'],
1262 target='isSignal'),
1263 PreCutConfiguration(userCut='0.08 < M < 0.18',
1264 bestCandidateVariable='abs(dM)',
1265 bestCandidateCut=20),
1266 PostCutConfiguration(bestCandidateCut=10, value=0.01))
1267 pi0.addChannel(['gamma', 'gamma'])
1268
1269 KS0 = Particle('K_S0',
1270 MVAConfiguration(variables=['dr', 'dz', 'distance', 'significanceOfDistance', 'chiProb', 'M', 'abs(dM)',
1271 'useCMSFrame(E)', 'daughterAngle(0,1)',
1272 'daughter({},extraInfo(SignalProbability))',
1273 'useRestFrame(daughter({}, p))', 'cosAngleBetweenMomentumAndVertexVector',
1274 'daughter({}, dz)', 'daughter({}, dr)', 'extraInfo(preCut_rank)'],
1275 target='isSignal'),
1276 PreCutConfiguration(userCut='0.4 < M < 0.6',
1277 bestCandidateVariable='abs(dM)',
1278 bestCandidateCut=20),
1279 PostCutConfiguration(bestCandidateCut=10, value=0.01))
1280 KS0.addChannel(['pi+', 'pi-'])
1281 KS0.addChannel(['pi0', 'pi0'])
1282 KS0.addChannel(['K_S0:V0'],
1283 MVAConfiguration(variables=['dr', 'dz', 'distance', 'significanceOfDistance', 'chiProb', 'M',
1284 'useCMSFrame(E)', 'daughterAngle(0,1)', 'extraInfo(preCut_rank)', 'abs(dM)',
1285 'useRestFrame(daughter({}, p))', 'cosAngleBetweenMomentumAndVertexVector',
1286 'daughter({}, dz)', 'daughter({}, dr)'],
1287 target='isSignal'))
1288
1289 # variables for D mesons and J/Psi
1290 intermediate_vars = ['daughterProductOf(extraInfo(SignalProbability))', 'daughter({},extraInfo(SignalProbability))',
1291 'chiProb', 'daughter({}, chiProb)', 'extraInfo(preCut_rank)', 'abs(dM)',
1292 'useRestFrame(daughter({}, p))',
1293 'useRestFrame(daughter({}, distance))',
1294 'decayAngle({})', 'daughterAngle({},{})', 'cosAngleBetweenMomentumAndVertexVector',
1295 'daughterInvariantMass({},{})', 'daughterInvariantMass({},{},{})', 'daughterInvariantMass({},{},{},{})',
1296 'daughterInvariantMass({},{},{},{},{})', 'dQ', 'Q', 'dM', 'daughter({},extraInfo(decayModeID))']
1297
1298 D0 = Particle('D0',
1299 MVAConfiguration(variables=intermediate_vars,
1300 target='isSignal'),
1301 PreCutConfiguration(userCut='1.7 < M < 1.95',
1302 bestCandidateVariable='abs(dM)',
1303 bestCandidateCut=20),
1304 PostCutConfiguration(bestCandidateCut=10, value=0.001))
1305 D0.addChannel(['K-', 'pi+'])
1306 D0.addChannel(['K-', 'pi+', 'pi0'])
1307 D0.addChannel(['K-', 'pi+', 'pi+', 'pi-'])
1308 D0.addChannel(['pi-', 'pi+'])
1309 D0.addChannel(['pi-', 'pi+', 'pi0'])
1310 D0.addChannel(['K_S0', 'pi0'])
1311 D0.addChannel(['K_S0', 'pi+', 'pi-'])
1312 D0.addChannel(['K_S0', 'pi+', 'pi-', 'pi0'])
1313 D0.addChannel(['K-', 'K+'])
1314 D0.addChannel(['K-', 'K+', 'K_S0'])
1315
1316 DP = Particle('D+',
1317 MVAConfiguration(variables=intermediate_vars,
1318 target='isSignal'),
1319 PreCutConfiguration(userCut='1.7 < M < 1.95',
1320 bestCandidateVariable='abs(dM)',
1321 bestCandidateCut=20),
1322 PostCutConfiguration(bestCandidateCut=10, value=0.001))
1323
1324 DP.addChannel(['K-', 'pi+', 'pi+'])
1325 DP.addChannel(['K-', 'pi+', 'pi+', 'pi0'])
1326 DP.addChannel(['K-', 'K+', 'pi+'])
1327 DP.addChannel(['K-', 'K+', 'pi+', 'pi0'])
1328 DP.addChannel(['K_S0', 'pi+'])
1329 DP.addChannel(['K_S0', 'pi+', 'pi0'])
1330 DP.addChannel(['K_S0', 'pi+', 'pi+', 'pi-'])
1331
1332 Jpsi = Particle('J/psi',
1333 MVAConfiguration(variables=intermediate_vars,
1334 target='isSignal'),
1335 PreCutConfiguration(userCut='2.5 < M < 3.7',
1336 bestCandidateVariable='abs(dM)',
1337 bestCandidateCut=20),
1338 PostCutConfiguration(bestCandidateCut=10, value=0.001))
1339
1340 Jpsi.addChannel(['e+', 'e-'])
1341 Jpsi.addChannel(['mu+', 'mu-'])
1342
1343 DSP = Particle('D*+',
1344 MVAConfiguration(variables=intermediate_vars,
1345 target='isSignal'),
1346 PreCutConfiguration(userCut='0 < Q < 0.3',
1347 bestCandidateVariable='abs(dQ)',
1348 bestCandidateCut=20),
1349 PostCutConfiguration(bestCandidateCut=10, value=0.001))
1350
1351 DSP.addChannel(['D0', 'pi+'])
1352 DSP.addChannel(['D+', 'pi0'])
1353
1354 DS0 = Particle('D*0',
1355 MVAConfiguration(variables=intermediate_vars,
1356 target='isSignal'),
1357 PreCutConfiguration(userCut='0 < Q < 0.3',
1358 bestCandidateVariable='abs(dQ)',
1359 bestCandidateCut=20),
1360 PostCutConfiguration(bestCandidateCut=10, value=0.001))
1361
1362 DS0.addChannel(['D0', 'pi0'])
1363 DS0.addChannel(['D0', 'gamma'])
1364
1365 DS = Particle('D_s+',
1366 MVAConfiguration(variables=intermediate_vars,
1367 target='isSignal'),
1368 PreCutConfiguration(userCut='1.68 < M < 2.1',
1369 bestCandidateVariable='abs(dM)',
1370 bestCandidateCut=20),
1371 PostCutConfiguration(bestCandidateCut=10, value=0.001))
1372
1373 DS.addChannel(['K+', 'K_S0'])
1374 DS.addChannel(['K+', 'pi+', 'pi-'])
1375 DS.addChannel(['K+', 'K-', 'pi+'])
1376 DS.addChannel(['K+', 'K-', 'pi+', 'pi0'])
1377 DS.addChannel(['K+', 'K_S0', 'pi+', 'pi-'])
1378 DS.addChannel(['K-', 'K_S0', 'pi+', 'pi+'])
1379 DS.addChannel(['K+', 'K-', 'pi+', 'pi+', 'pi-'])
1380 DS.addChannel(['pi+', 'pi+', 'pi-'])
1381
1382 DSS = Particle('D_s*+',
1383 MVAConfiguration(variables=intermediate_vars,
1384 target='isSignal'),
1385 PreCutConfiguration(userCut='0.0 < Q < 0.3',
1386 bestCandidateVariable='abs(dQ)',
1387 bestCandidateCut=20),
1388 PostCutConfiguration(bestCandidateCut=10, value=0.001))
1389
1390 DSS.addChannel(['D_s+', 'gamma'])
1391
1392 # note: these should not be correlated to Mbc (weak correlation of deltaE is OK)
1393 B_vars = ['daughterProductOf(extraInfo(SignalProbability))', 'daughter({},extraInfo(SignalProbability))',
1394 'chiProb', 'daughter({}, chiProb)', 'extraInfo(preCut_rank)',
1395 'useRestFrame(daughter({}, p))',
1396 'useRestFrame(daughter({}, distance))',
1397 'decayAngle({})', 'daughterAngle({},{})', 'cosAngleBetweenMomentumAndVertexVector',
1398 'dr', 'dz', 'dx', 'dy', 'distance', 'significanceOfDistance', 'deltaE', 'daughter({},extraInfo(decayModeID))']
1399
1400 hadronic_user_cut = 'Mbc > 5.2 and abs(deltaE) < 0.5'
1401
1402 BP = Particle('B+',
1403 MVAConfiguration(variables=B_vars,
1404 target='isSignal'),
1405 PreCutConfiguration(userCut=hadronic_user_cut,
1406 bestCandidateMode='highest',
1407 bestCandidateVariable='daughterProductOf(extraInfo(SignalProbability))',
1408 bestCandidateCut=20),
1409 PostCutConfiguration(bestCandidateCut=20))
1410
1411 BP.addChannel(['anti-D0', 'pi+'])
1412 BP.addChannel(['anti-D0', 'pi+', 'pi0'])
1413 BP.addChannel(['anti-D0', 'pi+', 'pi+', 'pi-'])
1414 BP.addChannel(['anti-D0', 'D+'])
1415 BP.addChannel(['D_s+', 'anti-D0'])
1416 BP.addChannel(['anti-D*0', 'pi+'])
1417 BP.addChannel(['anti-D*0', 'pi+', 'pi0'])
1418 BP.addChannel(['anti-D*0', 'pi+', 'pi+', 'pi-'])
1419 BP.addChannel(['anti-D*0', 'pi+', 'pi+', 'pi-', 'pi0'])
1420 BP.addChannel(['D_s*+', 'anti-D0'])
1421 BP.addChannel(['D_s+', 'anti-D*0'])
1422 BP.addChannel(['anti-D0', 'K+'])
1423 BP.addChannel(['D-', 'pi+', 'pi+'])
1424 BP.addChannel(['J/psi', 'K+'])
1425 BP.addChannel(['J/psi', 'K+', 'pi+', 'pi-'])
1426 BP.addChannel(['J/psi', 'K+', 'pi0'])
1427 BP.addChannel(['J/psi', 'K_S0', 'pi+'])
1428
1429 B0 = Particle('B0',
1430 MVAConfiguration(variables=B_vars,
1431 target='isSignal'),
1432 PreCutConfiguration(userCut=hadronic_user_cut,
1433 bestCandidateMode='highest',
1434 bestCandidateVariable='daughterProductOf(extraInfo(SignalProbability))',
1435 bestCandidateCut=20),
1436 PostCutConfiguration(bestCandidateCut=20))
1437 B0.addChannel(['D-', 'pi+'])
1438 B0.addChannel(['D-', 'pi+', 'pi0'])
1439 B0.addChannel(['D-', 'pi+', 'pi+', 'pi-'])
1440 B0.addChannel(['anti-D0', 'pi0'])
1441 B0.addChannel(['D_s+', 'D-'])
1442 B0.addChannel(['D*-', 'pi+'])
1443 B0.addChannel(['D*-', 'pi+', 'pi0'])
1444 B0.addChannel(['D*-', 'pi+', 'pi+', 'pi-'])
1445 B0.addChannel(['D*-', 'pi+', 'pi+', 'pi-', 'pi0'])
1446 B0.addChannel(['D_s*+', 'D-'])
1447 B0.addChannel(['D_s+', 'D*-'])
1448 B0.addChannel(['D_s*+', 'D*-'])
1449 B0.addChannel(['J/psi', 'K_S0'])
1450 B0.addChannel(['J/psi', 'K+', 'pi-'])
1451 B0.addChannel(['J/psi', 'K_S0', 'pi+', 'pi-'])
1452
1453 particles = []
1454 particles.append(pion)
1455 particles.append(kaon)
1456 particles.append(muon)
1457 particles.append(electron)
1458 particles.append(gamma)
1459
1460 particles.append(pi0)
1461 particles.append(KS0)
1462 particles.append(Jpsi)
1463
1464 particles.append(D0)
1465 particles.append(DP)
1466 particles.append(DS)
1467
1468 particles.append(DS0)
1469 particles.append(DSP)
1470 particles.append(DSS)
1471
1472 particles.append(B0)
1473 particles.append(BP)
1474
1475 return particles
1476
1477
1478def get_mode_names(particle_name: str,
1479 hadronic=True,
1480 semileptonic=False,
1481 removeSLD=True,
1482 remove_list_labels=True,
1483 **channel_kwargs) -> list:
1484 """
1485 Get the ordered list of mode names for a given FEI particle name
1486
1487 Arguments:
1488 particle_name(str): the name of the particle, e.g. B0 or B+
1489 hadronic(bool): whether to include hadronic modes
1490 semileptonic(bool): whether to include semileptonic modes
1491 removeSLD(bool): whether to remove the semileptonic D and D* modes, should be True for FEI skim
1492 remove_list_labels(bool): whether to remove the generic and semileptonic labels from the mode names
1493 channel_kwargs: keyword arguments for get_default_channels
1494
1495 Returns:
1496 list(str): the list of mode names, or empty list if the particle was not found
1497 """
1498 if hadronic and semileptonic:
1499 B2INFO('Both semileptonic and hadronic arguments are set to True, set one of them to False for a more definite result.')
1500 if not hadronic and not semileptonic:
1501 B2INFO('Both semileptonic and hadronic arguments are set to False, set one of them to True for a more definite result.')
1502 return []
1503 channel_kwargs.update({'hadronic': hadronic,
1504 'semileptonic': semileptonic,
1505 'removeSLD': removeSLD
1506 })
1507 channels = get_default_channels(**channel_kwargs)
1508 modes = []
1509 conjugate_name = particle_name.replace('-', '+')
1510 for channel in channels:
1511 if channel.name == particle_name or channel.name == conjugate_name:
1512 modes += [d_channel.label.split(' ==> ')[1] for d_channel in channel.channels]
1513 if remove_list_labels:
1514 modes = [mode.replace(':generic', '').replace(':semileptonic', '') for mode in modes]
1515 return modes
def isB2BII()
Definition: b2bii.py:14