ATLAS Offline Software
Loading...
Searching...
No Matches
MaterialTrackRecorder.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7#include "GaudiKernel/Bootstrap.h"
8#include "GaudiKernel/ISvcLocator.h"
9#include "GaudiKernel/IMessageSvc.h"
10#include "GaudiKernel/ThreadLocalContext.h"
11
13
14#include "G4Event.hh"
15#include "G4Run.hh"
16#include "G4Step.hh"
17
18namespace ActsTrk
19{
21 AthMessaging{"MaterialTrackRecorder"},
22 m_cfg{config}{}
23
25 {
26 ATH_MSG_DEBUG(" BeginOfEventAction");
27
28 // Get the event context for the write handle below
29 const EventContext& ctx = Gaudi::Hive::currentContext();
30
31 SG::WriteHandle<RecordedMaterialTrackCollection> materialTracks(m_cfg.materialTrackCollectionName, ctx);
32
33 // Only record if it does NOT already exist
34 if (!materialTracks.isPresent()) {
35 auto coll = std::make_unique<RecordedMaterialTrackCollection>();
36 if (materialTracks.record(std::move(coll)).isFailure()) {
37 ATH_MSG_ERROR("Failed to record RecordedMaterialTrackCollection with key "
38 << m_cfg.materialTrackCollectionName);
39 m_rmtCollection = nullptr;
40 return;
41 }
42 } else {
43 // Sanity check (should normally not happen unless someone else records it)
44 ATH_MSG_DEBUG("Collection already present: " << m_cfg.materialTrackCollectionName);
45 }
46
47 m_rmtCollection = materialTracks.ptr();
48
49 if (!m_rmtCollection) {
50 ATH_MSG_ERROR("Recorded collection pointer is null right after record/present for key "
51 << m_cfg.materialTrackCollectionName);
52 }
53
54 ATH_MSG_DEBUG("ctx event=" << ctx.eventID().event_number()
55 << " slot=" << ctx.slot() << " key=" << m_cfg.materialTrackCollectionName);
56 ATH_MSG_DEBUG("recorded? present=" << materialTracks.isPresent() << " valid=" << materialTracks.isValid());
57 }
58
60 {
61 ATH_MSG_DEBUG(" EndOfEventAction");
62 }
63
65 {
66 ATH_MSG_DEBUG(" BeginOfRunAction");
67 m_rmtCollection = nullptr;
68 }
69
71 {
72 ATH_MSG_DEBUG(" UserSteppingAction");
73
74 if (!m_rmtCollection) {
75 ATH_MSG_ERROR("No per-event collection pointer cached (m_coll is null).");
76 return;
77 }
78
79 // Get the material & check if it is present
80 G4Material* material = step->GetPreStepPoint()->GetMaterial();
81 if (material == nullptr) {
82 return;
83 }
84
85 // First check for exclusion
86 std::string materialName = material->GetName();
87 for (const auto& emat : m_cfg.excludeMaterials) {
88 if (emat == materialName) {
89 ATH_MSG_DEBUG("Exclude step in material '" << materialName << "'.");
90 return;
91 }
92 }
93
94 ATH_MSG_DEBUG("Performing a step with step size = "
95 << s_convertLength * step->GetStepLength());
96
97 // Quantities valid for elemental materials and mixtures
98 double X0 = s_convertLength * material->GetRadlen();
99 double L0 = s_convertLength * material->GetNuclearInterLength();
100 double rho = s_convertDensity * material->GetDensity();
101
102 // Get{A,Z} is only meaningful for single-element materials (according to
103 // the Geant4 docs). Need to compute average manually.
104 const G4ElementVector* elements = material->GetElementVector();
105 const G4double* fraction = material->GetFractionVector();
106 std::size_t nElements = material->GetNumberOfElements();
107
108 double Ar = 0.;
109 double Z = 0.;
110 if (nElements == 1) {
111 Ar = material->GetA() / (CLHEP::gram / CLHEP::mole);
112 Z = material->GetZ();
113 } else {
114 for (std::size_t i = 0; i < nElements; i++) {
115 Ar += elements->at(i)->GetA() * fraction[i] / (CLHEP::gram / CLHEP::mole);
116 Z += elements->at(i)->GetZ() * fraction[i];
117 }
118 }
119
120 // Construct passed material slab for the step
121 const auto slab = Acts::MaterialSlab(Acts::Material::fromMassDensity(X0, L0, Ar, Z, rho), s_convertLength * step->GetStepLength());
122
123 // Create the RecordedMaterialSlab
124 Acts::MaterialInteraction mInteraction;
125 mInteraction.position = convertPosition(step->GetPreStepPoint()->GetPosition());
126 mInteraction.direction = convertDirection(step->GetPreStepPoint()->GetMomentum()).normalized();
127 mInteraction.materialSlab = slab;
128 mInteraction.pathCorrection = (step->GetStepLength() / CLHEP::mm);
129
130 G4Track* g4Track = step->GetTrack();
131
132 Acts::RecordedMaterialTrack rmTrack;
133 Acts::Vector3 vertex = convertPosition(g4Track->GetVertexPosition());
134 Acts::Vector3 direction = convertDirection(g4Track->GetMomentumDirection());
135 rmTrack.first = {vertex, direction};
136 rmTrack.second.materialInX0 = mInteraction.materialSlab.thicknessInX0();
137 rmTrack.second.materialInL0 = mInteraction.materialSlab.thicknessInL0();
138 rmTrack.second.materialInteractions.push_back(mInteraction);
139 m_rmtCollection->push_back(std::move(rmTrack));
140 }
141}
142
#define ATH_MSG_ERROR(x)
#define ATH_MSG_DEBUG(x)
Handle class for recording to StoreGate.
virtual void UserSteppingAction(const G4Step *) override
static constexpr double s_convertDensity
Acts::Vector3 convertPosition(const G4ThreeVector &g4vec)
Useful fuction for position coversion.
static constexpr double s_convertLength
Conversion constants.
virtual void EndOfEventAction(const G4Event *) override
Acts::Vector3 convertDirection(const G4ThreeVector &g4vec)
Useful fuction for direction coversion.
virtual void BeginOfRunAction(const G4Run *) override
virtual void BeginOfEventAction(const G4Event *) override
MaterialTrackRecorder(const Config &config)
RecordedMaterialTrackCollection * m_rmtCollection
Pointer to the collection, non-owning.
AthMessaging(IMessageSvc *msgSvc, const std::string &name)
Constructor.
bool isPresent() const
Is the referenced object present in SG?
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
pointer_type ptr()
Dereference the pointer.
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...