Belle II Software development
stdHyperons.py
1#!/usr/bin/env python3
2
3
10
11from basf2 import B2ERROR, B2WARNING
12from b2bii import isB2BII
13from modularAnalysis import cutAndCopyList, reconstructDecay, applyCuts
14from vertex import treeFit, kFit
15
16from stdCharged import stdPi, stdK
17from stdV0s import stdLambdas
18from stdPhotons import stdPhotons
19
20
21def 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
81def stdXi0(gammatype='eff40', beamBackgroundMVAWeight="", fakePhotonMVAWeight="", biasCorrectionTable="", path=None):
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
92 beamBackgroundMVAWeight (str): type of weight file for beam background MVA; if empty, beam background MVA will not be used
93
94 .. tip::
95 Please refer to the
96 `Neutrals Performance XWiki page <https://xwiki.desy.de/xwiki/rest/p/e23c8>`_
97 for information on the beam background MVA.
98
99 fakePhotonMVAWeight (str): type of weight file for fake photon MVA; if empty, fake photon MVA will not be used
100
101 .. tip::
102 Please refer to the
103 `Neutrals Performance XWiki page <https://xwiki.desy.de/xwiki/rest/p/e23c8>`_
104 for information on the fake photon MVA.
105
106 biasCorrectionTable (str): correction table for the photon energy bias correction (should only be applied to data)
107
108 .. tip::
109 Please refer to the
110 `Neutrals Performance XWiki page <https://xwiki.desy.de/xwiki/rest/p/e23c8>`_
111 for information on the names of available correction tables.
112
113 path (basf2.Path): modules are added to this path building the ``Xi0:std`` list
114 """
115
116 if not isB2BII():
117 stdLambdas(path=path)
118 # 3.5 MeV Range around nominal mass (~7*sigma_core)
119 cutAndCopyList(
120 'Lambda0:reco',
121 'Lambda0:merged',
122 '[ abs( dM ) < 0.0035 ] and \
123 [ cosAngleBetweenMomentumAndVertexVector > 0.0 ] and \
124 [ formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.35 ] and \
125 [ daughter(0,protonID) > 0.01 ] and \
126 [ chiProb > 0.0 ]',
127 True, path=path)
128 # ~7*sigma Range around nominal mass
130 f'pi0{gammatype}_May2020',
131 path=path,
132 beamBackgroundMVAWeight=beamBackgroundMVAWeight,
133 fakePhotonMVAWeight=fakePhotonMVAWeight,
134 biasCorrectionTable=biasCorrectionTable)
135 reconstructDecay(f'pi0:reco -> gamma:pi0{gammatype}_May2020 gamma:pi0{gammatype}_May2020',
136 'abs( dM ) < 0.0406',
137 True, path=path)
138
139 else:
140 # Rough pi0/Lambda0 cuts from J. Yelton Observations of an Excited Omega- Baryon
141 cutAndCopyList(
142 'pi0:reco',
143 'pi0:mdst',
144 '[ abs( dM ) < 0.0189 ] and \
145 [ [ daughter(0,clusterReg) == 1 and daughter(0,E) > 0.05 ] or [ daughter(0,clusterReg) == 3 and daughter(0,E) > 0.05 ] or \
146 [ daughter(0,clusterReg) == 2 and daughter(0,E) > 0.03 ] ] and \
147 [ [ daughter(1,clusterReg) == 1 and daughter(1,E) > 0.05 ] or [ daughter(1,clusterReg) == 3 and daughter(1,E) > 0.05 ] or \
148 [ daughter(1,clusterReg) == 2 and daughter(1,E) > 0.03 ] ]',
149 path=path)
150 kFit('Lambda0:mdst', conf_level=0.0, path=path) # Re-vertexing, recover vertex variables and error matrix
151 cutAndCopyList(
152 'Lambda0:reco',
153 'Lambda0:mdst',
154 '[ abs( dM ) < 0.0035 ] and \
155 [ cosAngleBetweenMomentumAndVertexVector > 0.0 ] and \
156 [ dr > 0.35 ] and \
157 [ daughter(0,atcPIDBelle(4,3)) > 0.2 ] and \
158 [ daughter(0,atcPIDBelle(4,2)) > 0.2 ] and \
159 [ chiProb > 0.0 ]',
160 True, path=path)
161
162 reconstructDecay(
163 'Xi0:prelim -> Lambda0:reco pi0:reco',
164 '1.225 < M < 1.405',
165 path=path)
166 treeFit('Xi0:prelim', conf_level=0.0, massConstraint=[3122], ipConstraint=True, updateAllDaughters=True, path=path)
167 # Selecting ~4*sigma around the pi0 nominal mass
168 # pi0 mass range is invariant for B2BII, tighter selection is required by user
169 applyCuts('Xi0:prelim', '[ abs( daughter(1,dM) ) < 0.0232 ]', path=path)
170 treeFit('Xi0:prelim', conf_level=0.0, massConstraint=[111, 3122], ipConstraint=True, updateAllDaughters=False, path=path)
171
172 cutAndCopyList(
173 'Xi0:std',
174 'Xi0:prelim',
175 '[ cosAngleBetweenMomentumAndVertexVector > 0.0 ] and \
176 [ daughter(0,cosAngleBetweenMomentumAndVertexVectorInXYPlane) < cosAngleBetweenMomentumAndVertexVectorInXYPlane ] and \
177 [ formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.0 and \
178 formula([dr^2 + dz^2]^[0.5])<formula([daughter(0,dr)^2 + daughter(0,dz)^2]^[0.5])] and \
179 [ chiProb > 0.0 ]',
180 True,
181 path=path)
182
183
184def stdOmega(fitter='TreeFit', path=None):
185 r"""
186 Reconstruct the standard :math:`\Omega^-` ``ParticleList`` named ``Omega-:std``.
187
188 .. seealso:: `BELLE2-NOTE-PH-2019-011 <https://docs.belle2.org/record/BELLE2-NOTE-PH-2019-011.pdf>`_.
189
190 Parameters:
191 fitter (str): specify either ``KFit`` or ``TreeFit`` for the vertex reconstructions (default ``TreeFit``)
192 path (basf2.Path): modules are added to this path building the ``Omega-:std`` list
193 """
194
195 if not isB2BII():
196 stdLambdas(path=path)
197 # 3.5 MeV Range around the nominal mass
198 cutAndCopyList(
199 'Lambda0:reco',
200 'Lambda0:merged',
201 '[ abs( dM ) < 0.0035 ] and \
202 [ cosAngleBetweenMomentumAndVertexVector > 0.0 ] and \
203 [ formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.35 ] and \
204 [ daughter(0,protonID) > 0.01 ] and \
205 [ chiProb > 0.0 ]',
206 True, path=path)
207 else:
208 stdPi('all', path=path)
209 # Rough Lambda0 cuts from J. Yelton Observations of an Excited Omega- Baryon
210 kFit('Lambda0:mdst', conf_level=0.0, path=path) # Re-vertexing, recover vertex variables and error matrix
211 cutAndCopyList(
212 'Lambda0:reco',
213 'Lambda0:mdst',
214 '[ abs( dM ) < 0.0035 ] and \
215 [ cosAngleBetweenMomentumAndVertexVector > 0.0 ] and \
216 [ dr > 0.35 ] and \
217 [ daughter(0,atcPIDBelle(4,3)) > 0.2 ] and \
218 [ daughter(0,atcPIDBelle(4,2)) > 0.2 ] and \
219 [ chiProb > 0.0 ]',
220 True, path=path)
221
222 stdK('all', path=path)
223 # stdOmega-
224 if fitter == 'KFit':
225 kFit('Lambda0:reco', 0.0, fit_type='massvertex', path=path)
226 reconstructDecay('Omega-:reco -> Lambda0:reco K-:all', '1.622 < M < 1.722', path=path)
227 kFit('Omega-:reco', conf_level=0.0, path=path)
228 elif fitter == 'TreeFit':
229 reconstructDecay('Omega-:reco -> Lambda0:reco K-:all', '1.622 < M < 1.722', path=path)
230 treeFit('Omega-:reco', conf_level=0.0, massConstraint=[3122], path=path)
231 else:
232 B2ERROR(f"stdOmega: invalid fitter ({fitter}). Choose from KFit or TreeFit")
233
234 if not isB2BII():
235 cutAndCopyList(
236 'Omega-:std',
237 'Omega-:reco',
238 '[ cosAngleBetweenMomentumAndVertexVector > 0.0] and \
239 [ formula( [ dr^2 + dz^2 ]^[0.5] ) > 0. and \
240 formula([dr^2 + dz^2]^[0.5])<formula([daughter(0,dr)^2 + daughter(0,dz)^2]^[0.5])] and \
241 [ chiProb > 0.0 ] and \
242 [ daughter(1,kaonID) > 0.01 ]',
243 True,
244 path=path)
245
246 else:
247 cutAndCopyList(
248 'Omega-:std',
249 'Omega-:reco',
250 '[ cosAngleBetweenMomentumAndVertexVector > 0.0 ] and \
251 [ formula( [ dr^2 + dz^2 ]^[0.5] ) > 0. and \
252 formula([dr^2 + dz^2]^[0.5])<formula([daughter(0,dr)^2 + daughter(0,dz)^2 ]^[0.5])] and \
253 [ chiProb > 0.0 ] and \
254 [ daughter(1,atcPIDBelle(3,4)) > 0.2 and daughter(1,atcPIDBelle(3,2)) > 0.2 ]',
255 True,
256 path=path)
257
258
259def goodXi(xitype='loose', path=None):
260 r"""
261 Select the standard good :math:`\Xi^-` ``ParticleList`` named ``Xi-:veryloose``, ``Xi-:loose``, or ``Xi-:tight``
262 from the reconstructed ``Xi-:std``.
263
264 .. seealso:: `BELLE2-NOTE-PH-2019-011 <https://docs.belle2.org/record/BELLE2-NOTE-PH-2019-011.pdf>`_.
265
266 Parameters:
267 xitype (str): specify either ``veryloose``, ``loose``, or ``tight`` for good ``ParticleList`` selection (default ``loose``)
268 path (basf2.Path): modules are added to this path building the ``Xi-:veryloose``, ``Xi-:loose``, or ``Xi-:tight``, list
269 """
270
271 if not _std_hyperon_is_in_path("Xi-", path):
272 B2WARNING("Could not find standard Xi particle list! Creating it with default options.")
273 stdXi(path=path)
274 assert _std_hyperon_is_in_path("Xi-", path)
275
276 if xitype == 'veryloose':
277 cutAndCopyList(
278 'Xi-:veryloose',
279 'Xi-:std',
280 '[ daughter(1,pt) > 0.05 and \
281 formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.1 ]',
282 True,
283 path=path)
284
285 elif xitype == 'loose':
286 cutAndCopyList(
287 'Xi-:loose',
288 'Xi-:std',
289 '[ daughter(1,pt) > 0.05 and \
290 formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.1 and \
291 formula([daughter(0,cosAngleBetweenMomentumAndVertexVectorInXYPlane)/cosAngleBetweenMomentumAndVertexVectorInXYPlane])\
292<1.006 ]',
293 True,
294 path=path)
295
296 elif xitype == 'tight':
297 cutAndCopyList(
298 'Xi-:tight',
299 'Xi-:std',
300 '[ daughter(1,pt) > 0.1 and \
301 formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.15 and \
302 formula([daughter(0,cosAngleBetweenMomentumAndVertexVectorInXYPlane)/cosAngleBetweenMomentumAndVertexVectorInXYPlane])\
303<1.001 ]',
304 True,
305 path=path)
306 else:
307 raise ValueError(f"\"{xitype}\" is none of the allowed Xi- list types!")
308
309
310def goodXi0(xitype='loose', path=None):
311 r"""
312 Select the standard good :math:`\Xi^0` ``ParticleList`` named ``Xi0:veryloose``, ``Xi0:loose``, or ``Xi0:tight``
313 from the reconstructed ``Xi0:std``.
314
315 .. seealso:: `BELLE2-NOTE-PH-2019-011 <https://docs.belle2.org/record/BELLE2-NOTE-PH-2019-011.pdf>`_.
316
317 Parameters:
318 xitype (str): specify either ``veryloose``, ``loose``, or ``tight`` for good ``ParticleList`` selection (default ``loose``)
319 path (basf2.Path): modules are added to this path building the ``Xi0:veryloose``, ``Xi0:loose``, or ``Xi0:tight``, list
320 """
321
322 if not _std_hyperon_is_in_path("Xi0", path):
323 B2WARNING("Could not find standard Xi0 particle list! Creating it with default options.")
324 stdXi0(path=path)
325 assert _std_hyperon_is_in_path("Xi0", path)
326
327 if xitype == 'veryloose':
328 # Select pi0 at 3*sigma around the nominal mass
329 cutAndCopyList(
330 'Xi0:veryloose',
331 'Xi0:std',
332 '[ formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.25 and \
333 daughter(1,p) > 0.1 and \
334 abs( daughter(1,dM) ) < 0.0174 ]',
335 True,
336 path=path)
337
338 elif xitype == 'loose':
339 # Select pi0 at 3*sigma around the nominal mass
340 cutAndCopyList(
341 'Xi0:loose',
342 'Xi0:std',
343 '[ formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.5 and \
344 daughter(1,p) > 0.15 and \
345 abs( daughter(1,dM) ) < 0.0174 ]',
346 True,
347 path=path)
348
349 elif xitype == 'tight':
350 # Select pi0 at 2*sigma around the nominal mass
351 cutAndCopyList(
352 'Xi0:tight',
353 'Xi0:std',
354 '[ formula( [ dr^2 + dz^2 ]^[0.5] ) > 1.4 and \
355 daughter(1,p) > 0.25 and \
356 abs( daughter(1,dM) ) < 0.0116 ]',
357 True,
358 path=path)
359 else:
360 raise ValueError(f"\"{xitype}\" is none of the allowed Xi0 list types!")
361
362
363def goodOmega(omegatype='loose', path=None):
364 r"""
365 Select the standard good :math:`\Omega^-` ``ParticleList`` named ``Omega-:veryloose``, ``Omega-:loose``,
366 or ``Omega-:tight`` from the reconstructed ``Omega-:std``.
367
368 .. seealso:: `BELLE2-NOTE-PH-2019-011 <https://docs.belle2.org/record/BELLE2-NOTE-PH-2019-011.pdf>`_.
369
370 Parameters:
371 omegatype (str): specify either ``veryloose``, ``loose``, or ``tight`` for good ``ParticleList`` selection
372 (default ``veryloose``)
373 path (basf2.Path): modules are added to this path building the ``Omega-:veryloose``, ``Omega-:loose``,
374 or ``Omega-:tight``, list
375 """
376
377 if not _std_hyperon_is_in_path("Omega-", path):
378 B2WARNING("Could not find standard Omega particle list! Creating it with default options.")
379 stdOmega(path=path)
380 assert _std_hyperon_is_in_path("Omega-", path)
381
382 if omegatype == 'veryloose':
383 cutAndCopyList(
384 'Omega-:veryloose',
385 'Omega-:std',
386 '[ daughter(1,pt) > 0.15 and \
387 formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.05 ]',
388 True,
389 path=path)
390
391 elif omegatype == 'loose':
392 cutAndCopyList(
393 'Omega-:loose',
394 'Omega-:std',
395 '[ daughter(1,pt) > 0.15 and \
396 formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.15 and \
397 formula([daughter(0,cosAngleBetweenMomentumAndVertexVectorInXYPlane)/cosAngleBetweenMomentumAndVertexVectorInXYPlane])\
398<1.0015 ]',
399 True,
400 path=path)
401
402 elif omegatype == 'tight':
403 cutAndCopyList(
404 'Omega-:tight',
405 'Omega-:std',
406 '[ daughter(1,pt) > 0.3 and \
407 formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.15 and \
408 formula([daughter(0,cosAngleBetweenMomentumAndVertexVectorInXYPlane)/cosAngleBetweenMomentumAndVertexVectorInXYPlane])\
409<1.0005 ]',
410 True,
411 path=path)
412 else:
413 raise ValueError(f"\"{omegatype}\" is none of the allowed Omega list types!")
414
415
416def _std_hyperon_is_in_path(hyperon, path):
417 """
418 Helper function to check if the std hyperon is already in the reconstruction path.
419
420 Checks whether there is a ``PListCutAndCopy`` module with the
421 ``outputListName``: ``<hyperon>:std``.
422 :param hyperon: One of ["Xi-", "Xi0", "Omega-"]
423 :param path: Instance of basf2.Path
424 :returns: Boolean, whether ``PListCutAndCopy`` with ``outputListName`` ``<hyperon>:std`` was found in path.
425 """
426 # maybe this function could be generalized for other standard particles, but
427 # so far it has only been tested for standard hyperons:
428 allowed_hyperons = {"Xi-", "Xi0", "Omega-"}
429 if hyperon not in allowed_hyperons:
430 raise ValueError(
431 f"\"{hyperon}\" is not in list of hyperons that this function has been tested for ({allowed_hyperons})."
432 )
433 for module in path.modules():
434 if (module.name() == f"PListCutAndCopy_{hyperon}:std" or
435 module.name().split(" -> ")[0] == f"ParticleCombiner_{hyperon}:std"):
436 return True
437 return False