From 6e0f7ea06818beebd3392676a858fb397bca45de Mon Sep 17 00:00:00 2001 From: Andre Sailer Date: Fri, 23 Aug 2024 13:58:11 +0200 Subject: [PATCH] RegexSD: change ddsim interface to use a dictionary instead of a list Too much hassle to ensure that the list was not duplicating the entries in the list The original implementation also caused infinite loop by appending to the list that was iterated over causing ddsim to use up all the memory and not do anything Added a test with an example ddsim steering file --- DDG4/python/DDSim/Helper/Geometry.py | 47 +++++++------------ examples/ClientTests/CMakeLists.txt | 14 ++++++ .../ClientTests/scripts/BoxOfStraws_DDSim.py | 16 +++++++ 3 files changed, 46 insertions(+), 31 deletions(-) create mode 100644 examples/ClientTests/scripts/BoxOfStraws_DDSim.py diff --git a/DDG4/python/DDSim/Helper/Geometry.py b/DDG4/python/DDSim/Helper/Geometry.py index f2bdf72af..80901b545 100644 --- a/DDG4/python/DDSim/Helper/Geometry.py +++ b/DDG4/python/DDSim/Helper/Geometry.py @@ -36,45 +36,29 @@ def __init__(self): self._dumpDGDML_EXTRA = {"help": "If not empty, filename to dump the Geometry as GDML"} self.dumpGDML = "" - self._regexSDDetectorList = [] + self._regexSDDict = {} self._closeProperties() @property def regexSensitiveDetector(self): - """Configure a sensitive detector for a given detector matched by regular expression (regex). - - 'Detector' and 'Match' are mandatory elements of the dictionary, other Keys are assigned as property to the object. - - >>> SIM.geometry.regexSensitiveDetector = {'Detector': 'DRcalo', - 'Match': ['(core|clad)'], - 'OutputLevel': 3, - } - - This can be assigned repeatedly to add multiple RegexSDs + """ The map key is the name of the Detector, and 'Match' is a mandatory elements of the dictionary, other Keys are + assigned as property to the object. OutputLevel _sets_ the outputlevel of the plugin, so lower numbers mean more + output from the plugin. + + >>> SIM.geometry.regexSensitiveDetector['DRcalo'] = { + 'Match': ['(core|clad)'], + 'OutputLevel': 3, + } """ - return self._regexSDDetectorList + return self._regexSDDict @regexSensitiveDetector.setter def regexSensitiveDetector(self, val): - if not val: - return if isinstance(val, dict): - self.__checkRegexKeys(val) - self._regexSDDetectorList.append(val) - elif isinstance(val, list): - for value in val: - self.__checkRegexKeys(value) - self._regexSDDetectorList.append(value) - else: - raise RuntimeError(f"Unsupported type for regexSensitiveDetector: {val!r}") - - @staticmethod - def __checkRegexKeys(val): - """Check the regex SD arguments for required keys.""" - requiredKeys = ('Detector', 'Match') - if not all(key in val for key in requiredKeys): - raise RuntimeError(f"RegexSD configuration {val} is missing mandatory key(s): {', '.join(requiredKeys)}") + self._regexSDDict = val + return + raise RuntimeError(f"Unsupported type for regexSensitiveDetector: {val!r}") def constructGeometry(self, kernel, geant4, geoPrintLevel=2, numberOfThreads=1): """Construct Geant4 geometry.""" @@ -100,8 +84,9 @@ def constructGeometry(self, kernel, geant4, geoPrintLevel=2, numberOfThreads=1): sensitives.enableUI() seq.adopt(sensitives) - for index, regexDetectors in enumerate(self._regexSDDetectorList): - seq, act = geant4.addDetectorConstruction(f'Geant4RegexSensitivesConstruction/ConstrSDRegEx_{index}') + for index, (detName, regexDetectors) in enumerate(sorted(self._regexSDDict.items())): + seq, act = geant4.addDetectorConstruction(f'Geant4RegexSensitivesConstruction/ConstrSDRegEx_{index} for {detName}') # this will set Match and Detector, and other properties if possible + setattr(act, "Detector", detName) for key, value in regexDetectors.items(): setattr(act, key, value) diff --git a/examples/ClientTests/CMakeLists.txt b/examples/ClientTests/CMakeLists.txt index 8ef15dc46..a32a0cc97 100644 --- a/examples/ClientTests/CMakeLists.txt +++ b/examples/ClientTests/CMakeLists.txt @@ -632,4 +632,18 @@ if (DD4HEP_USE_GEANT4) REGEX_PASS "ResourcesAfterConstruction ConstructSD: VmRSS" REGEX_FAIL "Error;ERROR; Exception" ) + + dd4hep_add_test_reg(ClientTests_ddsim_setup_BoxOfStraws + COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_ClientTests.sh" + EXEC_ARGS ddsim + --steeringFile ${ClientTestsEx_INSTALL}/scripts/BoxOfStraws_DDSim.py + --compactFile ${ClientTestsEx_INSTALL}/compact/BoxOfStraws.xml + --enableGun + --numberOfEvents 1 + --outputFile regex.slcio + + REGEX_PASS "BoxOfStrawsDet Handled 1 nodes with 1 sensitive volume type" + REGEX_FAIL "Error;ERROR; Exception" + ) + endif(DD4HEP_USE_GEANT4) diff --git a/examples/ClientTests/scripts/BoxOfStraws_DDSim.py b/examples/ClientTests/scripts/BoxOfStraws_DDSim.py new file mode 100644 index 000000000..e523840d2 --- /dev/null +++ b/examples/ClientTests/scripts/BoxOfStraws_DDSim.py @@ -0,0 +1,16 @@ +from DDSim.DD4hepSimulation import DD4hepSimulation +from g4units import mm, GeV, MeV +SIM = DD4hepSimulation() + +# make ddsim find the sensitive detector for box of straws +SIM.action.calorimeterSDTypes = ['sensitive'] + +# Configure the regexSD for the BoxOfStraws gas_ +SIM.geometry.regexSensitiveDetector['BoxOfStrawsDet'] = { + 'Match': ['gas_'], + 'OutputLevel': 4, + } + + +# Disable userParticleHander for box if straws +SIM.part.userParticleHandler = ""