File indexing completed on 2026-04-22 07:47:22
0001
0002
0003 import os
0004 import argparse
0005 import pathlib
0006 from pathlib import Path
0007
0008 import acts
0009 import acts.examples
0010
0011 from acts.examples import (
0012 TelescopeDetector,
0013 Sequencer,
0014 StructureSelector,
0015 RandomNumbers,
0016 GaussianVertexGenerator,
0017 )
0018
0019 from acts.examples.alignment import (
0020 AlignmentDecorator,
0021 GeoIdAlignmentStore,
0022 AlignmentGeneratorGlobalShift,
0023 )
0024 from acts.examples.alignmentmillepede import (
0025 MillePedeAlignmentSandbox,
0026 ActsSolverFromMille,
0027 )
0028
0029 from acts.examples.simulation import (
0030 MomentumConfig,
0031 EtaConfig,
0032 PhiConfig,
0033 ParticleConfig,
0034 ParticleSelectorConfig,
0035 addParticleGun,
0036 addFatras,
0037 addDigitization,
0038 addDigiParticleSelection,
0039 )
0040 from acts.examples.reconstruction import (
0041 addSeeding,
0042 CkfConfig,
0043 addCKFTracks,
0044 TrackSelectorConfig,
0045 SeedingAlgorithm,
0046 TrackSelectorConfig,
0047 addSeeding,
0048 SeedingAlgorithm,
0049 SeedFinderConfigArg,
0050 SeedFinderOptionsArg,
0051 SeedingAlgorithm,
0052 CkfConfig,
0053 addCKFTracks,
0054 TrackSelectorConfig,
0055 )
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072 def getTelescopeDetector():
0073 bounds = [200, 200]
0074 positions = [30, 60, 90, 120, 150, 180, 210, 240, 270]
0075 stereos = [0] * len(positions)
0076 detector = TelescopeDetector(
0077 bounds=bounds, positions=positions, stereos=stereos, binValue=1
0078 )
0079
0080 return detector
0081
0082
0083
0084 def addAlignmentSandbox(
0085 s: Sequencer,
0086 trackingGeometry: acts.TrackingGeometry,
0087 magField: acts.MagneticFieldProvider,
0088 fixModules: set,
0089 inputMeasurements: str = "measurements",
0090 inputTracks: str = "ckf_tracks",
0091 logLevel: acts.logging.Level = acts.logging.INFO,
0092 milleOutput: str = "MilleBinary.root",
0093 ):
0094 sandbox = MillePedeAlignmentSandbox(
0095 level=logLevel,
0096 milleOutput=milleOutput,
0097 inputMeasurements=inputMeasurements,
0098 inputTracks=inputTracks,
0099 trackingGeometry=trackingGeometry,
0100 magneticField=magField,
0101 fixModules=fixModules,
0102 )
0103 s.addAlgorithm(sandbox)
0104 return s
0105
0106
0107 def addSolverFromMille(
0108 s: Sequencer,
0109 trackingGeometry: acts.TrackingGeometry,
0110 magField: acts.MagneticFieldProvider,
0111 fixModules: set,
0112 logLevel: acts.logging.Level = acts.logging.INFO,
0113 milleInput: str = "MilleBinary.root",
0114 ):
0115
0116 solver = ActsSolverFromMille(
0117 level=logLevel,
0118 milleInput=milleInput,
0119 trackingGeometry=trackingGeometry,
0120 magneticField=magField,
0121 fixModules=fixModules,
0122 )
0123 s.addAlgorithm(solver)
0124 return s
0125
0126
0127 u = acts.UnitConstants
0128
0129
0130
0131 field = acts.ConstantBField(acts.Vector3(0, 0, 2 * acts.UnitConstants.T))
0132
0133
0134 parser = argparse.ArgumentParser(
0135 description="MillePede alignment demo with the Telescope Detector"
0136 )
0137 parser.add_argument(
0138 "--output",
0139 "-o",
0140 help="Output directory",
0141 type=pathlib.Path,
0142 default=pathlib.Path.cwd() / "mpali_output",
0143 )
0144 parser.add_argument("--events", "-n", help="Number of events", type=int, default=2000)
0145 parser.add_argument("--skip", "-s", help="Number of events", type=int, default=0)
0146
0147
0148 args = parser.parse_args()
0149
0150 outputDir = args.output
0151
0152 os.makedirs(outputDir, exist_ok=True)
0153
0154
0155 detector = getTelescopeDetector()
0156 trackingGeometry = detector.trackingGeometry()
0157 decorators = detector.contextDecorators()
0158
0159
0160
0161
0162 layerToBump = acts.GeometryIdentifier(layer=4, volume=1, sensitive=1)
0163
0164
0165 leShift = AlignmentGeneratorGlobalShift()
0166 leShift.shift = acts.Vector3(0, 0, 200.0e-3)
0167
0168
0169 alignDecoConfig = AlignmentDecorator.Config()
0170 alignDecoConfig.nominalStore = GeoIdAlignmentStore(
0171 StructureSelector(trackingGeometry).selectedTransforms(
0172 acts.GeometryContext.dangerouslyDefaultConstruct(), layerToBump
0173 )
0174 )
0175 alignDecoConfig.iovGenerators = [((0, 10000000), leShift)]
0176 alignDeco = AlignmentDecorator(alignDecoConfig, acts.logging.WARNING)
0177 contextDecorators = [alignDeco]
0178
0179
0180
0181
0182 fixModules = {acts.GeometryIdentifier(layer=2, volume=1, sensitive=1)}
0183
0184
0185
0186
0187 rnd = RandomNumbers(seed=42)
0188 s = Sequencer(
0189 events=args.events,
0190 skip=args.skip,
0191 numThreads=1,
0192 outputDir=str(outputDir),
0193 )
0194
0195
0196
0197 s.addContextDecorator(alignDeco)
0198
0199
0200 addParticleGun(
0201 s,
0202 MomentumConfig(
0203 10 * u.GeV,
0204 100 * u.GeV,
0205 transverse=True,
0206 ),
0207 EtaConfig(-0.3, 0.3),
0208
0209 PhiConfig(60 * u.degree, 120 * u.degree),
0210 ParticleConfig(1, acts.PdgParticle.eMuon, randomizeCharge=True),
0211 vtxGen=GaussianVertexGenerator(
0212 mean=acts.Vector4(0, 0, 0, 0),
0213 stddev=acts.Vector4(5.0 * u.mm, 0.0 * u.mm, 5.0 * u.mm, 0.0 * u.ns),
0214 ),
0215 multiplicity=1,
0216 rnd=rnd,
0217 )
0218
0219 addFatras(
0220 s,
0221 trackingGeometry,
0222 field,
0223 enableInteractions=True,
0224 outputDirRoot=None,
0225 outputDirCsv=None,
0226 outputDirObj=None,
0227 rnd=rnd,
0228 )
0229
0230
0231 srcdir = Path(__file__).resolve().parent.parent.parent.parent
0232 addDigitization(
0233 s,
0234 trackingGeometry,
0235 field,
0236 digiConfigFile=srcdir / "Examples/Configs/telescope-digi-smearing-config.json",
0237 outputDirRoot=None,
0238 outputDirCsv=None,
0239 rnd=rnd,
0240 )
0241 addDigiParticleSelection(
0242 s,
0243 ParticleSelectorConfig(
0244 measurements=(3, None),
0245 removeNeutral=True,
0246 ),
0247 )
0248
0249
0250 addSeeding(
0251 s,
0252 trackingGeometry,
0253 field,
0254
0255 seedFinderConfigArg=SeedFinderConfigArg(
0256 r=(20 * u.mm, 200 * u.mm),
0257 deltaR=(1 * u.mm, 300 * u.mm),
0258 collisionRegion=(-250 * u.mm, 250 * u.mm),
0259 z=(-100 * u.mm, 100 * u.mm),
0260 maxSeedsPerSpM=1,
0261 sigmaScattering=5,
0262 radLengthPerSeed=0.1,
0263 minPt=0.5 * u.GeV,
0264 impactMax=3 * u.mm,
0265 ),
0266
0267 seedFinderOptionsArg=SeedFinderOptionsArg(bFieldInZ=2 * u.T),
0268 seedingAlgorithm=SeedingAlgorithm.GridTriplet,
0269 initialSigmas=[
0270 3 * u.mm,
0271 3 * u.mm,
0272 1 * u.degree,
0273 1 * u.degree,
0274 0 * u.e / u.GeV,
0275 1 * u.ns,
0276 ],
0277 initialSigmaQoverPt=0.1 * u.e / u.GeV,
0278 initialSigmaPtRel=0.1,
0279 initialVarInflation=[1.0] * 6,
0280
0281
0282 geoSelectionConfigFile=srcdir / "Examples/Configs/telescope-seeding-config.json",
0283 outputDirRoot=None,
0284 )
0285
0286
0287 addCKFTracks(
0288 s,
0289 trackingGeometry,
0290 field,
0291 TrackSelectorConfig(),
0292 CkfConfig(
0293 chi2CutOffMeasurement=150.0,
0294 chi2CutOffOutlier=250.0,
0295 numMeasurementsCutOff=50,
0296 seedDeduplication=(True),
0297 stayOnSeed=True,
0298 ),
0299 outputDirRoot=None,
0300 writePerformance=False,
0301 writeTrackSummary=False,
0302 )
0303
0304
0305 addAlignmentSandbox(
0306 s, trackingGeometry, field, fixModules, milleOutput=outputDir / "MyBinary.root"
0307 )
0308
0309 addSolverFromMille(
0310 s, trackingGeometry, field, fixModules, milleInput=outputDir / "MyBinary.root"
0311 )
0312
0313 s.run()