File indexing completed on 2025-01-18 09:14:22
0001 """Helper object for Filters
0002
0003 Later the parameter dictionary is used to instantiate the filter object
0004 The default filters are a GeantinoRejector and a 1keV minimum energy cut
0005
0006 """
0007 from DDSim.Helper.ConfigHelper import ConfigHelper
0008 from g4units import keV
0009 import logging
0010
0011 logger = logging.getLogger(__name__)
0012
0013
0014 class Filter(ConfigHelper):
0015 """Configuration for sensitive detector filters
0016
0017 Set the default filter for 'tracker'
0018 >>> SIM.filter.tracker = "edep1kev"
0019 Use no filter for 'calorimeter' by default
0020 >>> SIM.filter.calo = ""
0021
0022 Assign a filter to a sensitive detector via pattern matching
0023 >>> SIM.filter.mapDetFilter['FTD'] = "edep1kev"
0024
0025 Or more than one filter:
0026 >>> SIM.filter.mapDetFilter['FTD'] = ["edep1kev", "geantino"]
0027
0028 Don't use the default filter or anything else:
0029 >>> SIM.filter.mapDetFilter['TPC'] = None ## or "" or []
0030
0031 Create a custom filter. The dictionary is used to instantiate the filter later on
0032 >>> SIM.filter.filters['edep3kev'] = dict(name="EnergyDepositMinimumCut/3keV", parameter={"Cut": 3.0*keV} )
0033
0034 """
0035
0036 def __init__(self):
0037 super(Filter, self).__init__()
0038 self._mapDetFilter = {}
0039 self._tracker = "edep1kev"
0040 self._calo = "edep0"
0041 self._filters = {}
0042 self._createDefaultFilters()
0043 self._closeProperties()
0044
0045 @property
0046 def tracker(self):
0047 """ default filter for tracking sensitive detectors; this is applied if no other filter is used for a tracker"""
0048 return self._tracker
0049
0050 @tracker.setter
0051 def tracker(self, val):
0052 self._tracker = val
0053
0054 @property
0055 def calo(self):
0056 """
0057 default filter for calorimeter sensitive detectors;
0058 this is applied if no other filter is used for a calorimeter
0059 """
0060 return self._calo
0061
0062 @calo.setter
0063 def calo(self, val):
0064 self._calo = val
0065
0066 @property
0067 def filters(self):
0068 """ list of filter objects: map between name and parameter dictionary """
0069 return self._filters
0070
0071 @filters.setter
0072 def filters(self, val):
0073 if isinstance(val, dict):
0074 self._filters.update(val)
0075 return
0076
0077 raise RuntimeError("Commandline setting of filters is not supported, use a steeringFile: %s " % val)
0078
0079 @property
0080 def mapDetFilter(self):
0081 """ a map between patterns and filter objects, using patterns to attach filters to sensitive detector """
0082 return self._mapDetFilter
0083
0084 @mapDetFilter.setter
0085 def mapDetFilter(self, val):
0086 if isinstance(val, dict):
0087 self._mapDetFilter.update(val)
0088 return
0089
0090 if isinstance(val, str):
0091 vals = val.split(" ")
0092 elif isinstance(val, list):
0093 vals = val
0094 if len(vals) % 2 != 0:
0095 raise RuntimeError("Not enough parameters for mapDetFilter")
0096 for index in range(0, len(vals), 2):
0097 self._mapDetFilter[vals[index]] = vals[index + 1]
0098
0099 def resetFilter(self):
0100 """ remove all filters """
0101 self._filters = {}
0102
0103 def _createDefaultFilters(self):
0104 """ create the map with the default filters """
0105 self.filters["geantino"] = dict(name="GeantinoRejectFilter/GeantinoRejector",
0106 parameter={})
0107
0108 self.filters["edep1kev"] = dict(name="EnergyDepositMinimumCut",
0109 parameter={"Cut": 1.0 * keV})
0110
0111 self.filters["edep0"] = dict(name="EnergyDepositMinimumCut/Cut0",
0112 parameter={"Cut": 0.0})
0113
0114 def __makeMapDetList(self):
0115 """ create the values of the mapDetFilters a list of filters """
0116 for pattern, filters in self._mapDetFilter.items():
0117 self._mapDetFilter[pattern] = ConfigHelper.makeList(filters)
0118
0119 def setupFilters(self, kernel):
0120 """ attach all filters to the kernel """
0121 import DDG4
0122 setOfFilters = set()
0123
0124 for name, filt in self.filters.items():
0125 setOfFilters.add(name)
0126 ddFilt = DDG4.Filter(kernel, filt['name'])
0127 for para, value in filt['parameter'].items():
0128 setattr(ddFilt, para, value)
0129 kernel.registerGlobalFilter(ddFilt)
0130 filt['filter'] = ddFilt
0131
0132 from itertools import chain
0133 listOfFilters = []
0134 for val in self.mapDetFilter.values():
0135 listOfFilters += ConfigHelper.makeList(val)
0136 requestedFilter = set(chain(ConfigHelper.makeList(self.tracker), ConfigHelper.makeList(self.calo), listOfFilters))
0137 logger.info("ReqFilt %s", requestedFilter)
0138 if requestedFilter - setOfFilters:
0139 raise RuntimeError(" Filter(s) '%s' are not registered!" % str(requestedFilter - setOfFilters))
0140
0141 def applyFilters(self, seq, det, defaultFilter=None):
0142 """apply the filters to to the sensitive detector
0143
0144 :param seq: sequence object returned when creating sensitive detector
0145 :param det: sensitive detector name
0146 :returns: None
0147 """
0148 self.__makeMapDetList()
0149 foundFilter = False
0150 for pattern, filts in self.mapDetFilter.items():
0151 if pattern.lower() in det.lower():
0152 foundFilter = True
0153 for filt in filts:
0154 logger.info("Adding filter '%s' matched with '%s' to sensitive detector for '%s' " % (filt, pattern, det))
0155 seq.add(self.filters[filt]['filter'])
0156
0157 if foundFilter:
0158 return
0159 if defaultFilter:
0160 logger.info("Adding default filter '%s' to sensitive detector for '%s' " % (defaultFilter, det))
0161 seq.add(self.filters[defaultFilter]['filter'])
0162 return
0163 logger.info("Not adding any filter to sensitive detector for '%s' " % det)