Newer
Older
"""Class for output file configuration"""
Andre Sailer
committed
import logging
from DDSim.Helper.ConfigHelper import ConfigHelper
Andre Sailer
committed
logger = logging.getLogger(__name__)
#: True if DD4hep was built with LCIO
DD4HEP_USE_LCIO = "@DD4HEP_USE_LCIO@" != "OFF"
#: True if DD4hep was built with EDM4hep
DD4HEP_USE_EDM4HEP = "@DD4HEP_USE_EDM4HEP@" != "OFF"
def defaultOutputFile():
if DD4HEP_USE_LCIO and not DD4HEP_USE_EDM4HEP:
return "ddsimOutput.slcio"
return "ddsimOutput.root"
class OutputConfig(ConfigHelper):
"""Configuration for Output Files."""
def __init__(self):
super(OutputConfig, self).__init__()
self._userPlugin = None
Andre Sailer
committed
self._forceLCIO = False
self._forceEDM4HEP = False
self._forceDD4HEP = False
# no closeProperties, allow custom ones for userPlugin configuration
Andre Sailer
committed
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
def _checkConsistency(self):
"""Raise error if more than one force flag is true."""
if self._forceLCIO + self._forceEDM4HEP + self._forceDD4HEP > 1:
raise RuntimeError(f"OutputConfig error: More than one force flag enabled: LCIO({self._forceLCIO}),"
f" EDM4HEP({self._forceEDM4HEP}), DD4HEP({self._forceDD4HEP})")
@property
def forceLCIO(self):
"""Use the LCIO output plugin regardless of outputfilename."""
return self._forceLCIO
@forceLCIO.setter
def forceLCIO(self, val):
self._forceLCIO = self.makeBool(val)
if self._forceLCIO:
if not DD4HEP_USE_LCIO:
raise RuntimeError("OutputConfig error: forceLCIO requested, but LCIO not available!")
self._checkConsistency()
@property
def forceEDM4HEP(self):
"""Use the EDM4HEP output plugin regardless of outputfilename."""
return self._forceEDM4HEP
@forceEDM4HEP.setter
def forceEDM4HEP(self, val):
self._forceEDM4HEP = self.makeBool(val)
if self._forceEDM4HEP:
if not DD4HEP_USE_EDM4HEP:
raise RuntimeError("OutputConfig error: forceEDM4HEP requested, but EDM4HEP not available!")
self._checkConsistency()
@property
def forceDD4HEP(self):
"""Use the DD4HEP output plugin regardless of outputfilename."""
return self._forceDD4HEP
@forceDD4HEP.setter
def forceDD4HEP(self, val):
self._forceDD4HEP = self.makeBool(val)
if self._forceDD4HEP:
self._checkConsistency()
@property
def userOutputPlugin(self):
"""Set a function to configure the outputFile.
The function must take a ``DD4hepSimulation`` object as its only argument and return ``None``.
For example one can add this to the ddsim steering file:
def exampleUserPlugin(dd4hepSimulation):
'''Example code for user created plugin.
:param DD4hepSimulation dd4hepSimulation: The DD4hepSimulation instance, so all parameters can be accessed
:return: None
'''
from DDG4 import EventAction, Kernel
dd = dd4hepSimulation # just shorter variable name
evt_root = EventAction(Kernel(), 'Geant4Output2ROOT/' + dd.outputFile, True)
evt_root.HandleMCTruth = True or False
evt_root.Control = True
output = dd.outputFile
if not dd.outputFile.endswith(dd.outputConfig.myExtension):
output = dd.outputFile + dd.outputConfig.myExtension
evt_root.Output = output
evt_root.enableUI()
Kernel().eventAction().add(evt_root)
return None
SIM.outputConfig.userOutputPlugin = exampleUserPlugin
# arbitrary options can be created and set via the steering file or command line
SIM.outputConfig.myExtension = '.csv'
"""
return self._userPlugin
@userOutputPlugin.setter
def userOutputPlugin(self, userOutputPluginConfig):
if userOutputPluginConfig is None:
return
if not callable(userOutputPluginConfig):
raise RuntimeError("The provided userPlugin is not a callable function.")
self._userPlugin = userOutputPluginConfig
Andre Sailer
committed
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
def initialize(self, dd4hepsimulation, geant4):
"""Configure the output file and plugin."""
if callable(self._userPlugin):
logger.info("++++ Setting up UserPlugin for Output ++++")
return self._userPlugin(dd4hepsimulation)
if self.forceLCIO:
return self._configureLCIO(dd4hepsimulation, geant4)
if self.forceEDM4HEP:
return self._configureEDM4HEP(dd4hepsimulation, geant4)
if self.forceDD4HEP:
return self._configureDD4HEP(dd4hepsimulation, geant4)
if dd4hepsimulation.outputFile.endswith(".slcio"):
return self._configureLCIO(dd4hepsimulation, geant4)
if dd4hepsimulation.outputFile.endswith(".root") and DD4HEP_USE_EDM4HEP:
return self._configureEDM4HEP(dd4hepsimulation, geant4)
if dd4hepsimulation.outputFile.endswith(".root"):
return self._configureDD4HEP(dd4hepsimulation, geant4)
def _configureLCIO(self, dds, geant4):
if not DD4HEP_USE_LCIO:
raise RuntimeError("DD4HEP was not build wiht LCIO support: please change output format %s" % dds.outputFile)
logger.info("++++ Setting up LCIO Output ++++")
lcOut = geant4.setupLCIOOutput('LcioOutput', dds.outputFile)
lcOut.RunHeader = dds.meta.addParametersToRunHeader(dds)
eventPars = dds.meta.parseEventParameters()
lcOut.EventParametersString, lcOut.EventParametersInt, lcOut.EventParametersFloat = eventPars
lcOut.RunNumberOffset = dds.meta.runNumberOffset if dds.meta.runNumberOffset > 0 else 0
lcOut.EventNumberOffset = dds.meta.eventNumberOffset if dds.meta.eventNumberOffset > 0 else 0
return
def _configureEDM4HEP(self, dds, geant4):
logger.info("++++ Setting up EDM4hep ROOT Output ++++")
e4Out = geant4.setupEDM4hepOutput('EDM4hepOutput', dds.outputFile)
eventPars = dds.meta.parseEventParameters()
Andre Sailer
committed
e4Out.RunHeader = dds.meta.addParametersToRunHeader(dds)
Andre Sailer
committed
e4Out.EventParametersString, e4Out.EventParametersInt, e4Out.EventParametersFloat = eventPars
e4Out.RunNumberOffset = dds.meta.runNumberOffset if dds.meta.runNumberOffset > 0 else 0
e4Out.EventNumberOffset = dds.meta.eventNumberOffset if dds.meta.eventNumberOffset > 0 else 0
return
def _configureDD4HEP(self, dds, geant4):
logger.info("++++ Setting up DD4hep's ROOT Output ++++")
geant4.setupROOTOutput('RootOutput', dds.outputFile)
return