def addGsfTracks( s: acts.examples.Sequencer, trackingGeometry: acts.TrackingGeometry, field: acts.MagneticFieldProvider, ): gsfOptions = { "maxComponents": 12, "abortOnError": False, "disableAllMaterialHandling": False, } gsfAlg = acts.examples.TrackFittingAlgorithm( level=acts.logging.INFO, inputMeasurements="measurements", inputSourceLinks="sourcelinks", inputProtoTracks="prototracks", inputInitialTrackParameters="estimatedparameters", outputTrajectories="gsf_trajectories", directNavigation=False, pickTrack=-1, trackingGeometry=trackingGeometry, fit=acts.examples.TrackFittingAlgorithm.makeGsfFitterFunction( trackingGeometry, field, **gsfOptions ), ) s.addAlgorithm(gsfAlg) return s
def addKalmanTracks( s: acts.examples.Sequencer, trackingGeometry: acts.TrackingGeometry, field: acts.MagneticFieldProvider, directNavigation=False, reverseFilteringMomThreshold=0 * u.GeV, ): truthTrkFndAlg = acts.examples.TruthTrackFinder( level=acts.logging.INFO, inputParticles="truth_seeds_selected", inputMeasurementParticlesMap="measurement_particles_map", outputProtoTracks="prototracks", ) s.addAlgorithm(truthTrkFndAlg) if directNavigation: srfSortAlg = acts.examples.SurfaceSortingAlgorithm( level=acts.logging.INFO, inputProtoTracks="prototracks", inputSimulatedHits=outputSimHits, inputMeasurementSimHitsMap=digiAlg.config. outputMeasurementSimHitsMap, outputProtoTracks="sortedprototracks", ) s.addAlgorithm(srfSortAlg) inputProtoTracks = srfSortAlg.config.outputProtoTracks else: inputProtoTracks = "prototracks" kalmanOptions = { "multipleScattering": True, "energyLoss": True, "reverseFilteringMomThreshold": reverseFilteringMomThreshold, "freeToBoundCorrection": acts.examples.FreeToBoundCorrection(False), } fitAlg = acts.examples.TrackFittingAlgorithm( level=acts.logging.INFO, inputMeasurements="measurements", inputSourceLinks="sourcelinks", inputProtoTracks=inputProtoTracks, inputInitialTrackParameters="estimatedparameters", outputTrajectories="trajectories", directNavigation=directNavigation, pickTrack=-1, trackingGeometry=trackingGeometry, dFit=acts.examples.TrackFittingAlgorithm.makeKalmanFitterFunction( field, **kalmanOptions), fit=acts.examples.TrackFittingAlgorithm.makeKalmanFitterFunction( trackingGeometry, field, **kalmanOptions), ) s.addAlgorithm(fitAlg) return s
def runTruthTracking( trackingGeometry, field, outputDir: Path, digiConfigFile: Path, directNavigation=False, s: acts.examples.Sequencer = None, ): # Preliminaries rnd = acts.examples.RandomNumbers() # Sequencer s = s or acts.examples.Sequencer( events=10, numThreads=-1, logLevel=acts.logging.INFO) # Input vtxGen = acts.examples.GaussianVertexGenerator() vtxGen.stddev = acts.Vector4(0, 0, 0, 0) ptclGen = acts.examples.ParametricParticleGenerator(p=(1 * u.GeV, 10 * u.GeV), eta=(-2, 2), numParticles=2) g = acts.examples.EventGenerator.Generator() g.multiplicity = acts.examples.FixedMultiplicityGenerator() g.vertex = vtxGen g.particles = ptclGen evGen = acts.examples.EventGenerator( level=acts.logging.INFO, generators=[g], outputParticles="particles_input", randomNumbers=rnd, ) s.addReader(evGen) s.addWriter( acts.examples.RootParticleWriter( level=acts.logging.INFO, inputParticles=evGen.config.outputParticles, filePath=str(outputDir / "particles.root"), )) # Selector selector = acts.examples.ParticleSelector( level=acts.logging.INFO, inputParticles=evGen.config.outputParticles, outputParticles="particles_selected", ) s.addAlgorithm(selector) # Simulation simAlg = acts.examples.FatrasSimulation( level=acts.logging.INFO, inputParticles=selector.config.outputParticles, outputParticlesInitial="particles_initial", outputParticlesFinal="particles_final", outputSimHits="simhits", randomNumbers=rnd, trackingGeometry=trackingGeometry, magneticField=field, generateHitsOnSensitive=True, ) s.addAlgorithm(simAlg) # Digitization digiCfg = acts.examples.DigitizationConfig( acts.examples.readDigiConfigFromJson(str(digiConfigFile), ), trackingGeometry=trackingGeometry, randomNumbers=rnd, inputSimHits=simAlg.config.outputSimHits, ) digiAlg = acts.examples.DigitizationAlgorithm(digiCfg, acts.logging.INFO) s.addAlgorithm(digiAlg) selAlg = acts.examples.TruthSeedSelector( level=acts.logging.INFO, ptMin=500 * u.MeV, nHitsMin=9, inputParticles=simAlg.config.outputParticlesInitial, inputMeasurementParticlesMap=digiCfg.outputMeasurementParticlesMap, outputParticles="particles_seed_selected", ) s.addAlgorithm(selAlg) inputParticles = selAlg.config.outputParticles smearAlg = acts.examples.ParticleSmearing( level=acts.logging.INFO, inputParticles=inputParticles, outputTrackParameters="smearedparameters", randomNumbers=rnd, # Gaussian sigmas to smear particle parameters # sigmaD0=20 * u.um, # sigmaD0PtA=30 * u.um, # sigmaD0PtB=0.3 / u.GeV, # sigmaZ0=20 * u.um, # sigmaZ0PtA=30 * u.um, # sigmaZ0PtB=0.3 / u.GeV, # sigmaPhi=1 * u.degree, # sigmaTheta=1 * u.degree, # sigmaPRel=0.01, # sigmaT0=1 * u.ns, # initialVarInflation=[1, 1, 1, 1, 1, 1], ) s.addAlgorithm(smearAlg) truthTrkFndAlg = acts.examples.TruthTrackFinder( level=acts.logging.INFO, inputParticles=inputParticles, inputMeasurementParticlesMap=digiAlg.config. outputMeasurementParticlesMap, outputProtoTracks="prototracks", ) s.addAlgorithm(truthTrkFndAlg) if directNavigation: srfSortAlg = acts.examples.SurfaceSortingAlgorithm( level=acts.logging.INFO, inputProtoTracks=truthTrkFndAlg.config.outputProtoTracks, inputSimulatedHits=simAlg.config.outputSimHits, inputMeasurementSimHitsMap=digiAlg.config. outputMeasurementSimHitsMap, outputProtoTracks="sortedprototracks", ) s.addAlgorithm(srfSortAlg) inputProtoTracks = srfSortAlg.config.outputProtoTracks else: inputProtoTracks = truthTrkFndAlg.config.outputProtoTracks fitAlg = acts.examples.TrackFittingAlgorithm( level=acts.logging.INFO, inputMeasurements=digiAlg.config.outputMeasurements, inputSourceLinks=digiAlg.config.outputSourceLinks, inputProtoTracks=inputProtoTracks, inputInitialTrackParameters=smearAlg.config.outputTrackParameters, outputTrajectories="trajectories", directNavigation=directNavigation, multipleScattering=True, energyLoss=True, pickTrack=-1, trackingGeometry=trackingGeometry, dFit=acts.examples.TrackFittingAlgorithm.makeTrackFitterFunction( field), fit=acts.examples.TrackFittingAlgorithm.makeTrackFitterFunction( trackingGeometry, field), ) s.addAlgorithm(fitAlg) # Output s.addWriter( acts.examples.RootTrajectoryStatesWriter( level=acts.logging.INFO, inputTrajectories=fitAlg.config.outputTrajectories, inputParticles=inputParticles, inputSimHits=simAlg.config.outputSimHits, inputMeasurementParticlesMap=digiAlg.config. outputMeasurementParticlesMap, inputMeasurementSimHitsMap=digiAlg.config. outputMeasurementSimHitsMap, filePath=str(outputDir / "trackstates_fitter.root"), )) s.addWriter( acts.examples.RootTrajectorySummaryWriter( level=acts.logging.INFO, inputTrajectories=fitAlg.config.outputTrajectories, inputParticles=inputParticles, inputMeasurementParticlesMap=digiAlg.config. outputMeasurementParticlesMap, filePath=str(outputDir / "tracksummary_fitter.root"), )) s.addWriter( acts.examples.TrackFinderPerformanceWriter( level=acts.logging.INFO, inputProtoTracks=truthTrkFndAlg.config.outputProtoTracks, inputParticles=inputParticles, inputMeasurementParticlesMap=digiAlg.config. outputMeasurementParticlesMap, filePath=str(outputDir / "performance_track_finder.root"), )) s.addWriter( acts.examples.TrackFitterPerformanceWriter( level=acts.logging.INFO, inputTrajectories=fitAlg.config.outputTrajectories, inputParticles=inputParticles, inputMeasurementParticlesMap=digiAlg.config. outputMeasurementParticlesMap, filePath=str(outputDir / "performance_track_fitter.root"), )) return s
def addCKFTracks( s: acts.examples.Sequencer, trackingGeometry: acts.TrackingGeometry, field: acts.MagneticFieldProvider, CKFPerformanceConfigArg: CKFPerformanceConfig = CKFPerformanceConfig(), outputDirCsv: Optional[Union[Path, str]] = None, outputDirRoot: Optional[Union[Path, str]] = None, selectedParticles: str = "truth_seeds_selected", ) -> acts.examples.Sequencer: """This function steers the seeding Parameters ---------- s: Sequencer the sequencer module to which we add the Seeding steps (returned from addSeeding) trackingGeometry : tracking geometry field : magnetic field CKFPerformanceConfigArg : CKFPerformanceConfig(truthMatchProbMin, nMeasurementsMin, ptMin) CKFPerformanceWriter configuration. Defaults specified in Examples/Io/Performance/ActsExamples/Io/Performance/CKFPerformanceWriter.hpp outputDirCsv : Path|str, path, None the output folder for the Csv output, None triggers no output outputDirRoot : Path|str, path, None the output folder for the Root output, None triggers no output selectedParticles : str, "truth_seeds_selected" CKFPerformanceWriter truth input """ if int(s.config.logLevel) <= int(acts.logging.DEBUG): acts.examples.dump_args_calls(locals()) # Setup the track finding algorithm with CKF # It takes all the source links created from truth hit smearing, seeds from # truth particle smearing and source link selection config trackFinder = acts.examples.TrackFindingAlgorithm( level=s.config.logLevel, measurementSelectorCfg=acts.MeasurementSelector.Config([ (acts.GeometryIdentifier(), ([], [15.0], [10])) ]), inputMeasurements="measurements", inputSourceLinks="sourcelinks", inputInitialTrackParameters="estimatedparameters", outputTrajectories="trajectories", findTracks=acts.examples.TrackFindingAlgorithm.makeTrackFinderFunction( trackingGeometry, field), ) s.addAlgorithm(trackFinder) if outputDirRoot is not None: outputDirRoot = Path(outputDirRoot) if not outputDirRoot.exists(): outputDirRoot.mkdir() # write track states from CKF trackStatesWriter = acts.examples.RootTrajectoryStatesWriter( level=s.config.logLevel, inputTrajectories=trackFinder.config.outputTrajectories, # @note The full particles collection is used here to avoid lots of warnings # since the unselected CKF track might have a majority particle not in the # filtered particle collection. This could be avoided when a seperate track # selection algorithm is used. inputParticles="particles_selected", inputSimHits="simhits", inputMeasurementParticlesMap="measurement_particles_map", inputMeasurementSimHitsMap="measurement_simhits_map", filePath=str(outputDirRoot / "trackstates_ckf.root"), treeName="trackstates", ) s.addWriter(trackStatesWriter) # write track summary from CKF trackSummaryWriter = acts.examples.RootTrajectorySummaryWriter( level=s.config.logLevel, inputTrajectories=trackFinder.config.outputTrajectories, # @note The full particles collection is used here to avoid lots of warnings # since the unselected CKF track might have a majority particle not in the # filtered particle collection. This could be avoided when a seperate track # selection algorithm is used. inputParticles="particles_selected", inputMeasurementParticlesMap="measurement_particles_map", filePath=str(outputDirRoot / "tracksummary_ckf.root"), treeName="tracksummary", ) s.addWriter(trackSummaryWriter) # Write CKF performance data ckfPerfWriter = acts.examples.CKFPerformanceWriter( level=s.config.logLevel, inputParticles=selectedParticles, inputTrajectories=trackFinder.config.outputTrajectories, inputMeasurementParticlesMap="measurement_particles_map", **acts.examples.defaultKWArgs( # The bottom seed could be the first, second or third hits on the truth track nMeasurementsMin=CKFPerformanceConfigArg.nMeasurementsMin, ptMin=CKFPerformanceConfigArg.ptMin, truthMatchProbMin=CKFPerformanceConfigArg.truthMatchProbMin, ), filePath=str(outputDirRoot / "performance_ckf.root"), ) s.addWriter(ckfPerfWriter) if outputDirCsv is not None: outputDirCsv = Path(outputDirCsv) if not outputDirCsv.exists(): outputDirCsv.mkdir() acts.logging.getLogger("CKFExample").info("Writing CSV files") csvMTJWriter = acts.examples.CsvMultiTrajectoryWriter( level=s.config.logLevel, inputTrajectories=trackFinder.config.outputTrajectories, inputMeasurementParticlesMap="measurement_particles_map", outputDir=str(outputDirCsv), ) s.addWriter(csvMTJWriter) return s
def addSeeding( s: acts.examples.Sequencer, trackingGeometry: acts.TrackingGeometry, field: acts.MagneticFieldProvider, geoSelectionConfigFile: Optional[Union[Path, str]] = None, seedingAlgorithm: SeedingAlgorithm = SeedingAlgorithm.Default, truthSeedRanges: TruthSeedRanges = TruthSeedRanges(), particleSmearingSigmas: ParticleSmearingSigmas = ParticleSmearingSigmas(), initialVarInflation: Optional[list] = None, seedfinderConfigArg: SeedfinderConfigArg = SeedfinderConfigArg(), trackParamsEstimationConfig: TrackParamsEstimationConfig = TrackParamsEstimationConfig(), inputParticles: str = "particles_initial", outputDirRoot: Optional[Union[Path, str]] = None, logLevel: Optional[acts.logging.Level] = None, rnd: Optional[acts.examples.RandomNumbers] = None, ) -> acts.examples.Sequencer: """This function steers the seeding Parameters ---------- s: Sequencer the sequencer module to which we add the Seeding steps (returned from addSeeding) trackingGeometry : tracking geometry field : magnetic field geoSelectionConfigFile : Path|str, path, None Json file for space point geometry selection. Not required for SeedingAlgorithm.TruthSmeared. seedingAlgorithm : SeedingAlgorithm, Default seeding algorithm to use: one of Default (no truth information used), TruthSmeared, TruthEstimated truthSeedRanges : TruthSeedRanges(rho, z, phi, eta, absEta, pt, nHits) TruthSeedSelector configuration. Each range is specified as a tuple of (min,max). Defaults of no cuts specified in Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/TruthSeedSelector.hpp particleSmearingSigmas : ParticleSmearingSigmas(d0, d0PtA, d0PtB, z0, z0PtA, z0PtB, t0, phi, theta, pRel) ParticleSmearing configuration. Defaults specified in Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSmearing.hpp initialVarInflation : list List of 6 scale factors to inflate the initial covariance matrix Defaults (all 1) specified in Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSmearing.hpp seedfinderConfigArg : SeedfinderConfigArg(maxSeedsPerSpM, cotThetaMax, sigmaScattering, radLengthPerSeed, minPt, bFieldInZ, impactMax, deltaR, collisionRegion, r, z, beamPos) SeedfinderConfig settings. deltaR, collisionRegion, r, z are ranges specified as a tuple of (min,max). beamPos is specified as (x,y). Defaults specified in Core/include/Acts/Seeding/SeedfinderConfig.hpp trackParamsEstimationConfig : TrackParamsEstimationConfig(deltaR) TrackParamsEstimationAlgorithm configuration. Currently only deltaR=(min,max) range specified here. Defaults specified in Examples/Algorithms/TrackFinding/include/ActsExamples/TrackFinding/TrackParamsEstimationAlgorithm.hpp inputParticles : str, "particles_initial" input particles name in the WhiteBoard outputDirRoot : Path|str, path, None the output folder for the Root output, None triggers no output logLevel : acts.logging.Level, None logging level to override setting given in `s` rnd : RandomNumbers, None random number generator. Only used by SeedingAlgorithm.TruthSmeared. """ def customLogLevel(custom: acts.logging.Level = acts.logging.INFO): """override logging level""" if logLevel is None: return s.config.logLevel return acts.logging.Level(max(custom.value, logLevel.value)) if int(customLogLevel()) <= int(acts.logging.DEBUG): acts.examples.dump_args_calls(locals()) logger = acts.logging.getLogger("addSeeding") if truthSeedRanges is not None: selAlg = acts.examples.TruthSeedSelector( **acts.examples.defaultKWArgs( ptMin=truthSeedRanges.pt[0], ptMax=truthSeedRanges.pt[1], etaMin=truthSeedRanges.eta[0], etaMax=truthSeedRanges.eta[1], nHitsMin=truthSeedRanges.nHits[0], nHitsMax=truthSeedRanges.nHits[1], rhoMin=truthSeedRanges.rho[0], rhoMax=truthSeedRanges.rho[1], zMin=truthSeedRanges.z[0], zMax=truthSeedRanges.z[1], phiMin=truthSeedRanges.phi[0], phiMax=truthSeedRanges.phi[1], absEtaMin=truthSeedRanges.absEta[0], absEtaMax=truthSeedRanges.absEta[1], ), level=customLogLevel(), inputParticles=inputParticles, inputMeasurementParticlesMap="measurement_particles_map", outputParticles="truth_seeds_selected", ) s.addAlgorithm(selAlg) selectedParticles = selAlg.config.outputParticles else: selectedParticles = inputParticles # Create starting parameters from either particle smearing or combined seed # finding and track parameters estimation if seedingAlgorithm == SeedingAlgorithm.TruthSmeared: rnd = rnd or acts.examples.RandomNumbers(seed=42) logger.info("Using smeared truth particles for seeding") # Run particle smearing ptclSmear = acts.examples.ParticleSmearing( level=customLogLevel(), inputParticles=selectedParticles, outputTrackParameters="estimatedparameters", randomNumbers=rnd, # gaussian sigmas to smear particle parameters **acts.examples.defaultKWArgs( sigmaD0=particleSmearingSigmas.d0, sigmaD0PtA=particleSmearingSigmas.d0PtA, sigmaD0PtB=particleSmearingSigmas.d0PtB, sigmaZ0=particleSmearingSigmas.z0, sigmaZ0PtA=particleSmearingSigmas.z0PtA, sigmaZ0PtB=particleSmearingSigmas.z0PtB, sigmaT0=particleSmearingSigmas.t0, sigmaPhi=particleSmearingSigmas.phi, sigmaTheta=particleSmearingSigmas.theta, sigmaPRel=particleSmearingSigmas.pRel, initialVarInflation=initialVarInflation, ), ) s.addAlgorithm(ptclSmear) else: spAlg = acts.examples.SpacePointMaker( level=customLogLevel(), inputSourceLinks="sourcelinks", inputMeasurements="measurements", outputSpacePoints="spacepoints", trackingGeometry=trackingGeometry, geometrySelection=acts.examples.readJsonGeometryList( str(geoSelectionConfigFile)), ) s.addAlgorithm(spAlg) # Run either: truth track finding or seeding if seedingAlgorithm == SeedingAlgorithm.TruthEstimated: logger.info( "Using truth track finding from space points for seeding") # Use truth tracking truthTrackFinder = acts.examples.TruthTrackFinder( level=customLogLevel(), inputParticles=selectedParticles, inputMeasurementParticlesMap=selAlg.config. inputMeasurementParticlesMap, outputProtoTracks="prototracks", ) s.addAlgorithm(truthTrackFinder) inputProtoTracks = truthTrackFinder.config.outputProtoTracks inputSeeds = "" elif seedingAlgorithm == SeedingAlgorithm.Default: logger.info("Using default seeding") # Use seeding seedFinderConfig = acts.SeedfinderConfig( **acts.examples.defaultKWArgs( rMin=seedfinderConfigArg.r[0], rMax=seedfinderConfigArg.r[1], deltaRMin=seedfinderConfigArg.deltaR[0], deltaRMax=seedfinderConfigArg.deltaR[1], deltaRMinTopSP=seedfinderConfigArg.deltaR[0], deltaRMinBottomSP=seedfinderConfigArg.deltaR[0], deltaRMaxTopSP=seedfinderConfigArg.deltaR[1], deltaRMaxBottomSP=seedfinderConfigArg.deltaR[1], collisionRegionMin=seedfinderConfigArg.collisionRegion[0], collisionRegionMax=seedfinderConfigArg.collisionRegion[1], zMin=seedfinderConfigArg.z[0], zMax=seedfinderConfigArg.z[1], maxSeedsPerSpM=seedfinderConfigArg.maxSeedsPerSpM, cotThetaMax=seedfinderConfigArg.cotThetaMax, sigmaScattering=seedfinderConfigArg.sigmaScattering, radLengthPerSeed=seedfinderConfigArg.radLengthPerSeed, minPt=seedfinderConfigArg.minPt, bFieldInZ=seedfinderConfigArg.bFieldInZ, impactMax=seedfinderConfigArg.impactMax, beamPos=( None if seedfinderConfigArg.beamPos is None or all( [x is None for x in seedfinderConfigArg.beamPos]) else acts.Vector2( seedfinderConfigArg.beamPos[0] or 0.0, seedfinderConfigArg.beamPos[1] or 0.0, )), ), ) seedFilterConfig = acts.SeedFilterConfig( maxSeedsPerSpM=seedFinderConfig.maxSeedsPerSpM, deltaRMin=seedFinderConfig.deltaRMin, ) gridConfig = acts.SpacePointGridConfig( bFieldInZ=seedFinderConfig.bFieldInZ, minPt=seedFinderConfig.minPt, rMax=seedFinderConfig.rMax, zMax=seedFinderConfig.zMax, zMin=seedFinderConfig.zMin, deltaRMax=seedFinderConfig.deltaRMax, cotThetaMax=seedFinderConfig.cotThetaMax, ) seedingAlg = acts.examples.SeedingAlgorithm( level=customLogLevel(acts.logging.VERBOSE), inputSpacePoints=[spAlg.config.outputSpacePoints], outputSeeds="seeds", outputProtoTracks="prototracks", gridConfig=gridConfig, seedFilterConfig=seedFilterConfig, seedFinderConfig=seedFinderConfig, ) s.addAlgorithm(seedingAlg) inputProtoTracks = seedingAlg.config.outputProtoTracks inputSeeds = seedingAlg.config.outputSeeds elif seedingAlgorithm == SeedingAlgorithm.Orthogonal: logger.info("Using orthogonal seeding") # Use seeding seedFinderConfig = acts.SeedFinderOrthogonalConfig( **acts.examples.defaultKWArgs( rMin=seedfinderConfigArg.r[0], rMax=seedfinderConfigArg.r[1], deltaRMin=seedfinderConfigArg.deltaR[0], deltaRMax=seedfinderConfigArg.deltaR[1], collisionRegionMin=seedfinderConfigArg.collisionRegion[0], collisionRegionMax=seedfinderConfigArg.collisionRegion[1], zMin=seedfinderConfigArg.z[0], zMax=seedfinderConfigArg.z[1], maxSeedsPerSpM=seedfinderConfigArg.maxSeedsPerSpM, cotThetaMax=seedfinderConfigArg.cotThetaMax, sigmaScattering=seedfinderConfigArg.sigmaScattering, radLengthPerSeed=seedfinderConfigArg.radLengthPerSeed, minPt=seedfinderConfigArg.minPt, bFieldInZ=seedfinderConfigArg.bFieldInZ, impactMax=seedfinderConfigArg.impactMax, beamPos=( None if seedfinderConfigArg.beamPos is None or all( [x is None for x in seedfinderConfigArg.beamPos]) else acts.Vector2( seedfinderConfigArg.beamPos[0] or 0.0, seedfinderConfigArg.beamPos[1] or 0.0, )), ), ) seedFilterConfig = acts.SeedFilterConfig( maxSeedsPerSpM=seedFinderConfig.maxSeedsPerSpM, deltaRMin=seedFinderConfig.deltaRMin, ) seedingAlg = acts.examples.SeedingOrthogonalAlgorithm( level=customLogLevel(acts.logging.VERBOSE), inputSpacePoints=[spAlg.config.outputSpacePoints], outputSeeds="seeds", outputProtoTracks="prototracks", seedFilterConfig=seedFilterConfig, seedFinderConfig=seedFinderConfig, ) s.addAlgorithm(seedingAlg) inputProtoTracks = seedingAlg.config.outputProtoTracks inputSeeds = seedingAlg.config.outputSeeds else: logger.fatal("unknown seedingAlgorithm %s", seedingAlgorithm) parEstimateAlg = acts.examples.TrackParamsEstimationAlgorithm( level=customLogLevel(acts.logging.VERBOSE), inputSeeds=inputSeeds, inputProtoTracks=inputProtoTracks, inputSpacePoints=[spAlg.config.outputSpacePoints], inputSourceLinks=spAlg.config.inputSourceLinks, outputTrackParameters="estimatedparameters", outputProtoTracks="prototracks_estimated", trackingGeometry=trackingGeometry, magneticField=field, **acts.examples.defaultKWArgs( initialVarInflation=initialVarInflation, deltaRMin=trackParamsEstimationConfig.deltaR[0], deltaRMax=trackParamsEstimationConfig.deltaR[1], ), ) s.addAlgorithm(parEstimateAlg) if outputDirRoot is not None: outputDirRoot = Path(outputDirRoot) if not outputDirRoot.exists(): outputDirRoot.mkdir() s.addWriter( acts.examples.TrackFinderPerformanceWriter( level=customLogLevel(), inputProtoTracks=inputProtoTracks, inputParticles= selectedParticles, # the original selected particles after digitization inputMeasurementParticlesMap=selAlg.config. inputMeasurementParticlesMap, filePath=str(outputDirRoot / "performance_seeding_trees.root"), )) s.addWriter( acts.examples.SeedingPerformanceWriter( level=customLogLevel(acts.logging.DEBUG), inputProtoTracks=inputProtoTracks, inputParticles=selectedParticles, inputMeasurementParticlesMap=selAlg.config. inputMeasurementParticlesMap, filePath=str(outputDirRoot / "performance_seeding_hists.root"), )) s.addWriter( acts.examples.RootTrackParameterWriter( level=customLogLevel(acts.logging.VERBOSE), inputTrackParameters=parEstimateAlg.config. outputTrackParameters, inputProtoTracks=parEstimateAlg.config.outputProtoTracks, inputParticles=inputParticles, inputSimHits="simhits", inputMeasurementParticlesMap=selAlg.config. inputMeasurementParticlesMap, inputMeasurementSimHitsMap="measurement_simhits_map", filePath=str(outputDirRoot / "estimatedparams.root"), treeName="estimatedparams", )) return s
def addExaTrkx( s: acts.examples.Sequencer, trackingGeometry: acts.TrackingGeometry, geometrySelection: Union[Path, str], onnxModelDir: Union[Path, str], outputDirRoot: Optional[Union[Path, str]] = None, ) -> acts.examples.Sequencer: # Run the particle selection # The pre-selection will select truth particles satisfying provided criteria # from all particles read in by particle reader for further processing. It # has no impact on the truth hits themselves s.addAlgorithm( acts.examples.TruthSeedSelector( level=acts.logging.INFO, ptMin=500 * u.MeV, nHitsMin=9, inputParticles="particles_initial", inputMeasurementParticlesMap="measurement_particle_map", outputParticles="particles_seed_selected", )) # Create space points s.addAlgorithm( acts.examples.SpacePointMaker( level=acts.logging.INFO, inputSourceLinks="source_links", inputMeasurements="measurements", outputSpacePoints="spacepoints", trackingGeometry=trackingGeometry, geometrySelection=acts.examples.readJsonGeometryList( str(geometrySelection)), )) # Setup the track finding algorithm with ExaTrkX # It takes all the source links created from truth hit smearing, seeds from # truth particle smearing and source link selection config exaTrkxFinding = acts.examples.ExaTrkXTrackFinding( inputMLModuleDir=str(onnxModelDir), spacepointFeatures=3, embeddingDim=8, rVal=1.6, knnVal=500, filterCut=0.21, ) s.addAlgorithm( acts.examples.TrackFindingMLBasedAlgorithm( level=acts.logging.INFO, inputSpacePoints="spacepoints", outputProtoTracks="protoTracks", trackFinderML=exaTrkxFinding, )) # Write truth track finding / seeding performance if outputDirRoot is not None: s.addWriter( acts.examples.TrackFinderPerformanceWriter( level=acts.logging.INFO, inputProtoTracks="protoTracks", inputParticles= "particles_initial", # the original selected particles after digitization inputMeasurementParticlesMap="measurement_particle_map", filePath=str( Path(outputDirRoot) / "performance_seeding_trees.root"), )) return s
def addDigitization( s: acts.examples.Sequencer, trackingGeometry: acts.TrackingGeometry, field: acts.MagneticFieldProvider, digiConfigFile: Union[Path, str], outputDirCsv: Optional[Union[Path, str]] = None, outputDirRoot: Optional[Union[Path, str]] = None, rnd: Optional[acts.examples.RandomNumbers] = None, ) -> acts.examples.Sequencer: """This function steers the digitization step Parameters ---------- s: Sequencer the sequencer module to which we add the Digitization steps (returned from addDigitization) trackingGeometry : tracking geometry field : magnetic field digiConfigFile : Path|str, path Configuration (.json) file for digitization or smearing description outputDirCsv : Path|str, path, None the output folder for the Csv output, None triggers no output outputDirRoot : Path|str, path, None the output folder for the Root output, None triggers no output rnd : RandomNumbers, None random number generator """ if int(s.config.logLevel) <= int(acts.logging.DEBUG): acts.examples.dump_args_calls(locals()) # Preliminaries rnd = rnd or acts.examples.RandomNumbers() # Digitization digiCfg = acts.examples.DigitizationConfig( acts.examples.readDigiConfigFromJson( str(digiConfigFile), ), trackingGeometry=trackingGeometry, randomNumbers=rnd, inputSimHits="simhits", outputSourceLinks="sourcelinks", outputMeasurements="measurements", outputMeasurementParticlesMap="measurement_particles_map", outputMeasurementSimHitsMap="measurement_simhits_map", ) digiAlg = acts.examples.DigitizationAlgorithm(digiCfg, s.config.logLevel) s.addAlgorithm(digiAlg) if outputDirRoot is not None: outputDirRoot = Path(outputDirRoot) if not outputDirRoot.exists(): outputDirRoot.mkdir() rmwConfig = acts.examples.RootMeasurementWriter.Config( inputMeasurements=digiAlg.config.outputMeasurements, inputClusters=digiAlg.config.outputClusters, inputSimHits=digiAlg.config.inputSimHits, inputMeasurementSimHitsMap=digiAlg.config.outputMeasurementSimHitsMap, filePath=str(outputDirRoot / f"{digiAlg.config.outputMeasurements}.root"), trackingGeometry=trackingGeometry, ) rmwConfig.addBoundIndicesFromDigiConfig(digiAlg.config) s.addWriter(acts.examples.RootMeasurementWriter(rmwConfig, s.config.logLevel)) if outputDirCsv is not None: outputDirCsv = Path(outputDirCsv) if not outputDirCsv.exists(): outputDirCsv.mkdir() s.addWriter( acts.examples.CsvMeasurementWriter( level=s.config.logLevel, inputMeasurements=digiAlg.config.outputMeasurements, inputClusters=digiAlg.config.outputClusters, inputSimHits=digiAlg.config.inputSimHits, inputMeasurementSimHitsMap=digiAlg.config.outputMeasurementSimHitsMap, outputDir=str(outputDirCsv), ) ) return s
def addPythia8( s: acts.examples.Sequencer, rnd: Optional[acts.examples.RandomNumbers] = None, nhard: int = 1, npileup: int = 200, beam: Optional[ Union[acts.PdgParticle, Iterable]] = None, # default: acts.PdgParticle.eProton cmsEnergy: Optional[float] = None, # default: 14 * acts.UnitConstants.TeV hardProcess: Optional[Iterable] = None, # default: ["HardQCD:all = on"] pileupProcess: Iterable = ["SoftQCD:all = on"], vtxGen: Optional[acts.examples.EventGenerator.VertexGenerator] = None, outputDirCsv: Optional[Union[Path, str]] = None, outputDirRoot: Optional[Union[Path, str]] = None, printParticles: bool = False, returnEvGen: bool = False, ) -> Union[acts.examples.Sequencer, acts.examples.EventGenerator]: """This function steers the particle generation using Pythia8 NB. this is a reimplementation of common.addPythia8, which is maintained for now for compatibility. Parameters ---------- s: Sequencer the sequencer module to which we add the particle gun steps (returned from addParticleGun) rnd : RandomNumbers, None random number generator nhard, npileup : int, 1, 200 Number of hard-scatter and pileup vertices beam : PdgParticle|[PdgParticle,PdgParticle], eProton beam particle(s) cmsEnergy : float, 14 TeV CMS energy hardProcess, pileupProcess : [str], ["HardQCD:all = on"], ["SoftQCD:all = on"] hard and pileup processes vtxGen : VertexGenerator, None vertex generator module outputDirCsv : Path|str, path, None the output folder for the Csv output, None triggers no output outputDirRoot : Path|str, path, None the output folder for the Root output, None triggers no output printParticles : bool, False print generated particles returnEvGen: bool, False returns EventGenerator instead of Sequencer. This option is included for compatibility and will be removed when common.addPythia8 is removed. """ if int(s.config.logLevel) <= int(acts.logging.DEBUG): acts.examples.dump_args_calls(locals()) # Preliminaries rnd = rnd or acts.examples.RandomNumbers() vtxGen = vtxGen or acts.examples.GaussianVertexGenerator( stddev=acts.Vector4(0, 0, 0, 0), mean=acts.Vector4(0, 0, 0, 0)) if not isinstance(beam, Iterable): beam = (beam, beam) generators = [] if nhard is not None and nhard > 0: generators.append( acts.examples.EventGenerator.Generator( multiplicity=acts.examples.FixedMultiplicityGenerator(n=nhard), vertex=vtxGen, particles=acts.examples.pythia8.Pythia8Generator( level=s.config.logLevel, **acts.examples.defaultKWArgs( pdgBeam0=beam[0], pdgBeam1=beam[1], cmsEnergy=cmsEnergy, settings=hardProcess, ), ), )) if npileup > 0: generators.append( acts.examples.EventGenerator.Generator( multiplicity=acts.examples.FixedMultiplicityGenerator( n=npileup), vertex=vtxGen, particles=acts.examples.pythia8.Pythia8Generator( level=s.config.logLevel, **acts.examples.defaultKWArgs( pdgBeam0=beam[0], pdgBeam1=beam[1], cmsEnergy=cmsEnergy, settings=pileupProcess, ), ), )) # Input evGen = acts.examples.EventGenerator( level=s.config.logLevel, generators=generators, outputParticles="particles_input", randomNumbers=rnd, ) s.addReader(evGen) if printParticles: s.addAlgorithm( acts.examples.ParticlesPrinter( level=s.config.logLevel, inputParticles=evGen.config.outputParticles)) if outputDirCsv is not None: outputDirCsv = Path(outputDirCsv) if not outputDirCsv.exists(): outputDirCsv.mkdir() s.addWriter( acts.examples.CsvParticleWriter( level=s.config.logLevel, inputParticles=evGen.config.outputParticles, outputDir=str(outputDirCsv), outputStem="particles", )) if outputDirRoot is not None: outputDirRoot = Path(outputDirRoot) if not outputDirRoot.exists(): outputDirRoot.mkdir() s.addWriter( acts.examples.RootParticleWriter( level=s.config.logLevel, inputParticles=evGen.config.outputParticles, filePath=str(outputDirRoot / "pythia8_particles.root"), )) return evGen if returnEvGen else s
def runFatras(trackingGeometry, field, outputDir, s: acts.examples.Sequencer = None): # Preliminaries rnd = acts.examples.RandomNumbers() # Input vtxGen = acts.examples.GaussianVertexGenerator() vtxGen.stddev = acts.Vector4(0, 0, 0, 0) ptclGen = acts.examples.ParametricParticleGenerator(p=(1 * u.GeV, 10 * u.GeV), eta=(-2, 2)) g = acts.examples.EventGenerator.Generator() g.multiplicity = acts.examples.FixedMultiplicityGenerator() g.vertex = vtxGen g.particles = ptclGen evGen = acts.examples.EventGenerator( level=acts.logging.INFO, generators=[g], outputParticles="particles_input", randomNumbers=rnd, ) # Selector selector = acts.examples.ParticleSelector( level=acts.logging.INFO, inputParticles=evGen.config.outputParticles, outputParticles="particles_selected", ) # Simulation alg = acts.examples.FatrasSimulation( level=acts.logging.INFO, inputParticles=selector.config.outputParticles, outputParticlesInitial="particles_initial", outputParticlesFinal="particles_final", outputSimHits="simhits", randomNumbers=rnd, trackingGeometry=trackingGeometry, magneticField=field, generateHitsOnSensitive=True, ) # Sequencer s = s or acts.examples.Sequencer( events=100, numThreads=-1, logLevel=acts.logging.INFO) s.addReader(evGen) s.addAlgorithm(selector) s.addAlgorithm(alg) # Output s.addWriter( acts.examples.CsvParticleWriter( level=acts.logging.INFO, outputDir=outputDir + "/csv", inputParticles="particles_final", outputStem="particles_final", )) s.addWriter( acts.examples.RootParticleWriter( level=acts.logging.INFO, inputParticles="particles_final", filePath=outputDir + "/fatras_particles_final.root", )) s.addWriter( acts.examples.CsvParticleWriter( level=acts.logging.INFO, outputDir=outputDir + "/csv", inputParticles="particles_initial", outputStem="particles_initial", )) s.addWriter( acts.examples.RootParticleWriter( level=acts.logging.INFO, inputParticles="particles_initial", filePath=outputDir + "/fatras_particles_initial.root", )) s.addWriter( acts.examples.CsvSimHitWriter( level=acts.logging.INFO, inputSimHits=alg.config.outputSimHits, outputDir=outputDir + "/csv", outputStem="hits", )) s.addWriter( acts.examples.RootSimHitWriter( level=acts.logging.INFO, inputSimHits=alg.config.outputSimHits, filePath=outputDir + "/hits.root", )) return s
def addFatras( s: acts.examples.Sequencer, trackingGeometry: acts.TrackingGeometry, field: acts.MagneticFieldProvider, outputDirCsv: Optional[Union[Path, str]] = None, outputDirRoot: Optional[Union[Path, str]] = None, rnd: Optional[acts.examples.RandomNumbers] = None, preselectParticles: bool = True, ) -> acts.examples.Sequencer: """This function steers the detector simulation using Fatras Parameters ---------- s: Sequencer the sequencer module to which we add the Fatras steps (returned from addFatras) trackingGeometry : tracking geometry field : magnetic field outputDirCsv : Path|str, path, None the output folder for the Csv output, None triggers no output outputDirRoot : Path|str, path, None the output folder for the Root output, None triggers no output rnd : RandomNumbers, None random number generator """ if int(s.config.logLevel) <= int(acts.logging.DEBUG): acts.examples.dump_args_calls(locals()) # Preliminaries rnd = rnd or acts.examples.RandomNumbers() # Selector if preselectParticles: particles_selected = "particles_selected" s.addAlgorithm( acts.examples.ParticleSelector( level=s.config.logLevel, inputParticles="particles_input", outputParticles=particles_selected, )) else: particles_selected = "particles_input" # Simulation alg = acts.examples.FatrasSimulation( level=s.config.logLevel, inputParticles=particles_selected, outputParticlesInitial="particles_initial", outputParticlesFinal="particles_final", outputSimHits="simhits", randomNumbers=rnd, trackingGeometry=trackingGeometry, magneticField=field, generateHitsOnSensitive=True, ) # Sequencer s.addAlgorithm(alg) # Output if outputDirCsv is not None: outputDirCsv = Path(outputDirCsv) if not outputDirCsv.exists(): outputDirCsv.mkdir() s.addWriter( acts.examples.CsvParticleWriter( level=s.config.logLevel, outputDir=str(outputDirCsv), inputParticles="particles_final", outputStem="particles_final", )) if outputDirRoot is not None: outputDirRoot = Path(outputDirRoot) if not outputDirRoot.exists(): outputDirRoot.mkdir() s.addWriter( acts.examples.RootParticleWriter( level=s.config.logLevel, inputParticles="particles_final", filePath=str(outputDirRoot / "fatras_particles_final.root"), )) if outputDirCsv is not None: s.addWriter( acts.examples.CsvParticleWriter( level=s.config.logLevel, outputDir=str(outputDirCsv), inputParticles="particles_initial", outputStem="particles_initial", )) if outputDirRoot is not None: s.addWriter( acts.examples.RootParticleWriter( level=s.config.logLevel, inputParticles="particles_initial", filePath=str(outputDirRoot / "fatras_particles_initial.root"), )) if outputDirCsv is not None: s.addWriter( acts.examples.CsvSimHitWriter( level=s.config.logLevel, inputSimHits=alg.config.outputSimHits, outputDir=str(outputDirCsv), outputStem="hits", )) if outputDirRoot is not None: s.addWriter( acts.examples.RootSimHitWriter( level=s.config.logLevel, inputSimHits=alg.config.outputSimHits, filePath=str(outputDirRoot / "hits.root"), )) return s