###############################################################################
# (c) Copyright 2000-2020 CERN for the benefit of the LHCb Collaboration #
# #
# This software is distributed under the terms of the GNU General Public #
# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". #
# #
# In applying this licence, CERN does not waive the privileges and immunities #
# granted to it by virtue of its status as an Intergovernmental Organization #
# or submit itself to any jurisdiction. #
###############################################################################
__author__ = "Gloria Corti, Dominik Muller, and Michal Mazurek"
__email__ = "lhcb-simulation@cern.ch"
from Gaudi.Configuration import log
from GaudiKernel import SystemOfUnits
from Gauss.Defaults import DEFAULT_DETECTORS
from Gaussino.Simulation import GaussinoSimulation
# Configurables
from Gaussino.Utilities import GaussinoConfigurable
[docs]class GaussSimulation(GaussinoConfigurable):
__required_configurables__ = [
"Gauss",
]
__slots__ = {
"EM": "Opt2",
"Hadron": "FTFP_BERT",
"GeneralPhys": True,
"LHCbPhys": False, # FIXME: not implemented yet
"Other": "",
"DeltaRays": True,
"RichUpgradeConfig": False, # FIXME: not implemented yet
"AddPhysConstr": [],
"CustomSimulation": "",
"G4BeginRunCommand": ["/tracking/verbose 0", "/process/eLoss/verbose 0"],
"G4EndRunCommand": [],
}
GAUSSINO_SIMULATION_OPTIONS = [
"CustomSimulation",
"G4BeginRunCommand",
"G4EndRunCommand",
]
_em_physics_options = {
"Opt1": ("G4EmStandardPhysics_option1", "EmOpt1Physics"),
"Opt2": ("G4EmStandardPhysics_option2", "EmOpt2Physics"),
"Opt3": ("G4EmStandardPhysics_option3", "EmOpt3Physics"),
"Std": ("G4EmStandardPhysics", "EmPhysics"),
"NoCuts": ("G4EmStandardPhysics_option1NoApplyCuts", "EmOpt1NoCutsPhysics"),
}
_hadron_physics_options = {
"QGSP_BERT": [
("G4HadronElasticPhysics", "ElasticPhysics"),
("G4HadronPhysicsQGSP_BERT", "QGSP_BERTPhysics"),
("G4StoppingPhysics", "StoppingPhysics"),
("G4NeutronTrackingCut", "NeutronTrkCut"),
],
"QGSP_BERT_HP": [
("G4HadronElasticPhysicsHP", "ElasticPhysicsHP"),
("G4HadronPhysicsQGSP_BERT_HP", "QGSP_BERT_HPPhysics"),
("G4StoppingPhysics", "StoppingPhysics"),
],
"QGSP_FTFP_BERT": [
("G4HadronElasticPhysics", "ElasticPhysics"),
("G4HadronPhysicsQGSP_FTFP_BERT", "QGSP_FTFP_BERTPhysics"),
("G4StoppingPhysics", "StoppingPhysics"),
("G4NeutronTrackingCut", "NeutronTrkCut"),
],
"FTFP_BERT": [
("G4HadronElasticPhysics", "ElasticPhysics"),
("G4HadronPhysicsFTFP_BERT", "FTFP_BERTPhysics"),
("G4StoppingPhysics", "StoppingPhysics"),
("G4NeutronTrackingCut", "NeutronTrkCut"),
],
"FTFP_BERT_HP": [
("G4HadronElasticPhysicsHP", "ElasticPhysicsHP"),
("G4HadronPhysicsFTFP_BERT_HP", "FTFP_BERT_HPPhysics"),
("G4StoppingPhysics", "StoppingPhysics"),
],
}
# internal options to be set by Gauss
run1or2 = False
only_generation_phase = False
[docs] def _add_constructor(self, sim, template, name):
sim.PhysicsConstructors.append("GiGaMT_{}/{}".format(template, name))
[docs] def __apply_configuration__(self):
log.debug("Configuring GaussSimulation")
if GaussSimulation.only_generation_phase:
log.debug("-> Only the generation phase, skipping.")
return
sim = GaussinoSimulation()
self.propagateProperties(
self.GAUSSINO_SIMULATION_OPTIONS,
sim,
)
self._set_production_cuts(sim)
self._update_truth_flagging()
# set up the physics list
sim.PhysicsConstructors += self.getProp("AddPhysConstr")
self._add_em_physics(sim)
self._add_gen_physics(sim)
self._add_hadron_physics(sim)
self._add_lhcb_physics(sim)
self._add_other_physics(sim)
self._add_tracking_cuts(sim)
[docs] def _set_production_cuts(self, sim):
# FIXME: to be passed as dictionary
# see: https://gitlab.cern.ch/Gaussino/Gaussino/-/issues/27
ecut = 5.0 * SystemOfUnits.mm
if not self.getProp("DeltaRays"):
ecut = 10000.0 * SystemOfUnits.m
sim.CutForElectron = ecut
sim.CutForPositron = 5.0 * SystemOfUnits.mm
sim.CutForGamma = 5.0 * SystemOfUnits.mm
[docs] def _add_em_physics(self, sim):
em = self.getProp("EM")
if not em:
log.warning("No EM physics defined!")
if em not in self._em_physics_options:
msg = f"Unknown EM physics '{em}'"
log.error(msg)
raise NotImplementedError(msg)
self._add_constructor(sim, *self._em_physics_options[em])
# FIXME: Not implemented!
# if 'LHCb' not in emPhys:
# return False
# if 'Test' in emPhys:
# self._add_constructor(sim, "G4EmStandardPhysics_LHCbTest",
# "EmOpt1LHCbPhysics")
# else:
# self._add_constructor(sim, "G4EmStandardPhysics_option1LHCb",
# "EmOpt1LHCbPhysics")
# overwrite cuts depending on choice of list
# if em == "NoCuts":
# sim.EmOpt1LHCbPhysics.ApplyCuts = False
# if 'OldForE' in emPhys:
# sim.EmOpt1LHCbPhysics.NewModelForE = False
[docs] def _add_gen_physics(self, sim):
if not self.getProp("GeneralPhys"):
log.warning("The general physics is disabled.")
log.debug("Applying general physics")
self._add_constructor(sim, "G4DecayPhysics", "DecayPhysics")
self._add_constructor(sim, "G4EmExtraPhysics", "EmExtraPhysics")
self._add_constructor(sim, "G4IonPhysics", "IonPhysics")
[docs] def _add_hadron_physics(self, sim):
hadron_phys = self.getProp("Hadron")
if not hadron_phys:
log.warning("No hadron physics defined!")
return
if hadron_phys not in self._hadron_physics_options:
msg = f"Unknown hadronic physics '{hadron_phys}'."
log.error(msg)
raise NotImplementedError(msg)
log.debug(f"Applying hadronic physics '{hadron_phys}'.")
for hp in self._hadron_physics_options[hadron_phys]:
self._add_constructor(sim, *hp)
[docs] def _add_lhcb_physics(self, sim):
# FIXME: this is not implmented yet
lhcb_phys = self.getProp("LHCbPhys")
rich = self.getProp("RichUpgradeConfig")
if lhcb_phys or rich:
msg = "LHCbPhysics not implemented yet"
log.error(msg)
raise NotImplementedError(msg)
sim.PhysicsConstructors.append("GiGaPhysUnknownParticles")
# FIXME: this is not implmented yet
# if lhcbPhys:
# log.info("Applying LHCb specific physics.")
# if richUpgradeConfig:
# self.defineRichMaPmtPhys(sim)
# else:
# self.defineRichPhys(sim)
# else:
# log.warning("The lhcb-related physics (RICH processed)"
# "is disabled")
[docs] def _add_other_physics(self, sim):
other = self.getProp("Other")
if not other:
return
if other == "Higgs":
log.debug("Enabling physics processe for Higgs particles")
sim.PhysicsConstructors.append("GiGaMTHiggsParticles")
msg = "Unknown other physics '{other}'"
log.error(msg)
raise NotImplementedError(msg)
[docs] def _add_tracking_cuts(self, sim):
log.debug("Adding tracking cuts.")
from Configurables import TrCutsRunAction
sim.addTool(TrCutsRunAction("TrCuts"), name="TrCuts")
sim.PhysicsConstructors.append("TrCutsRunAction/TrCuts")
[docs] def _update_truth_flagging(self):
from Configurables import TruthFlaggingTrackAction
# FIXME: this is set by Gaussino,
# it would be better to pass this option
# to GaussinoSimulation as a key in dict
# see: https://gitlab.cern.ch/Gaussino/Gaussino/-/issues/30
trth = TruthFlaggingTrackAction(
"GiGaMT.GiGaActionInitializer.TruthFlaggingTrackAction"
)
# new ZMaxPlane settings depend now on the geometry
if self.run1or2:
# Other -> M1 | ZMax | PRS/SPD | ECAL
trth.ZmaxForStoring = 12280.0 * SystemOfUnits.mm
else:
# Upgrade -> ZMax | Neutron Shielding | ECAL
trth.ZmaxForStoring = 11948.0 * SystemOfUnits.mm
# tilt of the zMax plane should be the same
trth.ZmaxForStoringTilt = 0.207 * SystemOfUnits.degree