Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-01 07:55:25

0001 """Helper object for physicslist properties"""
0002 
0003 import os
0004 
0005 from DDSim.Helper.ConfigHelper import ConfigHelper
0006 from g4units import mm
0007 import logging
0008 
0009 logger = logging.getLogger(__name__)
0010 
0011 
0012 class Physics(ConfigHelper):
0013   """Configuration for the PhysicsList and Monte Carlo particle selection."""
0014 
0015   def __init__(self):
0016     super(Physics, self).__init__()
0017     self._rangecut = 0.7 * mm
0018     self._list = "FTFP_BERT"
0019     self._decays = False
0020     self._pdgfile = None
0021     self._rejectPDGs = {1, 2, 3, 4, 5, 6,  # quarks
0022                         21, 23, 24, 25,  # bosons
0023                         1103,  # d? diquarks
0024                         2101, 2103, 2203,  # u? diquarks
0025                         3101, 3103, 3201, 3203, 3303,  # s? diquarks
0026                         4101, 4103, 4201, 4203, 4301, 4303, 4403,  # c? diquarks
0027                         5101, 5103, 5201, 5203, 5301, 5303, 5401, 5403, 5503}  # b? diquarks
0028     self._zeroTimePDGs = {11, 13, 15, 17}
0029     self._alternativeDecayStatuses = set()
0030     self._alternativeStableStatuses = set()
0031     self._userFunctions = []
0032     self._closeProperties()
0033     Physics.__doc__ += "\n\n" + self.setupUserPhysics.__doc__
0034 
0035   @property
0036   def rejectPDGs(self):
0037     """Set of PDG IDs that will not be passed from the input record to Geant4.
0038 
0039     Quarks, gluons and W's Z's etc should not be treated by Geant4
0040     """
0041     return self._rejectPDGs
0042 
0043   @rejectPDGs.setter
0044   def rejectPDGs(self, val):
0045     self._rejectPDGs = self.makeSet(val)
0046 
0047   @property
0048   def zeroTimePDGs(self):
0049     """Set of PDG IDs for particles that should not be passed to Geant4 if their properTime is 0.
0050 
0051     The properTime of 0 indicates a documentation to add FSR to a lepton for example.
0052     """
0053     return self._zeroTimePDGs
0054 
0055   @zeroTimePDGs.setter
0056   def zeroTimePDGs(self, val):
0057     self._zeroTimePDGs = self.makeSet(val)
0058 
0059   @property
0060   def alternativeDecayStatuses(self):
0061     """Set of Generator Statuses that are used to mark unstable particles that should decay inside of Geant4.
0062     """
0063     return self._alternativeDecayStatuses
0064 
0065   @alternativeDecayStatuses.setter
0066   def alternativeDecayStatuses(self, val):
0067     self._alternativeDecayStatuses = self.makeSet(val)
0068 
0069   @property
0070   def alternativeStableStatuses(self):
0071     """Set of Generator Statuses that are used to mark stable particles that should be forwarded to Geant4.
0072     """
0073     return self._alternativeStableStatuses
0074 
0075   @alternativeStableStatuses.setter
0076   def alternativeStableStatuses(self, val):
0077     self._alternativeStableStatuses = self.makeSet(val)
0078 
0079   @property
0080   def rangecut(self):
0081     """ The global geant4 rangecut for secondary production
0082 
0083     Default is 0.7 mm as is the case in geant4 10
0084 
0085     To disable this plugin and be absolutely sure to use the Geant4 default range cut use "None"
0086 
0087     Set printlevel to DEBUG to see a printout of all range cuts,
0088     but this only works if range cut is not "None"
0089     """
0090     return self._rangecut
0091 
0092   @rangecut.setter
0093   def rangecut(self, val):
0094     if val is None:
0095       self._rangecut = None
0096       return
0097     if isinstance(val, str):
0098       if val == "None":
0099         self._rangecut = None
0100         return
0101     self._rangecut = val
0102 
0103   @property
0104   def pdgfile(self):
0105     """ location of particle.tbl file containing extra particles and their lifetime information
0106 
0107     For example in $DD4HEP/examples/DDG4/examples/particle.tbl
0108     """
0109     return self._pdgfile
0110 
0111   @pdgfile.setter
0112   def pdgfile(self, val):
0113     if not val:
0114       self._pdgfile = None
0115       return
0116     if not os.path.exists(val):
0117       raise RuntimeError("PDGFile: %s not found" % os.path.abspath(val))
0118     self._pdgfile = os.path.abspath(val)
0119 
0120   @property
0121   def decays(self):
0122     """If true, add decay processes for all particles.
0123 
0124     Only enable when creating a physics list not based on an existing Geant4 list!
0125     """
0126     return self._decays
0127 
0128   @decays.setter
0129   def decays(self, val):
0130     self._decays = val
0131 
0132   @property
0133   def list(self):  # noqa: A003
0134     """The name of the Geant4 Physics list."""
0135     return self._list
0136 
0137   @list.setter
0138   def list(self, val):  # noqa: A003
0139     self._list = val
0140 
0141   def setupPhysics(self, kernel, name=None):
0142     seq = kernel.physicsList()
0143     seq.extends = name if name is not None else self.list
0144     seq.decays = self.decays
0145     seq.enableUI()
0146     seq.dump()
0147 
0148     from DDG4 import PhysicsList
0149 
0150     # Add special particle types from specialized physics constructor
0151     if self.pdgfile:
0152       seq = kernel.physicsList()
0153       part = PhysicsList(kernel, 'Geant4ExtraParticles/ExtraParticles')
0154       part.enableUI()
0155       seq.adopt(part)
0156       part.pdgfile = self.pdgfile
0157 
0158     # Add global range cut
0159     if self.rangecut is not None:
0160       seq = kernel.physicsList()
0161       rg = PhysicsList(kernel, 'Geant4DefaultRangeCut/GlobalRangeCut')
0162       rg.enableUI()
0163       seq.adopt(rg)
0164       rg.RangeCut = self.rangecut
0165 
0166     for func in self._userFunctions:
0167       try:
0168         func(kernel)
0169       except Exception as e:
0170         logger.error("Exception in UserFunction: %r", e)
0171         raise RuntimeError("Exception in UserFunction: %r" % e)
0172 
0173     return seq
0174 
0175   def setupUserPhysics(self, userFunction):
0176     """To load arbitrary plugins, add a function to be executed.
0177 
0178     The function must take the DDG4.Kernel() object as the only argument.
0179 
0180     For example, add a function definition and the call to a steering file::
0181 
0182       def setupCerenkov(kernel):
0183         from DDG4 import PhysicsList
0184         seq = kernel.physicsList()
0185         cerenkov = PhysicsList(kernel, 'Geant4CerenkovPhysics/CerenkovPhys')
0186         cerenkov.MaxNumPhotonsPerStep = 10
0187         cerenkov.MaxBetaChangePerStep = 10.0
0188         cerenkov.TrackSecondariesFirst = True
0189         cerenkov.VerboseLevel = 2
0190         cerenkov.enableUI()
0191         seq.adopt(cerenkov)
0192         ph = PhysicsList(kernel, 'Geant4OpticalPhotonPhysics/OpticalGammaPhys')
0193         ph.addParticleConstructor('G4OpticalPhoton')
0194         ph.VerboseLevel = 2
0195         ph.enableUI()
0196         seq.adopt(ph)
0197         return None
0198 
0199       SIM.physics.setupUserPhysics(setupCerenkov)
0200 
0201     # End of example
0202     """
0203     self._userFunctions.append(userFunction)