File indexing completed on 2025-12-15 09:25:58
0001 from pathlib import Path
0002 from typing import Optional, Union, List
0003 from enum import Enum
0004 from collections import namedtuple
0005
0006 import acts
0007 import acts.examples
0008
0009 u = acts.UnitConstants
0010
0011 SeedingAlgorithm = Enum(
0012 "SeedingAlgorithm",
0013 "Default TruthSmeared TruthEstimated Orthogonal HoughTransform AdaptiveHoughTransform Gbts Hashing GridTriplet OrthogonalTriplet",
0014 )
0015
0016 TrackSmearingSigmas = namedtuple(
0017 "TrackSmearingSigmas",
0018 [
0019 "loc0",
0020 "loc0PtA",
0021 "loc0PtB",
0022 "loc1",
0023 "loc1PtA",
0024 "loc1PtB",
0025 "time",
0026 "phi",
0027 "theta",
0028 "ptRel",
0029 ],
0030 defaults=[None] * 10,
0031 )
0032
0033 SeedFinderConfigArg = namedtuple(
0034 "SeedFinderConfig",
0035 [
0036 "maxSeedsPerSpM",
0037 "cotThetaMax",
0038 "sigmaScattering",
0039 "radLengthPerSeed",
0040 "minPt",
0041 "impactMax",
0042 "deltaPhiMax",
0043 "interactionPointCut",
0044 "deltaZMax",
0045 "maxPtScattering",
0046 "zBinEdges",
0047 "zBinsCustomLooping",
0048 "rRangeMiddleSP",
0049 "useVariableMiddleSPRange",
0050 "binSizeR",
0051 "seedConfirmation",
0052 "centralSeedConfirmationRange",
0053 "forwardSeedConfirmationRange",
0054 "deltaR",
0055 "deltaRBottomSP",
0056 "deltaRTopSP",
0057 "deltaRMiddleSPRange",
0058 "collisionRegion",
0059 "r",
0060 "z",
0061 ],
0062 defaults=[None] * 18 + [(None, None)] * 7,
0063 )
0064 SeedFinderOptionsArg = namedtuple(
0065 "SeedFinderOptions", ["beamPos", "bFieldInZ"], defaults=[(None, None), None]
0066 )
0067
0068 SeedFilterConfigArg = namedtuple(
0069 "SeedFilterConfig",
0070 [
0071 "impactWeightFactor",
0072 "zOriginWeightFactor",
0073 "compatSeedWeight",
0074 "compatSeedLimit",
0075 "numSeedIncrement",
0076 "seedWeightIncrement",
0077 "seedConfirmation",
0078 "maxSeedsPerSpMConf",
0079 "maxQualitySeedsPerSpMConf",
0080 "useDeltaRorTopRadius",
0081 "deltaRMin",
0082 ],
0083 defaults=[None] * 11,
0084 )
0085
0086 SpacePointGridConfigArg = namedtuple(
0087 "SeedGridConfig",
0088 [
0089 "rMax",
0090 "zBinEdges",
0091 "phiBinDeflectionCoverage",
0092 "impactMax",
0093 "deltaRMax",
0094 "maxPhiBins",
0095 "phi",
0096 ],
0097 defaults=[None] * 6 + [(None, None)] * 1,
0098 )
0099
0100 SeedingAlgorithmConfigArg = namedtuple(
0101 "SeedingAlgorithmConfig",
0102 [
0103 "allowSeparateRMax",
0104 "zBinNeighborsTop",
0105 "zBinNeighborsBottom",
0106 "numPhiNeighbors",
0107 "useExtraCuts",
0108 ],
0109 defaults=[None] * 5,
0110 )
0111
0112 TruthEstimatedSeedingAlgorithmConfigArg = namedtuple(
0113 "TruthSeederConfig",
0114 [
0115 "deltaR",
0116 ],
0117 defaults=[(None, None)],
0118 )
0119
0120 TrackSelectorConfig = namedtuple(
0121 "TrackSelectorConfig",
0122 [
0123 "loc0",
0124 "loc1",
0125 "time",
0126 "eta",
0127 "absEta",
0128 "pt",
0129 "phi",
0130 "nMeasurementsMin",
0131 "maxHoles",
0132 "maxOutliers",
0133 "maxHolesAndOutliers",
0134 "maxSharedHits",
0135 "maxChi2",
0136 "nMeasurementsGroupMin",
0137 "requireReferenceSurface",
0138 ],
0139 defaults=[(None, None)] * 7 + [None] * 8,
0140 )
0141
0142
0143 def trackSelectorDefaultKWArgs(c):
0144 """
0145 Encapsulate this boilerplate code into a function so different uses do not get out of sync
0146 """
0147 return acts.examples.defaultKWArgs(
0148 loc0Min=c.loc0[0],
0149 loc0Max=c.loc0[1],
0150 loc1Min=c.loc1[0],
0151 loc1Max=c.loc1[1],
0152 timeMin=c.time[0],
0153 timeMax=c.time[1],
0154 phiMin=c.phi[0],
0155 phiMax=c.phi[1],
0156 etaMin=c.eta[0],
0157 etaMax=c.eta[1],
0158 absEtaMin=c.absEta[0],
0159 absEtaMax=c.absEta[1],
0160 ptMin=c.pt[0],
0161 ptMax=c.pt[1],
0162 minMeasurements=c.nMeasurementsMin,
0163 maxHoles=c.maxHoles,
0164 maxOutliers=c.maxOutliers,
0165 maxHolesAndOutliers=c.maxHolesAndOutliers,
0166 maxSharedHits=c.maxSharedHits,
0167 maxChi2=c.maxChi2,
0168 measurementCounter=c.nMeasurementsGroupMin,
0169 requireReferenceSurface=c.requireReferenceSurface,
0170 )
0171
0172
0173 CkfConfig = namedtuple(
0174 "CkfConfig",
0175 [
0176 "chi2CutOffMeasurement",
0177 "chi2CutOffOutlier",
0178 "numMeasurementsCutOff",
0179 "maxSteps",
0180 "seedDeduplication",
0181 "stayOnSeed",
0182 "pixelVolumes",
0183 "stripVolumes",
0184 "maxPixelHoles",
0185 "maxStripHoles",
0186 "trimTracks",
0187 "constrainToVolumes",
0188 "endOfWorldVolumes",
0189 ],
0190 defaults=[
0191 15.0,
0192 25.0,
0193 10,
0194 None,
0195 None,
0196 None,
0197 None,
0198 None,
0199 None,
0200 None,
0201 None,
0202 None,
0203 None,
0204 ],
0205 )
0206
0207 AmbiguityResolutionConfig = namedtuple(
0208 "AmbiguityResolutionConfig",
0209 ["maximumSharedHits", "nMeasurementsMin", "maximumIterations"],
0210 defaults=[None] * 3,
0211 )
0212
0213 ScoreBasedAmbiguityResolutionConfig = namedtuple(
0214 "ScoreBasedAmbiguityResolutionConfig",
0215 [
0216 "minScore",
0217 "minScoreSharedTracks",
0218 "maxShared",
0219 "minUnshared",
0220 "maxSharedTracksPerMeasurement",
0221 "useAmbiguityScoring",
0222 ],
0223 defaults=[None] * 6,
0224 )
0225
0226 AmbiguityResolutionMLConfig = namedtuple(
0227 "AmbiguityResolutionMLConfig",
0228 ["maximumSharedHits", "nMeasurementsMin", "maximumIterations"],
0229 defaults=[None] * 3,
0230 )
0231
0232 SeedFilterMLDBScanConfig = namedtuple(
0233 "SeedFilterMLDBScanConfig",
0234 ["epsilonDBScan", "minPointsDBScan", "minSeedScore"],
0235 defaults=[None] * 3,
0236 )
0237
0238 HashingTrainingConfigArg = namedtuple(
0239 "HashingTrainingConfig",
0240 ["annoySeed", "f"],
0241 defaults=[None] * 2,
0242 )
0243
0244 HashingAlgorithmConfigArg = namedtuple(
0245 "HashingAlgorithmConfig",
0246 ["bucketSize", "zBins", "phiBins"],
0247 defaults=[None] * 3,
0248 )
0249
0250
0251 class VertexFinder(Enum):
0252 Truth = (1,)
0253 AMVF = (2,)
0254 Iterative = (3,)
0255
0256
0257 @acts.examples.NamedTypeArgs(
0258 seedingAlgorithm=SeedingAlgorithm,
0259 trackSmearingSigmas=TrackSmearingSigmas,
0260 seedFinderConfigArg=SeedFinderConfigArg,
0261 seedFinderOptionsArg=SeedFinderOptionsArg,
0262 seedFilterConfigArg=SeedFilterConfigArg,
0263 spacePointGridConfigArg=SpacePointGridConfigArg,
0264 seedingAlgorithmConfigArg=SeedingAlgorithmConfigArg,
0265 hashingTrainingConfigArg=HashingTrainingConfigArg,
0266 hashingAlgorithmConfigArg=HashingAlgorithmConfigArg,
0267 truthEstimatedSeedingAlgorithmConfigArg=TruthEstimatedSeedingAlgorithmConfigArg,
0268 logLevel=acts.logging.Level,
0269 )
0270 def addSeeding(
0271 s: acts.examples.Sequencer,
0272 trackingGeometry: acts.TrackingGeometry,
0273 field: acts.MagneticFieldProvider,
0274 geoSelectionConfigFile: Optional[Union[Path, str]] = None,
0275 stripGeoSelectionConfigFile: Optional[Union[Path, str]] = None,
0276 layerMappingConfigFile: Optional[Union[Path, str]] = None,
0277 ConnectorInputConfigFile: Optional[Union[Path, str]] = None,
0278 seedingAlgorithm: SeedingAlgorithm = SeedingAlgorithm.GridTriplet,
0279 trackSmearingSigmas: TrackSmearingSigmas = TrackSmearingSigmas(),
0280 initialSigmas: Optional[list] = None,
0281 initialSigmaQoverPt: Optional[float] = None,
0282 initialSigmaPtRel: Optional[float] = None,
0283 initialVarInflation: Optional[list] = None,
0284 seedFinderConfigArg: SeedFinderConfigArg = SeedFinderConfigArg(),
0285 seedFinderOptionsArg: SeedFinderOptionsArg = SeedFinderOptionsArg(),
0286 seedFilterConfigArg: SeedFilterConfigArg = SeedFilterConfigArg(),
0287 spacePointGridConfigArg: SpacePointGridConfigArg = SpacePointGridConfigArg(),
0288 seedingAlgorithmConfigArg: SeedingAlgorithmConfigArg = SeedingAlgorithmConfigArg(),
0289 houghTransformConfig: acts.examples.HoughTransformSeeder.Config = acts.examples.HoughTransformSeeder.Config(),
0290 adaptiveHoughTransformConfig: Optional[
0291 acts.examples.AdaptiveHoughTransformSeeder.Config
0292 ] = None,
0293 hashingTrainingConfigArg: Optional[
0294 HashingTrainingConfigArg
0295 ] = HashingTrainingConfigArg(),
0296 hashingAlgorithmConfigArg: Optional[
0297 HashingAlgorithmConfigArg
0298 ] = HashingAlgorithmConfigArg(),
0299 truthEstimatedSeedingAlgorithmConfigArg: TruthEstimatedSeedingAlgorithmConfigArg = TruthEstimatedSeedingAlgorithmConfigArg(),
0300 particleHypothesis: Optional[
0301 acts.ParticleHypothesis
0302 ] = acts.ParticleHypothesis.pion,
0303 inputParticles: str = "particles",
0304 selectedParticles: str = "particles_selected",
0305 outputDirRoot: Optional[Union[Path, str]] = None,
0306 outputDirCsv: Optional[Union[Path, str]] = None,
0307 logLevel: Optional[acts.logging.Level] = None,
0308 rnd: Optional[acts.examples.RandomNumbers] = None,
0309 ) -> None:
0310 """This function steers the seeding
0311 Parameters
0312 ----------
0313 s: Sequencer
0314 the sequencer module to which we add the Seeding steps (returned from addSeeding)
0315 trackingGeometry : tracking geometry
0316 field : magnetic field
0317 geoSelectionConfigFile : Path|str, path, None
0318 Json file for space point geometry selection. Not required for SeedingAlgorithm.TruthSmeared.
0319 stripGeoSelectionConfigFile : Path|str, path, None
0320 Json file for space point geometry selection in strips. Needed for SpacePoint making.
0321 seedingAlgorithm : SeedingAlgorithm, Default
0322 seeding algorithm to use: one of Default (no truth information used), TruthSmeared, TruthEstimated
0323 trackSmearingSigmas : TrackSmearingSigmas(loc0, loc0PtA, loc0PtB, loc1, loc1PtA, loc1PtB, time, phi, theta, ptRel)
0324 TrackSmearing configuration.
0325 Defaults specified in Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/TrackParameterSmearing.hpp
0326 initialSigmas : list
0327 Sets the initial covariance matrix diagonal. This is ignored in case of TruthSmearing.
0328 Defaults specified in Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/TrackParamsEstimationAlgorithm.hpp
0329 initialVarInflation : list
0330 List of 6 scale factors to inflate the initial covariance matrix
0331 Defaults (all 1) specified in Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/TrackParameterSmearing.hpp
0332 seedFinderConfigArg : SeedFinderConfigArg(maxSeedsPerSpM, cotThetaMax, sigmaScattering, radLengthPerSeed, minPt, impactMax, deltaPhiMax, interactionPointCut, deltaZMax, maxPtScattering, zBinEdges, zBinsCustomLooping, rRangeMiddleSP, useVariableMiddleSPRange, binSizeR, seedConfirmation, centralSeedConfirmationRange, forwardSeedConfirmationRange, deltaR, deltaRBottomSP, deltaRTopSP, deltaRMiddleSPRange, collisionRegion, r, z)
0333 SeedFinderConfig settings. deltaR, deltaRBottomSP, deltaRTopSP, deltaRMiddleSPRange, collisionRegion, r, z.
0334 Defaults specified in Core/include/Acts/Seeding/SeedFinderConfig.hpp
0335 seedFinderOptionsArg : SeedFinderOptionsArg(bFieldInZ, beamPos)
0336 Defaults specified in Core/include/Acts/Seeding/SeedFinderConfig.hpp
0337 seedFilterConfigArg : SeedFilterConfigArg(compatSeedWeight, compatSeedLimit, numSeedIncrement, seedWeightIncrement, seedConfirmation, maxSeedsPerSpMConf, maxQualitySeedsPerSpMConf, useDeltaRorTopRadius)
0338 Defaults specified in Core/include/Acts/Seeding/SeedFilterConfig.hpp
0339 spacePointGridConfigArg : SpacePointGridConfigArg(rMax, zBinEdges, phiBinDeflectionCoverage, phi, maxPhiBins, impactMax)
0340 SpacePointGridConfigArg settings. phi is specified as a tuple of (min,max).
0341 Defaults specified in Core/include/Acts/Seeding/SpacePointGrid.hpp
0342 seedingAlgorithmConfigArg : SeedingAlgorithmConfigArg(allowSeparateRMax, zBinNeighborsTop, zBinNeighborsBottom, numPhiNeighbors, useExtraCuts)
0343 Defaults specified in Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/SeedingAlgorithm.hpp
0344 hashingTrainingConfigArg : HashingTrainingConfigArg(annoySeed, f)
0345 Defaults specified in Plugins/Hashing/include/ActsPlugins/Hashing/HashingTrainingConfig.hpp
0346 hashingAlgorithmConfigArg : HashingAlgorithmConfigArg(bucketSize, zBins, phiBins)
0347 Defaults specified in Plugins/Hashing/include/ActsPlugins/Hashing/HashingAlgorithmConfig.hpp
0348 truthEstimatedSeedingAlgorithmConfigArg : TruthEstimatedSeedingAlgorithmConfigArg(deltaR)
0349 Currently only deltaR=(min,max) range specified here.
0350 particleHypothesis : Optional[acts.ParticleHypothesis]
0351 The hypothesis used for track finding. Defaults to pion.
0352 inputParticles : str, "particles"
0353 input particles name in the WhiteBoard
0354 selectedParticles : str, "particles_selected"
0355 selected particles name in the WhiteBoard
0356 outputDirRoot : Path|str, path, None
0357 the output folder for ROOT output, None triggers no output
0358 logLevel : acts.logging.Level, None
0359 logging level to override setting given in `s`
0360 rnd : RandomNumbers, None
0361 random number generator. Only used by SeedingAlgorithm.TruthSmeared.
0362 """
0363
0364 logLevel = acts.examples.defaultLogging(s, logLevel)()
0365 logger = acts.logging.getLogger("addSeeding")
0366 logger.setLevel(logLevel)
0367
0368
0369
0370 if seedingAlgorithm == SeedingAlgorithm.TruthSmeared:
0371 logger.info("Using smeared truth particles for seeding")
0372 addTruthSmearedSeeding(
0373 s=s,
0374 rnd=rnd,
0375 selectedParticles=selectedParticles,
0376 trackSmearingSigmas=trackSmearingSigmas,
0377 initialSigmas=initialSigmas,
0378 initialSigmaQoverPt=initialSigmaQoverPt,
0379 initialSigmaPtRel=initialSigmaPtRel,
0380 initialVarInflation=initialVarInflation,
0381 particleHypothesis=particleHypothesis,
0382 logLevel=logLevel,
0383 )
0384 else:
0385 spacePoints = addSpacePointsMaking(
0386 s,
0387 trackingGeometry,
0388 geoSelectionConfigFile,
0389 stripGeoSelectionConfigFile,
0390 logLevel,
0391 )
0392 seeds = None
0393 perSeedParticleHypothesis = None
0394
0395 if seedingAlgorithm == SeedingAlgorithm.TruthEstimated:
0396 logger.info("Using truth track finding from space points for seeding")
0397 seeds, perSeedParticleHypothesis = addTruthEstimatedSeeding(
0398 s,
0399 spacePoints,
0400 selectedParticles,
0401 truthEstimatedSeedingAlgorithmConfigArg,
0402 particleHypothesis=particleHypothesis,
0403 logLevel=logLevel,
0404 )
0405 elif seedingAlgorithm == SeedingAlgorithm.Default:
0406 logger.info("Using default seeding")
0407 seeds = addStandardSeeding(
0408 s,
0409 spacePoints,
0410 seedingAlgorithmConfigArg,
0411 seedFinderConfigArg,
0412 seedFinderOptionsArg,
0413 seedFilterConfigArg,
0414 spacePointGridConfigArg,
0415 logLevel,
0416 )
0417 elif seedingAlgorithm == SeedingAlgorithm.Orthogonal:
0418 logger.info("Using orthogonal seeding")
0419 seeds = addOrthogonalSeeding(
0420 s,
0421 spacePoints,
0422 seedFinderConfigArg,
0423 seedFinderOptionsArg,
0424 seedFilterConfigArg,
0425 logLevel,
0426 )
0427 elif seedingAlgorithm == SeedingAlgorithm.HoughTransform:
0428 logger.info("Using Hough Transform seeding")
0429 houghTransformConfig.inputSpacePoints = [spacePoints]
0430 houghTransformConfig.inputMeasurements = "measurements"
0431 houghTransformConfig.outputProtoTracks = "prototracks"
0432 houghTransformConfig.outputSeeds = "seeds"
0433 houghTransformConfig.trackingGeometry = trackingGeometry
0434 seeds = addHoughTransformSeeding(s, houghTransformConfig, logLevel)
0435 elif seedingAlgorithm == SeedingAlgorithm.AdaptiveHoughTransform:
0436 logger.info("Using Adaptive Hough Transform seeding")
0437 adaptiveHoughTransformConfig.inputSpacePoints = [spacePoints]
0438 adaptiveHoughTransformConfig.outputProtoTracks = "prototracks"
0439 adaptiveHoughTransformConfig.outputSeeds = "seeds"
0440 adaptiveHoughTransformConfig.trackingGeometry = trackingGeometry
0441 adaptiveHoughTransformConfig.threshold = 4
0442 adaptiveHoughTransformConfig.noiseThreshold = 12
0443 adaptiveHoughTransformConfig.phiMinBinSize = 3.14 / (2.0 * 257.0)
0444 adaptiveHoughTransformConfig.qOverPtMinBinSize = 1.1 / (2.0 * 257.0)
0445 adaptiveHoughTransformConfig.qOverPtMin = 1.1
0446 adaptiveHoughTransformConfig.doSecondPhase = True
0447 adaptiveHoughTransformConfig.zMinBinSize = 1 * u.mm
0448 adaptiveHoughTransformConfig.cotThetaMinBinSize = 0.1
0449 adaptiveHoughTransformConfig.deduplicate = True
0450 seeds = addAdaptiveHoughTransformSeeding(
0451 s, adaptiveHoughTransformConfig, logLevel=logLevel
0452 )
0453 elif seedingAlgorithm == SeedingAlgorithm.Gbts:
0454 logger.info("Using Gbts seeding")
0455
0456 seeds = addGbtsSeeding(
0457 s,
0458 spacePoints,
0459 seedFinderConfigArg,
0460 seedFinderOptionsArg,
0461 trackingGeometry,
0462 logLevel,
0463 layerMappingConfigFile,
0464 geoSelectionConfigFile,
0465 ConnectorInputConfigFile,
0466 )
0467 elif seedingAlgorithm == SeedingAlgorithm.Hashing:
0468 logger.info("Using Hashing seeding")
0469 seeds, buckets = addHashingSeeding(
0470 s,
0471 spacePoints,
0472 seedingAlgorithmConfigArg,
0473 seedFinderConfigArg,
0474 seedFinderOptionsArg,
0475 seedFilterConfigArg,
0476 spacePointGridConfigArg,
0477 hashingTrainingConfigArg,
0478 hashingAlgorithmConfigArg,
0479 logLevel,
0480 )
0481 elif seedingAlgorithm == SeedingAlgorithm.GridTriplet:
0482 logger.info("Using grid triplet seeding")
0483 seeds = addGridTripletSeeding(
0484 s,
0485 spacePoints,
0486 seedingAlgorithmConfigArg,
0487 seedFinderConfigArg,
0488 seedFinderOptionsArg,
0489 seedFilterConfigArg,
0490 spacePointGridConfigArg,
0491 logLevel,
0492 )
0493 elif seedingAlgorithm == SeedingAlgorithm.OrthogonalTriplet:
0494 logger.info("Using orthogonal triplet seeding")
0495 seeds = addOrthogonalTripletSeeding(
0496 s,
0497 spacePoints,
0498 seedingAlgorithmConfigArg,
0499 seedFinderConfigArg,
0500 seedFinderOptionsArg,
0501 seedFilterConfigArg,
0502 spacePointGridConfigArg,
0503 logLevel,
0504 )
0505 else:
0506 logger.fatal("unknown seedingAlgorithm %s", seedingAlgorithm)
0507
0508 parEstimateAlg = acts.examples.TrackParamsEstimationAlgorithm(
0509 level=logLevel,
0510 inputSeeds=seeds,
0511 inputParticleHypotheses=perSeedParticleHypothesis,
0512 outputTrackParameters="estimatedparameters",
0513 outputSeeds="estimatedseeds",
0514 trackingGeometry=trackingGeometry,
0515 magneticField=field,
0516 **acts.examples.defaultKWArgs(
0517 initialSigmas=initialSigmas,
0518 initialSigmaQoverPt=initialSigmaQoverPt,
0519 initialSigmaPtRel=initialSigmaPtRel,
0520 initialVarInflation=initialVarInflation,
0521 particleHypothesis=particleHypothesis,
0522 ),
0523 )
0524 s.addAlgorithm(parEstimateAlg)
0525
0526 prototracks = "seed-prototracks"
0527 s.addAlgorithm(
0528 acts.examples.SeedsToPrototracks(
0529 level=logLevel,
0530 inputSeeds="estimatedseeds",
0531 outputProtoTracks=prototracks,
0532 )
0533 )
0534
0535 tracks = "seed-tracks"
0536 s.addAlgorithm(
0537 acts.examples.PrototracksToTracks(
0538 level=logLevel,
0539 inputProtoTracks=prototracks,
0540 inputTrackParameters="estimatedparameters",
0541 inputMeasurements="measurements",
0542 outputTracks=tracks,
0543 )
0544 )
0545
0546 s.addAlgorithm(
0547 acts.examples.TrackTruthMatcher(
0548 level=logLevel,
0549 inputTracks=tracks,
0550 inputParticles=selectedParticles,
0551 inputMeasurementParticlesMap="measurement_particles_map",
0552 outputTrackParticleMatching="seed_particle_matching",
0553 outputParticleTrackMatching="particle_seed_matching",
0554 matchingRatio=1.0,
0555 doubleMatching=False,
0556 )
0557 )
0558
0559 if outputDirRoot is not None:
0560 addSeedPerformanceWriters(
0561 s,
0562 outputDirRoot,
0563 tracks,
0564 prototracks,
0565 selectedParticles,
0566 inputParticles,
0567 parEstimateAlg.config.outputTrackParameters,
0568 logLevel,
0569 )
0570
0571 if outputDirCsv is not None:
0572 outputDirCsv = Path(outputDirCsv)
0573
0574 if not outputDirCsv.exists():
0575 outputDirCsv.mkdir()
0576
0577 csvSeedWriter = acts.examples.CsvSeedWriter(
0578 level=logLevel,
0579 inputTrackParameters=parEstimateAlg.config.outputTrackParameters,
0580 inputSimSeeds=seeds,
0581 inputSimHits="simhits",
0582 inputMeasurementParticlesMap="measurement_particles_map",
0583 inputMeasurementSimHitsMap="measurement_simhits_map",
0584 outputDir=str(outputDirCsv),
0585 fileName=str(f"seed.csv"),
0586 )
0587 s.addWriter(csvSeedWriter)
0588
0589 if seedingAlgorithm == SeedingAlgorithm.Hashing:
0590 s.addWriter(
0591 acts.examples.CsvSpacePointsBucketWriter(
0592 level=logLevel,
0593 inputBuckets=buckets,
0594 outputDir=str(outputDirCsv),
0595 )
0596 )
0597
0598 return s
0599
0600
0601 def addTruthSmearedSeeding(
0602 s: acts.examples.Sequencer,
0603 rnd: Optional[acts.examples.RandomNumbers],
0604 selectedParticles: str,
0605 trackSmearingSigmas: TrackSmearingSigmas,
0606 initialSigmas: Optional[List[float]],
0607 initialSigmaQoverPt: Optional[float],
0608 initialSigmaPtRel: Optional[float],
0609 initialVarInflation: Optional[List[float]],
0610 particleHypothesis: Optional[acts.ParticleHypothesis],
0611 logLevel: acts.logging.Level = None,
0612 ):
0613 """adds algorithm that would mimic detector response uncertainties for truth seeding
0614 For parameters description see addSeeding
0615 """
0616
0617 rnd = rnd or acts.examples.RandomNumbers(seed=42)
0618
0619 trkParamExtractor = acts.examples.ParticleTrackParamExtractor(
0620 level=logLevel,
0621 inputParticles=selectedParticles,
0622 outputTrackParameters="trueparameters",
0623 )
0624 s.addAlgorithm(trkParamExtractor)
0625
0626
0627 trkSmear = acts.examples.TrackParameterSmearing(
0628 level=logLevel,
0629 inputTrackParameters=trkParamExtractor.config.outputTrackParameters,
0630 outputTrackParameters="estimatedparameters",
0631 randomNumbers=rnd,
0632
0633 **acts.examples.defaultKWArgs(
0634 sigmaLoc0=trackSmearingSigmas.loc0,
0635 sigmaLoc0PtA=trackSmearingSigmas.loc0PtA,
0636 sigmaLoc0PtB=trackSmearingSigmas.loc0PtB,
0637 sigmaLoc1=trackSmearingSigmas.loc1,
0638 sigmaLoc1PtA=trackSmearingSigmas.loc1PtA,
0639 sigmaLoc1PtB=trackSmearingSigmas.loc1PtB,
0640 sigmaTime=trackSmearingSigmas.time,
0641 sigmaPhi=trackSmearingSigmas.phi,
0642 sigmaTheta=trackSmearingSigmas.theta,
0643 sigmaPtRel=trackSmearingSigmas.ptRel,
0644 initialSigmas=initialSigmas,
0645 initialSigmaQoverPt=initialSigmaQoverPt,
0646 initialSigmaPtRel=initialSigmaPtRel,
0647 initialVarInflation=initialVarInflation,
0648 particleHypothesis=particleHypothesis,
0649 ),
0650 )
0651 s.addAlgorithm(trkSmear)
0652
0653 truthTrkFndAlg = acts.examples.TruthTrackFinder(
0654 level=logLevel,
0655 inputParticles=selectedParticles,
0656 inputMeasurements="measurements",
0657 inputParticleMeasurementsMap="particle_measurements_map",
0658 inputSimHits="simhits",
0659 inputMeasurementSimHitsMap="measurement_simhits_map",
0660 outputProtoTracks="truth_particle_tracks",
0661 )
0662 s.addAlgorithm(truthTrkFndAlg)
0663
0664
0665 def addTruthEstimatedSeeding(
0666 sequence: acts.examples.Sequencer,
0667 spacePoints: str,
0668 inputParticles: str,
0669 TruthEstimatedSeedingAlgorithmConfigArg: TruthEstimatedSeedingAlgorithmConfigArg,
0670 particleHypothesis: Optional[acts.ParticleHypothesis] = None,
0671 logLevel: acts.logging.Level = None,
0672 ):
0673 """adds truth seeding
0674 For parameters description see addSeeding
0675 """
0676 logLevel = acts.examples.defaultLogging(sequence, logLevel)()
0677
0678 truthSeeding = acts.examples.TruthSeedingAlgorithm(
0679 level=logLevel,
0680 inputParticles=inputParticles,
0681 inputParticleMeasurementsMap="particle_measurements_map",
0682 inputSpacePoints=[spacePoints],
0683 inputSimHits="simhits",
0684 inputMeasurementSimHitsMap="measurement_simhits_map",
0685 outputParticles="truth_seeded_particles",
0686 outputProtoTracks="truth_particle_tracks",
0687 outputSeeds="seeds",
0688 outputParticleHypotheses="seed_particle_hypotheses",
0689 **acts.examples.defaultKWArgs(
0690 deltaRMin=TruthEstimatedSeedingAlgorithmConfigArg.deltaR[0],
0691 deltaRMax=TruthEstimatedSeedingAlgorithmConfigArg.deltaR[1],
0692 particleHypothesis=particleHypothesis,
0693 ),
0694 )
0695 sequence.addAlgorithm(truthSeeding)
0696
0697 return truthSeeding.config.outputSeeds, truthSeeding.config.outputParticleHypotheses
0698
0699
0700 def addSpacePointsMaking(
0701 sequence: acts.examples.Sequencer,
0702 trackingGeometry: acts.TrackingGeometry,
0703 geoSelectionConfigFile: Union[Path, str],
0704 stripGeoSelectionConfigFile: Union[Path, str],
0705 logLevel: acts.logging.Level = None,
0706 ):
0707 """adds space points making
0708 For parameters description see addSeeding
0709 """
0710 logLevel = acts.examples.defaultLogging(sequence, logLevel)()
0711 spAlg = acts.examples.SpacePointMaker(
0712 level=logLevel,
0713 inputMeasurements="measurements",
0714 outputSpacePoints="spacepoints",
0715 trackingGeometry=trackingGeometry,
0716 geometrySelection=acts.examples.json.readJsonGeometryList(
0717 str(geoSelectionConfigFile)
0718 ),
0719 stripGeometrySelection=(
0720 acts.examples.json.readJsonGeometryList(str(stripGeoSelectionConfigFile))
0721 if stripGeoSelectionConfigFile
0722 else []
0723 ),
0724 )
0725 sequence.addAlgorithm(spAlg)
0726 return spAlg.config.outputSpacePoints
0727
0728
0729 def addStandardSeeding(
0730 sequence: acts.examples.Sequencer,
0731 spacePoints: str,
0732 seedingAlgorithmConfigArg: SeedingAlgorithmConfigArg,
0733 seedFinderConfigArg: SeedFinderConfigArg,
0734 seedFinderOptionsArg: SeedFinderOptionsArg,
0735 seedFilterConfigArg: SeedFilterConfigArg,
0736 spacePointGridConfigArg: SpacePointGridConfigArg,
0737 logLevel: acts.logging.Level = None,
0738 outputSeeds: str = "seeds",
0739 ):
0740 """adds standard seeding
0741 For parameters description see addSeeding
0742 """
0743 logLevel = acts.examples.defaultLogging(sequence, logLevel)()
0744
0745 seedFinderConfig = acts.examples.SeedFinderConfig(
0746 **acts.examples.defaultKWArgs(
0747 rMin=seedFinderConfigArg.r[0],
0748 rMax=seedFinderConfigArg.r[1],
0749 deltaRMin=seedFinderConfigArg.deltaR[0],
0750 deltaRMax=seedFinderConfigArg.deltaR[1],
0751 deltaRMinTopSP=(
0752 seedFinderConfigArg.deltaR[0]
0753 if seedFinderConfigArg.deltaRTopSP[0] is None
0754 else seedFinderConfigArg.deltaRTopSP[0]
0755 ),
0756 deltaRMaxTopSP=(
0757 seedFinderConfigArg.deltaR[1]
0758 if seedFinderConfigArg.deltaRTopSP[1] is None
0759 else seedFinderConfigArg.deltaRTopSP[1]
0760 ),
0761 deltaRMinBottomSP=(
0762 seedFinderConfigArg.deltaR[0]
0763 if seedFinderConfigArg.deltaRBottomSP[0] is None
0764 else seedFinderConfigArg.deltaRBottomSP[0]
0765 ),
0766 deltaRMaxBottomSP=(
0767 seedFinderConfigArg.deltaR[1]
0768 if seedFinderConfigArg.deltaRBottomSP[1] is None
0769 else seedFinderConfigArg.deltaRBottomSP[1]
0770 ),
0771 deltaRMiddleMinSPRange=seedFinderConfigArg.deltaRMiddleSPRange[0],
0772 deltaRMiddleMaxSPRange=seedFinderConfigArg.deltaRMiddleSPRange[1],
0773 collisionRegionMin=seedFinderConfigArg.collisionRegion[0],
0774 collisionRegionMax=seedFinderConfigArg.collisionRegion[1],
0775 zMin=seedFinderConfigArg.z[0],
0776 zMax=seedFinderConfigArg.z[1],
0777 maxSeedsPerSpM=seedFinderConfigArg.maxSeedsPerSpM,
0778 cotThetaMax=seedFinderConfigArg.cotThetaMax,
0779 sigmaScattering=seedFinderConfigArg.sigmaScattering,
0780 radLengthPerSeed=seedFinderConfigArg.radLengthPerSeed,
0781 minPt=seedFinderConfigArg.minPt,
0782 impactMax=seedFinderConfigArg.impactMax,
0783 interactionPointCut=seedFinderConfigArg.interactionPointCut,
0784 deltaZMax=seedFinderConfigArg.deltaZMax,
0785 maxPtScattering=seedFinderConfigArg.maxPtScattering,
0786 zBinEdges=seedFinderConfigArg.zBinEdges,
0787 zBinsCustomLooping=seedFinderConfigArg.zBinsCustomLooping,
0788 rRangeMiddleSP=seedFinderConfigArg.rRangeMiddleSP,
0789 useVariableMiddleSPRange=seedFinderConfigArg.useVariableMiddleSPRange,
0790 binSizeR=seedFinderConfigArg.binSizeR,
0791 seedConfirmation=seedFinderConfigArg.seedConfirmation,
0792 centralSeedConfirmationRange=seedFinderConfigArg.centralSeedConfirmationRange,
0793 forwardSeedConfirmationRange=seedFinderConfigArg.forwardSeedConfirmationRange,
0794 ),
0795 )
0796 seedFinderOptions = acts.SeedFinderOptions(
0797 **acts.examples.defaultKWArgs(
0798 beamPos=(
0799 acts.Vector2(0.0, 0.0)
0800 if seedFinderOptionsArg.beamPos == (None, None)
0801 else acts.Vector2(
0802 seedFinderOptionsArg.beamPos[0], seedFinderOptionsArg.beamPos[1]
0803 )
0804 ),
0805 bFieldInZ=seedFinderOptionsArg.bFieldInZ,
0806 )
0807 )
0808 seedFilterConfig = acts.SeedFilterConfig(
0809 **acts.examples.defaultKWArgs(
0810 maxSeedsPerSpM=seedFinderConfig.maxSeedsPerSpM,
0811 deltaRMin=(
0812 seedFinderConfig.deltaRMin
0813 if seedFilterConfigArg.deltaRMin is None
0814 else seedFilterConfigArg.deltaRMin
0815 ),
0816 impactWeightFactor=seedFilterConfigArg.impactWeightFactor,
0817 zOriginWeightFactor=seedFilterConfigArg.zOriginWeightFactor,
0818 compatSeedWeight=seedFilterConfigArg.compatSeedWeight,
0819 compatSeedLimit=seedFilterConfigArg.compatSeedLimit,
0820 numSeedIncrement=seedFilterConfigArg.numSeedIncrement,
0821 seedWeightIncrement=seedFilterConfigArg.seedWeightIncrement,
0822 seedConfirmation=seedFilterConfigArg.seedConfirmation,
0823 centralSeedConfirmationRange=seedFinderConfig.centralSeedConfirmationRange,
0824 forwardSeedConfirmationRange=seedFinderConfig.forwardSeedConfirmationRange,
0825 maxSeedsPerSpMConf=seedFilterConfigArg.maxSeedsPerSpMConf,
0826 maxQualitySeedsPerSpMConf=seedFilterConfigArg.maxQualitySeedsPerSpMConf,
0827 useDeltaRorTopRadius=seedFilterConfigArg.useDeltaRorTopRadius,
0828 )
0829 )
0830
0831 gridConfig = acts.SpacePointGridConfig(
0832 **acts.examples.defaultKWArgs(
0833 minPt=seedFinderConfig.minPt,
0834 rMax=(
0835 seedFinderConfig.rMax
0836 if spacePointGridConfigArg.rMax is None
0837 else spacePointGridConfigArg.rMax
0838 ),
0839 zMax=seedFinderConfig.zMax,
0840 zMin=seedFinderConfig.zMin,
0841 deltaRMax=(
0842 seedFinderConfig.deltaRMax
0843 if spacePointGridConfigArg.deltaRMax is None
0844 else spacePointGridConfigArg.deltaRMax
0845 ),
0846 cotThetaMax=seedFinderConfig.cotThetaMax,
0847 phiMin=spacePointGridConfigArg.phi[0],
0848 phiMax=spacePointGridConfigArg.phi[1],
0849 maxPhiBins=spacePointGridConfigArg.maxPhiBins,
0850 impactMax=spacePointGridConfigArg.impactMax,
0851 zBinEdges=spacePointGridConfigArg.zBinEdges,
0852 phiBinDeflectionCoverage=spacePointGridConfigArg.phiBinDeflectionCoverage,
0853 )
0854 )
0855
0856 gridOptions = acts.SpacePointGridOptions(
0857 **acts.examples.defaultKWArgs(
0858 bFieldInZ=seedFinderOptions.bFieldInZ,
0859 )
0860 )
0861
0862 seedingAlg = acts.examples.SeedingAlgorithm(
0863 level=logLevel,
0864 inputSpacePoints=[spacePoints],
0865 outputSeeds=outputSeeds,
0866 **acts.examples.defaultKWArgs(
0867 allowSeparateRMax=seedingAlgorithmConfigArg.allowSeparateRMax,
0868 zBinNeighborsTop=seedingAlgorithmConfigArg.zBinNeighborsTop,
0869 zBinNeighborsBottom=seedingAlgorithmConfigArg.zBinNeighborsBottom,
0870 numPhiNeighbors=seedingAlgorithmConfigArg.numPhiNeighbors,
0871 useExtraCuts=seedingAlgorithmConfigArg.useExtraCuts,
0872 ),
0873 gridConfig=gridConfig,
0874 gridOptions=gridOptions,
0875 seedFilterConfig=seedFilterConfig,
0876 seedFinderConfig=seedFinderConfig,
0877 seedFinderOptions=seedFinderOptions,
0878 )
0879 sequence.addAlgorithm(seedingAlg)
0880
0881 return seedingAlg.config.outputSeeds
0882
0883
0884 def addGridTripletSeeding(
0885 sequence: acts.examples.Sequencer,
0886 spacePoints: str,
0887 seedingAlgorithmConfigArg: SeedingAlgorithmConfigArg,
0888 seedFinderConfigArg: SeedFinderConfigArg,
0889 seedFinderOptionsArg: SeedFinderOptionsArg,
0890 seedFilterConfigArg: SeedFilterConfigArg,
0891 spacePointGridConfigArg: SpacePointGridConfigArg,
0892 logLevel: acts.logging.Level = None,
0893 outputSeeds: str = "seeds",
0894 ):
0895 """adds grid triplet seeding
0896 For parameters description see addSeeding
0897 """
0898 logLevel = acts.examples.defaultLogging(sequence, logLevel)()
0899
0900 seedingAlg = acts.examples.GridTripletSeedingAlgorithm(
0901 level=logLevel,
0902 inputSpacePoints=spacePoints,
0903 outputSeeds=outputSeeds,
0904 **acts.examples.defaultKWArgs(
0905 bFieldInZ=seedFinderOptionsArg.bFieldInZ,
0906 minPt=seedFinderConfigArg.minPt,
0907 cotThetaMax=seedFinderConfigArg.cotThetaMax,
0908 impactMax=seedFinderConfigArg.impactMax,
0909 deltaRMin=seedFinderConfigArg.deltaR[0],
0910 deltaRMax=seedFinderConfigArg.deltaR[1],
0911 deltaRMinTop=(
0912 seedFinderConfigArg.deltaR[0]
0913 if seedFinderConfigArg.deltaRTopSP[0] is None
0914 else seedFinderConfigArg.deltaRTopSP[0]
0915 ),
0916 deltaRMaxTop=(
0917 seedFinderConfigArg.deltaR[1]
0918 if seedFinderConfigArg.deltaRTopSP[1] is None
0919 else seedFinderConfigArg.deltaRTopSP[1]
0920 ),
0921 deltaRMinBottom=(
0922 seedFinderConfigArg.deltaR[0]
0923 if seedFinderConfigArg.deltaRBottomSP[0] is None
0924 else seedFinderConfigArg.deltaRBottomSP[0]
0925 ),
0926 deltaRMaxBottom=(
0927 seedFinderConfigArg.deltaR[1]
0928 if seedFinderConfigArg.deltaRBottomSP[1] is None
0929 else seedFinderConfigArg.deltaRBottomSP[1]
0930 ),
0931 rMin=seedFinderConfigArg.r[0],
0932 rMax=seedFinderConfigArg.r[1],
0933 zMin=seedFinderConfigArg.z[0],
0934 zMax=seedFinderConfigArg.z[1],
0935 phiMin=spacePointGridConfigArg.phi[0],
0936 phiMax=spacePointGridConfigArg.phi[1],
0937 phiBinDeflectionCoverage=spacePointGridConfigArg.phiBinDeflectionCoverage,
0938 maxPhiBins=spacePointGridConfigArg.maxPhiBins,
0939 zBinEdges=spacePointGridConfigArg.zBinEdges,
0940 zBinsCustomLooping=seedFinderConfigArg.zBinsCustomLooping,
0941 rMinMiddle=None,
0942 rMaxMiddle=None,
0943 useVariableMiddleSPRange=seedFinderConfigArg.useVariableMiddleSPRange,
0944 rRangeMiddleSP=seedFinderConfigArg.rRangeMiddleSP,
0945 deltaRMiddleMinSPRange=seedFinderConfigArg.deltaRMiddleSPRange[0],
0946 deltaRMiddleMaxSPRange=seedFinderConfigArg.deltaRMiddleSPRange[1],
0947 deltaZMin=None,
0948 deltaZMax=None,
0949 interactionPointCut=seedFinderConfigArg.interactionPointCut,
0950 collisionRegionMin=seedFinderConfigArg.collisionRegion[0],
0951 collisionRegionMax=seedFinderConfigArg.collisionRegion[1],
0952 helixCutTolerance=None,
0953 sigmaScattering=seedFinderConfigArg.sigmaScattering,
0954 radLengthPerSeed=seedFinderConfigArg.radLengthPerSeed,
0955 toleranceParam=None,
0956 deltaInvHelixDiameter=None,
0957 compatSeedWeight=seedFilterConfigArg.compatSeedWeight,
0958 impactWeightFactor=seedFilterConfigArg.impactWeightFactor,
0959 zOriginWeightFactor=seedFilterConfigArg.zOriginWeightFactor,
0960 maxSeedsPerSpM=seedFinderConfigArg.maxSeedsPerSpM,
0961 compatSeedLimit=seedFilterConfigArg.compatSeedLimit,
0962 seedWeightIncrement=seedFilterConfigArg.seedWeightIncrement,
0963 numSeedIncrement=seedFilterConfigArg.numSeedIncrement,
0964 seedConfirmation=seedFinderConfigArg.seedConfirmation,
0965 centralSeedConfirmationRange=seedFinderConfigArg.centralSeedConfirmationRange,
0966 forwardSeedConfirmationRange=seedFinderConfigArg.forwardSeedConfirmationRange,
0967 maxSeedsPerSpMConf=seedFilterConfigArg.maxSeedsPerSpMConf,
0968 maxQualitySeedsPerSpMConf=seedFilterConfigArg.maxQualitySeedsPerSpMConf,
0969 useDeltaRinsteadOfTopRadius=seedFilterConfigArg.useDeltaRorTopRadius,
0970 useExtraCuts=seedingAlgorithmConfigArg.useExtraCuts,
0971 ),
0972 )
0973 sequence.addAlgorithm(seedingAlg)
0974
0975 return seedingAlg.config.outputSeeds
0976
0977
0978 def addOrthogonalTripletSeeding(
0979 sequence: acts.examples.Sequencer,
0980 spacePoints: str,
0981 seedingAlgorithmConfigArg: SeedingAlgorithmConfigArg,
0982 seedFinderConfigArg: SeedFinderConfigArg,
0983 seedFinderOptionsArg: SeedFinderOptionsArg,
0984 seedFilterConfigArg: SeedFilterConfigArg,
0985 spacePointGridConfigArg: SpacePointGridConfigArg,
0986 logLevel: acts.logging.Level = None,
0987 outputSeeds: str = "seeds",
0988 ):
0989 """adds orthogonal triplet seeding
0990 For parameters description see addSeeding
0991 """
0992 logLevel = acts.examples.defaultLogging(sequence, logLevel)()
0993
0994 seedingAlg = acts.examples.OrthogonalTripletSeedingAlgorithm(
0995 level=logLevel,
0996 inputSpacePoints=spacePoints,
0997 outputSeeds=outputSeeds,
0998 **acts.examples.defaultKWArgs(
0999 bFieldInZ=seedFinderOptionsArg.bFieldInZ,
1000 minPt=seedFinderConfigArg.minPt,
1001 cotThetaMax=seedFinderConfigArg.cotThetaMax,
1002 impactMax=seedFinderConfigArg.impactMax,
1003 deltaRMin=seedFinderConfigArg.deltaR[0],
1004 deltaRMax=seedFinderConfigArg.deltaR[1],
1005 deltaRMinTop=(
1006 seedFinderConfigArg.deltaR[0]
1007 if seedFinderConfigArg.deltaRTopSP[0] is None
1008 else seedFinderConfigArg.deltaRTopSP[0]
1009 ),
1010 deltaRMaxTop=(
1011 seedFinderConfigArg.deltaR[1]
1012 if seedFinderConfigArg.deltaRTopSP[1] is None
1013 else seedFinderConfigArg.deltaRTopSP[1]
1014 ),
1015 deltaRMinBottom=(
1016 seedFinderConfigArg.deltaR[0]
1017 if seedFinderConfigArg.deltaRBottomSP[0] is None
1018 else seedFinderConfigArg.deltaRBottomSP[0]
1019 ),
1020 deltaRMaxBottom=(
1021 seedFinderConfigArg.deltaR[1]
1022 if seedFinderConfigArg.deltaRBottomSP[1] is None
1023 else seedFinderConfigArg.deltaRBottomSP[1]
1024 ),
1025 rMin=seedFinderConfigArg.r[0],
1026 rMax=seedFinderConfigArg.r[1],
1027 zMin=seedFinderConfigArg.z[0],
1028 zMax=seedFinderConfigArg.z[1],
1029 phiMin=spacePointGridConfigArg.phi[0],
1030 phiMax=spacePointGridConfigArg.phi[1],
1031 phiBinDeflectionCoverage=spacePointGridConfigArg.phiBinDeflectionCoverage,
1032 maxPhiBins=spacePointGridConfigArg.maxPhiBins,
1033 zBinEdges=spacePointGridConfigArg.zBinEdges,
1034 zBinsCustomLooping=seedFinderConfigArg.zBinsCustomLooping,
1035 rMinMiddle=None,
1036 rMaxMiddle=None,
1037 useVariableMiddleSPRange=seedFinderConfigArg.useVariableMiddleSPRange,
1038 rRangeMiddleSP=seedFinderConfigArg.rRangeMiddleSP,
1039 deltaRMiddleMinSPRange=seedFinderConfigArg.deltaRMiddleSPRange[0],
1040 deltaRMiddleMaxSPRange=seedFinderConfigArg.deltaRMiddleSPRange[1],
1041 deltaZMin=None,
1042 deltaZMax=None,
1043 interactionPointCut=seedFinderConfigArg.interactionPointCut,
1044 collisionRegionMin=seedFinderConfigArg.collisionRegion[0],
1045 collisionRegionMax=seedFinderConfigArg.collisionRegion[1],
1046 helixCutTolerance=None,
1047 sigmaScattering=seedFinderConfigArg.sigmaScattering,
1048 radLengthPerSeed=seedFinderConfigArg.radLengthPerSeed,
1049 toleranceParam=None,
1050 deltaInvHelixDiameter=None,
1051 compatSeedWeight=seedFilterConfigArg.compatSeedWeight,
1052 impactWeightFactor=seedFilterConfigArg.impactWeightFactor,
1053 zOriginWeightFactor=seedFilterConfigArg.zOriginWeightFactor,
1054 maxSeedsPerSpM=seedFinderConfigArg.maxSeedsPerSpM,
1055 compatSeedLimit=seedFilterConfigArg.compatSeedLimit,
1056 seedWeightIncrement=seedFilterConfigArg.seedWeightIncrement,
1057 numSeedIncrement=seedFilterConfigArg.numSeedIncrement,
1058 seedConfirmation=seedFinderConfigArg.seedConfirmation,
1059 centralSeedConfirmationRange=seedFinderConfigArg.centralSeedConfirmationRange,
1060 forwardSeedConfirmationRange=seedFinderConfigArg.forwardSeedConfirmationRange,
1061 maxSeedsPerSpMConf=seedFilterConfigArg.maxSeedsPerSpMConf,
1062 maxQualitySeedsPerSpMConf=seedFilterConfigArg.maxQualitySeedsPerSpMConf,
1063 useDeltaRinsteadOfTopRadius=seedFilterConfigArg.useDeltaRorTopRadius,
1064 useExtraCuts=seedingAlgorithmConfigArg.useExtraCuts,
1065 ),
1066 )
1067 sequence.addAlgorithm(seedingAlg)
1068
1069 return seedingAlg.config.outputSeeds
1070
1071
1072 def addOrthogonalSeeding(
1073 sequence: acts.examples.Sequencer,
1074 spacePoints: str,
1075 seedFinderConfigArg: SeedFinderConfigArg,
1076 seedFinderOptionsArg: SeedFinderOptionsArg,
1077 seedFilterConfigArg: SeedFilterConfigArg,
1078 logLevel: acts.logging.Level = None,
1079 ):
1080 """adds orthogonal seeding algorithm
1081 For parameters description see addSeeding
1082 """
1083 logLevel = acts.examples.defaultLogging(sequence, logLevel)()
1084 seedFinderConfig = acts.examples.SeedFinderOrthogonalConfig(
1085 **acts.examples.defaultKWArgs(
1086 rMin=seedFinderConfigArg.r[0],
1087 rMax=seedFinderConfigArg.r[1],
1088 deltaRMinTopSP=(
1089 seedFinderConfigArg.deltaR[0]
1090 if seedFinderConfigArg.deltaRTopSP[0] is None
1091 else seedFinderConfigArg.deltaRTopSP[0]
1092 ),
1093 deltaRMaxTopSP=(
1094 seedFinderConfigArg.deltaR[1]
1095 if seedFinderConfigArg.deltaRTopSP[1] is None
1096 else seedFinderConfigArg.deltaRTopSP[1]
1097 ),
1098 deltaRMinBottomSP=(
1099 seedFinderConfigArg.deltaR[0]
1100 if seedFinderConfigArg.deltaRBottomSP[0] is None
1101 else seedFinderConfigArg.deltaRBottomSP[0]
1102 ),
1103 deltaRMaxBottomSP=(
1104 seedFinderConfigArg.deltaR[1]
1105 if seedFinderConfigArg.deltaRBottomSP[1] is None
1106 else seedFinderConfigArg.deltaRBottomSP[1]
1107 ),
1108 collisionRegionMin=seedFinderConfigArg.collisionRegion[0],
1109 collisionRegionMax=seedFinderConfigArg.collisionRegion[1],
1110 zMin=seedFinderConfigArg.z[0],
1111 zMax=seedFinderConfigArg.z[1],
1112 maxSeedsPerSpM=seedFinderConfigArg.maxSeedsPerSpM,
1113 cotThetaMax=seedFinderConfigArg.cotThetaMax,
1114 sigmaScattering=seedFinderConfigArg.sigmaScattering,
1115 radLengthPerSeed=seedFinderConfigArg.radLengthPerSeed,
1116 minPt=seedFinderConfigArg.minPt,
1117 impactMax=seedFinderConfigArg.impactMax,
1118 deltaPhiMax=seedFinderConfigArg.deltaPhiMax,
1119 interactionPointCut=seedFinderConfigArg.interactionPointCut,
1120 deltaZMax=seedFinderConfigArg.deltaZMax,
1121 maxPtScattering=seedFinderConfigArg.maxPtScattering,
1122 rRangeMiddleSP=seedFinderConfigArg.rRangeMiddleSP,
1123 useVariableMiddleSPRange=seedFinderConfigArg.useVariableMiddleSPRange,
1124 seedConfirmation=seedFinderConfigArg.seedConfirmation,
1125 centralSeedConfirmationRange=seedFinderConfigArg.centralSeedConfirmationRange,
1126 forwardSeedConfirmationRange=seedFinderConfigArg.forwardSeedConfirmationRange,
1127 ),
1128 )
1129 seedFinderOptions = acts.SeedFinderOptions(
1130 **acts.examples.defaultKWArgs(
1131 beamPos=(
1132 acts.Vector2(0.0, 0.0)
1133 if seedFinderOptionsArg.beamPos == (None, None)
1134 else acts.Vector2(
1135 seedFinderOptionsArg.beamPos[0], seedFinderOptionsArg.beamPos[1]
1136 )
1137 ),
1138 bFieldInZ=seedFinderOptionsArg.bFieldInZ,
1139 )
1140 )
1141 seedFilterConfig = acts.SeedFilterConfig(
1142 **acts.examples.defaultKWArgs(
1143 maxSeedsPerSpM=seedFinderConfig.maxSeedsPerSpM,
1144 deltaRMin=(
1145 seedFinderConfigArg.deltaR[0]
1146 if seedFilterConfigArg.deltaRMin is None
1147 else seedFilterConfigArg.deltaRMin
1148 ),
1149 impactWeightFactor=seedFilterConfigArg.impactWeightFactor,
1150 zOriginWeightFactor=seedFilterConfigArg.zOriginWeightFactor,
1151 compatSeedWeight=seedFilterConfigArg.compatSeedWeight,
1152 compatSeedLimit=seedFilterConfigArg.compatSeedLimit,
1153 numSeedIncrement=seedFilterConfigArg.numSeedIncrement,
1154 seedWeightIncrement=seedFilterConfigArg.seedWeightIncrement,
1155 seedConfirmation=seedFilterConfigArg.seedConfirmation,
1156 maxSeedsPerSpMConf=seedFilterConfigArg.maxSeedsPerSpMConf,
1157 maxQualitySeedsPerSpMConf=seedFilterConfigArg.maxQualitySeedsPerSpMConf,
1158 useDeltaRorTopRadius=seedFilterConfigArg.useDeltaRorTopRadius,
1159 )
1160 )
1161 seedingAlg = acts.examples.SeedingOrthogonalAlgorithm(
1162 level=logLevel,
1163 inputSpacePoints=[spacePoints],
1164 outputSeeds="seeds",
1165 seedFilterConfig=seedFilterConfig,
1166 seedFinderConfig=seedFinderConfig,
1167 seedFinderOptions=seedFinderOptions,
1168 )
1169 sequence.addAlgorithm(seedingAlg)
1170
1171 return seedingAlg.config.outputSeeds
1172
1173
1174 def addHashingSeeding(
1175 sequence: acts.examples.Sequencer,
1176 spacePoints: str,
1177 seedingAlgorithmConfigArg: SeedingAlgorithmConfigArg,
1178 seedFinderConfigArg: SeedFinderConfigArg,
1179 seedFinderOptionsArg: SeedFinderOptionsArg,
1180 seedFilterConfigArg: SeedFilterConfigArg,
1181 spacePointGridConfigArg: SpacePointGridConfigArg,
1182 hashingTrainingConfigArg: HashingTrainingConfigArg,
1183 hashingAlgorithmConfigArg: HashingAlgorithmConfigArg,
1184 logLevel: acts.logging.Level = None,
1185 ):
1186 """adds Hashing seeding
1187 For parameters description see addSeeding docstring
1188 """
1189 logLevel = acts.examples.defaultLogging(sequence, logLevel)()
1190 from acts.examples.hashing import SeedingAlgorithmHashing
1191
1192
1193 seedFinderConfig = acts.examples.SeedFinderConfig(
1194 **acts.examples.defaultKWArgs(
1195 rMin=seedFinderConfigArg.r[0],
1196 rMax=seedFinderConfigArg.r[1],
1197 deltaRMin=seedFinderConfigArg.deltaR[0],
1198 deltaRMax=seedFinderConfigArg.deltaR[1],
1199 deltaRMinTopSP=(
1200 seedFinderConfigArg.deltaR[0]
1201 if seedFinderConfigArg.deltaRTopSP[0] is None
1202 else seedFinderConfigArg.deltaRTopSP[0]
1203 ),
1204 deltaRMaxTopSP=(
1205 seedFinderConfigArg.deltaR[1]
1206 if seedFinderConfigArg.deltaRTopSP[1] is None
1207 else seedFinderConfigArg.deltaRTopSP[1]
1208 ),
1209 deltaRMinBottomSP=(
1210 seedFinderConfigArg.deltaR[0]
1211 if seedFinderConfigArg.deltaRBottomSP[0] is None
1212 else seedFinderConfigArg.deltaRBottomSP[0]
1213 ),
1214 deltaRMaxBottomSP=(
1215 seedFinderConfigArg.deltaR[1]
1216 if seedFinderConfigArg.deltaRBottomSP[1] is None
1217 else seedFinderConfigArg.deltaRBottomSP[1]
1218 ),
1219 deltaRMiddleMinSPRange=seedFinderConfigArg.deltaRMiddleSPRange[0],
1220 deltaRMiddleMaxSPRange=seedFinderConfigArg.deltaRMiddleSPRange[1],
1221 collisionRegionMin=seedFinderConfigArg.collisionRegion[0],
1222 collisionRegionMax=seedFinderConfigArg.collisionRegion[1],
1223 zMin=seedFinderConfigArg.z[0],
1224 zMax=seedFinderConfigArg.z[1],
1225 maxSeedsPerSpM=seedFinderConfigArg.maxSeedsPerSpM,
1226 cotThetaMax=seedFinderConfigArg.cotThetaMax,
1227 sigmaScattering=seedFinderConfigArg.sigmaScattering,
1228 radLengthPerSeed=seedFinderConfigArg.radLengthPerSeed,
1229 minPt=seedFinderConfigArg.minPt,
1230 impactMax=seedFinderConfigArg.impactMax,
1231 interactionPointCut=seedFinderConfigArg.interactionPointCut,
1232 deltaZMax=seedFinderConfigArg.deltaZMax,
1233 maxPtScattering=seedFinderConfigArg.maxPtScattering,
1234 zBinEdges=seedFinderConfigArg.zBinEdges,
1235 zBinsCustomLooping=seedFinderConfigArg.zBinsCustomLooping,
1236 rRangeMiddleSP=seedFinderConfigArg.rRangeMiddleSP,
1237 useVariableMiddleSPRange=seedFinderConfigArg.useVariableMiddleSPRange,
1238 binSizeR=seedFinderConfigArg.binSizeR,
1239 seedConfirmation=seedFinderConfigArg.seedConfirmation,
1240 centralSeedConfirmationRange=seedFinderConfigArg.centralSeedConfirmationRange,
1241 forwardSeedConfirmationRange=seedFinderConfigArg.forwardSeedConfirmationRange,
1242 ),
1243 )
1244 seedFinderOptions = acts.SeedFinderOptions(
1245 **acts.examples.defaultKWArgs(
1246 beamPos=(
1247 acts.Vector2(0.0, 0.0)
1248 if seedFinderOptionsArg.beamPos == (None, None)
1249 else acts.Vector2(
1250 seedFinderOptionsArg.beamPos[0], seedFinderOptionsArg.beamPos[1]
1251 )
1252 ),
1253 bFieldInZ=seedFinderOptionsArg.bFieldInZ,
1254 )
1255 )
1256 seedFilterConfig = acts.SeedFilterConfig(
1257 **acts.examples.defaultKWArgs(
1258 maxSeedsPerSpM=seedFinderConfig.maxSeedsPerSpM,
1259 deltaRMin=(
1260 seedFinderConfig.deltaRMin
1261 if seedFilterConfigArg.deltaRMin is None
1262 else seedFilterConfigArg.deltaRMin
1263 ),
1264 impactWeightFactor=seedFilterConfigArg.impactWeightFactor,
1265 zOriginWeightFactor=seedFilterConfigArg.zOriginWeightFactor,
1266 compatSeedWeight=seedFilterConfigArg.compatSeedWeight,
1267 compatSeedLimit=seedFilterConfigArg.compatSeedLimit,
1268 numSeedIncrement=seedFilterConfigArg.numSeedIncrement,
1269 seedWeightIncrement=seedFilterConfigArg.seedWeightIncrement,
1270 seedConfirmation=seedFilterConfigArg.seedConfirmation,
1271 centralSeedConfirmationRange=seedFinderConfig.centralSeedConfirmationRange,
1272 forwardSeedConfirmationRange=seedFinderConfig.forwardSeedConfirmationRange,
1273 maxSeedsPerSpMConf=seedFilterConfigArg.maxSeedsPerSpMConf,
1274 maxQualitySeedsPerSpMConf=seedFilterConfigArg.maxQualitySeedsPerSpMConf,
1275 useDeltaRorTopRadius=seedFilterConfigArg.useDeltaRorTopRadius,
1276 )
1277 )
1278
1279 gridConfig = acts.SpacePointGridConfig(
1280 **acts.examples.defaultKWArgs(
1281 minPt=seedFinderConfig.minPt,
1282 rMax=(
1283 seedFinderConfig.rMax
1284 if spacePointGridConfigArg.rMax is None
1285 else spacePointGridConfigArg.rMax
1286 ),
1287 zMax=seedFinderConfig.zMax,
1288 zMin=seedFinderConfig.zMin,
1289 deltaRMax=(
1290 seedFinderConfig.deltaRMax
1291 if spacePointGridConfigArg.deltaRMax is None
1292 else spacePointGridConfigArg.deltaRMax
1293 ),
1294 cotThetaMax=seedFinderConfig.cotThetaMax,
1295 phiMin=spacePointGridConfigArg.phi[0],
1296 phiMax=spacePointGridConfigArg.phi[1],
1297 maxPhiBins=spacePointGridConfigArg.maxPhiBins,
1298 impactMax=spacePointGridConfigArg.impactMax,
1299 zBinEdges=spacePointGridConfigArg.zBinEdges,
1300 phiBinDeflectionCoverage=spacePointGridConfigArg.phiBinDeflectionCoverage,
1301 )
1302 )
1303
1304 gridOptions = acts.SpacePointGridOptions(
1305 **acts.examples.defaultKWArgs(
1306 bFieldInZ=seedFinderOptions.bFieldInZ,
1307 )
1308 )
1309
1310
1311 hashingTrainingConfig = acts.hashing.HashingTrainingConfig(
1312 **acts.examples.defaultKWArgs(
1313 annoySeed=hashingTrainingConfigArg.annoySeed,
1314 f=hashingTrainingConfigArg.f,
1315 ),
1316 )
1317
1318 hashingConfig = acts.hashing.HashingAlgorithmConfig(
1319 **acts.examples.defaultKWArgs(
1320 bucketSize=hashingAlgorithmConfigArg.bucketSize,
1321 zBins=hashingAlgorithmConfigArg.zBins,
1322 phiBins=hashingAlgorithmConfigArg.phiBins,
1323 ),
1324 )
1325
1326
1327 seedingAlg = SeedingAlgorithmHashing(
1328 level=logLevel,
1329 inputSpacePoints=[spacePoints],
1330 outputSeeds="seeds",
1331 outputBuckets="buckets",
1332 **acts.examples.defaultKWArgs(
1333 allowSeparateRMax=seedingAlgorithmConfigArg.allowSeparateRMax,
1334 zBinNeighborsTop=seedingAlgorithmConfigArg.zBinNeighborsTop,
1335 zBinNeighborsBottom=seedingAlgorithmConfigArg.zBinNeighborsBottom,
1336 numPhiNeighbors=seedingAlgorithmConfigArg.numPhiNeighbors,
1337 ),
1338 gridConfig=gridConfig,
1339 gridOptions=gridOptions,
1340 seedFilterConfig=seedFilterConfig,
1341 seedFinderConfig=seedFinderConfig,
1342 seedFinderOptions=seedFinderOptions,
1343 hashingConfig=hashingConfig,
1344 hashingTrainingConfig=hashingTrainingConfig,
1345 )
1346 sequence.addAlgorithm(seedingAlg)
1347
1348 return seedingAlg.config.outputSeeds, seedingAlg.config.outputBuckets
1349
1350
1351 def addHoughTransformSeeding(
1352 sequence: acts.examples.Sequencer,
1353 config: acts.examples.HoughTransformSeeder.Config,
1354 logLevel: acts.logging.Level = None,
1355 ):
1356 """
1357 Configures HoughTransform (HT) for seeding, instead of extra proxy config objects it takes
1358 directly the HT example algorithm config.
1359 """
1360 logLevel = acts.examples.defaultLogging(sequence, logLevel)()
1361 ht = acts.examples.HoughTransformSeeder(config=config, level=logLevel)
1362 sequence.addAlgorithm(ht)
1363
1364
1365 return ht.config.outputSeeds
1366
1367
1368 def addAdaptiveHoughTransformSeeding(
1369 sequence: acts.examples.Sequencer,
1370 config: acts.examples.AdaptiveHoughTransformSeeder.Config,
1371 logLevel: acts.logging.Level = None,
1372 ):
1373 """
1374 Configures AdaptiveHoughTransform (AHT) for seeding, instead of extra proxy config objects it takes
1375 directly the AHT example algorithm config.
1376 """
1377 logLevel = acts.examples.defaultLogging(sequence, logLevel)()
1378 ht = acts.examples.AdaptiveHoughTransformSeeder(config=config, level=logLevel)
1379 sequence.addAlgorithm(ht)
1380
1381
1382 return ht.config.outputSeeds
1383
1384
1385 def addGbtsSeeding(
1386 sequence: acts.examples.Sequencer,
1387 spacePoints: str,
1388 seedFinderConfigArg: SeedFinderConfigArg,
1389 seedFinderOptionsArg: SeedFinderOptionsArg,
1390 trackingGeometry: acts.TrackingGeometry,
1391 logLevel: acts.logging.Level = None,
1392 layerMappingConfigFile: Union[Path, str] = None,
1393 geoSelectionConfigFile: Union[Path, str] = None,
1394 ConnectorInputConfigFile: Union[Path, str] = None,
1395 ):
1396 """Gbts seeding"""
1397
1398 logLevel = acts.examples.defaultLogging(sequence, logLevel)()
1399 layerMappingFile = str(layerMappingConfigFile)
1400 ConnectorInputFileStr = str(ConnectorInputConfigFile)
1401 seedFinderConfig = acts.examples.SeedFinderGbtsConfig(
1402 **acts.examples.defaultKWArgs(
1403 minPt=seedFinderConfigArg.minPt, ConnectorInputFile=ConnectorInputFileStr
1404 ),
1405 )
1406 seedFinderOptions = acts.SeedFinderOptions(
1407 **acts.examples.defaultKWArgs(
1408 beamPos=(
1409 acts.Vector2(0.0, 0.0)
1410 if seedFinderOptionsArg.beamPos == (None, None)
1411 else acts.Vector2(
1412 seedFinderOptionsArg.beamPos[0], seedFinderOptionsArg.beamPos[1]
1413 )
1414 ),
1415 bFieldInZ=seedFinderOptionsArg.bFieldInZ,
1416 )
1417 )
1418
1419 seedingAlg = acts.examples.GbtsSeedingAlgorithm(
1420 level=logLevel,
1421 inputSpacePoints=spacePoints,
1422 outputSeeds="seeds",
1423 seedFinderConfig=seedFinderConfig,
1424 seedFinderOptions=seedFinderOptions,
1425 layerMappingFile=layerMappingFile,
1426 trackingGeometry=trackingGeometry,
1427 fill_module_csv=False,
1428 inputClusters="clusters",
1429 )
1430
1431 sequence.addAlgorithm(seedingAlg)
1432 return seedingAlg.config.outputSeeds
1433
1434
1435 def addSeedPerformanceWriters(
1436 sequence: acts.examples.Sequencer,
1437 outputDirRoot: Union[Path, str],
1438 tracks: str,
1439 prototracks: str,
1440 selectedParticles: str,
1441 inputParticles: str,
1442 outputTrackParameters: str,
1443 logLevel: acts.logging.Level = None,
1444 ):
1445 """Writes seeding related performance output"""
1446 customLogLevel = acts.examples.defaultLogging(sequence, logLevel)
1447 outputDirRoot = Path(outputDirRoot)
1448 if not outputDirRoot.exists():
1449 outputDirRoot.mkdir()
1450
1451 sequence.addWriter(
1452 acts.examples.root.RootTrackFinderPerformanceWriter(
1453 level=customLogLevel(),
1454 inputTracks=tracks,
1455 inputParticles=selectedParticles,
1456 inputTrackParticleMatching="seed_particle_matching",
1457 inputParticleTrackMatching="particle_seed_matching",
1458 inputParticleMeasurementsMap="particle_measurements_map",
1459 filePath=str(outputDirRoot / f"performance_seeding.root"),
1460 )
1461 )
1462
1463 sequence.addWriter(
1464 acts.examples.root.RootTrackParameterWriter(
1465 level=customLogLevel(),
1466 inputTrackParameters=outputTrackParameters,
1467 inputProtoTracks=prototracks,
1468 inputParticles=inputParticles,
1469 inputSimHits="simhits",
1470 inputMeasurementParticlesMap="measurement_particles_map",
1471 inputMeasurementSimHitsMap="measurement_simhits_map",
1472 filePath=str(outputDirRoot / "estimatedparams.root"),
1473 treeName="estimatedparams",
1474 )
1475 )
1476
1477
1478 acts.examples.NamedTypeArgs(
1479 config=SeedFilterMLDBScanConfig,
1480 )
1481
1482
1483 def addSeedFilterML(
1484 s,
1485 config: SeedFilterMLDBScanConfig = SeedFilterMLDBScanConfig(),
1486 onnxModelFile: Optional[Union[Path, str]] = None,
1487 logLevel: Optional[acts.logging.Level] = None,
1488 outputDirRoot: Optional[Union[Path, str]] = None,
1489 outputDirCsv: Optional[Union[Path, str]] = None,
1490 ) -> None:
1491 customLogLevel = acts.examples.defaultLogging(s, logLevel)()
1492 from acts.examples.onnx import SeedFilterMLAlgorithm
1493
1494 inputParticles = "particles"
1495 selectedParticles = "particles_selected"
1496 seeds = "seeds"
1497 estParams = "estimatedparameters"
1498 prototracks = "seed-prototracks-ML"
1499 tracks = "seed-tracks-ML"
1500
1501 filterML = SeedFilterMLAlgorithm(
1502 level=customLogLevel,
1503 inputTrackParameters="estimatedparameters",
1504 inputSimSeeds="seeds",
1505 inputSeedFilterNN=onnxModelFile,
1506 outputTrackParameters="filtered-parameters",
1507 outputSimSeeds="filtered-seeds",
1508 **acts.examples.defaultKWArgs(
1509 epsilonDBScan=config.epsilonDBScan,
1510 minPointsDBScan=config.minPointsDBScan,
1511 minSeedScore=config.minSeedScore,
1512 ),
1513 )
1514 s.addAlgorithm(filterML)
1515 s.addWhiteboardAlias(seeds, "filtered-seeds")
1516 s.addWhiteboardAlias("estimatedparameters", "filtered-parameters")
1517
1518 s.addAlgorithm(
1519 acts.examples.SeedsToPrototracks(
1520 level=customLogLevel,
1521 inputSeeds=seeds,
1522 outputProtoTracks=prototracks,
1523 )
1524 )
1525
1526 s.addAlgorithm(
1527 acts.examples.PrototracksToTracks(
1528 level=customLogLevel,
1529 inputProtoTracks=prototracks,
1530 inputTrackParameters="estimatedparameters",
1531 outputTracks=tracks,
1532 )
1533 )
1534
1535 s.addAlgorithm(
1536 acts.examples.TrackTruthMatcher(
1537 level=customLogLevel,
1538 inputTracks=tracks,
1539 inputParticles=selectedParticles,
1540 inputMeasurementParticlesMap="measurement_particles_map",
1541 outputTrackParticleMatching="seed_particle_matching",
1542 outputParticleTrackMatching="particle_seed_matching",
1543 matchingRatio=1.0,
1544 doubleMatching=False,
1545 )
1546 )
1547
1548 if outputDirRoot is not None:
1549 addSeedPerformanceWriters(
1550 s,
1551 outputDirRoot,
1552 tracks,
1553 selectedParticles,
1554 inputParticles,
1555 estParams,
1556 customLogLevel,
1557 )
1558
1559 if outputDirCsv is not None:
1560 outputDirCsv = Path(outputDirCsv)
1561
1562 if not outputDirCsv.exists():
1563 outputDirCsv.mkdir()
1564
1565 csvSeedWriter = acts.examples.CsvSeedWriter(
1566 level=customLogLevel,
1567 inputTrackParameters=estParams,
1568 inputSimSeeds=seeds,
1569 inputSimHits="simhits",
1570 inputMeasurementParticlesMap="measurement_particles_map",
1571 inputMeasurementSimHitsMap="measurement_simhits_map",
1572 outputDir=str(outputDirCsv),
1573 fileName=str(f"seed.csv"),
1574 )
1575 s.addWriter(csvSeedWriter)
1576
1577 return s
1578
1579
1580 def addKalmanTracks(
1581 s: acts.examples.Sequencer,
1582 trackingGeometry: acts.TrackingGeometry,
1583 field: acts.MagneticFieldProvider,
1584 reverseFilteringMomThreshold: float = 0 * u.GeV,
1585 reverseFilteringCovarianceScaling: float = 1.0,
1586 inputProtoTracks: str = "truth_particle_tracks",
1587 multipleScattering: bool = True,
1588 energyLoss: bool = True,
1589 clusters: str = None,
1590 calibrator: acts.examples.MeasurementCalibrator = acts.examples.makePassThroughCalibrator(),
1591 logLevel: Optional[acts.logging.Level] = None,
1592 ) -> None:
1593 customLogLevel = acts.examples.defaultLogging(s, logLevel)
1594
1595 kalmanOptions = {
1596 "multipleScattering": multipleScattering,
1597 "energyLoss": energyLoss,
1598 "reverseFilteringMomThreshold": reverseFilteringMomThreshold,
1599 "reverseFilteringCovarianceScaling": reverseFilteringCovarianceScaling,
1600 "freeToBoundCorrection": acts.examples.FreeToBoundCorrection(False),
1601 "level": customLogLevel(),
1602 "chi2Cut": float("inf"),
1603 }
1604
1605 fitAlg = acts.examples.TrackFittingAlgorithm(
1606 level=customLogLevel(),
1607 inputMeasurements="measurements",
1608 inputProtoTracks=inputProtoTracks,
1609 inputInitialTrackParameters="estimatedparameters",
1610 inputClusters=clusters if clusters is not None else "",
1611 outputTracks="kf_tracks",
1612 pickTrack=-1,
1613 fit=acts.examples.makeKalmanFitterFunction(
1614 trackingGeometry, field, **kalmanOptions
1615 ),
1616 calibrator=calibrator,
1617 )
1618 s.addAlgorithm(fitAlg)
1619 s.addWhiteboardAlias("tracks", fitAlg.config.outputTracks)
1620
1621 matchAlg = acts.examples.TrackTruthMatcher(
1622 level=customLogLevel(),
1623 inputTracks=fitAlg.config.outputTracks,
1624 inputParticles="particles",
1625 inputMeasurementParticlesMap="measurement_particles_map",
1626 outputTrackParticleMatching="kf_track_particle_matching",
1627 outputParticleTrackMatching="kf_particle_track_matching",
1628 doubleMatching=True,
1629 )
1630 s.addAlgorithm(matchAlg)
1631 s.addWhiteboardAlias(
1632 "track_particle_matching", matchAlg.config.outputTrackParticleMatching
1633 )
1634 s.addWhiteboardAlias(
1635 "particle_track_matching", matchAlg.config.outputParticleTrackMatching
1636 )
1637
1638 return s
1639
1640
1641 def addTruthTrackingGsf(
1642 s: acts.examples.Sequencer,
1643 trackingGeometry: acts.TrackingGeometry,
1644 field: acts.MagneticFieldProvider,
1645 inputProtoTracks: str = "truth_particle_tracks",
1646 logLevel: Optional[acts.logging.Level] = None,
1647 ) -> None:
1648 customLogLevel = acts.examples.defaultLogging(s, logLevel)
1649
1650
1651
1652
1653 bha = acts.examples.AtlasBetheHeitlerApprox.makeDefault(clampToRange=True)
1654
1655 gsfOptions = {
1656 "betheHeitlerApprox": bha,
1657 "maxComponents": 12,
1658 "componentMergeMethod": acts.examples.ComponentMergeMethod.maxWeight,
1659 "mixtureReductionAlgorithm": acts.examples.MixtureReductionAlgorithm.KLDistance,
1660 "weightCutoff": 1.0e-4,
1661 "reverseFilteringCovarianceScaling": 100.0,
1662 "level": customLogLevel(),
1663 }
1664
1665 gsfAlg = acts.examples.TrackFittingAlgorithm(
1666 level=customLogLevel(),
1667 inputMeasurements="measurements",
1668 inputProtoTracks=inputProtoTracks,
1669 inputInitialTrackParameters="estimatedparameters",
1670 outputTracks="gsf_tracks",
1671 pickTrack=-1,
1672 fit=acts.examples.makeGsfFitterFunction(trackingGeometry, field, **gsfOptions),
1673 calibrator=acts.examples.makePassThroughCalibrator(),
1674 )
1675 s.addAlgorithm(gsfAlg)
1676 s.addWhiteboardAlias("tracks", gsfAlg.config.outputTracks)
1677
1678 matchAlg = acts.examples.TrackTruthMatcher(
1679 level=customLogLevel(),
1680 inputTracks=gsfAlg.config.outputTracks,
1681 inputParticles="particles",
1682 inputMeasurementParticlesMap="measurement_particles_map",
1683 outputTrackParticleMatching="gsf_track_particle_matching",
1684 outputParticleTrackMatching="gsf_particle_track_matching",
1685 doubleMatching=True,
1686 )
1687 s.addAlgorithm(matchAlg)
1688 s.addWhiteboardAlias(
1689 "track_particle_matching", matchAlg.config.outputTrackParticleMatching
1690 )
1691 s.addWhiteboardAlias(
1692 "particle_track_matching", matchAlg.config.outputParticleTrackMatching
1693 )
1694
1695 return s
1696
1697
1698 @acts.examples.NamedTypeArgs(
1699 trackSelectorConfig=TrackSelectorConfig,
1700 ckfConfig=CkfConfig,
1701 )
1702 def addCKFTracks(
1703 s: acts.examples.Sequencer,
1704 trackingGeometry: acts.TrackingGeometry,
1705 field: acts.MagneticFieldProvider,
1706 trackSelectorConfig: Optional[
1707 Union[TrackSelectorConfig, List[TrackSelectorConfig]]
1708 ] = None,
1709 ckfConfig: CkfConfig = CkfConfig(),
1710 twoWay: bool = True,
1711 reverseSearch: bool = False,
1712 outputDirCsv: Optional[Union[Path, str]] = None,
1713 outputDirRoot: Optional[Union[Path, str]] = None,
1714 writeTrackSummary: bool = True,
1715 writeTrackStates: bool = False,
1716 writePerformance: bool = True,
1717 writeCovMat=False,
1718 logLevel: Optional[acts.logging.Level] = None,
1719 ) -> None:
1720 """This function steers the seeding
1721
1722 Parameters
1723 ----------
1724 s: Sequencer
1725 the sequencer module to which we add the Seeding steps (returned from addSeeding)
1726 trackingGeometry : tracking geometry
1727 field : magnetic field
1728 outputDirCsv : Path|str, path, None
1729 the output folder for the Csv output, None triggers no output
1730 outputDirRoot : Path|str, path, None
1731 the output folder for ROOT output, None triggers no output
1732 trackSelectorConfig : TrackSelectorConfig(loc0, loc1, time, eta, absEta, pt, phi, minMeasurements)
1733 TrackSelector configuration. Each range is specified as a tuple of (min,max).
1734 Specify as a list(TrackSelectorConfig) for eta-dependent cuts, with binning specified by absEta[1].
1735 Defaults of no cuts specified in Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/TrackSelector.hpp
1736 writeTrackSummary : bool, True
1737 write tracksummary_ckf.root ntuple?
1738 writeTrackStates : bool, False
1739 write trackstates_ckf.root ntuple? This can be quite large.
1740 writePerformance : bool, True
1741 write performance_fitting_ckf.root and performance_finding_ckf.root ntuples?
1742 writeCovMat : bool, False
1743 write covaraiance matrices to tracksummary_ckf.root ntuple?
1744 """
1745
1746 customLogLevel = acts.examples.defaultLogging(s, logLevel)
1747
1748 tslist = (
1749 []
1750 if trackSelectorConfig is None
1751 else (
1752 [trackSelectorConfig]
1753 if type(trackSelectorConfig) is TrackSelectorConfig
1754 else trackSelectorConfig
1755 )
1756 )
1757
1758 if len(tslist) > 1:
1759 cutSets = []
1760 for c in tslist:
1761 defKW = trackSelectorDefaultKWArgs(c)
1762 defKW.pop("absEtaMax", None)
1763 cutSets += [acts.TrackSelector.Config(**(defKW))]
1764 else:
1765 cutSets = [
1766 acts.TrackSelector.Config(**(trackSelectorDefaultKWArgs(c))) for c in tslist
1767 ]
1768
1769 if len(tslist) == 0:
1770 trkSelCfg = None
1771 elif len(tslist) == 1:
1772 trkSelCfg = cutSets[0]
1773 else:
1774 trkSelCfg = acts.TrackSelector.EtaBinnedConfig(
1775 cutSets=cutSets,
1776 absEtaEdges=[cutSets[0].absEtaMin] + [c.absEta[1] for c in tslist],
1777 )
1778
1779
1780
1781
1782 trackFinder = acts.examples.TrackFindingAlgorithm(
1783 level=customLogLevel(),
1784 measurementSelectorCfg=acts.MeasurementSelector.Config(
1785 [
1786 (
1787 acts.GeometryIdentifier(),
1788 (
1789 [],
1790 [ckfConfig.chi2CutOffMeasurement],
1791 [ckfConfig.chi2CutOffOutlier],
1792 [ckfConfig.numMeasurementsCutOff],
1793 ),
1794 )
1795 ]
1796 ),
1797 inputMeasurements="measurements",
1798 inputInitialTrackParameters="estimatedparameters",
1799 inputSeeds=(
1800 "estimatedseeds"
1801 if ckfConfig.seedDeduplication or ckfConfig.stayOnSeed
1802 else ""
1803 ),
1804 outputTracks="ckf_tracks",
1805 findTracks=acts.examples.TrackFindingAlgorithm.makeTrackFinderFunction(
1806 trackingGeometry, field, customLogLevel()
1807 ),
1808 **acts.examples.defaultKWArgs(
1809 trackingGeometry=trackingGeometry,
1810 magneticField=field,
1811 trackSelectorCfg=trkSelCfg,
1812 maxSteps=ckfConfig.maxSteps,
1813 twoWay=twoWay,
1814 reverseSearch=reverseSearch,
1815 seedDeduplication=ckfConfig.seedDeduplication,
1816 stayOnSeed=ckfConfig.stayOnSeed,
1817 pixelVolumeIds=ckfConfig.pixelVolumes,
1818 stripVolumeIds=ckfConfig.stripVolumes,
1819 maxPixelHoles=ckfConfig.maxPixelHoles,
1820 maxStripHoles=ckfConfig.maxStripHoles,
1821 trimTracks=ckfConfig.trimTracks,
1822 constrainToVolumeIds=ckfConfig.constrainToVolumes,
1823 endOfWorldVolumeIds=ckfConfig.endOfWorldVolumes,
1824 ),
1825 )
1826 s.addAlgorithm(trackFinder)
1827 s.addWhiteboardAlias("tracks", trackFinder.config.outputTracks)
1828
1829 matchAlg = acts.examples.TrackTruthMatcher(
1830 level=customLogLevel(),
1831 inputTracks=trackFinder.config.outputTracks,
1832 inputParticles="particles_selected",
1833 inputMeasurementParticlesMap="measurement_particles_map",
1834 outputTrackParticleMatching="ckf_track_particle_matching",
1835 outputParticleTrackMatching="ckf_particle_track_matching",
1836 doubleMatching=True,
1837 )
1838 s.addAlgorithm(matchAlg)
1839 s.addWhiteboardAlias(
1840 "track_particle_matching", matchAlg.config.outputTrackParticleMatching
1841 )
1842 s.addWhiteboardAlias(
1843 "particle_track_matching", matchAlg.config.outputParticleTrackMatching
1844 )
1845
1846 addTrackWriters(
1847 s,
1848 name="ckf",
1849 tracks=trackFinder.config.outputTracks,
1850 outputDirCsv=outputDirCsv,
1851 outputDirRoot=outputDirRoot,
1852 writeSummary=writeTrackSummary,
1853 writeStates=writeTrackStates,
1854 writeFitterPerformance=writePerformance,
1855 writeFinderPerformance=writePerformance,
1856 writeCovMat=writeCovMat,
1857 logLevel=logLevel,
1858 )
1859
1860 return s
1861
1862
1863 def addGx2fTracks(
1864 s: acts.examples.Sequencer,
1865 trackingGeometry: acts.TrackingGeometry,
1866 field: acts.MagneticFieldProvider,
1867 inputProtoTracks: str = "truth_particle_tracks",
1868 multipleScattering: bool = False,
1869 energyLoss: bool = False,
1870 nUpdateMax: int = 5,
1871 relChi2changeCutOff: float = 1e-7,
1872 clusters: str = None,
1873 calibrator: acts.examples.MeasurementCalibrator = acts.examples.makePassThroughCalibrator(),
1874 logLevel: Optional[acts.logging.Level] = None,
1875 ) -> None:
1876 customLogLevel = acts.examples.defaultLogging(s, logLevel)
1877
1878 gx2fOptions = {
1879 "multipleScattering": multipleScattering,
1880 "energyLoss": energyLoss,
1881 "freeToBoundCorrection": acts.examples.FreeToBoundCorrection(False),
1882 "nUpdateMax": nUpdateMax,
1883 "relChi2changeCutOff": relChi2changeCutOff,
1884 "level": customLogLevel(),
1885 }
1886
1887 fitAlg = acts.examples.TrackFittingAlgorithm(
1888 level=customLogLevel(),
1889 inputMeasurements="measurements",
1890 inputProtoTracks=inputProtoTracks,
1891 inputInitialTrackParameters="estimatedparameters",
1892 inputClusters=clusters if clusters is not None else "",
1893 outputTracks="gx2f_tracks",
1894 pickTrack=-1,
1895 fit=acts.examples.makeGlobalChiSquareFitterFunction(
1896 trackingGeometry, field, **gx2fOptions
1897 ),
1898 calibrator=calibrator,
1899 )
1900 s.addAlgorithm(fitAlg)
1901 s.addWhiteboardAlias("tracks", fitAlg.config.outputTracks)
1902
1903 matchAlg = acts.examples.TrackTruthMatcher(
1904 level=customLogLevel(),
1905 inputTracks=fitAlg.config.outputTracks,
1906 inputParticles="particles",
1907 inputMeasurementParticlesMap="measurement_particles_map",
1908 outputTrackParticleMatching="gx2f_track_particle_matching",
1909 outputParticleTrackMatching="gx2f_particle_track_matching",
1910 doubleMatching=True,
1911 )
1912 s.addAlgorithm(matchAlg)
1913 s.addWhiteboardAlias(
1914 "track_particle_matching", matchAlg.config.outputTrackParticleMatching
1915 )
1916 s.addWhiteboardAlias(
1917 "particle_track_matching", matchAlg.config.outputParticleTrackMatching
1918 )
1919
1920 return s
1921
1922
1923 def addTrackWriters(
1924 s: acts.examples.Sequencer,
1925 name: str,
1926 tracks: str = "tracks",
1927 outputDirCsv: Optional[Union[Path, str]] = None,
1928 outputDirRoot: Optional[Union[Path, str]] = None,
1929 writeSummary: bool = True,
1930 writeStates: bool = False,
1931 writeFitterPerformance: bool = False,
1932 writeFinderPerformance: bool = False,
1933 logLevel: Optional[acts.logging.Level] = None,
1934 writeCovMat=False,
1935 ):
1936 customLogLevel = acts.examples.defaultLogging(s, logLevel)
1937
1938 if outputDirRoot is not None:
1939 outputDirRoot = Path(outputDirRoot)
1940 if not outputDirRoot.exists():
1941 outputDirRoot.mkdir()
1942
1943 if writeSummary:
1944 trackSummaryWriter = acts.examples.root.RootTrackSummaryWriter(
1945 level=customLogLevel(),
1946 inputTracks=tracks,
1947 inputParticles="particles_selected",
1948 inputTrackParticleMatching="track_particle_matching",
1949 filePath=str(outputDirRoot / f"tracksummary_{name}.root"),
1950 treeName="tracksummary",
1951 writeCovMat=writeCovMat,
1952 )
1953 s.addWriter(trackSummaryWriter)
1954
1955 if writeStates:
1956 trackStatesWriter = acts.examples.root.RootTrackStatesWriter(
1957 level=customLogLevel(),
1958 inputTracks=tracks,
1959 inputParticles="particles_selected",
1960 inputTrackParticleMatching="track_particle_matching",
1961 inputSimHits="simhits",
1962 inputMeasurementSimHitsMap="measurement_simhits_map",
1963 filePath=str(outputDirRoot / f"trackstates_{name}.root"),
1964 treeName="trackstates",
1965 )
1966 s.addWriter(trackStatesWriter)
1967
1968 if writeFitterPerformance:
1969 trackFitterPerformanceWriter = (
1970 acts.examples.root.RootTrackFitterPerformanceWriter(
1971 level=customLogLevel(),
1972 inputTracks=tracks,
1973 inputParticles="particles_selected",
1974 inputTrackParticleMatching="track_particle_matching",
1975 filePath=str(outputDirRoot / f"performance_fitting_{name}.root"),
1976 )
1977 )
1978 s.addWriter(trackFitterPerformanceWriter)
1979
1980 if writeFinderPerformance:
1981 trackFinderPerfWriter = acts.examples.root.RootTrackFinderPerformanceWriter(
1982 level=customLogLevel(),
1983 inputTracks=tracks,
1984 inputParticles="particles_selected",
1985 inputTrackParticleMatching="track_particle_matching",
1986 inputParticleTrackMatching="particle_track_matching",
1987 inputParticleMeasurementsMap="particle_measurements_map",
1988 filePath=str(outputDirRoot / f"performance_finding_{name}.root"),
1989 )
1990 s.addWriter(trackFinderPerfWriter)
1991
1992 if outputDirCsv is not None:
1993 outputDirCsv = Path(outputDirCsv)
1994 if not outputDirCsv.exists():
1995 outputDirCsv.mkdir()
1996
1997 if writeSummary:
1998 csvWriter = acts.examples.CsvTrackWriter(
1999 level=customLogLevel(),
2000 inputTracks=tracks,
2001 inputMeasurementParticlesMap="measurement_particles_map",
2002 outputDir=str(outputDirCsv),
2003 fileName=str(f"tracks_{name}.csv"),
2004 )
2005 s.addWriter(csvWriter)
2006
2007 trackParameterWriter = acts.examples.CsvTrackParameterWriter(
2008 level=customLogLevel(),
2009 inputTracks=tracks,
2010 outputDir=str(outputDirCsv),
2011 outputStem=str(f"track_parameters_{name}"),
2012 )
2013 s.addWriter(trackParameterWriter)
2014
2015
2016 @acts.examples.NamedTypeArgs(
2017 trackSelectorConfig=TrackSelectorConfig,
2018 )
2019 def addTrackSelection(
2020 s: acts.examples.Sequencer,
2021 trackSelectorConfig: TrackSelectorConfig,
2022 inputTracks: str,
2023 outputTracks: str,
2024 logLevel: Optional[acts.logging.Level] = None,
2025 ) -> acts.examples.TrackSelectorAlgorithm:
2026 customLogLevel = acts.examples.defaultLogging(s, logLevel)
2027
2028
2029 selectorConfig = acts.TrackSelector.Config(
2030 **trackSelectorDefaultKWArgs(trackSelectorConfig)
2031 )
2032
2033 trackSelector = acts.examples.TrackSelectorAlgorithm(
2034 level=customLogLevel(),
2035 inputTracks=inputTracks,
2036 outputTracks=outputTracks,
2037 selectorConfig=selectorConfig,
2038 )
2039
2040 s.addAlgorithm(trackSelector)
2041
2042 return trackSelector
2043
2044
2045 GnnBackend = Enum("GnnBackend", "Torch Onnx")
2046
2047
2048 def addGnn(
2049 s: acts.examples.Sequencer,
2050 graphConstructor,
2051 edgeClassifiers: list,
2052 trackBuilder,
2053 nodeFeatures: list,
2054 featureScales: list,
2055 inputSpacePoints: str = "spacepoints",
2056 inputClusters: str = "",
2057 outputDirRoot: Optional[Union[Path, str]] = None,
2058 logLevel: Optional[acts.logging.Level] = None,
2059 ) -> acts.examples.Sequencer:
2060 """
2061 Add GNN track finding with custom stage implementations.
2062
2063 This is a flexible low-level API that accepts pre-configured GNN stage components.
2064 For examples of how to configure stages, see gnn_metric_learning.py and gnn_module_map.py.
2065
2066 Args:
2067 s: Sequencer to add algorithms to
2068 graphConstructor: Graph construction stage (TorchMetricLearning, ModuleMapCuda, etc.)
2069 edgeClassifiers: List of edge classification stages (run sequentially)
2070 trackBuilder: Track building stage (BoostTrackBuilding, CudaTrackBuilding, etc.)
2071 nodeFeatures: List of node features to extract from spacepoints/clusters
2072 featureScales: Scaling factors for each feature
2073 trackingGeometry: Optional tracking geometry for creating spacepoints
2074 geometrySelection: Optional geometry selection file for spacepoint creation
2075 inputSpacePoints: Name of input spacepoint collection (default: "spacepoints")
2076 inputClusters: Name of input cluster collection (default: "")
2077 outputDirRoot: Optional output directory for performance ROOT files
2078 logLevel: Logging level
2079
2080 Note:
2081 The trackingGeometry parameter serves two distinct purposes depending on the workflow:
2082 1. Spacepoint creation: When provided along with geometrySelection, creates spacepoints
2083 from measurements using SpacePointMaker (typical for simulation workflows)
2084 2. Module map usage: Some graph constructors (e.g., ModuleMapCuda) require
2085 trackingGeometry to map module IDs even when using pre-existing spacepoints
2086 """
2087 customLogLevel = acts.examples.defaultLogging(s, logLevel)
2088
2089
2090 if len(nodeFeatures) != len(featureScales):
2091 raise ValueError(
2092 f"nodeFeatures and featureScales must have the same length "
2093 f"(got {len(nodeFeatures)} and {len(featureScales)})"
2094 )
2095
2096
2097 findingAlg = acts.examples.gnn.TrackFindingAlgorithmGnn(
2098 level=customLogLevel(),
2099 inputSpacePoints=inputSpacePoints,
2100 inputClusters=inputClusters,
2101 outputProtoTracks="gnn_prototracks",
2102 graphConstructor=graphConstructor,
2103 edgeClassifiers=edgeClassifiers,
2104 trackBuilder=trackBuilder,
2105 nodeFeatures=nodeFeatures,
2106 featureScales=featureScales,
2107 )
2108 s.addAlgorithm(findingAlg)
2109 s.addWhiteboardAlias("prototracks", findingAlg.config.outputProtoTracks)
2110
2111
2112 s.addAlgorithm(
2113 acts.examples.PrototracksToTracks(
2114 level=customLogLevel(),
2115 inputProtoTracks="prototracks",
2116 inputMeasurements="measurements",
2117 outputTracks="tracks",
2118 )
2119 )
2120
2121
2122 matchAlg = acts.examples.TrackTruthMatcher(
2123 level=customLogLevel(),
2124 inputTracks="tracks",
2125 inputParticles="particles",
2126 inputMeasurementParticlesMap="measurement_particles_map",
2127 outputTrackParticleMatching="gnn_track_particle_matching",
2128 outputParticleTrackMatching="gnn_particle_track_matching",
2129 doubleMatching=True,
2130 )
2131 s.addAlgorithm(matchAlg)
2132 s.addWhiteboardAlias(
2133 "track_particle_matching", matchAlg.config.outputTrackParticleMatching
2134 )
2135 s.addWhiteboardAlias(
2136 "particle_track_matching", matchAlg.config.outputParticleTrackMatching
2137 )
2138
2139
2140 if outputDirRoot is not None:
2141 s.addWriter(
2142 acts.examples.root.RootTrackFinderNTupleWriter(
2143 level=customLogLevel(),
2144 inputTracks="tracks",
2145 inputParticles="particles",
2146 inputParticleMeasurementsMap="particle_measurements_map",
2147 inputTrackParticleMatching=matchAlg.config.outputTrackParticleMatching,
2148 filePath=str(Path(outputDirRoot) / "performance_track_finding.root"),
2149 )
2150 )
2151
2152 return s
2153
2154
2155 @acts.examples.NamedTypeArgs(
2156 config=AmbiguityResolutionConfig,
2157 )
2158 def addAmbiguityResolution(
2159 s,
2160 config: AmbiguityResolutionConfig = AmbiguityResolutionConfig(),
2161 tracks: str = "tracks",
2162 outputDirCsv: Optional[Union[Path, str]] = None,
2163 outputDirRoot: Optional[Union[Path, str]] = None,
2164 writeTrackSummary: bool = True,
2165 writeTrackStates: bool = False,
2166 writePerformance: bool = True,
2167 writeCovMat=False,
2168 logLevel: Optional[acts.logging.Level] = None,
2169 ) -> None:
2170 from acts.examples import GreedyAmbiguityResolutionAlgorithm
2171
2172 customLogLevel = acts.examples.defaultLogging(s, logLevel)
2173
2174 alg = GreedyAmbiguityResolutionAlgorithm(
2175 level=customLogLevel(),
2176 inputTracks=tracks,
2177 outputTracks="ambi_tracks",
2178 **acts.examples.defaultKWArgs(
2179 maximumSharedHits=config.maximumSharedHits,
2180 nMeasurementsMin=config.nMeasurementsMin,
2181 maximumIterations=config.maximumIterations,
2182 ),
2183 )
2184 s.addAlgorithm(alg)
2185 s.addWhiteboardAlias("tracks", alg.config.outputTracks)
2186
2187 matchAlg = acts.examples.TrackTruthMatcher(
2188 level=customLogLevel(),
2189 inputTracks=alg.config.outputTracks,
2190 inputParticles="particles",
2191 inputMeasurementParticlesMap="measurement_particles_map",
2192 outputTrackParticleMatching="ambi_track_particle_matching",
2193 outputParticleTrackMatching="ambi_particle_track_matching",
2194 doubleMatching=True,
2195 )
2196 s.addAlgorithm(matchAlg)
2197 s.addWhiteboardAlias(
2198 "track_particle_matching", matchAlg.config.outputTrackParticleMatching
2199 )
2200 s.addWhiteboardAlias(
2201 "particle_track_matching", matchAlg.config.outputParticleTrackMatching
2202 )
2203
2204 addTrackWriters(
2205 s,
2206 name="ambi",
2207 tracks=alg.config.outputTracks,
2208 outputDirCsv=outputDirCsv,
2209 outputDirRoot=outputDirRoot,
2210 writeSummary=writeTrackSummary,
2211 writeStates=writeTrackStates,
2212 writeFitterPerformance=writePerformance,
2213 writeFinderPerformance=writePerformance,
2214 writeCovMat=writeCovMat,
2215 logLevel=logLevel,
2216 )
2217
2218 return s
2219
2220
2221 @acts.examples.NamedTypeArgs(
2222 config=ScoreBasedAmbiguityResolutionConfig,
2223 )
2224 def addScoreBasedAmbiguityResolution(
2225 s,
2226 config: ScoreBasedAmbiguityResolutionConfig = ScoreBasedAmbiguityResolutionConfig(),
2227 tracks: str = "tracks",
2228 outputDirCsv: Optional[Union[Path, str]] = None,
2229 outputDirRoot: Optional[Union[Path, str]] = None,
2230 ambiVolumeFile: Optional[Union[Path, str]] = None,
2231 writeTrackSummary: bool = True,
2232 writeTrackStates: bool = False,
2233 writePerformance: bool = True,
2234 writeCovMat=False,
2235 logLevel: Optional[acts.logging.Level] = None,
2236 ) -> None:
2237 from acts.examples import ScoreBasedAmbiguityResolutionAlgorithm
2238
2239 customLogLevel = acts.examples.defaultLogging(s, acts.logging.INFO)
2240
2241 algScoreBased = ScoreBasedAmbiguityResolutionAlgorithm(
2242 level=customLogLevel(),
2243 inputTracks=tracks,
2244 configFile=ambiVolumeFile,
2245 outputTracks="ambiTracksScoreBased",
2246 **acts.examples.defaultKWArgs(
2247 minScore=config.minScore,
2248 minScoreSharedTracks=config.minScoreSharedTracks,
2249 maxShared=config.maxShared,
2250 minUnshared=config.minUnshared,
2251 maxSharedTracksPerMeasurement=config.maxSharedTracksPerMeasurement,
2252 useAmbiguityScoring=config.useAmbiguityScoring,
2253 ),
2254 )
2255 s.addAlgorithm(algScoreBased)
2256 s.addWhiteboardAlias("tracks", algScoreBased.config.outputTracks)
2257
2258 matchAlg = acts.examples.TrackTruthMatcher(
2259 level=customLogLevel(),
2260 inputTracks=algScoreBased.config.outputTracks,
2261 inputParticles="particles",
2262 inputMeasurementParticlesMap="measurement_particles_map",
2263 outputTrackParticleMatching="ambi_scorebased_track_particle_matching",
2264 outputParticleTrackMatching="ambi_scorebased_particle_track_matching",
2265 doubleMatching=True,
2266 )
2267 s.addAlgorithm(matchAlg)
2268 s.addWhiteboardAlias(
2269 "track_particle_matching", matchAlg.config.outputTrackParticleMatching
2270 )
2271 s.addWhiteboardAlias(
2272 "particle_track_matching", matchAlg.config.outputParticleTrackMatching
2273 )
2274
2275 addTrackWriters(
2276 s,
2277 name="ambi_scorebased",
2278 tracks=algScoreBased.config.outputTracks,
2279 outputDirCsv=outputDirCsv,
2280 outputDirRoot=outputDirRoot,
2281 writeSummary=writeTrackSummary,
2282 writeStates=writeTrackStates,
2283 writeFitterPerformance=writePerformance,
2284 writeFinderPerformance=writePerformance,
2285 writeCovMat=writeCovMat,
2286 logLevel=logLevel,
2287 )
2288
2289 return s
2290
2291
2292 @acts.examples.NamedTypeArgs(
2293 config=AmbiguityResolutionMLConfig,
2294 )
2295 def addAmbiguityResolutionML(
2296 s,
2297 config: AmbiguityResolutionMLConfig = AmbiguityResolutionMLConfig(),
2298 tracks: str = "tracks",
2299 onnxModelFile: Optional[Union[Path, str]] = None,
2300 outputDirCsv: Optional[Union[Path, str]] = None,
2301 outputDirRoot: Optional[Union[Path, str]] = None,
2302 writeTrackSummary: bool = True,
2303 writeTrackStates: bool = False,
2304 writePerformance: bool = True,
2305 writeCovMat=False,
2306 logLevel: Optional[acts.logging.Level] = None,
2307 ) -> None:
2308 from acts.examples.onnx import AmbiguityResolutionMLAlgorithm
2309 from acts.examples import GreedyAmbiguityResolutionAlgorithm
2310
2311 customLogLevel = acts.examples.defaultLogging(s, logLevel)
2312 algML = AmbiguityResolutionMLAlgorithm(
2313 level=customLogLevel(),
2314 inputTracks=tracks,
2315 inputDuplicateNN=onnxModelFile,
2316 outputTracks="ambiTracksML",
2317 **acts.examples.defaultKWArgs(
2318 nMeasurementsMin=config.nMeasurementsMin,
2319 ),
2320 )
2321
2322 algGreedy = GreedyAmbiguityResolutionAlgorithm(
2323 level=customLogLevel(),
2324 inputTracks=algML.config.outputTracks,
2325 outputTracks="ambiTracksMLGreedy",
2326 **acts.examples.defaultKWArgs(
2327 maximumSharedHits=config.maximumSharedHits,
2328 nMeasurementsMin=config.nMeasurementsMin,
2329 maximumIterations=config.maximumIterations,
2330 ),
2331 )
2332
2333 s.addAlgorithm(algML)
2334 s.addAlgorithm(algGreedy)
2335
2336 s.addWhiteboardAlias("tracks", algGreedy.config.outputTracks)
2337
2338 matchAlg = acts.examples.TrackTruthMatcher(
2339 level=customLogLevel(),
2340 inputTracks=algGreedy.config.outputTracks,
2341 inputParticles="particles",
2342 inputMeasurementParticlesMap="measurement_particles_map",
2343 outputTrackParticleMatching="ambiML_track_particle_matching",
2344 outputParticleTrackMatching="ambiML_particle_track_matching",
2345 doubleMatching=True,
2346 )
2347 s.addAlgorithm(matchAlg)
2348 s.addWhiteboardAlias(
2349 "track_particle_matching", matchAlg.config.outputTrackParticleMatching
2350 )
2351 s.addWhiteboardAlias(
2352 "particle_track_matching", matchAlg.config.outputParticleTrackMatching
2353 )
2354
2355 addTrackWriters(
2356 s,
2357 name="ambiML",
2358 tracks=algGreedy.config.outputTracks,
2359 outputDirCsv=outputDirCsv,
2360 outputDirRoot=outputDirRoot,
2361 writeSummary=writeTrackSummary,
2362 writeStates=writeTrackStates,
2363 writeFitterPerformance=writePerformance,
2364 writeFinderPerformance=writePerformance,
2365 writeCovMat=writeCovMat,
2366 logLevel=logLevel,
2367 )
2368
2369 return s
2370
2371
2372 @acts.examples.NamedTypeArgs(
2373 trackSelectorConfig=TrackSelectorConfig,
2374 )
2375 def addVertexFitting(
2376 s,
2377 field,
2378 tracks: Optional[str] = "tracks",
2379 trackParameters: Optional[str] = None,
2380 outputProtoVertices: str = "protovertices",
2381 outputVertices: str = "fittedVertices",
2382 vertexFinder: VertexFinder = VertexFinder.Truth,
2383 maxIterations: Optional[int] = None,
2384 initialVariances: Optional[List[float]] = None,
2385 useTime: Optional[bool] = False,
2386 seeder: Optional[
2387 acts.examples.VertexSeedFinder
2388 ] = acts.examples.VertexSeedFinder.GaussianSeeder,
2389 spatialBinExtent: Optional[float] = None,
2390 temporalBinExtent: Optional[float] = None,
2391 simultaneousSeeds: Optional[int] = None,
2392 trackSelectorConfig: Optional[TrackSelectorConfig] = None,
2393 writeTrackInfo: bool = False,
2394 outputDirRoot: Optional[Union[Path, str]] = None,
2395 outputDirCsv: Optional[Union[Path, str]] = None,
2396 logLevel: Optional[acts.logging.Level] = None,
2397 ) -> None:
2398 """This function steers the vertex fitting
2399
2400 Parameters
2401 ----------
2402 s: Sequencer
2403 the sequencer module to which we add the Seeding steps (returned from
2404 addVertexFitting)
2405 field : magnetic field
2406 outputDirRoot : Path|str, path, None
2407 the output folder for ROOT output, None triggers no output
2408 outputDirCsv : Path|str, path, None
2409 the output folder for the CSV output, None triggers no output
2410 vertexFinder : VertexFinder, Truth
2411 vertexFinder algorithm: one of Truth, AMVF, Iterative
2412 seeder : enum member
2413 determines vertex seeder for AMVF, can be acts.seeder.GaussianSeeder or
2414 acts.seeder.AdaptiveGridSeeder
2415 useTime : bool, False
2416 determines whether time information is used in vertex seeder, finder,
2417 and fitter
2418 only implemented for the AMVF and the AdaptiveGridSeeder
2419 spatialBinExtent : float, None
2420 spatial bin extent for the AdaptiveGridSeeder
2421 temporalBinExtent : float, None
2422 temporal bin extent for the AdaptiveGridSeeder
2423 logLevel : acts.logging.Level, None
2424 logging level to override setting given in `s`
2425 """
2426 from acts.examples import (
2427 TruthVertexFinder,
2428 VertexFitterAlgorithm,
2429 IterativeVertexFinderAlgorithm,
2430 AdaptiveMultiVertexFinderAlgorithm,
2431 CsvVertexWriter,
2432 )
2433 from acts.examples.root import RootVertexNTupleWriter
2434
2435 customLogLevel = acts.examples.defaultLogging(s, logLevel)
2436
2437 if tracks is not None and trackSelectorConfig is not None:
2438 trackSelector = addTrackSelection(
2439 s,
2440 trackSelectorConfig,
2441 inputTracks=tracks,
2442 outputTracks="selectedTracksVertexing",
2443 logLevel=customLogLevel(),
2444 )
2445 tracks = trackSelector.config.outputTracks
2446
2447 if trackParameters is None:
2448 converter = acts.examples.TracksToParameters(
2449 level=customLogLevel(),
2450 inputTracks=tracks,
2451 outputTrackParameters="selectedTracksParametersVertexing",
2452 )
2453 s.addAlgorithm(converter)
2454 trackParameters = converter.config.outputTrackParameters
2455
2456 tracks = tracks if tracks is not None else ""
2457 inputParticles = "particles"
2458 selectedParticles = "particles_selected"
2459 inputTruthVertices = "vertices_truth"
2460
2461 if vertexFinder == VertexFinder.Truth:
2462 findVertices = TruthVertexFinder(
2463 level=customLogLevel(),
2464 inputTracks=tracks,
2465 inputTrackParticleMatching="track_particle_matching",
2466 outputProtoVertices=outputProtoVertices,
2467 excludeSecondaries=True,
2468 )
2469 s.addAlgorithm(findVertices)
2470 fitVertices = VertexFitterAlgorithm(
2471 level=customLogLevel(),
2472 inputTrackParameters=trackParameters,
2473 inputProtoVertices=findVertices.config.outputProtoVertices,
2474 outputVertices=outputVertices,
2475 bField=field,
2476 )
2477 s.addAlgorithm(fitVertices)
2478 elif vertexFinder == VertexFinder.Iterative:
2479 findVertices = IterativeVertexFinderAlgorithm(
2480 level=customLogLevel(),
2481 inputTrackParameters=trackParameters,
2482 outputProtoVertices=outputProtoVertices,
2483 outputVertices=outputVertices,
2484 bField=field,
2485 )
2486 s.addAlgorithm(findVertices)
2487 elif vertexFinder == VertexFinder.AMVF:
2488 findVertices = AdaptiveMultiVertexFinderAlgorithm(
2489 level=customLogLevel(),
2490 inputTrackParameters=trackParameters,
2491 inputTruthParticles=selectedParticles,
2492 inputTruthVertices=inputTruthVertices,
2493 outputProtoVertices=outputProtoVertices,
2494 outputVertices=outputVertices,
2495 bField=field,
2496 seedFinder=seeder,
2497 **acts.examples.defaultKWArgs(
2498 maxIterations=maxIterations,
2499 initialVariances=initialVariances,
2500 useTime=useTime,
2501 spatialBinExtent=spatialBinExtent,
2502 temporalBinExtent=temporalBinExtent,
2503 simultaneousSeeds=simultaneousSeeds,
2504 ),
2505 )
2506 s.addAlgorithm(findVertices)
2507 else:
2508 raise RuntimeError("Invalid finder argument")
2509
2510 if outputDirCsv is not None:
2511 outputDirCsv = Path(outputDirCsv)
2512 if not outputDirCsv.exists():
2513 outputDirCsv.mkdir()
2514 s.addWriter(
2515 CsvVertexWriter(
2516 level=customLogLevel(),
2517 inputVertices=outputVertices,
2518 outputDir=str(outputDirCsv),
2519 outputStem="vertices",
2520 )
2521 )
2522
2523 if outputDirRoot is not None:
2524 outputDirRoot = Path(outputDirRoot)
2525 if not outputDirRoot.exists():
2526 outputDirRoot.mkdir()
2527 s.addWriter(
2528 RootVertexNTupleWriter(
2529 level=customLogLevel(),
2530 inputVertices=outputVertices,
2531 inputTracks=tracks,
2532 inputTruthVertices=inputTruthVertices,
2533 inputParticles=inputParticles,
2534 inputSelectedParticles=selectedParticles,
2535 inputTrackParticleMatching="track_particle_matching",
2536 bField=field,
2537 writeTrackInfo=writeTrackInfo,
2538 treeName="vertexing",
2539 filePath=str(outputDirRoot / "performance_vertexing.root"),
2540 )
2541 )
2542
2543 return s
2544
2545
2546 def addHoughVertexFinding(
2547 s,
2548 outputDirRoot: Optional[Union[Path, str]] = None,
2549 logLevel: Optional[acts.logging.Level] = None,
2550 inputSpacePoints: Optional[str] = "spacepoints",
2551 outputVertices: Optional[str] = "fittedHoughVertices",
2552 ) -> None:
2553 from acts.examples import (
2554 HoughVertexFinderAlgorithm,
2555 RootVertexNTupleWriter,
2556 )
2557
2558 customLogLevel = acts.examples.defaultLogging(s, logLevel)
2559
2560 findHoughVertex = HoughVertexFinderAlgorithm(
2561 level=customLogLevel(),
2562 inputSpacepoints=inputSpacePoints,
2563 outputVertices=outputVertices,
2564 )
2565 s.addAlgorithm(findHoughVertex)
2566
2567 inputParticles = "particles"
2568 selectedParticles = "particles_selected"
2569 inputTruthVertices = "vertices_truth"
2570
2571 if outputDirRoot is not None:
2572 outputDirRoot = Path(outputDirRoot)
2573 if not outputDirRoot.exists():
2574 outputDirRoot.mkdir()
2575
2576 s.addWriter(
2577 RootVertexNTupleWriter(
2578 level=customLogLevel(),
2579 inputParticles=inputParticles,
2580 inputSelectedParticles=selectedParticles,
2581 inputTracks="",
2582 inputTrackParticleMatching="",
2583 writeTrackInfo=False,
2584 inputTruthVertices=inputTruthVertices,
2585 inputVertices=outputVertices,
2586 treeName="houghvertexing",
2587 filePath=str(outputDirRoot / "performance_houghvertexing.root"),
2588 )
2589 )
2590
2591 return s