File indexing completed on 2025-01-18 09:14:22
0001 """Helper object for SD Actions
0002 """
0003
0004 from DDSim.Helper.ConfigHelper import ConfigHelper
0005
0006
0007 class Action(ConfigHelper):
0008 """Helper holding sensitive detector and other actions.
0009
0010 The default tracker and calorimeter sensitive actions can be set with
0011
0012 >>> SIM = DD4hepSimulation()
0013 >>> SIM.action.tracker=('Geant4TrackerWeightedAction', {'HitPositionCombination': 2, 'CollectSingleDeposits': False})
0014 >>> SIM.action.calo = "Geant4CalorimeterAction"
0015
0016 The default sensitive actions for calorimeters and trackers are applied based on the sensitive type.
0017 The list of sensitive types can be changed with
0018
0019 >>> SIM = DD4hepSimulation()
0020 >>> SIM.action.trackerSDTypes = ['tracker', 'myTrackerSensType']
0021 >>> SIM.calor.calorimeterSDTypes = ['calorimeter', 'myCaloSensType']
0022
0023 For specific subdetectors specific sensitive detectors can be set based on patterns in the name of the subdetector.
0024
0025 >>> SIM = DD4hepSimulation()
0026 >>> SIM.action.mapActions['tpc'] = "TPCSDAction"
0027
0028 and additional parameters for the sensitive detectors can be set when the map is given a tuple
0029
0030 >>> SIM = DD4hepSimulation()
0031 >>> SIM.action.mapActions['ecal'] =( "CaloPreShowerSDAction", {"FirstLayerNumber": 1} )
0032
0033 Additional actions can be set as well with the following syntax variations:
0034
0035 >>> SIM = DD4hepSimulation()
0036 # single action by name only:
0037 >>> SIM.action.run = "Geant4TestRunAction"
0038 # multiple actions with comma-separated names:
0039 >>> SIM.action.event = "Geant4TestEventAction/Action0,Geant4TestEventAction/Action1"
0040 # single action by tuple of name and parameter dict:
0041 >>> SIM.action.track = ( "Geant4TestTrackAction", {"Property_int": 10} )
0042 # single action by dict of name and parameter dict:
0043 >>> SIM.action.step = { "name": "Geant4TestStepAction", "parameter": {"Property_int": 10} }
0044 # multiple actions by list of dict of name and parameter dict:
0045 >>> SIM.action.stack = [ { "name": "Geant4TestStackAction", "parameter": {"Property_int": 10} } ]
0046
0047 On the command line or in python, these actions can be specified as JSON strings:
0048 $ ddsim --action.stack '{ "name": "Geant4TestStackAction", "parameter": { "Property_int": 10 } }'
0049 or
0050 >>> SIM.action.stack = '''
0051 {
0052 "name": "Geant4TestStackAction",
0053 "parameter": {
0054 "Property_int": 10,
0055 "Property_double": "1.0*mm"
0056 }
0057 }
0058 '''
0059
0060 """
0061
0062 def __init__(self):
0063 super(Action, self).__init__()
0064 self._tracker = ('Geant4TrackerWeightedAction', {'HitPositionCombination': 2, 'CollectSingleDeposits': False})
0065 self._calo = 'Geant4ScintillatorCalorimeterAction'
0066 self._mapActions = dict()
0067 self._trackerSDTypes = ['tracker']
0068 self._calorimeterSDTypes = ['calorimeter']
0069 self._run = []
0070 self._run_EXTRA = {"action": "append"}
0071 self._event = []
0072 self._event_EXTRA = {"action": "append"}
0073 self._track = []
0074 self._track_EXTRA = {"action": "append"}
0075 self._step = []
0076 self._step_EXTRA = {"action": "append"}
0077 self._stack = []
0078 self._stack_EXTRA = {"action": "append"}
0079 self._closeProperties()
0080
0081 @property
0082 def tracker(self):
0083 """ set the default tracker action """
0084 return self._tracker
0085
0086 @tracker.setter
0087 def tracker(self, val):
0088 self._tracker = val
0089
0090 @property
0091 def calo(self):
0092 """ set the default calorimeter action """
0093 return self._calo
0094
0095 @calo.setter
0096 def calo(self, val):
0097 self._calo = val
0098
0099 @property
0100 def mapActions(self):
0101 """Create a map of patterns and actions to be applied to sensitive detectors.
0102
0103 Example: if the name of the detector matches 'tpc' the TPCSDAction is used.
0104
0105 SIM.action.mapActions['tpc'] = "TPCSDAction"
0106 """
0107 return self._mapActions
0108
0109 @mapActions.setter
0110 def mapActions(self, val):
0111 """check if the argument is a dict, then we just update mapActions
0112 if it is a string or list, we use pairs as patterns --> Action
0113 """
0114 if isinstance(val, dict):
0115 self._mapActions.update(val)
0116 return
0117
0118 if isinstance(val, str):
0119 vals = val.split(" ")
0120 elif isinstance(val, list):
0121 vals = val
0122 if len(vals) % 2 != 0:
0123 raise RuntimeError("Not enough parameters for mapActions")
0124 for index in range(0, len(vals), 2):
0125 self._mapActions[vals[index]] = vals[index + 1]
0126
0127 def clearMapActions(self):
0128 """empty the mapActions dictionary"""
0129 self._mapActions = dict()
0130
0131 @property
0132 def trackerSDTypes(self):
0133 """List of patterns matching sensitive detectors of type Tracker."""
0134 return self._trackerSDTypes
0135
0136 @trackerSDTypes.setter
0137 def trackerSDTypes(self, val):
0138 self._trackerSDTypes = ConfigHelper.makeList(val)
0139
0140 @property
0141 def calorimeterSDTypes(self):
0142 """List of patterns matching sensitive detectors of type Calorimeter."""
0143 return self._calorimeterSDTypes
0144
0145 @calorimeterSDTypes.setter
0146 def calorimeterSDTypes(self, val):
0147 self._calorimeterSDTypes = ConfigHelper.makeList(val)
0148
0149 @staticmethod
0150 def makeListOfDictFromJSON(val):
0151 if isinstance(val, str):
0152
0153 import json
0154 try:
0155 val = json.loads(val)
0156
0157 return Action.makeListOfDictFromJSON(val)
0158 except ValueError:
0159
0160 return [dict(name=v) for v in val.split(",")]
0161 if isinstance(val, tuple):
0162
0163
0164
0165 return [dict(name=val[0], parameter=val[1])]
0166 if isinstance(val, dict):
0167
0168
0169 return [val]
0170 if isinstance(val, list):
0171
0172 return [i for v in val for i in Action.makeListOfDictFromJSON(v)]
0173 raise RuntimeError("Commandline setting of action is not successful for: %s " % val)
0174
0175 @property
0176 def run(self):
0177 """ set the default run action """
0178 return self._run
0179
0180 @run.setter
0181 def run(self, val):
0182 for action in Action.makeListOfDictFromJSON(val):
0183 if action not in self._run:
0184 self._run.append(action)
0185
0186 @property
0187 def event(self):
0188 """ set the default event action """
0189 return self._event
0190
0191 @event.setter
0192 def event(self, val):
0193 for action in Action.makeListOfDictFromJSON(val):
0194 if action not in self._event:
0195 self._event.append(action)
0196
0197 @property
0198 def track(self):
0199 """ set the default track action """
0200 return self._track
0201
0202 @track.setter
0203 def track(self, val):
0204 for action in Action.makeListOfDictFromJSON(val):
0205 if action not in self._track:
0206 self._track.append(action)
0207
0208 @property
0209 def step(self):
0210 """ set the default step action """
0211 return self._step
0212
0213 @step.setter
0214 def step(self, val):
0215 for action in Action.makeListOfDictFromJSON(val):
0216 if action not in self._step:
0217 self._step.append(action)
0218
0219 @property
0220 def stack(self):
0221 """ set the default stack action """
0222 return self._stack
0223
0224 @stack.setter
0225 def stack(self, val):
0226 for action in Action.makeListOfDictFromJSON(val):
0227 if action not in self._stack:
0228 self._stack.append(action)