ATLAS Offline Software
Loading...
Searching...
No Matches
ActsFatrasSimTool.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5#ifndef ISF_ACTSTOOLS_ACTSFATRASSIMTOOL_H
6#define ISF_ACTSTOOLS_ACTSFATRASSIMTOOL_H
7
8// Gaudi
9#include "GaudiKernel/ServiceHandle.h"
10#include "GaudiKernel/ToolHandle.h"
11
12// Athena
16
17// ISF
26
27// ACTS
28#include "Acts/Utilities/UnitVectors.hpp"
29#include "ActsInterop/Logger.h"
31#include "Acts/Geometry/GeometryContext.hpp"
32#include "Acts/MagneticField/MagneticFieldContext.hpp"
33#include "Acts/EventData/BoundTrackParameters.hpp"
34#include "Acts/Propagator/Navigator.hpp"
35#include "Acts/Propagator/EigenStepper.hpp"
36#include "Acts/Propagator/EigenStepperDefaultExtension.hpp"
37#include "Acts/Propagator/StraightLineStepper.hpp"
38#include "Acts/Propagator/detail/SteppingLogger.hpp"
39#include "Acts/Propagator/ActorList.hpp"
40#include "Acts/Propagator/Propagator.hpp"
41#include "Acts/Definitions/ParticleData.hpp"
42#include "ActsFatras/EventData/GenerationProcess.hpp"
43#include "ActsFatras/Kernel/InteractionList.hpp"
44#include "ActsFatras/Kernel/SingleParticleSimulation.hpp"
45#include "ActsFatras/Kernel/SingleParticleSimulationResult.hpp"
46#include "ActsFatras/Kernel/MultiParticleSimulation.hpp"
47#include "ActsFatras/Physics/Decay/NoDecay.hpp"
48#include "ActsFatras/Physics/StandardInteractions.hpp"
49#include "ActsFatras/Physics/ElectroMagnetic/PhotonConversion.hpp"
50#include "ActsFatras/Selectors/SurfaceSelectors.hpp"
51// Tracking
54
55#include <algorithm>
56#include <cassert>
57#include <vector>
58
59class AtlasDetectorID;
60
61namespace iFatras {
62 class ISimHitCreator;
63}
64
65namespace ISF {
66class IParticleHelper;
67
73
75
76 public:
80 bool operator()(const Acts::Surface &surface) const {
81 return surface.isSensitive();
82 }
83 };
84 // SingleParticleSimulation
91 template <typename propagator_t, typename interactions_t,
92 typename hit_surface_selector_t, typename decay_t>
95 propagator_t propagator;
97 decay_t decay;
99 interactions_t interactions;
101 hit_surface_selector_t selectHitSurface;
103 double maxStepSize = 3.0; // leght in m
104 double maxStep = 1000;
106 double pathLimit = 100.0; // lenght in cm
107 bool loopProtection = true;
108 double loopFraction = 0.5;
109 double targetTolerance = 0.0001;
110 double stepSizeCutOff = 0.;
111 // parameters for densEnv propagator options
112 double meanEnergyLoss = true;
113 bool includeGgradient = true;
114 double momentumCutOff = 0.;
115
117 std::shared_ptr<const Acts::Logger> localLogger = nullptr;
118
120 SingleParticleSimulation(propagator_t &&propagator_,
121 std::shared_ptr<const Acts::Logger> localLogger_)
122 : propagator(propagator_), localLogger(localLogger_) {}
123
125 const Acts::Logger &logger() const { return *localLogger; }
126
136 template <typename generator_t>
137 Acts::Result<ActsFatras::SingleParticleSimulationResult> simulate(
138 const Acts::GeometryContext &geoCtx,
139 const Acts::MagneticFieldContext &magCtx, generator_t &generator,
140 const ActsFatras::Particle &particle) const {
141 assert(localLogger and "Missing local logger");
142 ACTS_VERBOSE("Using ActsFatrasSimTool simulate()");
143 // propagator-related additional types
144 using SteppingLogger = Acts::detail::SteppingLogger;
145 using SimulationActor = ActsFatras::detail::SimulationActor<generator_t, decay_t, interactions_t, hit_surface_selector_t>;
146 using Result = typename SimulationActor::result_type;
147 using Actions = Acts::ActorList<SteppingLogger, SimulationActor, Acts::EndOfWorldReached>;
148 using PropagatorOptions = typename propagator_t::template Options<Actions>;
149
150 // Construct per-call options.
151 PropagatorOptions options(geoCtx, magCtx);
152 // setup the interactor as part of the propagator options
153 auto &actor = options.actorList.template get<SimulationActor>();
154 actor.generator = &generator;
155 actor.decay = decay;
156 actor.interactions = interactions;
157 actor.selectHitSurface = selectHitSurface;
158 actor.initialParticle = particle;
159 // use AnyCharge to be able to handle neutral and charged parameters
160 Acts::BoundTrackParameters startPoint = Acts::BoundTrackParameters::createCurvilinear(
161 particle.fourPosition(), particle.direction(),
162 particle.qOverP(), std::nullopt, particle.hypothesis());
163 options.pathLimit = pathLimit * Acts::UnitConstants::cm;
164 options.loopProtection = loopProtection;
165 options.maxSteps = maxStep;
166 options.stepping.maxStepSize = maxStepSize * Acts::UnitConstants::m;
167 options.direction = Acts::Direction::Forward();
168
169 auto result = propagator.propagate(startPoint, options);
170 if (not result.ok()) {
171 return result.error();
172 }
173 return result.value().template get<Result>();
174 }
175 };// end of SingleParticleSimulation
176
177 // Standard generator
178 using Generator = std::ranlux48;
179 // Use default navigator
180 using Navigator = Acts::Navigator;
181 // Propagate charged particles numerically in the B-field
182 using ChargedStepper = Acts::EigenStepper<Acts::EigenStepperDefaultExtension>;
183 using ChargedPropagator = Acts::Propagator<ChargedStepper, Navigator>;
184 // Propagate neutral particles in straight lines
185 using NeutralStepper = Acts::StraightLineStepper;
186 using NeutralPropagator = Acts::Propagator<NeutralStepper, Navigator>;
187
188 // ===============================
189 // Setup ActsFatras simulator types
190 // Charged
191 using ChargedSelector = ActsFatras::ChargedSelector;
193 ActsFatras::StandardChargedElectroMagneticInteractions;
196 ActsFatras::NoDecay>;
197 // Neutral
198 using NeutralSelector = ActsFatras::NeutralSelector;
199 using NeutralInteractions = ActsFatras::InteractionList<ActsFatras::PhotonConversion>;
201 NeutralPropagator, NeutralInteractions, ActsFatras::NoSurface,
202 ActsFatras::NoDecay>;
203 // Combined
204 using Simulation = ActsFatras::MultiParticleSimulation<
207 // ===============================
209 inline Amg::Vector3D convertMom3FromActs(const Acts::Vector3& actsMom) {
210 Amg::Vector3D threeMom{Amg::Vector3D::Zero()};
211 threeMom[Amg::x] = ActsTrk::energyToAthena(actsMom[Acts::eMom0]);
212 threeMom[Amg::y] = ActsTrk::energyToAthena(actsMom[Acts::eMom1]);
213 threeMom[Amg::z] = ActsTrk::energyToAthena(actsMom[Acts::eMom2]);
214 return threeMom;
215 }
216
217 inline Amg::Vector3D convertPos3FromActs(const Acts::Vector3& actsPos) {
218 Amg::Vector3D pos{Amg::Vector3D::Zero()};
219 pos[Amg::x] = ActsTrk::lengthToAthena(actsPos[Acts::ePos0]);
220 pos[Amg::y] = ActsTrk::lengthToAthena(actsPos[Acts::ePos1]);
221 pos[Amg::z] = ActsTrk::lengthToAthena(actsPos[Acts::ePos2]);
222 return pos;
223 }
224
225 ActsFatrasSimTool(const std::string& type, const std::string& name,
226 const IInterface* parent);
227 virtual ~ActsFatrasSimTool();
228
229 // ISF BaseSimulatorTool Interface methods
230 virtual StatusCode initialize() override;
231 virtual StatusCode simulate(const EventContext& ctx, ISFParticle& isp, ISFParticleContainer&,
232 McEventCollection*) override;
233 virtual StatusCode simulateVector(
234 const EventContext& ctx,
235 const ISFParticleVector& particles,
236 ISFParticleContainer& secondaries,
237 McEventCollection* mcEventCollection, McEventCollection *shadowTruth=nullptr) override;
238 virtual StatusCode setupEvent(const EventContext&) override {
239 ATH_CHECK(m_truthRecordSvc->initializeTruthCollection());
240 m_pixelSiHits.Clear();
241 m_sctSiHits.Clear();
242 return StatusCode::SUCCESS; };
243 virtual StatusCode releaseEvent(const EventContext& ctx) override {
244 std::vector<SiHitCollection> hitcolls;
245 hitcolls.push_back(m_pixelSiHits);
246 hitcolls.push_back(m_sctSiHits);
247 ATH_CHECK(m_ActsFatrasWriteHandler->WriteHits(hitcolls,ctx));
248 ATH_CHECK(m_truthRecordSvc->releaseEvent());
249 return StatusCode::SUCCESS; };
250 virtual ISF::SimulationFlavor simFlavor() const override{
251 return ISF::Fatras; };
252
253 virtual Acts::MagneticFieldContext getMagneticFieldContext(
254 const EventContext&) const;
255
256 private:
257 // For sihit creation
260 // Templated tool retrieval
261 template <class T>
262 StatusCode retrieveTool(ToolHandle<T>& thandle) {
263 if (!thandle.empty() && thandle.retrieve().isFailure()) {
264 ATH_MSG_FATAL("Cannot retrieve " << thandle << ". Abort.");
265 return StatusCode::FAILURE;
266 } else ATH_MSG_DEBUG("Successfully retrieved " << thandle);
267 return StatusCode::SUCCESS;
268 }
269
270 bool checkStartSurface(const Acts::MagneticFieldContext& mctx,
271 const Acts::GeometryContext& anygctx,
272 const ChargedPropagator& chargedPropagator,
273 const Acts::BoundTrackParameters& startParameters,
274 Acts::Direction navDir = Acts::Direction::Forward(),
275 double pathLimit = std::numeric_limits<double>::max()) const;
276
277 // Random number service
278 ServiceHandle<IAthRNGSvc> m_rngSvc{this, "RNGService", "AthRNGSvc"};
280 Gaudi::Property<std::string> m_randomEngineName{this, "RandomEngineName",
281 "RandomEngineName", "Name of random number stream"};
282
283 // GeoID service
284 ServiceHandle<ISF::IGeoIDSvc> m_geoIDSvc{this, "GeoIDSvc", "ISF::GeoIDSvc"};
285
286 // ACTS Extrapolator
287 PublicToolHandle<ActsTrk::IExtrapolationTool> m_extrapolationTool{this, "ExtrapolationTool", "ActsExtrapolationTool"};
288
289 // Tracking geometry
290 PublicToolHandle<ActsTrk::ITrackingGeometryTool> m_trackingGeometryTool{
291 this, "TrackingGeometryTool", "ActsTrackingGeometryTool"};
292 std::shared_ptr<const Acts::TrackingGeometry> m_trackingGeometry;
293
294 // Magnetic field
295 SG::ReadCondHandleKey<AtlasFieldCacheCondObj> m_fieldCacheCondObjInputKey {this, "AtlasFieldCacheCondObj", "fieldCondObj", "Name of the Magnetic Field conditions object key"};
296
297 // Logging
298 std::shared_ptr<const Acts::Logger> m_logger{nullptr};
299
300 // ISF Tools
301 PublicToolHandle<ISF::IParticleFilter> m_particleFilter{
302 this, "ParticleFilter", "", "Particle filter kinematic cuts, etc."};
303
304 ServiceHandle<ISF::ITruthSvc> m_truthRecordSvc{this, "TruthRecordService", "ISF_TruthRecordSvc", ""};
305
306 // ActsFatrasHitConvtTool
307 ToolHandle<ActsFatrasWriteHandler> m_ActsFatrasWriteHandler{
308 this, "ActsFatrasWriteHandler", "ActsFatrasWriteHandler"};
309
310 Gaudi::Property<double> m_interact_minPt{this, "Interact_MinPt", 50.0,
311 "Min pT of the interactions (MeV)"};
312
313 // DensEnviroment Propergator option
314 Gaudi::Property<bool> m_meanEnergyLoss{this, "MeanEnergyLoss", true, "Toggle between mean and mode evaluation of energy loss"};
315 Gaudi::Property<bool> m_includeGgradient{this, "IncludeGgradient", true, "Boolean flag for inclusion of d(dEds)d(q/p) into energy loss"};
316 Gaudi::Property<double> m_momentumCutOff{this, "MomentumCutOff", 0., "Cut-off value for the momentum in SI units"};
317 // Propergator option
318 Gaudi::Property<double> m_maxStep{this, "MaxSteps", 1000,
319 "Max number of steps"};
320 Gaudi::Property<double> m_maxRungeKuttaStepTrials{this, "MaxRungeKuttaStepTrials", 10000,
321 "Maximum number of Runge-Kutta steps for the stepper step call"};
322 Gaudi::Property<double> m_maxStepSize{this, "MaxStepSize", 3.0,
323 "Max step size (converted to Acts::UnitConstants::m)"};
324 Gaudi::Property<double> m_pathLimit{this, "PathLimit", 100.0,
325 "Track path limit (converted to Acts::UnitConstants::cm)"};
326 Gaudi::Property<bool> m_loopProtection{this, "LoopProtection", true,
327 "Loop protection, it adapts the pathLimit"};
328 Gaudi::Property<double> m_loopFraction{this, "LoopFraction", 0.5,
329 "Allowed loop fraction, 1 is a full loop"};
330 Gaudi::Property<double> m_tolerance{this, "Tolerance", 0.0001,
331 "Tolerance for the error of the integration"};
332 Gaudi::Property<double> m_stepSizeCutOff{this, "StepSizeCutOff", 0.,
333 "Cut-off value for the step size"};
334
335 // https://vmc-project.github.io/geant4_vmc/g4vmc_html/TG4ProcessMapPhysics_8cxx_source.html#:~:text=155%20pMap%2D%3EAdd(DECAY,);%20//%20G4%20value:%20231
336 Gaudi::Property<std::map<int,int>> m_processTypeMap{this, "ProcessTypeMap",
337 {{0,0}, {1,201}, {2,14}, {3,3}, {4,121}}, "proessType map <ActsFatras,G4>"};
338 //{{ActsFatras::GenerationProcess::eUndefined,0}, {ActsFatras::GenerationProcess::eDecay,201}, {ActsFatras::GenerationProcess::ePhotonConversion,14}, {ActsFatras::GenerationProcess::eBremsstrahlung,3}, {ActsFatras::GenerationProcess::eNuclearInteraction,121}}
339 inline int getATLASProcessCode(ActsFatras::GenerationProcess actspt){return m_processTypeMap[static_cast<uint32_t>(actspt)];};
340};
341
342} // namespace ISF
343
344#endif
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_FATAL(x)
#define ATH_MSG_DEBUG(x)
AtlasHitsVector< SiHit > SiHitCollection
Define macros for attributes used to control the static checker.
A wrapper class for event-slot-local random engines.
Definition RNGWrapper.h:56
This class provides an interface to generate or decode an identifier for the upper levels of the dete...
ActsFatras::StandardChargedElectroMagneticInteractions ChargedInteractions
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCacheCondObjInputKey
ActsFatras::NeutralSelector NeutralSelector
Gaudi::Property< double > m_maxStepSize
ActsFatras::ChargedSelector ChargedSelector
Acts::EigenStepper< Acts::EigenStepperDefaultExtension > ChargedStepper
PublicToolHandle< ActsTrk::ITrackingGeometryTool > m_trackingGeometryTool
Gaudi::Property< double > m_tolerance
Gaudi::Property< double > m_interact_minPt
StatusCode retrieveTool(ToolHandle< T > &thandle)
Gaudi::Property< bool > m_meanEnergyLoss
ServiceHandle< IAthRNGSvc > m_rngSvc
Acts::Propagator< NeutralStepper, Navigator > NeutralPropagator
virtual StatusCode simulate(const EventContext &ctx, ISFParticle &isp, ISFParticleContainer &, McEventCollection *) override
PublicToolHandle< ActsTrk::IExtrapolationTool > m_extrapolationTool
std::shared_ptr< const Acts::TrackingGeometry > m_trackingGeometry
Gaudi::Property< double > m_momentumCutOff
virtual ISF::SimulationFlavor simFlavor() const override
std::shared_ptr< const Acts::Logger > m_logger
bool checkStartSurface(const Acts::MagneticFieldContext &mctx, const Acts::GeometryContext &anygctx, const ChargedPropagator &chargedPropagator, const Acts::BoundTrackParameters &startParameters, Acts::Direction navDir=Acts::Direction::Forward(), double pathLimit=std::numeric_limits< double >::max()) const
Gaudi::Property< double > m_maxStep
Gaudi::Property< double > m_pathLimit
Gaudi::Property< double > m_stepSizeCutOff
Gaudi::Property< bool > m_loopProtection
Gaudi::Property< std::map< int, int > > m_processTypeMap
ActsFatrasSimTool(const std::string &type, const std::string &name, const IInterface *parent)
int getATLASProcessCode(ActsFatras::GenerationProcess actspt)
virtual StatusCode setupEvent(const EventContext &) override
Setup Event chain - in case of a begin-of event action is needed.
ServiceHandle< ISF::ITruthSvc > m_truthRecordSvc
ATHRNG::RNGWrapper *m_randomEngine ATLAS_THREAD_SAFE
SiHitCollection m_pixelSiHits
Gaudi::Property< bool > m_includeGgradient
virtual StatusCode initialize() override
PublicToolHandle< ISF::IParticleFilter > m_particleFilter
SingleParticleSimulation< ChargedPropagator, ChargedInteractions, HitSurfaceSelector, ActsFatras::NoDecay > ChargedSimulation
virtual StatusCode releaseEvent(const EventContext &ctx) override
Release Event chain - in case of an end-of event action is needed.
Amg::Vector3D convertMom3FromActs(const Acts::Vector3 &actsMom)
Convert ACTS momentum to Athena momentum.
ToolHandle< ActsFatrasWriteHandler > m_ActsFatrasWriteHandler
virtual StatusCode simulateVector(const EventContext &ctx, const ISFParticleVector &particles, ISFParticleContainer &secondaries, McEventCollection *mcEventCollection, McEventCollection *shadowTruth=nullptr) override
Simulation call for vectors of particles.
Gaudi::Property< double > m_maxRungeKuttaStepTrials
SingleParticleSimulation< NeutralPropagator, NeutralInteractions, ActsFatras::NoSurface, ActsFatras::NoDecay > NeutralSimulation
virtual Acts::MagneticFieldContext getMagneticFieldContext(const EventContext &) const
Gaudi::Property< double > m_loopFraction
ServiceHandle< ISF::IGeoIDSvc > m_geoIDSvc
ActsFatras::InteractionList< ActsFatras::PhotonConversion > NeutralInteractions
Amg::Vector3D convertPos3FromActs(const Acts::Vector3 &actsPos)
Acts::Propagator< ChargedStepper, Navigator > ChargedPropagator
Gaudi::Property< std::string > m_randomEngineName
Acts::StraightLineStepper NeutralStepper
BaseSimulatorTool(const std::string &type, const std::string &name, const IInterface *parent)
The generic ISF particle definition,.
Definition ISFParticle.h:42
This defines the McEventCollection, which is really just an ObjectVector of McEvent objectsFile: Gene...
The sim hit creator recieves a std::vector of Trk::TrackParameters and uses them to create simulated ...
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition hcg.cxx:132
constexpr double energyToAthena(const double actsE)
Converts an energy scalar from Acts to Athena units.
constexpr double lengthToAthena(const double actsL)
Converts a length scalar from Acts to Athena units.
Eigen::Matrix< double, 3, 1 > Vector3D
ISFParticleOrderedQueue.
int SimulationFlavor
Identifier type for simulation flavor.
std::list< ISF::ISFParticle * > ISFParticleContainer
generic ISFParticle container (not necessarily a std::list!)
std::vector< ISF::ISFParticle * > ISFParticleVector
ISFParticle vector.
Simple struct to select surfaces where hits should be generated.
bool operator()(const Acts::Surface &surface) const
Check if the surface should be used.
Single particle simulation with fixed propagator, interactions, and decay.
const Acts::Logger & logger() const
Provide access to the local logger instance, e.g. for logging macros.
Acts::Result< ActsFatras::SingleParticleSimulationResult > simulate(const Acts::GeometryContext &geoCtx, const Acts::MagneticFieldContext &magCtx, generator_t &generator, const ActsFatras::Particle &particle) const
Simulate a single particle without secondaries.
SingleParticleSimulation(propagator_t &&propagator_, std::shared_ptr< const Acts::Logger > localLogger_)
Alternatively construct the simulator with an external logger.