ATLAS Offline Software
Loading...
Searching...
No Matches
ActsFatrasSimTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4#include <algorithm>
5#include <random>
6
7#include "ActsFatrasSimTool.h"
8#include "Acts/ActsVersion.hpp"
9#include <Acts/Utilities/StringHelpers.hpp>
10#include "Acts/Definitions/PdgParticle.hpp"
11
12#include "CLHEP/Random/RandFlat.h"
13#include "CLHEP/Random/RandomEngine.h"
14
17
18using namespace Acts::UnitLiterals;
19
21 const std::string& name,
22 const IInterface* parent)
23 : BaseSimulatorTool(type, name, parent) {}
24
26
29 ATH_MSG_INFO("ISF::ActsFatrasSimTool update with ACTS version: v"
30 << Acts::VersionMajor << "." << Acts::VersionMinor << "."
31 << Acts::VersionPatch << " [" << Acts::CommitHash.value_or("unknown hash") << "]");
32 // Retrieve particle filter
33 ATH_CHECK(m_particleFilter.retrieve());
34 ATH_MSG_INFO("Using particle filter: " << m_particleFilter.typeAndName());
35 // setup logger
36 m_logger = makeActsAthenaLogger(this, std::string("ActsFatras"),std::string("ActsFatrasSimTool"));
37
38 // Geometry identifier service
39 if ( !m_geoIDSvc.empty() && m_geoIDSvc.retrieve().isFailure()){
40 ATH_MSG_FATAL ("Could not retrieve " << m_geoIDSvc);
41 return StatusCode::FAILURE;
42 }
43
44 // Acts Extrapolator
46 ATH_MSG_INFO( "- ActsExtrapolationTool : " << m_extrapolationTool.typeAndName() );
47
48 // retrive tracking geo tool
50 m_trackingGeometry = m_trackingGeometryTool->trackingGeometry();
51
52 //retrive Magnetfield tool
53 ATH_MSG_VERBOSE("Using ATLAS magnetic field service");
55
56 // Random number service
57 if (m_rngSvc.retrieve().isFailure()) {
58 ATH_MSG_FATAL("Could not retrieve " << m_rngSvc);
59 return StatusCode::FAILURE;
60 }
61 // Get own engine with own seeds
62 m_randomEngine = m_rngSvc->getEngine(this, m_randomEngineName.value());
63 if (!m_randomEngine) {
64 ATH_MSG_FATAL("Could not get random engine '" << m_randomEngineName.value() << "'");
65 return StatusCode::FAILURE;
66 }
67
68 // ISF truth service
69 ATH_CHECK (m_truthRecordSvc.retrieve());
70 ATH_MSG_DEBUG( "- Using ISF TruthRecordSvc : " << m_truthRecordSvc.typeAndName() );
71 return StatusCode::SUCCESS;
72}
73
74StatusCode ISF::ActsFatrasSimTool::simulate(const EventContext& ctx,
75 ISFParticle& isp, ISFParticleContainer& secondaries,
76 McEventCollection* mcEventCollection) {
77 ATH_MSG_VERBOSE("Particle " << isp << " received for simulation.");
78 // Check if particle passes filter, if there is one
79 if (!m_particleFilter.empty() && !m_particleFilter->passFilter(isp)) {
80 ATH_MSG_VERBOSE("ISFParticle " << isp << " does not pass selection. Ignoring.");
81 return StatusCode::SUCCESS;
82 }
83 // Process ParticleState from particle stack
84 // Wrap the input ISFParticle in an STL vector with size of 1
85 const ISF::ISFParticleVector ispVector(1, &isp);
86 ATH_CHECK(this->simulateVector(ctx, ispVector, secondaries, mcEventCollection));
87 ATH_MSG_VERBOSE("Simulation done");
88 return StatusCode::SUCCESS;
89}
90
92 const EventContext& ctx,
93 const ISFParticleVector& particles,
94 ISFParticleContainer& secondaries,
95 McEventCollection* /*mcEventCollection*/, McEventCollection *) {
96 // filter particles
97 std::vector<ISFParticle*> selectedParticles;
98 for (const auto isfp : particles) {
99 if (!m_particleFilter.empty() && !m_particleFilter->passFilter(*isfp)) {
100 ATH_MSG_VERBOSE("ISFParticle " << *isfp << " does not pass selection. Ignoring.");
101 continue;
102 }
103 selectedParticles.push_back(isfp);
104 }
105 if (selectedParticles.empty()) {
106 ATH_MSG_VERBOSE("No particles passed selection. Ignoring.");
107 return StatusCode::SUCCESS;
108 }
109 // Set random seed for current event
110 m_randomEngine->setSeed(m_randomEngineName, ctx);
111 CLHEP::HepRandomEngine* randomEngine = m_randomEngine->getEngine(ctx);
112 Generator generator(CLHEP::RandFlat::shoot(randomEngine->flat()));
113 ATH_MSG_VERBOSE(name() << " RNG seed " << CLHEP::RandFlat::shoot(randomEngine->flat()));
114 ATH_MSG_VERBOSE(name() << " received vector of size "
115 << selectedParticles.size() << " particles for simulation.");
116
117 // construct the ACTS simulator
118 Acts::Navigator navigator( Acts::Navigator::Config{ m_trackingGeometry }, m_logger);
119 auto bField = std::make_shared<ATLASMagneticFieldWrapper>();
120 auto chargedStepper = ChargedStepper(std::move(bField));
121 auto neutralStepper = NeutralStepper();
122 auto chargedPropagator = ChargedPropagator(chargedStepper, navigator, m_logger);
123 auto neutralPropagator = NeutralPropagator(neutralStepper, navigator, m_logger);
124 ChargedSimulation simulatorCharged(std::move(chargedPropagator), m_logger);
125 NeutralSimulation simulatorNeutral(std::move(neutralPropagator), m_logger);
126 Simulation simulator=Simulation(std::move(simulatorCharged),std::move(simulatorNeutral));
127 ATH_MSG_VERBOSE(name() << " Min pT for interaction " << m_interact_minPt * Acts::UnitConstants::MeV << " GeV");
128 // Acts propagater options
129 simulator.charged.maxStepSize = m_maxStepSize;
130 simulator.charged.maxStep = m_maxStep;
131 simulator.charged.pathLimit = m_pathLimit;
132 simulator.charged.maxRungeKuttaStepTrials = m_maxRungeKuttaStepTrials;
133 simulator.charged.loopProtection = m_loopProtection;
134 simulator.charged.loopFraction = m_loopFraction;
135 simulator.charged.targetTolerance = m_tolerance;
136 simulator.charged.stepSizeCutOff = m_stepSizeCutOff;
137 // Create interaction list
138 simulator.charged.interactions = ActsFatras::makeStandardChargedElectroMagneticInteractions(m_interact_minPt * Acts::UnitConstants::MeV);
139
140 // Construct the ACTS propagator for starting surface check
141 auto surfaceCheckPropagator = ChargedPropagator(chargedStepper, navigator);
142
143 // get Geo and Mag map
144 ATH_MSG_VERBOSE(name() << " Getting per event Geo and Mag map");
145 Acts::MagneticFieldContext mctx = getMagneticFieldContext(ctx);
146 const auto& gctx = m_trackingGeometryTool->getGeometryContext(ctx);
147 auto anygctx = gctx.context();
148 // Loop over ISFParticleVector and process each separately
149 ATH_MSG_VERBOSE(name() << " Processing particles in ISFParticleVector.");
150 for (const auto isfp : selectedParticles) {
151 // ====ACTSFatras Simulation====
152 // //
153 // input/output particle and hits containers
154 // Convert to ActsFatras::Particle
155 // ISF: Energy, mass, and momentum are in MeV, position in mm
156 // Acts: Energy, mass, and momentum are in GeV, position in mm
157 ATH_MSG_DEBUG(name() << " Convert ISF::Particle(mass) " << isfp->id()<<"|" << *isfp<<"(" << isfp->mass() << ")");
158 std::vector<ActsFatras::Particle> input = std::vector<ActsFatras::Particle>{
159 ActsFatras::Particle(ActsFatras::Barcode().withVertexPrimary(0).withParticle(isfp->id()), static_cast<Acts::PdgParticle>(isfp->pdgCode()),
160 isfp->charge(),isfp->mass() * Acts::UnitConstants::MeV)
161 .setDirection(Acts::makeDirectionFromPhiEta(isfp->momentum().phi(), isfp->momentum().eta()))
162 .setAbsoluteMomentum(isfp->momentum().mag() * Acts::UnitConstants::MeV)
163 .setPosition4(ActsTrk::convertPosToActs(isfp->position(), isfp->timeStamp()))};
164 ATH_MSG_DEBUG(name() << " Propagating ActsFatras::Particle vertex|particle|generation|subparticle, " << input[0]);
165 std::vector<ActsFatras::Particle> simulatedInitial;
166 std::vector<ActsFatras::Particle> simulatedFinal;
167 std::vector<ActsFatras::Hit> hits;
168 // simulate
169 auto result=simulator.simulate(anygctx, mctx, generator, input, simulatedInitial, simulatedFinal, hits);
170 auto simulatedFailure=result.value();
171 if (simulatedFailure.size()>0){
172 for (const auto& simfail : simulatedFailure){
173 auto errCode = Acts::make_error_code(Acts::PropagatorError(simfail.error.value()));
174 ATH_MSG_WARNING(name() << " Particle id " <<simfail.particle.particleId()<< ": fail to be simulated during Propagation: " << errCode.message());
175 ATH_MSG_WARNING(name() << " Particle vertex|particle|generation|subparticle"<<simfail.particle << " starts from position" << Acts::toString(simfail.particle.position()) << " and direction " << Acts::toString(simfail.particle.direction()));
176 return StatusCode::SUCCESS;
177 }
178 }
179
180 ATH_MSG_DEBUG(name() << " initial particle " << simulatedInitial[0]);
181 ATH_MSG_DEBUG(name() << " ActsFatras simulator hits: " << hits.size());
182 int i = 0;
183 for (const auto& hit : hits) {
184 ATH_MSG_DEBUG(name() << " hit pos: " << hit.position() );
185 ++i;
186 if (i>5) break;
187 }
188 ATH_MSG_DEBUG(name() << " No. of particles after ActsFatras simulator: " << simulatedFinal.size());
189 if (!simulatedFinal.empty()){
190 ATH_MSG_DEBUG(name() << " start procesing secondaries");
191 auto itr = simulatedFinal.begin();
192 // Save hits of isfp
193 std::vector<ActsFatras::Hit> particle_hits;
194 if (itr->numberOfHits() > 0) {
195 std::copy(hits.begin(), hits.begin()+itr->numberOfHits(), std::back_inserter(particle_hits));
197 }
198 // Process secondaries
199 auto isKilled = !itr->isAlive();
200 int maxGeneration = simulatedFinal.back().particleId().generation();
201 ATH_MSG_DEBUG(name() << " maxGeneration: "<< maxGeneration);
202 for (int gen = 0; gen <= maxGeneration; ++gen){
203 ATH_MSG_DEBUG(name() << " start with generation "<< gen << "|" << maxGeneration << ": "<< *itr);
204 auto vecsecisfp = std::make_unique<ISF::ISFParticleVector>();
205 std::unique_ptr<ISF::ISFParticle> newisfp = nullptr; // Boundary crossing particle
206
207 while (itr != simulatedFinal.end() && static_cast<int>(itr->particleId().generation()) == gen) {
208 ATH_MSG_DEBUG(name() << " genration "<< gen << "|" << maxGeneration << ": "<< *itr);
209 if(itr->isSecondary()){
210 // convert final particles to ISF::particle
211 const auto pos = ActsTrk::convertPosFromActs(itr->fourPosition()).first;
212 const auto mom = ActsTrk::convertMomFromActs(itr->fourMomentum()).first;
213 double mass = itr->mass() / Acts::UnitConstants::MeV;
214 double charge = itr->charge();
215 int pdgid = itr->pdg();
216 auto properTime = ActsTrk::timeToAthena(itr->time());
217 const int status = 1 + HepMC::SIM_STATUS_THRESHOLD;
218 const int id = HepMC::UNDEFINED_ID;
219 auto secisfp = std::make_unique<ISF::ISFParticle>(pos,mom,mass,charge,pdgid,status,properTime,*isfp,id);
220 secisfp->setNextGeoID(m_geoIDSvc->identifyNextGeoID(*secisfp));
221 ATH_MSG_DEBUG(name() <<" secondaries particle (ACTS): "<<*itr<< "("<<itr->momentum()<<")|time "<<itr->time()<<"|process "<< getATLASProcessCode(itr->process()));
222 ATH_MSG_DEBUG(name() <<" secondaries particle (ISF): pdg=" << secisfp->pdgCode()
223 << " pos=" << secisfp->position() << " mom=" << secisfp->momentum()
224 << " GeoID=" << m_geoIDSvc->identifyNextGeoID(*secisfp));
225 vecsecisfp->push_back(secisfp.release());
226 }
227 else{
228 // Primary particle handling
229 ATH_MSG_DEBUG(name() <<" primary particle found with generation ("<< gen <<")");
230 // After simulation, check particle's final state
231 if (!isKilled) {
232 auto fisfp = std::make_unique<ISF::ISFParticle>(*isfp);
233 fisfp->updateMomentum(ActsTrk::convertMomFromActs(itr->fourMomentum()).first);
234 fisfp->updatePosition(ActsTrk::convertPosFromActs(itr->fourPosition()).first);
235 ATH_MSG_DEBUG(name() << " After simulation, primary particle state: " << *fisfp);
236 if (!m_particleFilter.empty() && !m_particleFilter->passFilter(*fisfp)) {
237 ATH_MSG_VERBOSE("ISFParticle" << fisfp << " after simulation does not pass selection. Ignoring for boundary check.");
238 continue;
239 }
240 ATH_MSG_DEBUG(name() << " [ISF] original GeoID: " << m_geoIDSvc->identifyGeoID(*isfp)
241 << " new particle GeoID: " << m_geoIDSvc->identifyGeoID(*fisfp)
242 << ", nextGeoID: " << m_geoIDSvc->identifyNextGeoID(*fisfp));
243
244 // Use ActsExtrapolationTool
245 ATH_MSG_DEBUG(name() << " Extrapolating using ActsExtrapolationTool");
246
247 // Convert to ACTS BoundTrackParameters for extrapolation
248 Acts::BoundTrackParameters startParams = Acts::BoundTrackParameters::createCurvilinear(
249 itr->fourPosition(), itr->direction(), itr->qOverP(), std::nullopt, itr->hypothesis());
250
251 //=============== try if a starting surface exist before passing to Extrapolator ==
252 auto do_exit_startsurface = checkStartSurface(mctx, anygctx, surfaceCheckPropagator, startParams);
253 ATH_MSG_DEBUG(name() << " checkStartSurface returned: " << do_exit_startsurface);
254 if (do_exit_startsurface) {
255 ATH_MSG_DEBUG(name() << " Particle starts at a valid surface, doing extrapolation...");
256
257 // Extrapolate and get propagation steps
259 Amg::Vector3D entryPos{Amg::Vector3D::Zero()};
260 try {
261 auto stepsResult = m_extrapolationTool->propagationSteps(ctx, startParams, Acts::Direction::Forward());
262 auto steps = stepsResult.value().first;
263 ATH_MSG_DEBUG(name() << " Number of propagation steps: " << steps.size());
264 if (steps.size() != 0) {
265 for (const auto& step : steps) {
266 ATH_MSG_DEBUG(name() << " [Acts] Step at position " << step.position
267 << " (eta " << Acts::VectorHelpers::eta(step.position)
268 << ") with GeoID " << step.geoID);
269 entryPos = convertPos3FromActs(step.position);
270 nextGeoID = m_geoIDSvc->identifyGeoID(entryPos);
271 ATH_MSG_DEBUG(name() << " [Acts] GeoID from service: " << nextGeoID);
272 if (nextGeoID > AtlasDetDescr::fAtlasID) { // Valid boundary crossing
273 ATH_MSG_DEBUG(name() << " Boundary crossing detected at GeoID " << nextGeoID);
274 break;
275 }
276 }
277 } else {
278 ATH_MSG_WARNING(name() << " No propagation steps returned by ActsExtrapolationTool");
279 }
280 }
281 catch (const std::exception& e) {
282 ATH_MSG_WARNING(name() << " extrapolation [" << m_extrapolationTool.name() << "] failed: " << e.what() << "\nSkip boundary check for " << *fisfp);
283 break; // Skip boundary check for this particle and continue with next one
284 }
285
286 if (fisfp && nextGeoID > AtlasDetDescr::fAtlasID){
287 const auto mom = ActsTrk::convertMomFromActs(itr->fourMomentum()).first;
288 double mass = itr->mass() / Acts::UnitConstants::MeV;
289 double charge = itr->charge();
290 int pdgid = itr->pdg();
291 auto properTime = ActsTrk::timeToAthena(itr->time());
292
293 // Create boundary crossing particle
294 newisfp = std::make_unique<ISF::ISFParticle>(entryPos, mom, mass, charge, pdgid, isfp->status(), properTime, *isfp, isfp->id(), isfp->barcode());
295 newisfp->setNextGeoID(nextGeoID);
296 ATH_MSG_DEBUG(name() << " Truthbinding of parent ISFParticle: " << (isfp->getTruthBinding() ? "exists" : "null"));
297 if (isfp->getTruthBinding()) {
298 ATH_MSG_DEBUG(name() << " Current GenParticle: " << isfp->getTruthBinding()->getCurrentGenParticle());
299 }
300 ATH_MSG_DEBUG(name() << " Created new ISFParticle at boundary with nextGeoID: "
302 << "(" << nextGeoID << ")");
303 }
304
305 // Handle boundary crossing particle separately - DON'T add to vecsecisfp yet
306 if (newisfp && nextGeoID > AtlasDetDescr::fAtlasID) {
307 ATH_MSG_DEBUG(name() << " [ISF] Processing boundary particle with nextGeoID: "
308 << AtlasDetDescr::AtlasRegionHelper::getName(newisfp->nextGeoID())
309 << "(" << newisfp->nextGeoID() << ")");
310
311 // Identify Entrylayer
313
314 switch(nextGeoID) {
316 entryLayer = ISF::fAtlasCaloEntry;
317 ATH_MSG_DEBUG("Particle crossing to Calorimeter");
318 break;
320 entryLayer = ISF::fAtlasMuonEntry;
321 ATH_MSG_DEBUG("Particle crossing to Muon System");
322 break;
323 default:
324 ATH_MSG_DEBUG("Particle at unspecified boundary");
325 break;
326 }
327
328 if (entryLayer != ISF::fUnsetEntryLayer) {
329 vecsecisfp->push_back(newisfp.release()); // Add boundary crossing particle to secondaries vector
330 } else {
331 ATH_MSG_WARNING("Invalid entry layer for boundary particle");
332 }
333 }
334 }
335 else {
336 ATH_MSG_DEBUG(name() << " No starting surface found, skipping boundary check and extrapolation.");
337 }
338 } // end of !isKilled
339 } // end of primary vs secondary
340 ++itr;
341 } // end of while loop over particles in generation
342
343 // Process truth for this generation
344 if (!vecsecisfp->empty()) {
345 // Determine process code and geoID based on whether we have boundary crossing
346 int processCode = 0;
348 auto isParentKilled = ISF::fPrimarySurvives;
349
350 if (newisfp) {
351 // Boundary crossing - use boundary info
352 processCode = 91; // Boundary crossing has no process
353 geoID = newisfp->nextGeoID();
354 isParentKilled = ISF::fKillsPrimary;
355 } else {
356 // Regular secondaries - use process from last particle
357 processCode = getATLASProcessCode((itr-1)->process());
358 geoID = (isfp->nextGeoID() <= AtlasDetDescr::fUndefinedAtlasRegion) ?
359 AtlasDetDescr::fAtlasID : isfp->nextGeoID();
360 isParentKilled = isKilled && gen==maxGeneration ? ISF::fKillsPrimary : ISF::fPrimarySurvives;
361 }
362
363 ISF::ISFTruthIncident truth(*isfp,
364 *vecsecisfp,
365 processCode,
366 geoID,
367 isParentKilled);
368
369 ATH_MSG_DEBUG(name() << " Truth incident parentPt2(MinPt2) " << truth.parentPt2() <<" (100 MeV)");
370 ATH_MSG_DEBUG(name() << " Truth incident ChildPt2(MinPt2) " << truth.childrenPt2Pass(300) <<" (300 MeV)");
371 m_truthRecordSvc->registerTruthIncident(truth, true);
374 for (auto *secisfp : *vecsecisfp){
375 if (secisfp->getTruthBinding()) {
376 secondaries.push_back(secisfp);
377 ATH_MSG_DEBUG(name() << " Secondary particle written out to truth.\n Parent ("
378 << *isfp << ")\n Secondary (" << *secisfp <<")");
379
380 ATH_MSG_DEBUG("Secondary particle push back to ISF, TruthBinding: " << secisfp->getTruthBinding()->getCurrentGenParticle() << " (current) | " << secisfp->getTruthBinding()->getPrimaryGenParticle() << " (primary) | " << secisfp->getTruthBinding()->getGenerationZeroGenParticle() << " (zero)");
381 if (secisfp->getTruthBinding()->getCurrentGenParticle() != nullptr) ATH_MSG_DEBUG("Secondary particle GenParticle EndVertex: " << (secisfp->getTruthBinding()->getCurrentGenParticle()->end_vertex() ? HepMC::barcode(secisfp->getTruthBinding()->getCurrentGenParticle()->end_vertex()) : 1));
382 } else {
383 ATH_MSG_WARNING("Secondary particle not written out to truth.\n Parent ("
384 << *isfp << ")\n Secondary (" << *secisfp <<")");
385 delete secisfp; // Clean up particles without truth binding
386 }
387 }
388 }
389 } // end of generation loop
390 } // end of !simulatedFinal.empty()
391 ATH_MSG_VERBOSE(name() << " No. of secondaries: " << secondaries.size());
392 ATH_MSG_DEBUG(name() << " End of particle " << isfp->id());
393
394 std::vector<ActsFatras::Particle>().swap(input);
395 std::vector<ActsFatras::Particle>().swap(simulatedInitial);
396 std::vector<ActsFatras::Particle>().swap(simulatedFinal);
397 std::vector<ActsFatras::Hit>().swap(hits);
398 } // end of isfp loop
399 return StatusCode::SUCCESS;
400}
401
402Acts::MagneticFieldContext ISF::ActsFatrasSimTool::getMagneticFieldContext(const EventContext& ctx) const {
404 if (!readHandle.isValid()) {
405 ATH_MSG_ERROR(name() + ": Failed to retrieve magnetic field condition data " + m_fieldCacheCondObjInputKey.key() + ".");
406 }
407 else ATH_MSG_DEBUG(name() << "retrieved magnetic field condition data "<< m_fieldCacheCondObjInputKey.key());
408 const AtlasFieldCacheCondObj* fieldCondObj{*readHandle};
409
410 return Acts::MagneticFieldContext(fieldCondObj);
411}
412
413bool ISF::ActsFatrasSimTool::checkStartSurface(const Acts::MagneticFieldContext& mctx,
414 const Acts::GeometryContext& anygctx,
415 const ChargedPropagator& chargedPropagator,
416 const Acts::BoundTrackParameters& startParameters,
417 Acts::Direction navDir /*= Acts::Direction::Forward()*/,
418 double pathLimit /*= std::numeric_limits<double>::max()*/) const
419{
420
421 ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " begin");
422 using ActorList =
423 Acts::ActorList<Acts::detail::SteppingLogger, Acts::MaterialInteractor>;
424 using PropagatorOptions = typename ChargedPropagator::template Options<ActorList>;
425
426 ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " Setting up propagator options for start surface check.");
427 PropagatorOptions options(anygctx, mctx);
428 options.loopProtection = (Acts::VectorHelpers::perp(startParameters.momentum()) < 300 * 1_MeV);
429 options.direction = navDir;
430 options.pathLimit = pathLimit;
431
432 // The state creation triggers the initial volume/surface lookup
433 ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " Initializing propagator state with start parameters: position "
434 << startParameters.position(anygctx).transpose() << ", momentum "
435 << startParameters.momentum().transpose());
436 auto state = chargedPropagator.makeState(options);
437 ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " Created propagator state. Now initializing with start parameters.");
438 auto initResult = chargedPropagator.initialize(state, startParameters);
439 if (!initResult.ok()) {
440 ATH_MSG_WARNING(name() << "::" << __FUNCTION__ << " Failed to initialize propagator state: "
441 << initResult.error().message());
442 return false;
443 }
444 return true;
445}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
double charge(const T &p)
Definition AtlasPID.h:997
std::unique_ptr< const Acts::Logger > makeActsAthenaLogger(IMessageSvc *svc, const std::string &name, int level, std::optional< std::string > parent_name)
static const char * getName(int region)
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCacheCondObjInputKey
Gaudi::Property< double > m_maxStepSize
Acts::EigenStepper< Acts::EigenStepperDefaultExtension > ChargedStepper
PublicToolHandle< ActsTrk::ITrackingGeometryTool > m_trackingGeometryTool
Gaudi::Property< double > m_tolerance
Gaudi::Property< double > m_interact_minPt
ServiceHandle< IAthRNGSvc > m_rngSvc
SingleParticleSimulation< NeutralPropagator, NeutralInteractions, ActsFatras::NoSurface, ActsFatras::NoDecay > NeutralSimulation
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
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
int getATLASProcessCode(ActsFatras::ProcessType actspt)
Gaudi::Property< double > m_pathLimit
Gaudi::Property< double > m_stepSizeCutOff
Gaudi::Property< bool > m_loopProtection
ActsFatrasSimTool(const std::string &type, const std::string &name, const IInterface *parent)
ServiceHandle< ISF::ITruthSvc > m_truthRecordSvc
SiHitCollection m_pixelSiHits
SingleParticleSimulation< ChargedPropagator, ChargedInteractions, HitSurfaceSelector, ActsFatras::NoDecay > ChargedSimulation
virtual StatusCode initialize() override
PublicToolHandle< ISF::IParticleFilter > m_particleFilter
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
virtual Acts::MagneticFieldContext getMagneticFieldContext(const EventContext &) const
Gaudi::Property< double > m_loopFraction
ServiceHandle< ISF::IGeoIDSvc > m_geoIDSvc
Amg::Vector3D convertPos3FromActs(const Acts::Vector3 &actsPos)
Acts::Propagator< ChargedStepper, Navigator > ChargedPropagator
Gaudi::Property< std::string > m_randomEngineName
Acts::StraightLineStepper NeutralStepper
virtual StatusCode initialize() override
BaseSimulatorTool(const std::string &type, const std::string &name, const IInterface *parent)
The generic ISF particle definition,.
Definition ISFParticle.h:42
Interface class for all truth incidents handled by the ISF.
void updateChildParticleProperties()
Update the id and particleLink properties of the child particles (to be called after registerTruthInc...
double parentPt2() const override final
Return pT^2 of the parent particle.
void updateParentAfterIncidentProperties()
Update the id and particleLink properties of the parentAfterIncident (to be called after registerTrut...
bool childrenPt2Pass(double pt2cut)
Return true if at least one child particle passes the given pT^2 cut (= at least one child with pT^2 ...
This defines the McEventCollection, which is really just an ObjectVector of McEvent objectsFile: Gene...
const std::string process
constexpr double timeToAthena(const double actsT)
Converts a time unit from Acts to Athena units.
std::pair< Amg::Vector3D, double > convertMomFromActs(const Acts::Vector4 &actsMom)
Converts an Acts four-momentum vector into an pair of an Athena three-momentum and the paritcle's ene...
std::pair< Amg::Vector3D, double > convertPosFromActs(const Acts::Vector4 &actsPos)
Converts an Acts 4-vector into a pair of an Athena spatial vector and the passed time.
Acts::Vector4 convertPosToActs(const Amg::Vector3D &athenaPos, const double athenaTime=0.)
Converts a position vector & time from Athena units into Acts units.
Eigen::Matrix< double, 3, 1 > Vector3D
AtlasRegion
A simple enum of ATLAS regions and sub-detectors.
Definition AtlasRegion.h:21
int barcode(const T *p)
Definition Barcode.h:16
constexpr int UNDEFINED_ID
constexpr int SIM_STATUS_THRESHOLD
Constant definiting the status threshold for simulated particles, eg. can be used to separate generat...
EntryLayer
Identifiers for the TrackRecordCollections on the boundaries between CaloEntry: Inner Detector - Calo...
Definition EntryLayer.h:31
@ fUnsetEntryLayer
Definition EntryLayer.h:33
@ fAtlasCaloEntry
Definition EntryLayer.h:37
@ fAtlasMuonEntry
Definition EntryLayer.h:38
@ fKillsPrimary
@ fPrimarySurvives
std::list< ISF::ISFParticle * > ISFParticleContainer
generic ISFParticle container (not necessarily a std::list!)
std::vector< ISF::ISFParticle * > ISFParticleVector
ISFParticle vector.