Belle II Software  release-06-01-15
semileptonic.py
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3 
4 
11 
12 """(Semi-)Leptonic Working Group Skim list building functions for semi-leptonic analyses.
13 """
14 
15 import modularAnalysis as ma
16 from skim.standardlists.charm import (loadKForBtoHadrons, loadPiForBtoHadrons,
17  loadStdD0, loadStdDplus, loadStdDstar0,
18  loadStdDstarPlus, loadPiSkimHighEff,
19  loadKSkimHighEff, loadSlowPi,
20  loadSkimHighEffD0_Kpi, loadSkimHighEffDstarPlus_D0pi_Kpi,
21  loadSkimHighEffD0_Kpipipi, loadSkimHighEffDstarPlus_D0pi_Kpipipi,
22  loadStdD0_eff20_Kpipi0, loadStdDstarPlus_D0pi_Kpipi0_eff20)
23 from skim.standardlists.lightmesons import loadStdPi0ForBToHadrons
24 from skim import BaseSkim, fancy_skim_header
25 from stdCharged import stdE, stdK, stdMu, stdPi
26 from stdPhotons import stdPhotons
27 from stdPi0s import stdPi0s
28 from stdV0s import stdKshorts
29 from variables import variables as vm
30 
31 __liaison__ = "Shanette De La Motte <shanette.delamotte@adelaide.edu.au>"
32 _VALIDATION_SAMPLE = "mdst14.root"
33 
34 
35 @fancy_skim_header
37  """
38  Reconstructed decay modes:
39 
40  * :math:`B^0 \\to \\pi^- e^+`
41  * :math:`B^0 \\to \\pi^- \\mu^+`
42 
43  Event-level cuts:
44 
45  * :math:`\\text{foxWolframR2} < 0.5` constructed using tracks with
46  :math:`p_T>0.1\\,\\text{GeV}` and clusters with :math:`E>0.1\\,\\text{GeV}`.
47  * :math:`n_{\\text{tracks}} > 4`
48 
49  Cuts on electrons:
50 
51  * :math:`\\text{electronID_noTOP} > 0.5`
52  * :math:`p > 1.5\\,\\text{GeV}` in CMS frame
53 
54  Cuts on muons:
55 
56  * :math:`\\text{muonID} > 0.5`
57  * :math:`p > 1.5\\,\\text{GeV}` in CMS frame
58 
59  Cuts on pions:
60 
61  * :math:`\\text{pionID}>0.5`
62  * :math:`\\text{muonID}<0.2`
63  * :math:`0.060\\,\\text{GeV}<p<0.220\\,\\text{GeV}` in CMS frame
64 
65  Cuts on partially reconstructed :math:`B` mesons:
66 
67  * :math:`\\cos\\theta_{\\ell,\\,\\pi}<0` in CMS frame.
68  """
69 
70  __authors__ = ["Lucien Cremaldi", "Racha Cheaib", "Romulus Godang"]
71  __description__ = "Skim for partial reconstruction analysis in leptonic group."
72  __contact__ = __liaison__
73  __category__ = "physics, semileptonic"
74 
75  validation_sample = _VALIDATION_SAMPLE
76 
77  def load_standard_lists(self, path):
78  stdE("all", path=path)
79  stdMu("all", path=path)
80  stdPi("all", path=path)
81 
82  def build_lists(self, path):
83  ma.fillParticleList(decayString="pi+:PRSL_eventshape",
84  cut="pt> 0.1", path=path)
85  ma.fillParticleList(decayString="gamma:PRSL_eventshape",
86  cut="E > 0.1", path=path, loadPhotonBeamBackgroundMVA=False)
87 
88  ma.buildEventShape(inputListNames=["pi+:PRSL_eventshape", "gamma:PRSL_eventshape"],
89  allMoments=False,
90  foxWolfram=True,
91  harmonicMoments=False,
92  cleoCones=False,
93  thrust=False,
94  collisionAxis=False,
95  jets=False,
96  sphericity=False,
97  checkForDuplicates=False,
98  path=path)
99 
100  path = self.skim_event_cutsskim_event_cuts("foxWolframR2<0.5 and nTracks>4", path=path)
101 
102  ma.cutAndCopyList("e+:PRSemileptonic_1", "e+:all",
103  "useCMSFrame(p) > 1.50 and electronID_noTOP > 0.5", path=path)
104  ma.cutAndCopyList("mu+:PRSemileptonic_1", "mu+:all",
105  "useCMSFrame(p) > 1.50 and muonID > 0.5", path=path)
106  ma.cutAndCopyList("pi-:PRSemileptonic_1", "pi-:all",
107  "pionID>0.5 and muonID<0.2 and 0.060<useCMSFrame(p)<0.220", path=path)
108 
109  ma.cutAndCopyList("e+:PRSemileptonic_2", "e+:all",
110  "0.600 < useCMSFrame(p) <= 1.50 and electronID_noTOP > 0.5", path=path)
111  ma.cutAndCopyList("mu+:PRSemileptonic_2", "mu+:all",
112  "0.350 < useCMSFrame(p) <= 1.50 and muonID > 0.5", path=path)
113  ma.cutAndCopyList("pi-:PRSemileptonic_2", "pi-:all",
114  "pionID>0.5 and muonID<0.2 and 0.060<useCMSFrame(p)<0.160", path=path)
115 
116  ma.reconstructDecay("B0:PRSemileptonic_1 -> pi-:PRSemileptonic_1 e+:PRSemileptonic_1",
117  "useCMSFrame(cos(daughterAngle(0,1)))<0.00", 1, path=path)
118  ma.reconstructDecay("B0:PRSemileptonic_2 -> pi-:PRSemileptonic_1 mu+:PRSemileptonic_1",
119  "useCMSFrame(cos(daughterAngle(0,1)))<0.00", 2, path=path)
120  ma.reconstructDecay("B0:PRSemileptonic_3 -> pi-:PRSemileptonic_2 e+:PRSemileptonic_2",
121  "useCMSFrame(cos(daughterAngle(0,1)))<1.00", 3, path=path)
122  ma.reconstructDecay("B0:PRSemileptonic_4 -> pi-:PRSemileptonic_2 mu+:PRSemileptonic_2",
123  "useCMSFrame(cos(daughterAngle(0,1)))<1.00", 4, path=path)
124 
125  return ["B0:PRSemileptonic_1", "B0:PRSemileptonic_2"]
126 
127  def validation_histograms(self, path):
128  # NOTE: the validation package is not part of the light releases, so this import
129  # must be made here rather than at the top of the file.
130  from validation_tools.metadata import create_validation_histograms
131 
132  ma.copyLists('B0:all', self.SkimListsSkimListsSkimLists, path=path)
133 
134  ma.buildRestOfEvent('B0:all', path=path)
135  ma.appendROEMask('B0:all', 'basic',
136  'pt>0.05 and -2<dr<2 and -4.0<dz<4.0',
137  'E>0.05',
138  path=path)
139  ma.buildContinuumSuppression('B0:all', 'basic', path=path)
140 
141  vm.addAlias('d0_p', 'daughter(0, p)')
142  vm.addAlias('d1_p', 'daughter(1, p)')
143  vm.addAlias('MissM2', 'weMissM2(basic,0)')
144 
145  histogramFilename = f'{self}_Validation.root'
146 
147  create_validation_histograms(
148  rootfile=histogramFilename,
149  particlelist='B0:all',
150  variables_1d=[
151  ('Mbc', 100, 4.0, 5.3, 'Mbc', __liaison__, '', ''),
152  ('d0_p', 100, 0, 5.2, 'Signal-side pion momentum', __liaison__, '', ''),
153  ('d1_p', 100, 0, 5.2, 'Signal-side lepton momentum', __liaison__, '', ''),
154  ('MissM2', 100, -5, 5, 'Missing mass squared', __liaison__, '', '')
155  ],
156  variables_2d=[('deltaE', 100, -5, 5, 'Mbc', 100, 4.0, 5.3, 'Mbc vs deltaE', __liaison__, '', '')],
157  path=path)
158 
159 
160 @fancy_skim_header
162  """
163  Cuts applied:
164 
165  * :math:`p_{\\ell} > 0.35\\,\\text{GeV}`
166  * :math:`5.24 < M_{\\text{bc}} < 5.29`
167  * :math:`|\\Delta E | < 0.5`
168  * :math:`n_{\\text{tracks}} > 4`
169 
170  Reconstructed decays:
171 
172  * :math:`B^+ \\to \\overline{D}^{0} e^+`
173  * :math:`B^+ \\to \\overline{D}^{0} \\mu^+`
174  * :math:`B^+ \\to \\overline{D}^{*0} e^+`
175  * :math:`B^+ \\to \\overline{D}^{*0} \\mu^+`
176  * :math:`B^0 \\to D^{-} e^+`
177  * :math:`B^0 \\to D^{-} \\mu^+`
178  * :math:`B^0 \\to D^{*-} e^+`
179  * :math:`B^0 \\to D^{*-} \\mu^+`
180  """
181 
182  __authors__ = ["Phillip Urquijo", "Racha Cheaib"]
183  __description__ = (
184  "Skim for semileptonic decays, :math:`B` decays "
185  "(:math:`B \\to D \\ell\\nu`, where :math:`\\ell=e,\\mu`)"
186  )
187  __contact__ = __liaison__
188  __category__ = "physics, semileptonic"
189 
190  validation_sample = _VALIDATION_SAMPLE
191 
192  def load_standard_lists(self, path):
193  stdE("all", path=path)
194  stdK("all", path=path)
195  stdMu("all", path=path)
196  stdPi("all", path=path)
197  stdPi("loose", path=path)
198  stdPhotons("loose", path=path, loadPhotonBeamBackgroundMVA=False)
199  stdPi0s("eff40_May2020", path=path, loadPhotonBeamBackgroundMVA=False)
200  stdKshorts(path=path)
201  loadStdPi0ForBToHadrons(path=path)
202  loadPiForBtoHadrons(path=path)
203  loadKForBtoHadrons(path=path)
204  loadStdD0(path=path)
205  loadStdDstar0(path=path)
206  loadStdDplus(path=path)
207  loadStdDstarPlus(path=path)
208 
209  def build_lists(self, path):
210  ma.cutAndCopyList("e+:SLUntagged", "e+:all", "p>0.35", True, path=path)
211  ma.cutAndCopyList("mu+:SLUntagged", "mu+:all", "p>0.35", True, path=path)
212  Bcuts = "5.24 < Mbc < 5.29 and abs(deltaE) < 0.5"
213 
214  BplusChannels = ["anti-D0:all e+:SLUntagged",
215  "anti-D0:all mu+:SLUntagged",
216  "anti-D*0:all e+:SLUntagged",
217  "anti-D*0:all mu+:SLUntagged"
218  ]
219 
220  B0Channels = ["D-:all e+:SLUntagged",
221  "D-:all mu+:SLUntagged",
222  "D*-:all e+:SLUntagged",
223  "D*-:all mu+:SLUntagged"
224  ]
225 
226  bplusList = []
227  for chID, channel in enumerate(BplusChannels):
228  ma.reconstructDecay(f"B+:SLUntagged_{chID} -> {channel}", Bcuts, chID, path=path)
229  ma.applyCuts(f"B+:SLUntagged_{chID}", "nTracks>4", path=path)
230  bplusList.append(f"B+:SLUntagged_{chID}")
231 
232  b0List = []
233  for chID, channel in enumerate(B0Channels):
234  ma.reconstructDecay(f"B0:SLUntagged_{chID} -> {channel}", Bcuts, chID, path=path)
235  ma.applyCuts(f"B0:SLUntagged_{chID}", "nTracks>4", path=path)
236  b0List.append(f"B0:SLUntagged_{chID}")
237 
238  return b0List + bplusList
239 
240  def validation_histograms(self, path):
241  # NOTE: the validation package is not part of the light releases, so this import
242  # must be made here rather than at the top of the file.
243  from validation_tools.metadata import create_validation_histograms
244 
245  ma.copyLists('B+:all', [lst for lst in self.SkimListsSkimListsSkimLists if "B+" in lst], path=path)
246 
247  ma.buildRestOfEvent('B+:all', path=path)
248  ma.appendROEMask('B+:all', 'basic',
249  'pt>0.05 and -2<dr<2 and -4.0<dz<4.0',
250  'E>0.05',
251  path=path)
252  ma.buildContinuumSuppression('B+:all', 'basic', path=path)
253 
254  vm.addAlias('d1_p', 'daughter(1,p)')
255  vm.addAlias('MissM2', 'weMissM2(basic,0)')
256 
257  histogramFilename = f'{self}_Validation.root'
258 
259  create_validation_histograms(
260  rootfile=histogramFilename,
261  particlelist='B+:all',
262  variables_1d=[
263  ('cosThetaBetweenParticleAndNominalB', 100, -6.0, 4.0, 'cosThetaBY', __liaison__, '', ''),
264  ('Mbc', 100, 4.0, 5.3, 'Mbc', __liaison__, '', ''),
265  ('d1_p', 100, 0, 5.2, 'Signal-side lepton momentum', __liaison__, '', ''),
266  ('MissM2', 100, -5, 5, 'Missing mass squared', __liaison__, '', '')
267  ],
268  variables_2d=[('deltaE', 100, -5, 5, 'Mbc', 100, 4.0, 5.3, 'Mbc vs deltaE', __liaison__, '', '')],
269  path=path)
270 
271 
272 @fancy_skim_header
274  """
275  Cuts applied:
276 
277  * ``SkimHighEff tracks thetaInCDCAcceptance AND abs(dr) < 2 AND abs(dz) < 5 AND PID>=0.01``
278  * ``slowPi tracks thetaInCDCAcceptance AND abs(dr) < 2 AND abs(dz) < 5 AND useCMSFrame(p) < 0.4``
279  * :math:`2.5 > p_{\\ell} > 1.1\\,\\text{GeV}`
280  * ``lepton with abs(d0) < 0.5 AND abs(z0) < 2 AND thetaInCDCAcceptance AND ID >= 0.95 AND 1.1 < useCMSFrame(p) < 2.5``
281  * ``1.8 < M_D0 < 2.0``
282  * ``DM_Dstar_D < 0.16``
283 
284  Reconstructed decays:
285 
286  * :math:`B^{0}\\to D^{*-} (D^{0} \\to K^+ \\pi^-) e^+`,
287  * :math:`B^{0}\\to D^{*-} (D^{0} \\to K^+ \\pi^- \\pi^0) e^+`,
288  * :math:`B^{0}\\to D^{*-} (D^{0} \\to K^+ \\pi^- \\pi^- \\pi^+) e^+`,
289  * :math:`B^{0}\\to D^{*-} (D^{0} \\to K^+ \\pi^-) mu^+`,
290  * :math:`B^{0}\\to D^{*-} (D^{0} \\to K^+ \\pi^- \\pi^0) mu^+`,
291  * :math:`B^{0}\\to D^{*-} (D^{0} \\to K^+ \\pi^- \\pi^- \\pi^+) mu^+`,
292 
293  Note:
294 
295  This skim uses `skim.standardlists.charm.loadSkimHighEffD0_Kpi`,
296  `skim.standardlists.charm.loadSkimHighEffD0_Kpipipi` and
297  `skim.standardlists.charm.loadStdD0_eff20_Kpipi0`, where :math:`D^0`
298  channel is defined.
299  `skim.standardlists.charm.loadSkimHighEffDstarPlus_D0pi_Kpi`,
300  `skim.standardlists.charm.loadSkimHighEffDstarPlus_D0pi_Kpipipi`,
301  `skim.standardlists.charm.loadStdDstarPlus_D0pi_Kpipi0_eff20`,where the
302  :math:`D^{*-}` channel is defined.
303 
304  The pion and kaon lists used to define :math:`D^0` and :math:`D^{*-}` are:
305  `skim.standardlists.charm.loadPiSkimHighEff`, `skim.standardlists.charm.loadKSkimHighEff` and
306  `skim.standardlists.charm.loadSlowPi`
307  """
308  __authors__ = ["Bae Hanwook, Chiara La Licata"]
309  __description__ = ""
310  __contact__ = __liaison__
311  __category__ = "physics, semileptonic"
312 
313  ApplyHLTHadronCut = True
314  produce_on_tau_samples = False # retention is very close to zero on taupair
315 
316  def load_standard_lists(self, path):
317  stdE("all", path=path)
318  stdMu("all", path=path)
319  stdPi("all", path=path)
320  stdK("all", path=path)
321  stdPi0s("eff20_May2020", path=path, loadPhotonBeamBackgroundMVA=False)
322  loadPiSkimHighEff(path=path)
323  loadKSkimHighEff(path=path)
324  loadSlowPi(path=path)
325  loadSkimHighEffD0_Kpi(path=path)
326  loadSkimHighEffDstarPlus_D0pi_Kpi(path=path)
327  loadSkimHighEffD0_Kpipipi(path=path)
328  loadSkimHighEffDstarPlus_D0pi_Kpipipi(path=path)
329  loadStdD0_eff20_Kpipi0(path=path)
330  loadStdDstarPlus_D0pi_Kpipi0_eff20(path=path)
331 
332  def build_lists(self, path):
333 
334  ma.cutAndCopyList(
335  'e+:sig',
336  'e+:all',
337  'abs(d0) < 0.5 and abs(z0) < 2 and thetaInCDCAcceptance and electronID_noTOP >= 0.95 and 1.1 < useCMSFrame(p) < 2.5 ',
338  path=path)
339  ma.cutAndCopyList(
340  'mu+:sig',
341  'mu+:all',
342  'abs(d0) < 0.5 and abs(z0) < 2 and thetaInCDCAcceptance and muonID >= 0.95 and 1.1 < useCMSFrame(p) < 2.5',
343  path=path)
344 
345  B0_channels = ["D*-:D0_Kpi_skimhigheff e+:sig",
346  "D*-:D0_Kpipi0_eff20 e+:sig",
347  "D*-:D0_Kpipipi_skimhigheff e+:sig",
348  "D*-:D0_Kpi_skimhigheff mu+:sig",
349  "D*-:D0_Kpipi0_eff20 mu+:sig",
350  "D*-:D0_Kpipipi_skimhigheff mu+:sig"]
351 
352  B0_list = []
353 
354  for chID, channel in enumerate(B0_channels):
355  ma.reconstructDecay("B0:Dstl_kpi_kpipi0_kpipipi" + str(chID) + " -> " + channel, "", chID, path=path)
356  B0_list.append("B0:Dstl_kpi_kpipi0_kpipipi" + str(chID))
357 
358  return B0_list
def build_lists(self, path)
def validation_histograms(self, path)
def load_standard_lists(self, path)
list SkimLists
Definition: core.py:260
def skim_event_cuts(self, cut, *path)
Definition: core.py:272