Source code for Gauss.Configuration

###############################################################################
# (c) Copyright 2000-2022 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 Configurables import ApplicationMgr
from Gaudi.Configuration import Configurable, log
from GaudiConf.SimConf import SimConf
from Gauss.Generation import GaussGeneration
from Gauss.Geometry import GaussGeometry
from Gauss.Simulation import GaussSimulation
from Gauss.Visualization import GaussVisualization
from Gaussino.Configuration import Gaussino

# Configurables (do NOT use 'from Configurables' here)
from Gaussino.Utilities import GaussinoConfigurable
from LHCbAlgs.Configuration import LHCbApp


[docs] class Gauss(GaussinoConfigurable): __used_configurables__ = [ LHCbApp, SimConf, GaussGeneration, GaussSimulation, GaussGeometry, GaussVisualization, Gaussino, ] __slots__ = { "Histograms": "DEFAULT", "EvtMax": -1, "Phases": ["Generator", "Simulation"], "EnableHive": True, "ThreadPoolSize": 1, "EventSlots": 1, "FirstTimingEvent": 1, "DatasetName": "Gauss", "OutputType": "SIM", "ReDecay": False, "Debug": False, "SpilloverPaths": [], "EnablePack": True, "DataType": "", "WriteFSR": False, "MergeGenFSR": False, "FirstEventNumber": 1, "RunNumber": 1, } # options to be directly propagated to Gaussino GAUSSINO_OPTIONS = [ "Histograms", "EvtMax", "Phases", "EnableHive", "ThreadPoolSize", "EventSlots", "FirstTimingEvent", "DatasetName", "OutputType", "ReDecay", "Debug", "FirstEventNumber", "RunNumber", ] # options to be directly propagated to LHCbApp LHCBAPP_OPTIONS = [ # TODO: investigate this! # I think this should be passed only to Gaussino "EvtMax", "DataType", ] SIMCONF_OPTIONS = [ "SpilloverPaths", "EnablePack", "Phases", "DataType", ] Run1DataTypes = ["2009", "2010", "2011", "2012", "2013"] Run2DataTypes = ["2015", "2016", "2017", "2018"] Run3DataTypes = ["2022", "2023", "2024", "2025", "Run3"] Run4DataTypes = ["Run4"] Run5DataTypes = ["Run5"] DataTypes = [ *Run1DataTypes, *Run2DataTypes, *Run3DataTypes, *Run4DataTypes, *Run5DataTypes, ] KNOWN_OUTPUTS = ["NONE", "GEN", "XGEN", "RGEN", "SIM", "XSIM"] def __init__(self, name=Configurable.DefaultName, _enabled=True, **kwargs): # -> the following makes sure that one does not instantiate Gaussino before # Gauss, otherwise the later in the code fix will be ill-formed if "Gaussino" in Configurable.allConfigurables: msg = "Gauss configurable must be instantiated before Gaussino" log.error(msg) raise RuntimeError(msg) # -> this makes the Gaussino configurable LHCbApp-dependent # -> explanation: in some cases different configurables have to be instantiated # with the same name (e.g. HiveWhiteBoard and EventDataSvc); # -> this makes sure that IOHelper via LHCbApp will not set the defaults before # Gaussino.__apply_configuration__ takes place Gaussino.__used_configurables__.append(LHCbApp) # -> end of the fix super(Gauss, self).__init__(name=name, _enabled=_enabled, **kwargs) # Apply the configuration
[docs] def __apply_configuration__(self): self._check_options_compatibility() self._propagate_gaussino() self._propagate_lhcbapp() packing = self._set_packing() self._propagate_sim_conf(packing) self._propagate_simulation() self._set_evtgen() self._define_output(prerequisites=[packing]) for conf in self.__used_configurables__: conf()
[docs] def _check_options_compatibility(self): if not self.getProp("DataType"): msg = "Must have a DataType." log.error(msg) raise ValueError(msg) if self.getProp("DataType") not in self.DataTypes: msg = ( f"Unknown DataType '{self.getProp('DataType')}'. " f"Must be one of: '{self.DataTypes}'" ) log.error(msg) raise ValueError(msg) for conf, props in Configurable.allConfigurables.items(): if conf.startswith("Gaussino") and props._enabled: msg = ( "When using Gauss, you must set " "Gaussino's properties through " "the corresponding configurable " "in Gauss. Setting Gaussino's options " "directly has been disabled." ) log.error(msg) raise RuntimeError(msg)
[docs] def _propagate_gaussino(self): self.propagateProperties(self.GAUSSINO_OPTIONS, Gaussino()) Gaussino().ConvertEDM = True
# FIXME: temporary! we have to wait for an official way of getting ParticleTable.txt # in the meantime, we use the internal ParticleTable.txt in Gaussino # see: https://gitlab.cern.ch/lhcb/LHCb/-/merge_requests/3510#note_5530125 # # Gaussino().ParticleTable = 'git:///param/ParticleTable.txt'
[docs] def _propagate_lhcbapp(self): self.propagateProperties(self.LHCBAPP_OPTIONS, LHCbApp()) LHCbApp( Simulation=True, # do not turn hive mode with LHCbApp # this is now done in Gaussino() in _setup_hive() EnableHive=False, )
[docs] def _set_packing(self): from Configurables import GaudiSequencer return GaudiSequencer("PackingSeq", Sequential=True, IgnoreFilterPassed=True)
[docs] def _propagate_sim_conf(self, packing): # Propagate properties to SimConf SimConf().setProp("Writer", "GaussTape") self.propagateProperties(self.SIMCONF_OPTIONS, SimConf()) # Empty the list of detectors, it is later populated when configuring # the subdetectors SimConf().Detectors = [] # if we have post-sim filters, we only want to write if the filter is # passed # if self.getProp("PostSimFilters"): # OutputStream("GaussTape").RequireAlgs.append("PostSimFilterSeq") # Don't want SIM data unpacking enabled in DoD service SimConf().EnableUnpack = False SimConf().SaveHepMC = False phases = self.getProp("Phases") if "GenToMCTree" in phases or "Simulation" in phases: for so in self.defineCrossingList(): SimConf().PackingSequencers[so] = packing
[docs] def defineCrossingList(self): crossingList = [""] spillOverList = self.getProp("SpilloverPaths") while "" in spillOverList: spillOverList.remove("") crossingList += spillOverList return crossingList
[docs] def _outStream(self, filename, winstance, writeFSR): winstance.Output = "DATAFILE='" + filename + "' SVC='RootCnvSvc' OPT='REC'" algs = [winstance] if writeFSR: # ignore name when name is type writer = writer.getFullName() if writer.split("/")[0] == writer.split("/")[-1]: writer = writer.split("/")[0] FSRWriter = GaudiConfigurables.RecordStream( "FSR" + writer.replace("/", "").replace("::", "").replace("__", ""), ItemList=["/FileRecords#999"], EvtDataSvc="FileRecordDataSvc", EvtConversionSvc="FileRecordPersistencySvc", Output="DATAFILE='" + filename + "' SVC='FileRecordCnvSvc' OPT='REC'", ) algs.append(FSRWriter) if ApplicationMgr().OutStream is None or len(ApplicationMgr().OutStream) == 0: ApplicationMgr().OutStream = [] ApplicationMgr().OutStream.extend(algs)
[docs] def _define_output(self, prerequisites): """ Set up output stream according to phase processed, the spill-over slots and the type of output """ output = self.getProp("OutputType").upper() if output == "NONE": log.warning("No event data output produced") return simWriter = SimConf().writer() # define default file extensions depending on the phase that has been # run fileDefaultExtension = ".gen" fileAllowedExtension = [fileDefaultExtension] if "GenToMCTree" in self.getProp("Phases"): fileDefaultExtension = ".xgen" fileAllowedExtension = [fileDefaultExtension, ".rgen"] elif "Simulation" in self.getProp("Phases"): fileDefaultExtension = ".sim" fileAllowedExtension = [fileDefaultExtension, ".xsim"] # choose the file extension from the one selected compatibly with the # phase run if output not in self.KNOWN_OUTPUTS: log.warning( "OutputType not supported. " f"Use default for chosen phases: {fileDefaultExtension}" ) fileExtension = "." + output.lower() if fileExtension not in fileAllowedExtension: fileExtension = fileDefaultExtension log.warning( "OutputType not supported " f"for this phase. Use default: {fileExtension}" ) # set saving or not of HepMC depending on chosen file extension if SimConf().isPropertySet("SaveHepMC"): log.warning("SimConf().SaveHepMC will " "be ignored. Value set by Gauss()") saveHepMC = False if fileExtension in [".gen", ".xgen", ".xsim"]: saveHepMC = True SimConf().setProp("SaveHepMC", saveHepMC) outputFile = Gaussino()._get_output_name() + fileExtension # Merge genFSRs if self.getProp("WriteFSR"): seqGenFSR = GaudiSequencer("GenFSRSeq") ApplicationMgr().TopAlg += [seqGenFSR] if self.getProp("MergeGenFSR"): seqGenFSR.Members += ["GenFSRMerge"] self._outStream(outputFile, simWriter, self.getProp("WriteFSR")) from Configurables import FileCatalog if not FileCatalog().isPropertySet("Catalogs"): FileCatalog().Catalogs = ["xmlcatalog_file:NewCatalog.xml"] edm_algos = Gaussino.edm_algorithms(self.getProp("ReDecay")) members = edm_algos + prerequisites + [SimConf().writer()] from Configurables import GaudiSequencer output_seq = GaudiSequencer( "OutputSeq", Members=members, Sequential=True, ) ApplicationMgr().TopAlg.append(output_seq)
[docs] def _propagate_simulation(self): if "Simulation" not in self.getProp("Phases"): GaussSimulation.only_generation_phase = True GaussGeometry.only_generation_phase = True return run1or2 = self.getProp("DataType") in self.Run1DataTypes + self.Run2DataTypes GaussGeometry.run1or2 = run1or2 GaussGeometry.run4or5 = ( self.getProp("DataType") in self.Run4DataTypes + self.Run5DataTypes ) GaussGeometry.datatype = self.getProp("DataType") GaussSimulation.run1or2 = run1or2
[docs] def _set_evtgen(self): from Configurables import EvtGenDecay EvtGenDecay().DecayFile = "$DECFILESROOT/dkfiles/DECAY.DEC"