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