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