File indexing completed on 2026-06-03 07:49:51
0001 import acts
0002 import argparse
0003 from acts.examples.simulation import (
0004 addParticleGun,
0005 addGeant4,
0006 EtaConfig,
0007 PhiConfig,
0008 ParticleConfig,
0009 MomentumConfig,
0010 )
0011
0012 from acts.examples.odd import getOpenDataDetector
0013
0014 u = acts.UnitConstants
0015
0016
0017 def main():
0018
0019 import acts
0020
0021 global __geant4Handle
0022 global __pmr
0023
0024 p = argparse.ArgumentParser()
0025
0026 p.add_argument("-n", "--events", type=int, default=1000, help="Number of Events")
0027
0028 p.add_argument(
0029 "-j",
0030 "--threads",
0031 type=int,
0032 default=1,
0033 help="Number of Threads for parallel execution",
0034 )
0035
0036 p.add_argument("-i", "--input", type=str, default="", help="Input SQL file")
0037
0038 p.add_argument("-o", "--output", type=str, default="", help="Output prefix")
0039
0040 p.add_argument(
0041 "-m", "--map", type=str, default="", help="Input file for the material map"
0042 )
0043
0044 p.add_argument("-s", "--seed", type=int, default=221177, help="Random number seed")
0045
0046
0047 p.add_argument(
0048 "--tracks", type=int, default=10, help="Number of tracks to generate per event"
0049 )
0050 p.add_argument(
0051 "--eta-range",
0052 type=float,
0053 nargs=2,
0054 default=[-2.5, 2.5],
0055 help="Pseudorapidity range for particle generation",
0056 )
0057 p.add_argument(
0058 "--phi-range",
0059 type=float,
0060 nargs=2,
0061 default=[0, 360],
0062 help="Azimuthal angle range (in degrees) for particle generation",
0063 )
0064 p.add_argument(
0065 "--pt-range",
0066 type=float,
0067 nargs=2,
0068 default=[0.5, 10],
0069 help="Transverse momentum range (in GeV) for particle generation",
0070 )
0071
0072
0073
0074
0075
0076
0077 p.add_argument(
0078 "--geo-mode",
0079 type=str,
0080 default="gen3",
0081 choices=["gen1", "gen3", "detray", "geant4"],
0082 help="Convert to detray detector and run detray navigation and propagation",
0083 )
0084
0085 p.add_argument(
0086 "--output-summary",
0087 action=argparse.BooleanOptionalAction,
0088 help="Write out the summary objects",
0089 )
0090
0091 p.add_argument(
0092 "--output-steps",
0093 action=argparse.BooleanOptionalAction,
0094 help="Write out the step objects",
0095 )
0096
0097 p.add_argument(
0098 "--output-material",
0099 action=argparse.BooleanOptionalAction,
0100 help="Write out the recorded",
0101 )
0102
0103 p.add_argument(
0104 "--output-sim-hits",
0105 action=argparse.BooleanOptionalAction,
0106 help="Write out sim hits, only makes sense for Geant4",
0107 )
0108
0109 args = p.parse_args()
0110
0111 prfx = args.output + "_" if args.output != "" else ""
0112
0113 gContext = acts.GeometryContext.dangerouslyDefaultConstruct()
0114 logLevel = acts.logging.INFO
0115
0116
0117 rnd = acts.examples.RandomNumbers(seed=args.seed)
0118
0119
0120 s = acts.examples.Sequencer(events=args.events, numThreads=args.threads)
0121
0122
0123 addParticleGun(
0124 s,
0125 ParticleConfig(
0126 num=args.tracks, pdg=acts.PdgParticle.eMuon, randomizeCharge=True
0127 ),
0128 EtaConfig(args.eta_range[0], args.eta_range[1]),
0129 PhiConfig(args.phi_range[0], args.phi_range[1]),
0130 MomentumConfig(
0131 args.pt_range[0] * u.GeV, args.pt_range[1] * u.GeV, transverse=True
0132 ),
0133 rnd=rnd,
0134 )
0135
0136
0137 sterileRun = False
0138 if not args.output_summary and not args.output_steps and not args.output_material:
0139 print(">> Timing measurement is enabled, no output is written")
0140 sterileRun = True
0141
0142
0143 materialDecorator = None
0144 if args.map != "":
0145 print(">>> Loading a material decorator from file:", args.map)
0146 materialDecorator = acts.IMaterialDecorator.fromFile(args.map)
0147
0148 trackingGeometry = None
0149 detectorStore = {}
0150
0151 buildGen3 = args.geo_mode == "gen3" or args.geo_mode == "detray"
0152
0153 with getOpenDataDetector(gen3=buildGen3) as detector:
0154 trackingGeometry = detector.trackingGeometry()
0155 detectorStore["Detector"] = detector
0156 detectorStore["Volume"] = trackingGeometry.highestTrackingVolume
0157 detectorStore["SurfaceByIdentifier"] = trackingGeometry.geoIdSurfaceMap()
0158
0159 print(">>> Test mode is :", args.geo_mode)
0160
0161 if args.geo_mode != "geant4":
0162
0163 propagatorImpl = None
0164 stepper = acts.StraightLineStepper()
0165
0166
0167 if args.geo_mode != "detray":
0168
0169 navigator = acts.Navigator(trackingGeometry=trackingGeometry)
0170 propagator = acts.Propagator(stepper, navigator)
0171 propagatorImpl = acts.examples.ConcretePropagator(propagator)
0172 else:
0173 import acts.vecmem, acts.detray
0174 import acts.examples.detray
0175
0176 __pmr = acts.vecmem.HostMemoryResource()
0177
0178 detrayGeometry = acts.detray.convertODD(
0179 __pmr,
0180 gContext,
0181 trackingGeometry,
0182 beampipeVolumeName="BeamPipe",
0183 logLevel=logLevel,
0184 )
0185 propagatorImpl = acts.examples.detray.StraightLinePropagatorODD(
0186 detrayGeometry, __pmr, sterileRun, logLevel
0187 )
0188
0189
0190 trkParamExtractor = acts.examples.ParticleTrackParamExtractor(
0191 level=acts.logging.INFO,
0192 inputParticles="particles_generated",
0193 outputTrackParameters="start_parameters",
0194 )
0195 s.addAlgorithm(trkParamExtractor)
0196
0197 propagationAlgorithm = acts.examples.PropagationAlgorithm(
0198 propagatorImpl=propagatorImpl,
0199 level=acts.logging.INFO,
0200 sterileLogger=sterileRun,
0201 inputTrackParameters="start_parameters",
0202 outputSummaryCollection="propagation_summary",
0203 outputMaterialCollection="material_tracks",
0204 )
0205 s.addAlgorithm(propagationAlgorithm)
0206 else:
0207 print(">>> Running Geant4 simulation, buckle up...")
0208 detector = detectorStore["Detector"]
0209
0210 import acts.examples.geant4
0211
0212 from acts.examples.geant4 import (
0213 Geant4Simulation,
0214 Geant4ConstructionOptions,
0215 SensitiveSurfaceMapper,
0216 )
0217
0218 customLogLevel = acts.examples.defaultLogging(s, logLevel)
0219
0220 smmConfig = SensitiveSurfaceMapper.Config()
0221 smmConfig.volumeMappings = []
0222 smmConfig.materialMappings = ["Silicon"]
0223 sensitiveMapper = SensitiveSurfaceMapper.create(
0224 smmConfig, customLogLevel(), trackingGeometry
0225 )
0226
0227 detectorConstructionOptions = acts.examples.geant4.Geant4ConstructionOptions()
0228
0229
0230 physicsList = "FTFP_BERT"
0231 killVolume = detectorStore["Volume"]
0232 killAfterTime = float("inf")
0233 bfield = None
0234
0235 inputParticles = "particles_generated"
0236 outputParticles = "particles_final"
0237
0238 addGeant4(
0239 s,
0240 detector,
0241 trackingGeometry,
0242 None,
0243 outputDirRoot=None,
0244 outputDirCsv=None,
0245 outputDirObj=None,
0246 rnd=rnd,
0247 killVolume=trackingGeometry.highestTrackingVolume,
0248 killAfterTime=25 * u.ns,
0249 killSecondaries=True,
0250 recordHitsOfSecondaries=False,
0251 recordPropagationSummaries=True,
0252 )
0253
0254 s.addWhiteboardAlias("propagation_summary", "propagation_summaries")
0255
0256
0257 if args.output_summary:
0258 s.addWriter(
0259 acts.examples.root.RootPropagationSummaryWriter(
0260 level=acts.logging.INFO,
0261 inputSummaryCollection="propagation_summary",
0262 filePath=prfx + args.geo_mode + "_propagation_summary.root",
0263 )
0264 )
0265
0266
0267 if args.output_steps:
0268 s.addWriter(
0269 acts.examples.root.RootPropagationStepsWriter(
0270 level=acts.logging.INFO,
0271 collection="propagation_summary",
0272 filePath=prfx + args.geo_mode + "_propagation_steps.root",
0273 )
0274 )
0275
0276
0277 if args.output_material:
0278 s.addWriter(
0279 acts.examples.root.RootMaterialTrackWriter(
0280 level=acts.logging.INFO,
0281 inputMaterialTracks="material_tracks",
0282 filePath=args.geo_mode + "_material_tracks.root",
0283 storeSurface=False,
0284 storeVolume=False,
0285 )
0286 )
0287
0288
0289 s.run()
0290
0291
0292 if "__main__" == __name__:
0293 main()