Belle II Software light-2604-jellyfish
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", addSuffix=False, path=None):
22 r"""
23 Reconstruct the standard :math:`\Xi^-` ``ParticleList`` named ``Xi-:std`` by default.
24 If ``addSuffix`` is set to True, then a suffix of form ``_<fitter>`` is added
25 depending on the chosen fitter.
26
27 .. seealso:: `BELLE2-NOTE-PH-2019-011 <https://docs.belle2.org/record/BELLE2-NOTE-PH-2019-011.pdf>`_.
28
29 Parameters:
30 fitter (str): specify either ``KFit`` or ``TreeFit`` for the vertex reconstructions (default ``TreeFit``)
31 addSuffix (bool): whether to add a suffix of form ``_<fitter>`` to the ParticleList name
32 depending on the chosen fitter
33 path (basf2.Path): modules are added to this path building the ``Xi-:std`` list
34 """
35
36 B2WARNING(
37 "stdXi is deprecated and will be removed at the end of 2026. "
38 "Please replace it with a custom hyperon reconstruction and selection optimised for "
39 "your specific analysis. To provide feedback on the removal, see "
40 "https://gitlab.desy.de/belle2/software/basf2/-/work_items/11641"
41 )
42
43 suffix = ""
44 if addSuffix:
45 suffix = f"_{fitter}"
46 if not isB2BII():
47 stdLambdas(path=path, addSuffix=addSuffix)
48 # 3.5 MeV Range around the nominal mass
49 cutAndCopyList(
50 f"Lambda0:reco{suffix}",
51 f"Lambda0:merged{suffix}",
52 "[ abs( dM ) < 0.0035 ] and \
53 [ cosAngleBetweenMomentumAndVertexVector > 0.0 ] and \
54 [ formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.35 ] and \
55 [ daughter(0,protonID) > 0.01 ] and \
56 [ chiProb > 0.0 ]",
57 True,
58 path=path,
59 )
60 else:
61 stdPi('all', path=path)
62 # Rough Lambda0 cuts from J. Yelton Observations of an Excited Omega- Baryon
63 kFit('Lambda0:mdst', conf_level=0.0, path=path) # Re-vertexing, recover vertex variables and error matrix
64 cutAndCopyList(
65 f"Lambda0:reco{suffix}",
66 "Lambda0:mdst",
67 "[ abs( dM ) < 0.0035 ] and \
68 [ cosAngleBetweenMomentumAndVertexVector > 0.0 ] and \
69 [ dr > 0.35 ] and \
70 [ daughter(0,atcPIDBelle(4,3)) > 0.2 ] and \
71 [ daughter(0,atcPIDBelle(4,2)) > 0.2 ] and \
72 [ chiProb > 0.0 ]",
73 True,
74 path=path,
75 )
76
77 # stdXi-
78 if fitter == "KFit":
79 kFit(f"Lambda0:reco{suffix}", 0.0, fit_type="massvertex", path=path)
80 reconstructDecay(
81 f"Xi-:reco{suffix} -> Lambda0:reco{suffix} pi-:all",
82 "1.295 < M < 1.35",
83 path=path,
84 )
85 kFit(f"Xi-:reco{suffix}", conf_level=0.0, path=path)
86 elif fitter == "TreeFit":
87 reconstructDecay(
88 f"Xi-:reco{suffix} -> Lambda0:reco{suffix} pi-:all",
89 "1.295 < M < 1.35",
90 path=path,
91 )
92 treeFit(f"Xi-:reco{suffix}", conf_level=0.0, massConstraint=[3122], path=path)
93 else:
94 B2ERROR(f"stdXi: invalid fitter ({fitter}). Choose from KFit or TreeFit")
95
96 cutAndCopyList(
97 f"Xi-:std{suffix}",
98 f"Xi-:reco{suffix}",
99 "[ cosAngleBetweenMomentumAndVertexVector > 0.0 ] and \
100 [ formula( [ dr^2 + dz^2 ]^[0.5] ) > 0. and \
101 formula([dr^2 + dz^2 ]^[0.5])<formula([daughter(0,dr)^2 + daughter(0,dz)^2]^[0.5])] and \
102 [ chiProb > 0.0 ]",
103 True,
104 path=path,
105 )
106
107
108def stdXi0(gammatype='eff40', beamBackgroundMVAWeight="", fakePhotonMVAWeight="", biasCorrectionTable="", path=None):
109 r"""
110 Reconstruct the standard :math:`\Xi^0` ``ParticleList`` named ``Xi0:std``.
111
112 .. seealso:: `BELLE2-NOTE-PH-2019-011 <https://docs.belle2.org/record/BELLE2-NOTE-PH-2019-011.pdf>`_.
113
114 Parameters:
115 gammatype (str): specify either ``eff60``, ``eff50``, ``eff40``, ``eff30``, or ``eff20``
116 to select the signal efficiency of the photons used in the pi0 reconstruction
117 (default ``eff40``)
118
119 beamBackgroundMVAWeight (str): type of weight file for beam background MVA; if empty, beam background MVA will not be used
120
121 .. tip::
122 Please refer to the
123 `Performance Recommendations <https://belle2.pages.desy.de/performance/recommendations/>`_
124 for information on the beam background MVA.
125
126 fakePhotonMVAWeight (str): type of weight file for fake photon MVA; if empty, fake photon MVA will not be used
127
128 .. tip::
129 Please refer to the
130 `Performance Recommendations <https://belle2.pages.desy.de/performance/recommendations/>`_
131 for information on the fake photon MVA.
132
133 biasCorrectionTable (str): correction table for the photon energy bias correction (should only be applied to data)
134
135 .. tip::
136 Please refer to the
137 `Performance Recommendations <https://belle2.pages.desy.de/performance/recommendations/>`_
138 for information on the names of available correction tables.
139
140 path (basf2.Path): modules are added to this path building the ``Xi0:std`` list
141 """
142
143 B2WARNING(
144 "stdXi0 is deprecated and will be removed at the end of 2026. "
145 "Please replace it with a custom hyperon reconstruction and selection optimised for "
146 "your specific analysis. To provide feedback on the removal, see "
147 "https://gitlab.desy.de/belle2/software/basf2/-/work_items/11641"
148 )
149
150 if not isB2BII():
151 stdLambdas(path=path)
152 # 3.5 MeV Range around nominal mass (~7*sigma_core)
153 cutAndCopyList(
154 'Lambda0:reco',
155 'Lambda0:merged',
156 '[ abs( dM ) < 0.0035 ] and \
157 [ cosAngleBetweenMomentumAndVertexVector > 0.0 ] and \
158 [ formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.35 ] and \
159 [ daughter(0,protonID) > 0.01 ] and \
160 [ chiProb > 0.0 ]',
161 True, path=path)
162 # ~7*sigma Range around nominal mass
164 f'pi0{gammatype}_May2020',
165 path=path,
166 beamBackgroundMVAWeight=beamBackgroundMVAWeight,
167 fakePhotonMVAWeight=fakePhotonMVAWeight,
168 biasCorrectionTable=biasCorrectionTable)
169 reconstructDecay(f'pi0:reco -> gamma:pi0{gammatype}_May2020 gamma:pi0{gammatype}_May2020',
170 'abs( dM ) < 0.0406',
171 True, path=path)
172
173 else:
174 # Rough pi0/Lambda0 cuts from J. Yelton Observations of an Excited Omega- Baryon
175 cutAndCopyList(
176 'pi0:reco',
177 'pi0:mdst',
178 '[ abs( dM ) < 0.0189 ] and \
179 [ [ daughter(0,clusterReg) == 1 and daughter(0,E) > 0.05 ] or [ daughter(0,clusterReg) == 3 and daughter(0,E) > 0.05 ] or \
180 [ daughter(0,clusterReg) == 2 and daughter(0,E) > 0.03 ] ] and \
181 [ [ daughter(1,clusterReg) == 1 and daughter(1,E) > 0.05 ] or [ daughter(1,clusterReg) == 3 and daughter(1,E) > 0.05 ] or \
182 [ daughter(1,clusterReg) == 2 and daughter(1,E) > 0.03 ] ]',
183 path=path)
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 reconstructDecay(
197 'Xi0:prelim -> Lambda0:reco pi0:reco',
198 '1.225 < M < 1.405',
199 path=path)
200 treeFit('Xi0:prelim', conf_level=0.0, massConstraint=[3122], ipConstraint=True, updateAllDaughters=True, path=path)
201 # Selecting ~4*sigma around the pi0 nominal mass
202 # pi0 mass range is invariant for B2BII, tighter selection is required by user
203 applyCuts('Xi0:prelim', '[ abs( daughter(1,dM) ) < 0.0232 ]', path=path)
204 treeFit('Xi0:prelim', conf_level=0.0, massConstraint=[111, 3122], ipConstraint=True, updateAllDaughters=False, path=path)
205
206 cutAndCopyList(
207 'Xi0:std',
208 'Xi0:prelim',
209 '[ cosAngleBetweenMomentumAndVertexVector > 0.0 ] and \
210 [ daughter(0,cosAngleBetweenMomentumAndVertexVectorInXYPlane) < cosAngleBetweenMomentumAndVertexVectorInXYPlane ] and \
211 [ formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.0 and \
212 formula([dr^2 + dz^2]^[0.5])<formula([daughter(0,dr)^2 + daughter(0,dz)^2]^[0.5])] and \
213 [ chiProb > 0.0 ]',
214 True,
215 path=path)
216
217
218def stdOmega(fitter="TreeFit", addSuffix=False, path=None):
219 r"""
220 Reconstruct the standard :math:`\Omega^-` ``ParticleList`` named ``Omega-:std``.
221 If ``addSuffix`` is set to True, then a suffix of form ``_<fitter>`` is added
222 depending on the chosen fitter.
223
224 .. seealso:: `BELLE2-NOTE-PH-2019-011 <https://docs.belle2.org/record/BELLE2-NOTE-PH-2019-011.pdf>`_.
225
226 Parameters:
227 fitter (str): specify either ``KFit`` or ``TreeFit`` for the vertex reconstructions (default ``TreeFit``)
228 addSuffix (bool): whether to add a suffix of form ``_<fitter>`` to the ParticleList name
229 depending on the chosen fitter
230 path (basf2.Path): modules are added to this path building the ``Omega-:std`` list
231 """
232
233 B2WARNING(
234 "stdOmega is deprecated and will be removed at the end of 2026. "
235 "Please replace it with a custom hyperon reconstruction and selection optimised for "
236 "your specific analysis. To provide feedback on the removal, see "
237 "https://gitlab.desy.de/belle2/software/basf2/-/work_items/11641"
238 )
239
240 suffix = ""
241 if addSuffix:
242 suffix = f"_{fitter}"
243 if not isB2BII():
244 stdLambdas(path=path, addSuffix=addSuffix)
245 # 3.5 MeV Range around the nominal mass
246 cutAndCopyList(
247 f"Lambda0:reco{suffix}",
248 f"Lambda0:merged{suffix}",
249 "[ abs( dM ) < 0.0035 ] and \
250 [ cosAngleBetweenMomentumAndVertexVector > 0.0 ] and \
251 [ formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.35 ] and \
252 [ daughter(0,protonID) > 0.01 ] and \
253 [ chiProb > 0.0 ]",
254 True,
255 path=path,
256 )
257 else:
258 stdPi('all', path=path)
259 # Rough Lambda0 cuts from J. Yelton Observations of an Excited Omega- Baryon
260 kFit('Lambda0:mdst', conf_level=0.0, path=path) # Re-vertexing, recover vertex variables and error matrix
261 cutAndCopyList(
262 f"Lambda0:reco{suffix}",
263 "Lambda0:mdst",
264 "[ abs( dM ) < 0.0035 ] and \
265 [ cosAngleBetweenMomentumAndVertexVector > 0.0 ] and \
266 [ dr > 0.35 ] and \
267 [ daughter(0,atcPIDBelle(4,3)) > 0.2 ] and \
268 [ daughter(0,atcPIDBelle(4,2)) > 0.2 ] and \
269 [ chiProb > 0.0 ]",
270 True,
271 path=path,
272 )
273
274 stdK('all', path=path)
275 # stdOmega-
276 if fitter == "KFit":
277 kFit(f"Lambda0:reco{suffix}", 0.0, fit_type="massvertex", path=path)
278 reconstructDecay(
279 f"Omega-:reco{suffix} -> Lambda0:reco{suffix} K-:all", "1.622 < M < 1.722", path=path
280 )
281 kFit(f"Omega-:reco{suffix}", conf_level=0.0, path=path)
282 elif fitter == "TreeFit":
283 reconstructDecay(
284 f"Omega-:reco{suffix} -> Lambda0:reco{suffix} K-:all", "1.622 < M < 1.722", path=path
285 )
286 treeFit(f"Omega-:reco{suffix}", conf_level=0.0, massConstraint=[3122], path=path)
287 else:
288 B2ERROR(f"stdOmega: invalid fitter ({fitter}). Choose from KFit or TreeFit")
289
290 if not isB2BII():
291 cutAndCopyList(
292 f"Omega-:std{suffix}",
293 f"Omega-:reco{suffix}",
294 "[ cosAngleBetweenMomentumAndVertexVector > 0.0] and \
295 [ formula( [ dr^2 + dz^2 ]^[0.5] ) > 0. and \
296 formula([dr^2 + dz^2]^[0.5])<formula([daughter(0,dr)^2 + daughter(0,dz)^2]^[0.5])] and \
297 [ chiProb > 0.0 ] and \
298 [ daughter(1,kaonID) > 0.01 ]",
299 True,
300 path=path,
301 )
302
303 else:
304 cutAndCopyList(
305 f"Omega-:std{suffix}",
306 f"Omega-:reco{suffix}",
307 "[ cosAngleBetweenMomentumAndVertexVector > 0.0 ] and \
308 [ formula( [ dr^2 + dz^2 ]^[0.5] ) > 0. and \
309 formula([dr^2 + dz^2]^[0.5])<formula([daughter(0,dr)^2 + daughter(0,dz)^2 ]^[0.5])] and \
310 [ chiProb > 0.0 ] and \
311 [ daughter(1,atcPIDBelle(3,4)) > 0.2 and daughter(1,atcPIDBelle(3,2)) > 0.2 ]",
312 True,
313 path=path,
314 )
315
316
317def goodXi(xitype='loose', path=None):
318 r"""
319 Select the standard good :math:`\Xi^-` ``ParticleList`` named ``Xi-:veryloose``, ``Xi-:loose``, or ``Xi-:tight``
320 from the reconstructed ``Xi-:std``.
321
322 .. seealso:: `BELLE2-NOTE-PH-2019-011 <https://docs.belle2.org/record/BELLE2-NOTE-PH-2019-011.pdf>`_.
323
324 Parameters:
325 xitype (str): specify either ``veryloose``, ``loose``, or ``tight`` for good ``ParticleList`` selection (default ``loose``)
326 path (basf2.Path): modules are added to this path building the ``Xi-:veryloose``, ``Xi-:loose``, or ``Xi-:tight``, list
327 """
328
329 B2WARNING(
330 "goodXi is deprecated and will be removed at the end of 2026. "
331 "Please replace it with a custom hyperon reconstruction and selection optimised for "
332 "your specific analysis. To provide feedback on the removal, see "
333 "https://gitlab.desy.de/belle2/software/basf2/-/work_items/11641"
334 )
335
336 if not _std_hyperon_is_in_path("Xi-", path):
337 B2WARNING("Could not find standard Xi particle list! Creating it with default options.")
338 stdXi(path=path)
339 assert _std_hyperon_is_in_path("Xi-", path)
340
341 if xitype == 'veryloose':
342 cutAndCopyList(
343 'Xi-:veryloose',
344 'Xi-:std',
345 '[ daughter(1,pt) > 0.05 and \
346 formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.1 ]',
347 True,
348 path=path)
349
350 elif xitype == 'loose':
351 cutAndCopyList(
352 'Xi-:loose',
353 'Xi-:std',
354 '[ daughter(1,pt) > 0.05 and \
355 formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.1 and \
356 formula([daughter(0,cosAngleBetweenMomentumAndVertexVectorInXYPlane)/cosAngleBetweenMomentumAndVertexVectorInXYPlane])\
357<1.006 ]',
358 True,
359 path=path)
360
361 elif xitype == 'tight':
362 cutAndCopyList(
363 'Xi-:tight',
364 'Xi-:std',
365 '[ daughter(1,pt) > 0.1 and \
366 formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.15 and \
367 formula([daughter(0,cosAngleBetweenMomentumAndVertexVectorInXYPlane)/cosAngleBetweenMomentumAndVertexVectorInXYPlane])\
368<1.001 ]',
369 True,
370 path=path)
371 else:
372 raise ValueError(f"\"{xitype}\" is none of the allowed Xi- list types!")
373
374
375def goodXi0(xitype='loose', path=None):
376 r"""
377 Select the standard good :math:`\Xi^0` ``ParticleList`` named ``Xi0:veryloose``, ``Xi0:loose``, or ``Xi0:tight``
378 from the reconstructed ``Xi0:std``.
379
380 .. seealso:: `BELLE2-NOTE-PH-2019-011 <https://docs.belle2.org/record/BELLE2-NOTE-PH-2019-011.pdf>`_.
381
382 Parameters:
383 xitype (str): specify either ``veryloose``, ``loose``, or ``tight`` for good ``ParticleList`` selection (default ``loose``)
384 path (basf2.Path): modules are added to this path building the ``Xi0:veryloose``, ``Xi0:loose``, or ``Xi0:tight``, list
385 """
386
387 B2WARNING(
388 "goodXi0 is deprecated and will be removed at the end of 2026. "
389 "Please replace it with a custom hyperon reconstruction and selection optimised for "
390 "your specific analysis. To provide feedback on the removal, see "
391 "https://gitlab.desy.de/belle2/software/basf2/-/work_items/11641"
392 )
393
394 if not _std_hyperon_is_in_path("Xi0", path):
395 B2WARNING("Could not find standard Xi0 particle list! Creating it with default options.")
396 stdXi0(path=path)
397 assert _std_hyperon_is_in_path("Xi0", path)
398
399 if xitype == 'veryloose':
400 # Select pi0 at 3*sigma around the nominal mass
401 cutAndCopyList(
402 'Xi0:veryloose',
403 'Xi0:std',
404 '[ formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.25 and \
405 daughter(1,p) > 0.1 and \
406 abs( daughter(1,dM) ) < 0.0174 ]',
407 True,
408 path=path)
409
410 elif xitype == 'loose':
411 # Select pi0 at 3*sigma around the nominal mass
412 cutAndCopyList(
413 'Xi0:loose',
414 'Xi0:std',
415 '[ formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.5 and \
416 daughter(1,p) > 0.15 and \
417 abs( daughter(1,dM) ) < 0.0174 ]',
418 True,
419 path=path)
420
421 elif xitype == 'tight':
422 # Select pi0 at 2*sigma around the nominal mass
423 cutAndCopyList(
424 'Xi0:tight',
425 'Xi0:std',
426 '[ formula( [ dr^2 + dz^2 ]^[0.5] ) > 1.4 and \
427 daughter(1,p) > 0.25 and \
428 abs( daughter(1,dM) ) < 0.0116 ]',
429 True,
430 path=path)
431 else:
432 raise ValueError(f"\"{xitype}\" is none of the allowed Xi0 list types!")
433
434
435def goodOmega(omegatype='loose', path=None):
436 r"""
437 Select the standard good :math:`\Omega^-` ``ParticleList`` named ``Omega-:veryloose``, ``Omega-:loose``,
438 or ``Omega-:tight`` from the reconstructed ``Omega-:std``.
439
440 .. seealso:: `BELLE2-NOTE-PH-2019-011 <https://docs.belle2.org/record/BELLE2-NOTE-PH-2019-011.pdf>`_.
441
442 Parameters:
443 omegatype (str): specify either ``veryloose``, ``loose``, or ``tight`` for good ``ParticleList`` selection
444 (default ``veryloose``)
445 path (basf2.Path): modules are added to this path building the ``Omega-:veryloose``, ``Omega-:loose``,
446 or ``Omega-:tight``, list
447 """
448
449 B2WARNING(
450 "goodOmega is deprecated and will be removed at the end of 2026. "
451 "Please replace it with a custom hyperon reconstruction and selection optimised for "
452 "your specific analysis. To provide feedback on the removal, see "
453 "https://gitlab.desy.de/belle2/software/basf2/-/work_items/11641"
454 )
455
456 if not _std_hyperon_is_in_path("Omega-", path):
457 B2WARNING("Could not find standard Omega particle list! Creating it with default options.")
458 stdOmega(path=path)
459 assert _std_hyperon_is_in_path("Omega-", path)
460
461 if omegatype == 'veryloose':
462 cutAndCopyList(
463 'Omega-:veryloose',
464 'Omega-:std',
465 '[ daughter(1,pt) > 0.15 and \
466 formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.05 ]',
467 True,
468 path=path)
469
470 elif omegatype == 'loose':
471 cutAndCopyList(
472 'Omega-:loose',
473 'Omega-:std',
474 '[ daughter(1,pt) > 0.15 and \
475 formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.15 and \
476 formula([daughter(0,cosAngleBetweenMomentumAndVertexVectorInXYPlane)/cosAngleBetweenMomentumAndVertexVectorInXYPlane])\
477<1.0015 ]',
478 True,
479 path=path)
480
481 elif omegatype == 'tight':
482 cutAndCopyList(
483 'Omega-:tight',
484 'Omega-:std',
485 '[ daughter(1,pt) > 0.3 and \
486 formula( [ dr^2 + dz^2 ]^[0.5] ) > 0.15 and \
487 formula([daughter(0,cosAngleBetweenMomentumAndVertexVectorInXYPlane)/cosAngleBetweenMomentumAndVertexVectorInXYPlane])\
488<1.0005 ]',
489 True,
490 path=path)
491 else:
492 raise ValueError(f"\"{omegatype}\" is none of the allowed Omega list types!")
493
494
495def _std_hyperon_is_in_path(hyperon, path):
496 """
497 Helper function to check if the std hyperon is already in the reconstruction path.
498
499 Checks whether there is a ``PListCutAndCopy`` module with the
500 ``outputListName``: ``<hyperon>:std``.
501 :param hyperon: One of ["Xi-", "Xi0", "Omega-"]
502 :param path: Instance of basf2.Path
503 :returns: Boolean, whether ``PListCutAndCopy`` with ``outputListName`` ``<hyperon>:std`` was found in path.
504 """
505 # maybe this function could be generalized for other standard particles, but
506 # so far it has only been tested for standard hyperons:
507 allowed_hyperons = {"Xi-", "Xi0", "Omega-"}
508 if hyperon not in allowed_hyperons:
509 raise ValueError(
510 f"\"{hyperon}\" is not in list of hyperons that this function has been tested for ({allowed_hyperons})."
511 )
512 for module in path.modules():
513 if (module.name() == f"PListCutAndCopy_{hyperon}:std" or
514 module.name().split(" -> ")[0] == f"ParticleCombiner_{hyperon}:std"):
515 return True
516 return False