Belle II Software  release-06-01-15
stdHyperons.py
1 #!/usr/bin/env python3
2 
3 
10 
11 from basf2 import B2ERROR, B2WARNING
12 from b2bii import isB2BII
13 from modularAnalysis import cutAndCopyList, reconstructDecay, applyCuts
14 from vertex import treeFit, kFit
15 
16 from stdCharged import stdPi, stdK
17 from stdV0s import stdLambdas
18 from stdPhotons import stdPhotons
19 
20 
21 def stdXi(fitter='TreeFit', path=None):
22  r"""
23  Reconstruct the standard :math:`\Xi^-` ``ParticleList`` named ``Xi-:std``.
24 
25  .. seealso:: `BELLE2-NOTE-PH-2019-011 <https://docs.belle2.org/record/BELLE2-NOTE-PH-2019-011.pdf>`_.
26 
27  Parameters:
28  fitter (str): specify either ``KFit`` or ``TreeFit`` for the vertex reconstructions (default ``TreeFit``)
29  path (basf2.Path): modules are added to this path building the ``Xi-:std`` list
30  """
31 
32  if not isB2BII():
33  stdLambdas(path=path)
34  # 3.5 MeV Range around the nominal mass
35  cutAndCopyList(
36  'Lambda0:reco',
37  'Lambda0:merged',
38  '[ abs( dM ) < 0.0035 ] and \
39  [ cosAngleBetweenMomentumAndVertexVector > 0.0 ] and \
40  [ formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.35 ] and \
41  [ daughter(0,protonID) > 0.01 ] and \
42  [ chiProb > 0.0 ]',
43  True, path=path)
44  else:
45  stdPi('all', path=path)
46  # Rough Lambda0 cuts from J. Yelton Observations of an Excited Omega- Baryon
47  kFit('Lambda0:mdst', conf_level=0.0, path=path) # Re-vertexing, recover vertex variables and error matrix
48  cutAndCopyList(
49  'Lambda0:reco',
50  'Lambda0:mdst',
51  '[ abs( dM ) < 0.0035 ] and \
52  [ cosAngleBetweenMomentumAndVertexVector > 0.0 ] and \
53  [ dr > 0.35 ] and \
54  [ daughter(0,atcPIDBelle(4,3)) > 0.2 ] and \
55  [ daughter(0,atcPIDBelle(4,2)) > 0.2 ] and \
56  [ chiProb > 0.0 ]',
57  True, path=path)
58 
59  # stdXi-
60  if fitter == 'KFit':
61  kFit('Lambda0:reco', 0.0, fit_type='massvertex', path=path)
62  reconstructDecay('Xi-:reco -> Lambda0:reco pi-:all', '1.295 < M < 1.35', path=path)
63  kFit('Xi-:reco', conf_level=0.0, path=path)
64  elif fitter == 'TreeFit':
65  reconstructDecay('Xi-:reco -> Lambda0:reco pi-:all', '1.295 < M < 1.35', path=path)
66  treeFit('Xi-:reco', conf_level=0.0, massConstraint=[3122], path=path)
67  else:
68  B2ERROR(f"stdXi: invalid fitter ({fitter}). Choose from KFit or TreeFit")
69 
70  cutAndCopyList(
71  'Xi-:std',
72  'Xi-:reco',
73  '[ cosAngleBetweenMomentumAndVertexVector > 0.0 ] and \
74  [ formula( [ dr^2 + dz^2 ]^[0.5] ) > 0. and \
75  formula([dr^2 + dz^2 ]^[0.5])<formula([daughter(0,dr)^2 + daughter(0,dz)^2]^[0.5])] and \
76  [ chiProb > 0.0 ]',
77  True,
78  path=path)
79 
80 
81 def stdXi0(gammatype='eff40', path=None, loadPhotonBeamBackgroundMVA=True):
82  r"""
83  Reconstruct the standard :math:`\Xi^0` ``ParticleList`` named ``Xi0:std``.
84 
85  .. seealso:: `BELLE2-NOTE-PH-2019-011 <https://docs.belle2.org/record/BELLE2-NOTE-PH-2019-011.pdf>`_.
86 
87  Parameters:
88  gammatype (str): specify either ``eff60``, ``eff50``, ``eff40``, ``eff30``, or ``eff20``
89  to select the signal efficiency of the photons used in the pi0 reconstruction
90  (default ``eff40``)
91  path (basf2.Path): modules are added to this path building the ``Xi0:std`` list
92  loadPhotonBeamBackgroundMVA (bool): If true, photon candidates will be assigned a beam background probability.
93  """
94 
95  if not isB2BII():
96  stdLambdas(path=path)
97  # 3.5 MeV Range around nominal mass (~7*sigma_core)
98  cutAndCopyList(
99  'Lambda0:reco',
100  'Lambda0:merged',
101  '[ abs( dM ) < 0.0035 ] and \
102  [ cosAngleBetweenMomentumAndVertexVector > 0.0 ] and \
103  [ formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.35 ] and \
104  [ daughter(0,protonID) > 0.01 ] and \
105  [ chiProb > 0.0 ]',
106  True, path=path)
107  # ~7*sigma Range around nominal mass
108  stdPhotons(f'pi0{gammatype}_May2020', path=path, loadPhotonBeamBackgroundMVA=loadPhotonBeamBackgroundMVA)
109  reconstructDecay(f'pi0:reco -> gamma:pi0{gammatype}_May2020 gamma:pi0{gammatype}_May2020',
110  'abs( dM ) < 0.0406',
111  True, path=path)
112 
113  else:
114  # Rough pi0/Lambda0 cuts from J. Yelton Observations of an Excited Omega- Baryon
115  cutAndCopyList(
116  'pi0:reco',
117  'pi0:mdst',
118  '[ abs( dM ) < 0.0189 ] and \
119  [ [ daughter(0,clusterReg) == 1 and daughter(0,E) > 0.05 ] or [ daughter(0,clusterReg) == 3 and daughter(0,E) > 0.05 ] or \
120  [ daughter(0,clusterReg) == 2 and daughter(0,E) > 0.03 ] ] and \
121  [ [ daughter(1,clusterReg) == 1 and daughter(1,E) > 0.05 ] or [ daughter(1,clusterReg) == 3 and daughter(1,E) > 0.05 ] or \
122  [ daughter(1,clusterReg) == 2 and daughter(1,E) > 0.03 ] ]',
123  path=path)
124  kFit('Lambda0:mdst', conf_level=0.0, path=path) # Re-vertexing, recover vertex variables and error matrix
125  cutAndCopyList(
126  'Lambda0:reco',
127  'Lambda0:mdst',
128  '[ abs( dM ) < 0.0035 ] and \
129  [ cosAngleBetweenMomentumAndVertexVector > 0.0 ] and \
130  [ dr > 0.35 ] and \
131  [ daughter(0,atcPIDBelle(4,3)) > 0.2 ] and \
132  [ daughter(0,atcPIDBelle(4,2)) > 0.2 ] and \
133  [ chiProb > 0.0 ]',
134  True, path=path)
135 
136  reconstructDecay(
137  'Xi0:prelim -> Lambda0:reco pi0:reco',
138  '1.225 < M < 1.405',
139  path=path)
140  treeFit('Xi0:prelim', conf_level=0.0, massConstraint=[3122], ipConstraint=True, updateAllDaughters=True, path=path)
141  # Selecting ~4*sigma around the pi0 nominal mass
142  # pi0 mass range is invariant for B2BII, tighter selection is required by user
143  applyCuts('Xi0:prelim', '[ abs( daughter(1,dM) ) < 0.0232 ]', path=path)
144  treeFit('Xi0:prelim', conf_level=0.0, massConstraint=[111, 3122], ipConstraint=True, updateAllDaughters=False, path=path)
145 
146  cutAndCopyList(
147  'Xi0:std',
148  'Xi0:prelim',
149  '[ cosAngleBetweenMomentumAndVertexVector > 0.0 ] and \
150  [ daughter(0,cosAngleBetweenMomentumAndVertexVectorInXYPlane) < cosAngleBetweenMomentumAndVertexVectorInXYPlane ] and \
151  [ formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.0 and \
152  formula([dr^2 + dz^2]^[0.5])<formula([daughter(0,dr)^2 + daughter(0,dz)^2]^[0.5])] and \
153  [ chiProb > 0.0 ]',
154  True,
155  path=path)
156 
157 
158 def stdOmega(fitter='TreeFit', path=None):
159  r"""
160  Reconstruct the standard :math:`\Omega^-` ``ParticleList`` named ``Omega-:std``.
161 
162  .. seealso:: `BELLE2-NOTE-PH-2019-011 <https://docs.belle2.org/record/BELLE2-NOTE-PH-2019-011.pdf>`_.
163 
164  Parameters:
165  fitter (str): specify either ``KFit`` or ``TreeFit`` for the vertex reconstructions (default ``TreeFit``)
166  path (basf2.Path): modules are added to this path building the ``Omega-:std`` list
167  """
168 
169  if not isB2BII():
170  stdLambdas(path=path)
171  # 3.5 MeV Range around the nominal mass
172  cutAndCopyList(
173  'Lambda0:reco',
174  'Lambda0:merged',
175  '[ abs( dM ) < 0.0035 ] and \
176  [ cosAngleBetweenMomentumAndVertexVector > 0.0 ] and \
177  [ formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.35 ] and \
178  [ daughter(0,protonID) > 0.01 ] and \
179  [ chiProb > 0.0 ]',
180  True, path=path)
181  else:
182  stdPi('all', path=path)
183  # Rough Lambda0 cuts from J. Yelton Observations of an Excited Omega- Baryon
184  kFit('Lambda0:mdst', conf_level=0.0, path=path) # Re-vertexing, recover vertex variables and error matrix
185  cutAndCopyList(
186  'Lambda0:reco',
187  'Lambda0:mdst',
188  '[ abs( dM ) < 0.0035 ] and \
189  [ cosAngleBetweenMomentumAndVertexVector > 0.0 ] and \
190  [ dr > 0.35 ] and \
191  [ daughter(0,atcPIDBelle(4,3)) > 0.2 ] and \
192  [ daughter(0,atcPIDBelle(4,2)) > 0.2 ] and \
193  [ chiProb > 0.0 ]',
194  True, path=path)
195 
196  stdK('all', path=path)
197  # stdOmega-
198  if fitter == 'KFit':
199  kFit('Lambda0:reco', 0.0, fit_type='massvertex', path=path)
200  reconstructDecay('Omega-:reco -> Lambda0:reco K-:all', '1.622 < M < 1.722', path=path)
201  kFit('Omega-:reco', conf_level=0.0, path=path)
202  elif fitter == 'TreeFit':
203  reconstructDecay('Omega-:reco -> Lambda0:reco K-:all', '1.622 < M < 1.722', path=path)
204  treeFit('Omega-:reco', conf_level=0.0, massConstraint=[3122], path=path)
205  else:
206  B2ERROR(f"stdOmega: invalid fitter ({fitter}). Choose from KFit or TreeFit")
207 
208  if not isB2BII():
209  cutAndCopyList(
210  'Omega-:std',
211  'Omega-:reco',
212  '[ cosAngleBetweenMomentumAndVertexVector > 0.0] and \
213  [ formula( [ dr^2 + dz^2 ]^[0.5] ) > 0. and \
214  formula([dr^2 + dz^2]^[0.5])<formula([daughter(0,dr)^2 + daughter(0,dz)^2]^[0.5])] and \
215  [ chiProb > 0.0 ] and \
216  [ daughter(1,kaonID) > 0.01 ]',
217  True,
218  path=path)
219 
220  else:
221  cutAndCopyList(
222  'Omega-:std',
223  'Omega-:reco',
224  '[ cosAngleBetweenMomentumAndVertexVector > 0.0 ] and \
225  [ formula( [ dr^2 + dz^2 ]^[0.5] ) > 0. and \
226  formula([dr^2 + dz^2]^[0.5])<formula([daughter(0,dr)^2 + daughter(0,dz)^2 ]^[0.5])] and \
227  [ chiProb > 0.0 ] and \
228  [ daughter(1,atcPIDBelle(3,4)) > 0.2 and daughter(1,atcPIDBelle(3,2)) > 0.2 ]',
229  True,
230  path=path)
231 
232 
233 def goodXi(xitype='loose', path=None):
234  r"""
235  Select the standard good :math:`\Xi^-` ``ParticleList`` named ``Xi-:veryloose``, ``Xi-:loose``, or ``Xi-:tight``
236  from the reconstructed ``Xi-:std``.
237 
238  .. seealso:: `BELLE2-NOTE-PH-2019-011 <https://docs.belle2.org/record/BELLE2-NOTE-PH-2019-011.pdf>`_.
239 
240  Parameters:
241  xitype (str): specify either ``veryloose``, ``loose``, or ``tight`` for good ``ParticleList`` selection (default ``loose``)
242  path (basf2.Path): modules are added to this path building the ``Xi-:veryloose``, ``Xi-:loose``, or ``Xi-:tight``, list
243  """
244 
245  if not _std_hyperon_is_in_path("Xi-", path):
246  B2WARNING("Could not find standard Xi particle list! Creating it with default options.")
247  stdXi(path=path)
248  assert _std_hyperon_is_in_path("Xi-", path)
249 
250  if xitype == 'veryloose':
251  cutAndCopyList(
252  'Xi-:veryloose',
253  'Xi-:std',
254  '[ daughter(1,pt) > 0.05 and \
255  formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.1 ]',
256  True,
257  path=path)
258 
259  elif xitype == 'loose':
260  cutAndCopyList(
261  'Xi-:loose',
262  'Xi-:std',
263  '[ daughter(1,pt) > 0.05 and \
264  formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.1 and \
265  formula([daughter(0,cosAngleBetweenMomentumAndVertexVectorInXYPlane)/cosAngleBetweenMomentumAndVertexVectorInXYPlane])\
266 <1.006 ]',
267  True,
268  path=path)
269 
270  elif xitype == 'tight':
271  cutAndCopyList(
272  'Xi-:tight',
273  'Xi-:std',
274  '[ daughter(1,pt) > 0.1 and \
275  formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.15 and \
276  formula([daughter(0,cosAngleBetweenMomentumAndVertexVectorInXYPlane)/cosAngleBetweenMomentumAndVertexVectorInXYPlane])\
277 <1.001 ]',
278  True,
279  path=path)
280  else:
281  raise ValueError(f"\"{xitype}\" is none of the allowed Xi- list types!")
282 
283 
284 def goodXi0(xitype='loose', path=None):
285  r"""
286  Select the standard good :math:`\Xi^0` ``ParticleList`` named ``Xi0:veryloose``, ``Xi0:loose``, or ``Xi0:tight``
287  from the reconstructed ``Xi0:std``.
288 
289  .. seealso:: `BELLE2-NOTE-PH-2019-011 <https://docs.belle2.org/record/BELLE2-NOTE-PH-2019-011.pdf>`_.
290 
291  Parameters:
292  xitype (str): specify either ``veryloose``, ``loose``, or ``tight`` for good ``ParticleList`` selection (default ``loose``)
293  path (basf2.Path): modules are added to this path building the ``Xi0:veryloose``, ``Xi0:loose``, or ``Xi0:tight``, list
294  """
295 
296  if not _std_hyperon_is_in_path("Xi0", path):
297  B2WARNING("Could not find standard Xi0 particle list! Creating it with default options.")
298  stdXi0(path=path)
299  assert _std_hyperon_is_in_path("Xi0", path)
300 
301  if xitype == 'veryloose':
302  # Select pi0 at 3*sigma around the nominal mass
303  cutAndCopyList(
304  'Xi0:veryloose',
305  'Xi0:std',
306  '[ formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.25 and \
307  daughter(1,p) > 0.1 and \
308  abs( daughter(1,dM) ) < 0.0174 ]',
309  True,
310  path=path)
311 
312  elif xitype == 'loose':
313  # Select pi0 at 3*sigma around the nominal mass
314  cutAndCopyList(
315  'Xi0:loose',
316  'Xi0:std',
317  '[ formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.5 and \
318  daughter(1,p) > 0.15 and \
319  abs( daughter(1,dM) ) < 0.0174 ]',
320  True,
321  path=path)
322 
323  elif xitype == 'tight':
324  # Select pi0 at 2*sigma around the nominal mass
325  cutAndCopyList(
326  'Xi0:tight',
327  'Xi0:std',
328  '[ formula( [ dr^2 + dz^2 ]^[0.5] ) > 1.4 and \
329  daughter(1,p) > 0.25 and \
330  abs( daughter(1,dM) ) < 0.0116 ]',
331  True,
332  path=path)
333  else:
334  raise ValueError(f"\"{xitype}\" is none of the allowed Xi0 list types!")
335 
336 
337 def goodOmega(omegatype='loose', path=None):
338  r"""
339  Select the standard good :math:`\Omega^-` ``ParticleList`` named ``Omega-:veryloose``, ``Omega-:loose``,
340  or ``Omega-:tight`` from the reconstructed ``Omega-:std``.
341 
342  .. seealso:: `BELLE2-NOTE-PH-2019-011 <https://docs.belle2.org/record/BELLE2-NOTE-PH-2019-011.pdf>`_.
343 
344  Parameters:
345  omegatype (str): specify either ``veryloose``, ``loose``, or ``tight`` for good ``ParticleList`` selection
346  (default ``veryloose``)
347  path (basf2.Path): modules are added to this path building the ``Omega-:veryloose``, ``Omega-:loose``,
348  or ``Omega-:tight``, list
349  """
350 
351  if not _std_hyperon_is_in_path("Omega-", path):
352  B2WARNING("Could not find standard Omega particle list! Creating it with default options.")
353  stdOmega(path=path)
354  assert _std_hyperon_is_in_path("Omega-", path)
355 
356  if omegatype == 'veryloose':
357  cutAndCopyList(
358  'Omega-:veryloose',
359  'Omega-:std',
360  '[ daughter(1,pt) > 0.15 and \
361  formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.05 ]',
362  True,
363  path=path)
364 
365  elif omegatype == 'loose':
366  cutAndCopyList(
367  'Omega-:loose',
368  'Omega-:std',
369  '[ daughter(1,pt) > 0.15 and \
370  formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.15 and \
371  formula([daughter(0,cosAngleBetweenMomentumAndVertexVectorInXYPlane)/cosAngleBetweenMomentumAndVertexVectorInXYPlane])\
372 <1.0015 ]',
373  True,
374  path=path)
375 
376  elif omegatype == 'tight':
377  cutAndCopyList(
378  'Omega-:tight',
379  'Omega-:std',
380  '[ daughter(1,pt) > 0.3 and \
381  formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.15 and \
382  formula([daughter(0,cosAngleBetweenMomentumAndVertexVectorInXYPlane)/cosAngleBetweenMomentumAndVertexVectorInXYPlane])\
383 <1.0005 ]',
384  True,
385  path=path)
386  else:
387  raise ValueError(f"\"{omegatype}\" is none of the allowed Omega list types!")
388 
389 
390 def _std_hyperon_is_in_path(hyperon, path):
391  """
392  Helper function to check if the std hyperon is already in the reconstruction path.
393 
394  Checks whether there is a ``PListCutAndCopy`` module with the
395  ``outputListName``: ``<hyperon>:std``.
396  :param hyperon: One of ["Xi-", "Xi0", "Omega-"]
397  :param path: Instance of basf2.Path
398  :returns: Boolean, whether ``PListCutAndCopy`` with ``outputListName`` ``<hyperon>:std`` was found in path.
399  """
400  # maybe this function could be generalized for other standard particles, but
401  # so far it has only been tested for standard hyperons:
402  allowed_hyperons = {"Xi-", "Xi0", "Omega-"}
403  if hyperon not in allowed_hyperons:
404  raise ValueError(
405  f"\"{hyperon}\" is not in list of hyperons that this function has been tested for ({allowed_hyperons})."
406  )
407  for module in path.modules():
408  if (module.name() == f"PListCutAndCopy_{hyperon}:std" or
409  module.name().split(" -> ")[0] == f"ParticleCombiner_{hyperon}:std"):
410  return True
411  return False