File indexing completed on 2026-09-23 08:23:40
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 import os
0014 import time
0015 import logging
0016 import DDG4
0017 from DDG4 import OutputLevel as Output
0018 from g4units import keV, GeV, mm, ns, MeV
0019
0020 logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO)
0021 logger = logging.getLogger(__name__)
0022
0023 """
0024
0025 dd4hep simulation example setup DDG4
0026 in multi-threaded mode using the python configuration
0027
0028 @author M.Frank
0029 @version 1.0
0030
0031 """
0032
0033
0034 def setupWorker(geant4):
0035 kernel = geant4.kernel()
0036 logger.info('#PYTHON: +++ Creating Geant4 worker thread ....')
0037 logger.info("#PYTHON: Configure Run actions")
0038 run1 = DDG4.RunAction(kernel, 'Geant4TestRunAction/RunInit', shared=True)
0039 run1.Property_int = int(12345)
0040 run1.Property_double = -5e15 * keV
0041 run1.Property_string = 'Startrun: Hello_2'
0042 logger.info("%s %s %s", run1.Property_string, str(run1.Property_double), str(run1.Property_int))
0043 run1.enableUI()
0044 kernel.runAction().adopt(run1)
0045
0046 logger.info("#PYTHON: Configure Event actions")
0047 prt = DDG4.EventAction(kernel, 'Geant4ParticlePrint/ParticlePrint')
0048 prt.OutputLevel = Output.INFO
0049 prt.OutputType = 3
0050 kernel.eventAction().adopt(prt)
0051
0052 logger.info("\n#PYTHON: Configure I/O\n")
0053
0054
0055
0056 geant4.setupROOTOutput('RootOutput', 'CLICSiD_' + time.strftime('%Y-%m-%d_%H-%M'))
0057
0058 gen = DDG4.GeneratorAction(kernel, "Geant4GeneratorActionInit/GenerationInit")
0059 kernel.generatorAction().adopt(gen)
0060
0061 logger.info("#PYTHON:\n#PYTHON: Generation of isotrope tracks of a given multiplicity with overlay:\n#PYTHON:")
0062 logger.info("#PYTHON: First particle generator: pi+")
0063 gen = DDG4.GeneratorAction(kernel, "Geant4IsotropeGenerator/IsotropPi+")
0064 gen.Mask = 1
0065 gen.Particle = 'pi+'
0066 gen.Energy = 20 * GeV
0067 gen.Multiplicity = 2
0068 kernel.generatorAction().adopt(gen)
0069 logger.info("#PYTHON: Install vertex smearing for this interaction")
0070 gen = DDG4.GeneratorAction(kernel, "Geant4InteractionVertexSmear/SmearPi+")
0071 gen.Mask = 1
0072 gen.Offset = (20 * mm, 10 * mm, 10 * mm, 0 * ns)
0073 gen.Sigma = (4 * mm, 1 * mm, 1 * mm, 0 * ns)
0074 kernel.generatorAction().adopt(gen)
0075
0076 logger.info("#PYTHON: Second particle generator: e-")
0077 gen = DDG4.GeneratorAction(kernel, "Geant4IsotropeGenerator/IsotropE-")
0078 gen.Mask = 2
0079 gen.Particle = 'e-'
0080 gen.Energy = 15 * GeV
0081 gen.Multiplicity = 3
0082 kernel.generatorAction().adopt(gen)
0083 logger.info("#PYTHON: Install vertex smearing for this interaction")
0084 gen = DDG4.GeneratorAction(kernel, "Geant4InteractionVertexSmear/SmearE-")
0085 gen.Mask = 2
0086 gen.Offset = (-20 * mm, -10 * mm, -10 * mm, 0 * ns)
0087 gen.Sigma = (12 * mm, 8 * mm, 8 * mm, 0 * ns)
0088 kernel.generatorAction().adopt(gen)
0089
0090
0091 logger.info("#PYTHON: Merge all existing interaction records")
0092 gen = DDG4.GeneratorAction(kernel, "Geant4InteractionMerger/InteractionMerger")
0093 gen.OutputLevel = 4
0094 gen.enableUI()
0095 kernel.generatorAction().adopt(gen)
0096
0097 logger.info("#PYTHON: Finally generate Geant4 primaries")
0098 gen = DDG4.GeneratorAction(kernel, "Geant4PrimaryHandler/PrimaryHandler")
0099 gen.OutputLevel = 4
0100 gen.enableUI()
0101 kernel.generatorAction().adopt(gen)
0102
0103 logger.info("#PYTHON: ....and handle the simulation particles.")
0104 part = DDG4.GeneratorAction(kernel, "Geant4ParticleHandler/ParticleHandler")
0105 kernel.generatorAction().adopt(part)
0106
0107 part.SaveProcesses = ['Decay']
0108 part.MinimalKineticEnergy = 100 * MeV
0109 part.OutputLevel = 5
0110 part.enableUI()
0111 user = DDG4.Action(kernel, "Geant4TCUserParticleHandler/UserParticleHandler")
0112 user.TrackingVolume_Zmax = DDG4.EcalEndcap_zmin
0113 user.TrackingVolume_Rmax = DDG4.EcalBarrel_rmin
0114 user.enableUI()
0115 part.adopt(user)
0116 logger.info('#PYTHON: +++ Geant4 worker thread configured successfully....')
0117 return 1
0118
0119
0120 def setupMaster(geant4):
0121 kernel = geant4.master()
0122 logger.info('#PYTHON: +++ Setting up master thread for %d workers', int(kernel.NumberOfThreads))
0123 return 1
0124
0125
0126 def setupSensitives(geant4):
0127 logger.info("#PYTHON: Setting up all sensitive detectors")
0128 geant4.printDetectors()
0129 logger.info("#PYTHON: First the tracking detectors")
0130 seq, act = geant4.setupTracker('SiVertexBarrel')
0131 seq, act = geant4.setupTracker('SiVertexEndcap')
0132 seq, act = geant4.setupTracker('SiTrackerBarrel')
0133 seq, act = geant4.setupTracker('SiTrackerEndcap')
0134 seq, act = geant4.setupTracker('SiTrackerForward')
0135 logger.info("#PYTHON: Now setup the calorimeters")
0136 seq, act = geant4.setupCalorimeter('EcalBarrel')
0137 seq, act = geant4.setupCalorimeter('EcalEndcap')
0138 seq, act = geant4.setupCalorimeter('HcalBarrel')
0139 seq, act = geant4.setupCalorimeter('HcalEndcap')
0140 seq, act = geant4.setupCalorimeter('HcalPlug')
0141 seq, act = geant4.setupCalorimeter('MuonBarrel')
0142 seq, act = geant4.setupCalorimeter('MuonEndcap')
0143 seq, act = geant4.setupCalorimeter('LumiCal')
0144 seq, act = geant4.setupCalorimeter('BeamCal')
0145 return 1
0146
0147
0148 def run():
0149 kernel = DDG4.Kernel()
0150 description = kernel.detectorDescription()
0151 install_dir = os.environ['DD4hepINSTALL']
0152 DDG4.Core.setPrintFormat(str("%-32s %6s %s"))
0153 kernel.loadGeometry(str("file:" + install_dir + "/DDDetectors/compact/SiD.xml"))
0154 DDG4.importConstants(description)
0155
0156 kernel.NumberOfThreads = 3
0157 kernel.RunManagerType = 'G4MTRunManager'
0158 geant4 = DDG4.Geant4(kernel, tracker='Geant4TrackerCombineAction')
0159 logger.info("# Configure UI")
0160 geant4.setupCshUI()
0161
0162 logger.info("# Geant4 user initialization action")
0163 geant4.addUserInitialization(worker=setupWorker, worker_args=(geant4,),
0164 master=setupMaster, master_args=(geant4,))
0165
0166 logger.info("# Configure G4 geometry setup")
0167 seq, act = geant4.addDetectorConstruction("Geant4DetectorGeometryConstruction/ConstructGeo")
0168
0169 logger.info("# Configure G4 sensitive detectors: python setup callback")
0170 seq, act = geant4.addDetectorConstruction("Geant4PythonDetectorConstruction/SetupSD",
0171 sensitives=setupSensitives, sensitives_args=(geant4,))
0172 logger.info("# Configure G4 sensitive detectors: atach'em to the sensitive volumes")
0173 seq, act = geant4.addDetectorConstruction("Geant4DetectorSensitivesConstruction/ConstructSD")
0174
0175
0176 logger.info("# Configure G4 magnetic field tracking")
0177 geant4.setupTrackingFieldMT()
0178
0179 logger.info("# Setup random generator")
0180 rndm = DDG4.Action(kernel, 'Geant4Random/Random')
0181 rndm.Seed = 987654321
0182 rndm.initialize()
0183
0184
0185 logger.info("# Now build the physics list:")
0186 phys = geant4.setupPhysics('QGSP_BERT')
0187 phys.dump()
0188
0189 geant4.run()
0190
0191
0192 if __name__ == "__main__":
0193 run()