Skip to content
Snippets Groups Projects
Physics.py 5.56 KiB
Newer Older
"""Helper object for physicslist properties"""

from DDSim.Helper.ConfigHelper import ConfigHelper
from g4units import mm
logger = logging.getLogger(__name__)

Marko Petric's avatar
Marko Petric committed

class Physics(ConfigHelper):
  """Configuration for the PhysicsList and Monte Carlo particle selection."""
Marko Petric's avatar
Marko Petric committed

  def __init__(self):
Marko Petric's avatar
Marko Petric committed
    self._rangecut = 0.7 * mm
    self._list = "FTFP_BERT"
    self._rejectPDGs = {1, 2, 3, 4, 5, 6,  # quarks
                        21, 23, 24, 25,  # bosons
                        1103,  # d? diquarks
                        2101, 2103, 2203,  # u? diquarks
                        3101, 3103, 3201, 3203, 3303,  # s? diquarks
                        4101, 4103, 4201, 4203, 4301, 4303, 4403,  # c? diquarks
                        5101, 5103, 5201, 5203, 5301, 5303, 5401, 5403, 5503}  # b? diquarks
    self._alternativeDecayStatuses = set()
    self._userFunctions = []
    self._closeProperties()
    Physics.__doc__ += "\n\n" + self.setupUserPhysics.__doc__
Marko Petric's avatar
Marko Petric committed
  def rejectPDGs(self):
    """Set of PDG IDs that will not be passed from the input record to Geant4.

    Quarks, gluons and W's Z's etc should not be treated by Geant4
    """
    return self._rejectPDGs
Marko Petric's avatar
Marko Petric committed

Marko Petric's avatar
Marko Petric committed
  def rejectPDGs(self, val):
    self._rejectPDGs = self.makeSet(val)

  @property
  def zeroTimePDGs(self):
    """Set of PDG IDs for particles that should not be passed to Geant4 if their properTime is 0.

    The properTime of 0 indicates a documentation to add FSR to a lepton for example.
    """
    return self._zeroTimePDGs
Marko Petric's avatar
Marko Petric committed

  @zeroTimePDGs.setter
  def zeroTimePDGs(self, val):
    self._zeroTimePDGs = self.makeSet(val)
  @property
  def alternativeDecayStatuses(self):
    """Set of Generator Statuses that are used to mark unstable particles that should decay inside of Geant4.
    """
    return self._alternativeDecayStatuses

  @alternativeDecayStatuses.setter
  def alternativeDecayStatuses(self, val):
    self._alternativeDecayStatuses = self.makeSet(val)

Marko Petric's avatar
Marko Petric committed
  def rangecut(self):
    """ The global geant4 rangecut for secondary production

    Default is 0.7 mm as is the case in geant4 10

    To disable this plugin and be absolutely sure to use the Geant4 default range cut use "None"

    Set printlevel to DEBUG to see a printout of all range cuts,
    but this only works if range cut is not "None"
    """
    return self._rangecut
Marko Petric's avatar
Marko Petric committed

Marko Petric's avatar
Marko Petric committed
  def rangecut(self, val):
    if val is None:
      self._rangecut = None
      return
    if isinstance(val, str):
      if val == "None":
        self._rangecut = None
        return
    self._rangecut = val

  @property
Marko Petric's avatar
Marko Petric committed
  def pdgfile(self):
    """ location of particle.tbl file containing extra particles and their lifetime information

    For example in $DD4HEP/examples/DDG4/examples/particle.tbl
Marko Petric's avatar
Marko Petric committed

Marko Petric's avatar
Marko Petric committed
  def pdgfile(self, val):
Marko Petric's avatar
Marko Petric committed
    if not os.path.exists(val):
      raise RuntimeError("PDGFile: %s not found" % os.path.abspath(val))
    self._pdgfile = os.path.abspath(val)
  @property
  def decays(self):
    """If true, add decay processes for all particles.

    Only enable when creating a physics list not based on an existing Geant4 list!
    """
    return self._decays
  @decays.setter
  def decays(self, val):
    self._decays = val
Markus Frank's avatar
Markus Frank committed
  def list(self):  # noqa: A003
    """The name of the Geant4 Physics list."""
    return self._list
  @list.setter
Markus Frank's avatar
Markus Frank committed
  def list(self, val):  # noqa: A003
    self._list = val

Marko Petric's avatar
Marko Petric committed
  def setupPhysics(self, kernel, name=None):
Marko Petric's avatar
Marko Petric committed
    seq.extends = name if name is not None else self.list
    seq.decays = self.decays
    seq.enableUI()
    seq.dump()

    from DDG4 import PhysicsList

    # Add special particle types from specialized physics constructor
    if self.pdgfile:
      seq = kernel.physicsList()
      part = PhysicsList(kernel, 'Geant4ExtraParticles/ExtraParticles')
      part.enableUI()
      seq.adopt(part)
      part.pdgfile = self.pdgfile

    # Add global range cut
    if self.rangecut is not None:
      seq = kernel.physicsList()
Marko Petric's avatar
Marko Petric committed
      rg = PhysicsList(kernel, 'Geant4DefaultRangeCut/GlobalRangeCut')
      rg.enableUI()
      seq.adopt(rg)
      rg.RangeCut = self.rangecut
    for func in self._userFunctions:
      try:
        func(kernel)
      except Exception as e:
        logger.error("Exception in UserFunction: %r", e)
        raise RuntimeError("Exception in UserFunction: %r" % e)

  def setupUserPhysics(self, userFunction):
    """To load arbitrary plugins, add a function to be executed.

    The function must take the DDG4.Kernel() object as the only argument.

    For example, add a function definition and the call to a steering file::

      def setupCerenkov(kernel):
        from DDG4 import PhysicsList
        seq = kernel.physicsList()
        cerenkov = PhysicsList(kernel, 'Geant4CerenkovPhysics/CerenkovPhys')
        cerenkov.MaxNumPhotonsPerStep = 10
        cerenkov.MaxBetaChangePerStep = 10.0
        cerenkov.TrackSecondariesFirst = True
        cerenkov.VerboseLevel = 2
        cerenkov.enableUI()
        seq.adopt(cerenkov)
        ph = PhysicsList(kernel, 'Geant4OpticalPhotonPhysics/OpticalGammaPhys')
        ph.addParticleConstructor('G4OpticalPhoton')
        ph.VerboseLevel = 2
        ph.enableUI()
        seq.adopt(ph)
        return None

      SIM.physics.setupUserPhysics(setupCerenkov)
    """
    self._userFunctions.append(userFunction)