diff --git a/DDSim/DD4hepSimulation.py b/DDSim/DD4hepSimulation.py index 4bc46f6f16ed24dd28b4b1d461c59fc621fdc863..11854b30e03708ff709ea4e6669df1db726deeb3 100644 --- a/DDSim/DD4hepSimulation.py +++ b/DDSim/DD4hepSimulation.py @@ -38,6 +38,8 @@ from DDSim.Helper.MagneticField import MagneticField from DDSim.Helper.ConfigHelper import ConfigHelper from DDSim.Helper.Action import Action from DDSim.Helper.Random import Random +from DDSim.Helper.Filter import Filter + import os import sys import datetime @@ -74,6 +76,8 @@ class DD4hepSimulation(object): self.field = MagneticField() self.action = Action() + self.filter = Filter() + ### use TCSH geant UI instead of QT os.environ['G4UI_USE_TCSH'] = "1" @@ -219,7 +223,7 @@ class DD4hepSimulation(object): detType = sd.type() # if len(detectorList) and not(name in detectorList): # continue - print 'getDetectorLists - found active detctor ' , name , ' type: ' , type + print 'getDetectorLists - found active detctor ' , name , ' type: ' , detType if detType == "tracker": trackers.append( det.name() ) if detType == "calorimeter": @@ -358,14 +362,7 @@ class DD4hepSimulation(object): # Setup global filters for use in sensitive detectors - - f1 = DDG4.Filter(kernel,'GeantinoRejectFilter/GeantinoRejector') - kernel.registerGlobalFilter(f1) - - f4 = DDG4.Filter(kernel,'EnergyDepositMinimumCut') - f4.Cut = 1.*keV - kernel.registerGlobalFilter(f4) - + self.filter.setupFilters( kernel ) #================================================================================= # get lists of trackers and calorimeters in lcdd @@ -373,9 +370,8 @@ class DD4hepSimulation(object): trk,cal = self.getDetectorLists( lcdd ) # ---- add the trackers: - # FIXME: this assumes the same filters for all trackers ... try: - self.__setupSensitiveDetectors( trk, simple.setupTracker, filt=f1) + self.__setupSensitiveDetectors( trk, simple.setupTracker) except Exception as e: print "ERROR setting up sensitive detector", str(e) raise @@ -560,13 +556,12 @@ class DD4hepSimulation(object): return runHeader - def __setupSensitiveDetectors(self, detectors, setupFuction, filt=None): + def __setupSensitiveDetectors(self, detectors, setupFuction): """ attach sensitive detector actions for all subdetectors can be steered with the `Action` ConfigHelpers :param detectors: list of detectors :param setupFunction: function used to register the sensitive detector - :param filt: optional, give a filter to attach to all sensitive detectors """ for det in detectors: print 'Setting up SD for %s' % det @@ -586,8 +581,10 @@ class DD4hepSimulation(object): seq,act = setupFuction( det, type=action ) else: seq,act = setupFuction( det ) - if filt: - seq.add(filt) + for pattern, filt in self.filter.mapDetFilter.iteritems(): + if pattern.lower() in det.lower(): + print "Adding filter '%s' matched with '%s' to sensitive detector for '%s' " %( filt, pattern, det ) + seq.add( self.filter.filters[filt]['filter'] ) ##set detailed hit creation mode for this if self.detailedShowerMode: act.HitCreationMode = 2 diff --git a/DDSim/Helper/Filter.py b/DDSim/Helper/Filter.py new file mode 100644 index 0000000000000000000000000000000000000000..18705b64aa9b36dd290bcd21ae7e10173f3ba779 --- /dev/null +++ b/DDSim/Helper/Filter.py @@ -0,0 +1,79 @@ +"""Helper object for Filters + +>>> SIM = DD4hepSimulation() +>>> SIM.filter.mapDetFilter['FTD'] = "edep3keV" +>>> SIM.filter.filters['edep3keV'] = dict(name="EnergyDepositMinimumCut/3keV", parameter={"Cut": 3.0*keV} ) + + +Later the paramter dictionary is used to instantiate the filter object +The default filters are a GeantinoRejector and a 1keV minimum energy cut + +""" + +from DDSim.Helper.ConfigHelper import ConfigHelper +from SystemOfUnits import keV + +class Filter( ConfigHelper ): + """Filter for sensitive detector actions""" + def __init__( self ): + super(Filter, self).__init__() + self._mapDetFilter = {} + self._tracker = "edep" + self._calo = None + self._filters = {} + self._createDefaultFilters() + + @property + def filters( self ): + """ list of filter objects: map between name and parameter dictionary """ + return self._filters + @filters.setter + def filters( self, val ): + if isinstance(val, dict): + self._filters.update(val) + return + ## + raise RuntimeError("Commandline setting of filters is not supported, use a steeringFile:%s " % val ) + + + @property + def mapDetFilter( self ): + """ a map between patterns and filter objects, using patterns to attach filters to sensitive detector """ + return self._mapDetFilter + @mapDetFilter.setter + def mapDetFilter( self, val ): + if isinstance(val, dict): + self._mapDetFilter.update(val) + return + + if isinstance(val, basestring): + vals = val.split(" ") + elif isinstance( val, list ): + vals = val + if len(vals)%2 != 0: + raise RuntimeError("Not enough parameters for mapDetFilter") + for index in xrange(0,len(vals),2): + self._mapDetFilter[vals[index]] = vals[index+1] + + self._mapDetFilter = val + + + def _createDefaultFilters( self ): + """ create the map with the default filters """ + self.filters["geantino"]= dict( name="GeantinoRejectFilter/GeantinoRejector", + parameter={} ) + + self.filters["edep1kev"] = dict( name="EnergyDepositMinimumCut", + parameter={"Cut": 1.0*keV} ) + + + def setupFilters( self, kernel): + """ attach all filters to the kernel """ + import DDG4 + + for _pattern, filt in self.filters.iteritems(): + ddFilt = DDG4.Filter(kernel,filt['name']) + for para, value in filt['parameter'].iteritems(): + setattr( ddFilt, para, value ) + kernel.registerGlobalFilter(ddFilt) + filt['filter'] = ddFilt