File indexing completed on 2026-04-09 07:46:33
0001
0002
0003 import argparse
0004
0005 import acts
0006 from acts import (
0007 MaterialValidator,
0008 IntersectionMaterialAssigner,
0009 )
0010
0011 from acts.examples.simulation import (
0012 addParticleGun,
0013 EtaConfig,
0014 PhiConfig,
0015 ParticleConfig,
0016 )
0017
0018 from acts.examples import (
0019 MaterialValidation,
0020 ParticleTrackParamExtractor,
0021 )
0022
0023 from acts.examples.odd import getOpenDataDetector
0024 from acts.examples.root import RootMaterialTrackWriter
0025
0026 u = acts.UnitConstants
0027
0028
0029 def runMaterialValidation(
0030 surfaces,
0031 s,
0032 tracksPerEvent=100,
0033 etaRange=(-4.0, 4.0),
0034 phiRange=(0.0, 360.0 * u.degree),
0035 materialTrackCollectionName="material_tracks",
0036 outputFileBase="material_validation",
0037 trackingGeometry=None,
0038 ):
0039
0040 rnd = acts.examples.RandomNumbers(seed=42)
0041
0042 addParticleGun(
0043 s,
0044 ParticleConfig(
0045 num=tracksPerEvent, pdg=acts.PdgParticle.eMuon, randomizeCharge=True
0046 ),
0047 EtaConfig(*etaRange),
0048 PhiConfig(*phiRange),
0049 rnd=rnd,
0050 )
0051
0052 trkParamExtractor = ParticleTrackParamExtractor(
0053 level=acts.logging.INFO,
0054 inputParticles="particles_generated",
0055 outputTrackParameters="params_particles_generated",
0056 )
0057 s.addAlgorithm(trkParamExtractor)
0058
0059
0060 materialAssingerConfig = IntersectionMaterialAssigner.Config()
0061 materialAssingerConfig.surfaces = surfaces
0062 materialAssinger = IntersectionMaterialAssigner(
0063 materialAssingerConfig, acts.logging.INFO
0064 )
0065
0066
0067 materialValidatorConfig = MaterialValidator.Config()
0068 materialValidatorConfig.materialAssigner = materialAssinger
0069
0070
0071 materialValidationConfig = MaterialValidation.Config()
0072 materialValidationConfig.inputTrackParameters = "params_particles_generated"
0073 materialValidationConfig.materialValidator = MaterialValidator(
0074 materialValidatorConfig, acts.logging.INFO
0075 )
0076 materialValidationConfig.outputMaterialTracks = materialTrackCollectionName
0077 materialValidation = MaterialValidation(materialValidationConfig, acts.logging.INFO)
0078 s.addAlgorithm(materialValidation)
0079
0080
0081 s.addWriter(
0082 RootMaterialTrackWriter(
0083 level=acts.logging.INFO,
0084 inputMaterialTracks=materialValidationConfig.outputMaterialTracks,
0085 treeName=materialTrackCollectionName,
0086 filePath=str(outputFileBase) + ".root",
0087 storeSurface=True,
0088 storeVolume=True,
0089 )
0090 )
0091
0092
0093 if trackingGeometry is not None:
0094 nav = acts.Navigator(trackingGeometry=trackingGeometry)
0095 stepper = acts.StraightLineStepper()
0096 propagator = acts.examples.ConcretePropagator(acts.Propagator(stepper, nav))
0097
0098 propagationAlgorithm = acts.examples.PropagationAlgorithm(
0099 propagatorImpl=propagator,
0100 level=acts.logging.INFO,
0101 sterileLogger=False,
0102 inputTrackParameters="params_particles_generated",
0103 outputSummaryCollection="propagation_summary",
0104 outputMaterialCollection=materialTrackCollectionName + "_propagated",
0105 )
0106 s.addAlgorithm(propagationAlgorithm)
0107
0108
0109 s.addWriter(
0110 RootMaterialTrackWriter(
0111 level=acts.logging.INFO,
0112 inputMaterialTracks=materialTrackCollectionName + "_propagated",
0113 treeName=materialTrackCollectionName,
0114 filePath=str(outputFileBase) + "_propagated.root",
0115 storeSurface=True,
0116 storeVolume=True,
0117 )
0118 )
0119
0120 return s
0121
0122
0123 def main():
0124 p = argparse.ArgumentParser()
0125
0126 p.add_argument(
0127 "-n", "--events", type=int, default=1000, help="Number of events to process"
0128 )
0129 p.add_argument(
0130 "-t", "--tracks", type=int, default=100, help="Number of tracks per event"
0131 )
0132 p.add_argument("-j", "--threads", type=int, default=-1, help="Number of threads")
0133 p.add_argument(
0134 "-m", "--map", type=str, default="", help="Input file for the material map"
0135 )
0136 p.add_argument(
0137 "--eta-range",
0138 nargs=2,
0139 type=float,
0140 metavar=("MIN", "MAX"),
0141 default=(-4.0, 4.0),
0142 help="Eta range for generated particles",
0143 )
0144 p.add_argument(
0145 "--phi-range",
0146 nargs=2,
0147 type=float,
0148 metavar=("MIN_DEG", "MAX_DEG"),
0149 default=(0.0, 360.0),
0150 help="Phi range in degree for generated particles",
0151 )
0152 p.add_argument(
0153 "--material-track-collection",
0154 type=str,
0155 default="material_tracks",
0156 help="Output material track collection name",
0157 )
0158 p.add_argument(
0159 "-o",
0160 "--output",
0161 type=str,
0162 default="propagation-material",
0163 help="Output file stem (without extension)",
0164 )
0165 p.add_argument(
0166 "-p",
0167 "--propagate",
0168 action="store_true",
0169 help="Enable propagation validation",
0170 )
0171
0172 args = p.parse_args()
0173 materialDecorator = None
0174 if args.map != "":
0175 materialDecorator = acts.IMaterialDecorator.fromFile(args.map)
0176
0177 detector = getOpenDataDetector(materialDecorator)
0178 trackingGeometry = detector.trackingGeometry()
0179
0180 materialSurfaces = trackingGeometry.extractMaterialSurfaces()
0181
0182 s = acts.examples.Sequencer(events=args.events, numThreads=args.threads)
0183
0184 runMaterialValidation(
0185 surfaces=materialSurfaces,
0186 s=s,
0187 tracksPerEvent=args.tracks,
0188 etaRange=tuple(args.eta_range),
0189 phiRange=(args.phi_range[0] * u.degree, args.phi_range[1] * u.degree),
0190 materialTrackCollectionName=args.material_track_collection,
0191 outputFileBase=args.output,
0192 trackingGeometry=trackingGeometry if args.propagate else None,
0193 ).run()
0194
0195
0196 if "__main__" == __name__:
0197 main()