Skip to content
Snippets Groups Projects
Gun.py 5.05 KiB
Newer Older
"""Helper object for particle gun properties"""

from __future__ import absolute_import, unicode_literals
from DDSim.Helper.ConfigHelper import ConfigHelper
from g4units import GeV
Marko Petric's avatar
Marko Petric committed

class Gun(ConfigHelper):
  """Configuration for the DDG4 ParticleGun"""
Marko Petric's avatar
Marko Petric committed

  def __init__(self):
    super(Gun, self).__init__()
Marko Petric's avatar
Marko Petric committed
    self.energy = 10 * GeV
    self.particle = "mu-"
    self.multiplicity = 1
Marko Petric's avatar
Marko Petric committed
    self._position = (0.0, 0.0, 0.0)
Marko Petric's avatar
Marko Petric committed
    self._direction = (0, 0, 1)
    self._phiMin_EXTRA = {'help': "Minimal azimuthal angle for random distribution"}
    self.phiMin = None
    self.phiMax = None
    self.thetaMin = None
    self.thetaMax = None
    self._momentumMin_EXTRA = {'help': "Minimal momentum when using distribution (default = 0.0)"}
    self.momentumMin = None
    self.momentumMax = None
    self._distribution_EXTRA = {'choices': ['uniform', 'cos(theta)',
                                            'eta', 'pseudorapidity',
Marko Petric's avatar
Marko Petric committed
                                            'ffbar']}  # (1+cos^2 theta)
Marko Petric's avatar
Marko Petric committed
  def distribution(self):
    """choose the distribution of the random direction for theta

    Options for random distributions:
    'uniform' is the default distribution, flat in theta
    'cos(theta)' is flat in cos(theta)
    'eta', or 'pseudorapidity' is flat in pseudorapity
    'ffbar' is distributed according to 1+cos^2(theta)

    Setting a distribution will set isotrop = True
    """
    return self._distribution
Marko Petric's avatar
Marko Petric committed

Marko Petric's avatar
Marko Petric committed
  def distribution(self, val):
    possibleDistributions = self._distribution_EXTRA['choices']
Marko Petric's avatar
Marko Petric committed
    if not isinstance(val, six.string_types):
      raise RuntimeError("malformed input '%s' for gun.distribution. Need a string : %s " %
                         (val, ",".join(possibleDistributions)))
    if val not in possibleDistributions:
Marko Petric's avatar
Marko Petric committed
      # surround options by quots to be explicit
      stringified = ["'%s'" % _ for _ in possibleDistributions]
      raise RuntimeError("Unknown distribution '%s', Use one of: %s " % (val,
                                                                         ", ".join(stringified)))
    self._distribution = val
    self._isotrop = True
Marko Petric's avatar
Marko Petric committed
  def isotrop(self):
    """ isotropic distribution for the particle gun

    use the options phiMin, phiMax, thetaMin, and thetaMax to limit the range of randomly distributed directions
    if one of these options is not None the random distribution will be set to True and cannot be turned off!
    """
    return self._isotrop or bool(self._distribution)
Marko Petric's avatar
Marko Petric committed

Marko Petric's avatar
Marko Petric committed
  def isotrop(self, val):
    """check that value is equivalent to bool"""
    try:
Marko Petric's avatar
Marko Petric committed
      self._isotrop = ConfigHelper.makeBool(val)
Marko Petric's avatar
Marko Petric committed
      raise RuntimeError("malformed input '%s' for gun.isotrop " % val)
    if val and self.distribution is None:
      self.distribution = 'uniform'
Marko Petric's avatar
Marko Petric committed
  def direction(self):
    """ direction of the particle gun, 3 vector """
    return self._direction
Marko Petric's avatar
Marko Petric committed

Marko Petric's avatar
Marko Petric committed
  def direction(self, val):
    """ make sure the direction is parseable by boost, i.e. (1.0, 1.0, 1.0) """
Marko Petric's avatar
Marko Petric committed
    self._direction = ConfigHelper.makeTuple(val)
Marko Petric's avatar
Marko Petric committed
      raise RuntimeError(
          " gun.direction: malformed input '%s', needs to be a string representing a three vector " % (val,))
Marko Petric's avatar
Marko Petric committed
  def position(self):
    """ position of the particle gun, 3 vector """
    return self._position
Marko Petric's avatar
Marko Petric committed
  def position(self, val):
    """check that the position is a three vector and can be parsed by ddg4"""
Marko Petric's avatar
Marko Petric committed
    self._position = ConfigHelper.makeTuple(val)
      raise RuntimeError(
          " gun.position: malformed input '%s', needs to be a string representing a three vector " % (val,))
Marko Petric's avatar
Marko Petric committed
  def setOptions(self, ddg4Gun):
    """set the starting properties of the DDG4 particle gun"""
    try:
      ddg4Gun.energy = self.energy  # ddg4Gun.energy actually sets momentum
      ddg4Gun.MomentumMin = 0.0
      ddg4Gun.MomentumMax = self.energy
Marko Petric's avatar
Marko Petric committed
      ddg4Gun.particle = self.particle
      ddg4Gun.multiplicity = self.multiplicity
Marko Petric's avatar
Marko Petric committed
      ddg4Gun.position = self.position
      ddg4Gun.isotrop = self.isotrop
      ddg4Gun.direction = self.direction
      ddg4Gun.Distribution = self.distribution
      if self.thetaMin is not None:
        ddg4Gun.ThetaMin = self.thetaMin
        ddg4Gun.isotrop = True
      if self.thetaMax is not None:
        ddg4Gun.ThetaMax = self.thetaMax
        ddg4Gun.isotrop = True
      if self.phiMin is not None:
        ddg4Gun.PhiMin = self.phiMin
        ddg4Gun.isotrop = True
      if self.phiMax is not None:
        ddg4Gun.PhiMax = self.phiMax
        ddg4Gun.isotrop = True
      if self.momentumMin is not None:
        ddg4Gun.MomentumMin = self.momentumMin
      if self.momentumMax is not None:
        ddg4Gun.MomentumMax = self.momentumMax
Marko Petric's avatar
Marko Petric committed
    except Exception as e:  # pylint: disable=W0703
      logger.error("parsing gun options:\n%s\nException: %s " % (self, e))