Skip to content

Commit

Permalink
feat: post simulation particle filter (#1851)
Browse files Browse the repository at this point in the history
as discovered in #1842 we should filter particles before and after simulation especially with geant4 as we get a lot of secondaries
  • Loading branch information
andiwand committed Feb 14, 2023
1 parent 3d91137 commit 4fac4ae
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 70 deletions.
1 change: 0 additions & 1 deletion CI/physmon/physmon.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import shutil
import datetime
import sys
import subprocess

sys.path += [
str(Path(__file__).parent.parent.parent / "Examples/Scripts/Python/"),
Expand Down
27 changes: 16 additions & 11 deletions Examples/Python/python/acts/examples/reconstruction.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ def addSeeding(
spacePointGridConfigArg: SpacePointGridConfigArg = SpacePointGridConfigArg(),
seedingAlgorithmConfigArg: SeedingAlgorithmConfigArg = SeedingAlgorithmConfigArg(),
trackParamsEstimationConfig: TrackParamsEstimationConfig = TrackParamsEstimationConfig(),
inputParticles: str = "particles_initial",
inputParticles: str = "particles",
outputDirRoot: Optional[Union[Path, str]] = None,
logLevel: Optional[acts.logging.Level] = None,
rnd: Optional[acts.examples.RandomNumbers] = None,
Expand All @@ -194,7 +194,7 @@ def addSeeding(
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
If specified as None, don't run ParticleSmearing at all (and use addCKFTracks(selectedParticles="particles_initial"))
If specified as None, don't run ParticleSmearing at all (and use addCKFTracks(selectedParticles="particles"))
particleSmearingSigmas : ParticleSmearingSigmas(d0, d0PtA, d0PtB, z0, z0PtA, z0PtB, t0, phi, theta, pRel)
ParticleSmearing configuration.
Defaults specified in Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSmearing.hpp
Expand All @@ -216,7 +216,7 @@ def addSeeding(
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"
inputParticles : str, "particles"
input particles name in the WhiteBoard
outputDirRoot : Path|str, path, None
the output folder for the Root output, None triggers no output
Expand All @@ -230,8 +230,13 @@ def addSeeding(
logger = acts.logging.getLogger("addSeeding")

if truthSeedRanges is not None:
selectedParticles = addSeedingTruthSelection(
s, inputParticles, truthSeedRanges, logLevel
selectedParticles = "truth_seeds_selected"
addSeedingTruthSelection(
s,
inputParticles,
selectedParticles,
truthSeedRanges,
logLevel,
)
else:
selectedParticles = inputParticles
Expand Down Expand Up @@ -319,13 +324,15 @@ def addSeeding(
parEstimateAlg.config.outputProtoTracks,
logLevel,
)

return s


def addSeedingTruthSelection(
s: acts.examples.Sequencer,
inputParticles: str,
truthSeedRanges: str,
outputParticles: str,
truthSeedRanges: TruthSeedRanges,
logLevel: acts.logging.Level = None,
):
"""adds truth particles filtering before filtering
Expand All @@ -351,10 +358,9 @@ def addSeedingTruthSelection(
level=logLevel,
inputParticles=inputParticles,
inputMeasurementParticlesMap="measurement_particles_map",
outputParticles="truth_seeds_selected",
outputParticles=outputParticles,
)
s.addAlgorithm(selAlg)
return selAlg.config.outputParticles


def addTruthSmearing(
Expand Down Expand Up @@ -852,7 +858,7 @@ def addCKFTracks(
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"
selectedParticles : str, "particles"
CKFPerformanceWriter truth input
trackSelectorRanges : TrackSelectorRanges(loc0, loc1, time, eta, absEta, pt, phi, removeNeutral, removeCharged)
TrackSelector configuration. Each range is specified as a tuple of (min,max).
Expand Down Expand Up @@ -1006,8 +1012,8 @@ def addTrajectoryWriters(
s.addWriter(
acts.examples.TrackFitterPerformanceWriter(
level=acts.logging.INFO,
inputTrajectories="trajectories",
inputParticles="truth_seeds_selected",
inputTrajectories="trajectories",
inputMeasurementParticlesMap="measurement_particles_map",
filePath=str(
outputDirRoot / f"performance_track_fitter_{name}.root"
Expand Down Expand Up @@ -1171,7 +1177,6 @@ def addExaTrkX(
def addAmbiguityResolution(
s,
config: AmbiguityResolutionConfig = AmbiguityResolutionConfig(),
selectedParticles: str = "truth_seeds_selected",
ckfPerformanceConfig: CKFPerformanceConfig = CKFPerformanceConfig(),
outputDirCsv: Optional[Union[Path, str]] = None,
outputDirRoot: Optional[Union[Path, str]] = None,
Expand Down
131 changes: 80 additions & 51 deletions Examples/Python/python/acts/examples/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ def addParticleGun(

s.addReader(evGen)

s.addWhiteboardAlias("particles", evGen.config.outputParticles)

if printParticles:
s.addAlgorithm(
ParticlesPrinter(
Expand Down Expand Up @@ -264,6 +266,8 @@ def addPythia8(

s.addReader(evGen)

s.addWhiteboardAlias("particles", evGen.config.outputParticles)

if printParticles:
s.addAlgorithm(
acts.examples.ParticlesPrinter(
Expand Down Expand Up @@ -304,9 +308,9 @@ def addPythia8(

def addParticleSelection(
s: acts.examples.Sequencer,
preselectParticles: ParticleSelectorConfig,
inputParticles="particles_input",
outputParticles="particles_selected",
config: ParticleSelectorConfig,
inputParticles: str,
outputParticles: str,
logLevel: Optional[acts.logging.Level] = None,
) -> None:
"""
Expand All @@ -328,22 +332,22 @@ def addParticleSelection(
s.addAlgorithm(
acts.examples.ParticleSelector(
**acts.examples.defaultKWArgs(
rhoMin=preselectParticles.rho[0],
rhoMax=preselectParticles.rho[1],
absZMin=preselectParticles.absZ[0],
absZMax=preselectParticles.absZ[1],
timeMin=preselectParticles.time[0],
timeMax=preselectParticles.time[1],
phiMin=preselectParticles.phi[0],
phiMax=preselectParticles.phi[1],
etaMin=preselectParticles.eta[0],
etaMax=preselectParticles.eta[1],
absEtaMin=preselectParticles.absEta[0],
absEtaMax=preselectParticles.absEta[1],
ptMin=preselectParticles.pt[0],
ptMax=preselectParticles.pt[1],
removeCharged=preselectParticles.removeCharged,
removeNeutral=preselectParticles.removeNeutral,
rhoMin=config.rho[0],
rhoMax=config.rho[1],
absZMin=config.absZ[0],
absZMax=config.absZ[1],
timeMin=config.time[0],
timeMax=config.time[1],
phiMin=config.phi[0],
phiMax=config.phi[1],
etaMin=config.eta[0],
etaMax=config.eta[1],
absEtaMin=config.absEta[0],
absEtaMax=config.absEta[1],
ptMin=config.pt[0],
ptMax=config.pt[1],
removeCharged=config.removeCharged,
removeNeutral=config.removeNeutral,
),
level=customLogLevel(),
inputParticles=inputParticles,
Expand All @@ -352,18 +356,17 @@ def addParticleSelection(
)


@acts.examples.NamedTypeArgs(
preselectParticles=ParticleSelectorConfig,
)
def addFatras(
s: acts.examples.Sequencer,
trackingGeometry: acts.TrackingGeometry,
field: acts.MagneticFieldProvider,
rnd: acts.examples.RandomNumbers,
preSelectParticles: Optional[ParticleSelectorConfig] = ParticleSelectorConfig(),
postSelectParticles: Optional[ParticleSelectorConfig] = None,
enableInteractions=False,
inputParticles: str = "particles_input",
outputDirCsv: Optional[Union[Path, str]] = None,
outputDirRoot: Optional[Union[Path, str]] = None,
rnd: Optional[acts.examples.RandomNumbers] = None,
preselectParticles: Optional[ParticleSelectorConfig] = ParticleSelectorConfig(),
enableInteractions=False,
logLevel: Optional[acts.logging.Level] = None,
) -> None:
"""This function steers the detector simulation using Fatras
Expand All @@ -374,35 +377,34 @@ def addFatras(
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
rnd : RandomNumbers
random number generator
preselectParticles : ParticleSelectorConfig(rho, absZ, time, phi, eta, absEta, pt, removeCharged, removeNeutral), None
preSelectParticles : ParticleSelectorConfig(rho, absZ, time, phi, eta, absEta, pt, removeCharged, removeNeutral), None
ParticleSelector configuration to select particles as input to Fatras. Each range is specified as a tuple of (min,max).
Default of no selections specified in Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.hpp
Specify preselectParticles=None to inhibit ParticleSelector altogether.
Specify preSelectParticles=None to inhibit ParticleSelector altogether.
postSelectParticles : ParticleSelectorConfig(rho, absZ, time, phi, eta, absEta, pt, removeCharged, removeNeutral), None
Similar to preSelectParticles but applied after simulation to "particles_initial", therefore also filters secondaries.
enableInteractions : Enable the particle interactions in the simulation
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
"""

customLogLevel = acts.examples.defaultLogging(s, logLevel)

# Preliminaries
rnd = rnd or acts.examples.RandomNumbers()

# Selector
if preselectParticles is not None:
if preSelectParticles is not None:
particles_selected = "particles_selected"
addParticleSelection(
s,
preselectParticles,
inputParticles="particles_input",
preSelectParticles,
inputParticles=inputParticles,
outputParticles=particles_selected,
)
else:
particles_selected = "particles_input"
particles_selected = inputParticles

# Simulation
alg = acts.examples.FatrasSimulation(
Expand All @@ -424,6 +426,19 @@ def addFatras(
# Sequencer
s.addAlgorithm(alg)

# Selector
if postSelectParticles is not None:
postSelectedParticles = "particles_initial_selected"
addParticleSelection(
s,
preSelectParticles,
inputParticles=alg.config.outputParticlesInitial,
outputParticles=postSelectedParticles,
)
s.addWhiteboardAlias("particles", postSelectedParticles)
else:
s.addWhiteboardAlias("particles", alg.config.outputParticlesInitial)

# Output
addSimWriters(
s,
Expand Down Expand Up @@ -526,9 +541,6 @@ def getG4DetectorContruction(
raise AttributeError(f"cannot find a suitable detector construction for {detector}")


@acts.examples.NamedTypeArgs(
preselectParticles=ParticleSelectorConfig,
)
def addGeant4(
s: acts.examples.Sequencer,
detector: Optional[Any],
Expand All @@ -538,7 +550,9 @@ def addGeant4(
g4detectorConstruction: Optional[Any] = None,
volumeMappings: List[str] = [],
materialMappings: List[str] = [],
preselectParticles: Optional[ParticleSelectorConfig] = ParticleSelectorConfig(),
inputParticles: str = "particles_input",
preSelectParticles: Optional[ParticleSelectorConfig] = ParticleSelectorConfig(),
postSelectParticles: Optional[ParticleSelectorConfig] = None,
outputDirCsv: Optional[Union[Path, str]] = None,
outputDirRoot: Optional[Union[Path, str]] = None,
logLevel: Optional[acts.logging.Level] = None,
Expand All @@ -553,31 +567,33 @@ def addGeant4(
field : magnetic field
rnd : RandomNumbers, None
random number generator
preSelectParticles : ParticleSelectorConfig(rho, absZ, time, phi, eta, absEta, pt, removeCharged, removeNeutral), None
ParticleSelector configuration to select particles as input to Geant4. Each range is specified as a tuple of (min,max).
Default of no selections specified in Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.hpp
Specify preSelectParticles=None to inhibit ParticleSelector altogether.
postSelectParticles : ParticleSelectorConfig(rho, absZ, time, phi, eta, absEta, pt, removeCharged, removeNeutral), None
Similar to preSelectParticles but applied after simulation to "particles_initial", therefore also filters secondaries.
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
preselectParticles : ParticleSelectorConfig(rho, absZ, time, phi, eta, absEta, pt, removeCharged, removeNeutral), None
ParticleSelector configuration to select particles as input to Geant4. Each range is specified as a tuple of (min,max).
Default of no selections specified in Examples/Algorithms/TruthTracking/ActsExamples/TruthTracking/ParticleSelector.hpp
Specify preselectParticles=None to inhibit ParticleSelector altogether.
"""

from acts.examples.geant4 import Geant4Simulation, geant4SimulationConfig

customLogLevel = acts.examples.defaultLogging(s, logLevel)

# Selector
if preselectParticles is not None:
if preSelectParticles is not None:
particles_selected = "particles_selected"
addParticleSelection(
s,
preselectParticles,
inputParticles="particles_input",
preSelectParticles,
inputParticles=inputParticles,
outputParticles=particles_selected,
)
else:
particles_selected = "particles_input"
particles_selected = inputParticles

if g4detectorConstruction is None:
if detector is None:
Expand Down Expand Up @@ -607,6 +623,19 @@ def addGeant4(
# Sequencer
s.addAlgorithm(alg)

# Selector
if postSelectParticles is not None:
postSelectedParticles = "particles_initial_selected"
addParticleSelection(
s,
preSelectParticles,
inputParticles=g4conf.outputParticlesInitial,
outputParticles=postSelectedParticles,
)
s.addWhiteboardAlias("particles", postSelectedParticles)
else:
s.addWhiteboardAlias("particles", alg.config.outputParticlesInitial)

# Output
addSimWriters(
s,
Expand Down

0 comments on commit 4fac4ae

Please sign in to comment.