Source code for pdg

#!/usr/bin/env python3

##########################################################################
# basf2 (Belle II Analysis Software Framework)                           #
# Author: The Belle II Collaboration                                     #
#                                                                        #
# See git log for contributors and copyright holders.                    #
# This file is licensed under LGPL-3.0, see LICENSE.md.                  #
##########################################################################

"""
pdg - access particle definitions
---------------------------------

This module helps to access particle definitions. When the software is loaded a
list of known particles is read from the EvtGen particle definition file
:file:`framework/particledb/data/evt.pdl`. This file contains all well-known
standard-model particles and their properties: mass, width or lifetime, charge,
spin.
...

This module allows to easily access this information (see `get`) or if necessary
add new particles using `add_particle` and even replace the whole particle
definition list using `load`.

It also provides simple getters to convert `PDG codes`_ into particle names and
vice versa for use with modules which require a list of PDG codes for the
particles to generate. See `from_name`, `from_names`, `to_name` and `to_names`

.. _PDG codes: http://pdg.lbl.gov/2020/reviews/rpp2020-rev-monte-carlo-numbering.pdf
"""

import re
import basf2
from fractions import Fraction


def _get_instance():
    """
    Function to return an instance of the EvtGenDatabasePDG class.
    """
    # Always avoid the top-level 'import ROOT'.
    from ROOT import Belle2  # noqa
    instance = Belle2.EvtGenDatabasePDG.Instance()
    return instance


[docs] def get(name): """ Function to return particle information (TParticlePDG) from ROOT Database. 'name' can be either the name of the particle, or a pdg code. Will throw an LookupError of no such particle exists. """ p = _get_instance().GetParticle(name) if not p: raise LookupError(f"No particle with name '{name}'") return p
[docs] def from_name(name): """ Function to return pdg code for the given particle name. >>> pdg.from_name("pi+") 211 """ return get(name).PdgCode()
[docs] def from_names(names): """ for a list/tuple of particle names, return list of pdg codes. >>> pdg.from_names(["e+","e-","gamma"]) [-11, 11, 22] """ assert not isinstance(names, str), 'Argument is not a list!' return [from_name(n) for n in names]
[docs] def to_name(pdg): """ Return particle name for given pdg code. >>> pdg.to_name(321) K+ """ return get(pdg).GetName()
[docs] def to_names(pdg_codes): """ for a list/tuple of pdg codes, return list of particle names. >>> pdg.to_names([11, -11, -211, 3212]) ['e-', 'e+', 'pi-', 'Sigma0'] """ assert not isinstance(pdg_codes, int), 'Argument is not a list!' return [to_name(pdg) for pdg in pdg_codes]
[docs] def conjugate(name): """ Function to return name of conjugated particle """ try: return to_name(-from_name(name)) except LookupError: return name
[docs] def load(filename): """ Read particle database from given evtgen pdl file """ _get_instance().ReadEvtGenTable(filename)
[docs] def load_default(): """Read default evt.pdl file""" _get_instance().ReadEvtGenTable()
[docs] def add_particle(name, pdgCode, mass, width, charge, spin, max_width=None, lifetime=0, pythiaID=0, define_anti_particle=False): """ Add a new particle to the list of known particles. The name cannot contain any whitespace character. Args: name (str): name of the particle pdgCode (int): pdg code identifiert for the particle mass (float): mass of the particle in GeV width (float): width of the particle in GeV charge (float): charge of the particle in e spin (float): spin of the particle max_width (float): max width, if omitted 3*width will be used lifetime (float): lifetime in ns, should be 0 as geant4 cannot handle it correctly otherwise pythiaID (int): pythiaID of the particle (if any), if omitted 0 will be used define_anti_particle (bool): if True, an anti-particle with the default name anti-{name} is defined and added. """ if lifetime > 0: basf2.B2WARNING("Userdefined particle with non-zero lifetime will not be simulated correctly") if max_width is None: # FIXME: is 3 a good default? max_width = width * 3 particle = _get_instance().AddParticle(name, name, mass, False, width, charge * 3, "userdefined", pdgCode, 0, 0, lifetime, spin, max_width, pythiaID) if particle: basf2.B2INFO( f"Adding new particle '{name}' (pdg={int(pdgCode)}, mass={mass:.3g} GeV, width={width:.3g} GeV, " + f"charge={int(charge)}, spin={Fraction(spin)})") if define_anti_particle: anti_particle = _get_instance().AddParticle( f'anti-{name}', f'anti-{name}', mass, False, width, -charge * 3, "userdefined", -pdgCode, 0, 0, lifetime, spin, max_width, pythiaID ) particle.SetAntiParticle(anti_particle) basf2.B2INFO(f"Adding new particle 'anti-{name}' as anti-particle of '{name}'") return True return False