ATLAS Offline Software
Loading...
Searching...
No Matches
ActsGeantFollowerHelper.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
6// ActsGeantFollowerHelper.cxx, (c) ATLAS Detector Software
8
9// StoreGate
11#include "TTree.h"
12#include "GaudiKernel/ITHistSvc.h"
13#include "GaudiKernel/EventContext.h"
14
15// CLHEP
16#include "CLHEP/Units/SystemOfUnits.h"
17#include "CLHEP/Geometry/Transform3D.h"
18// Trk
21// Amg
23//other
24#include "Acts/Surfaces/PerigeeSurface.hpp"
25#include "Acts/Surfaces/PlaneSurface.hpp"
26#include "Acts/Surfaces/CurvilinearSurface.hpp"
27
29#include "Acts/Geometry/GeometryContext.hpp"
30#include "Acts/Geometry/TrackingGeometry.hpp"
31
32// constructor
33ActsGeantFollowerHelper::ActsGeantFollowerHelper(const std::string& t, const std::string& n, const IInterface* p) :
34 base_class(t,n,p),
35 m_validationTreeName("G4Follower_"+n),
36 m_validationTreeDescription("Output of the G4Follower_"),
37 m_validationTreeFolder("/val/G4Follower_"+n),
38 m_validationTree(nullptr){}
39
40
41
42// Athena standard methods
43// initialize
45{
46 m_treeData = std::make_unique<TreeData>();
47
48 // if (m_extrapolator.retrieve().isFailure()){
49 // ATH_MSG_ERROR("Could not retrieve Extrapolator " << m_extrapolator << " . Abort.");
50 // return StatusCode::FAILURE;
51 // }
54 ATH_CHECK(m_actsExtrapolator.retrieve());
55
56 // create the new Tree
58
59 m_validationTree->Branch("InitX", &m_treeData->m_t_x, "initX/F");
60 m_validationTree->Branch("InitY", &m_treeData->m_t_y, "initY/F");
61 m_validationTree->Branch("InitZ", &m_treeData->m_t_z, "initZ/F");
62 m_validationTree->Branch("InitTheta", &m_treeData->m_t_theta, "initTheta/F");
63 m_validationTree->Branch("InitEta", &m_treeData->m_t_eta, "initEta/F");
64 m_validationTree->Branch("InitPhi", &m_treeData->m_t_phi, "initPhi/F");
65 m_validationTree->Branch("InitP", &m_treeData->m_t_p, "initP/F");
66 m_validationTree->Branch("InitPdg", &m_treeData->m_t_pdg, "initPdg/I");
67 m_validationTree->Branch("InitCharge", &m_treeData->m_t_charge, "initQ/F");
68
69 m_validationTree->Branch("G4Steps", &m_treeData->m_g4_steps, "g4steps/I");
70 m_validationTree->Branch("G4StepPt", m_treeData->m_g4_pt, "g4stepPt[g4steps]/F");
71 m_validationTree->Branch("G4StepEta", m_treeData->m_g4_eta, "g4stepEta[g4steps]/F");
72 m_validationTree->Branch("G4StepTheta", m_treeData->m_g4_theta, "g4stepTheta[g4steps]/F");
73 m_validationTree->Branch("G4StepPhi", m_treeData->m_g4_phi, "g4stepPhi[g4steps]/F");
74 m_validationTree->Branch("G4StepX", m_treeData->m_g4_x, "g4stepX[g4steps]/F");
75 m_validationTree->Branch("G4StepY", m_treeData->m_g4_y, "g4stepY[g4steps]/F");
76 m_validationTree->Branch("G4StepZ", m_treeData->m_g4_z, "g4stepZ[g4steps]/F");
77 m_validationTree->Branch("G4StepTX0", m_treeData->m_g4_tX0, "g4stepTX0[g4steps]/F");
78 m_validationTree->Branch("G4AccumX0", m_treeData->m_g4_accX0, "g4stepAccTX0[g4steps]/F");
79 m_validationTree->Branch("G4StepT", m_treeData->m_g4_t, "g4stepTX[g4steps]/F");
80 m_validationTree->Branch("G4StepX0", m_treeData->m_g4_X0, "g4stepX0[g4steps]/F");
81
82 m_validationTree->Branch("TrkStepStatus",m_treeData->m_trk_status, "trkstepStatus[g4steps]/I");
83 m_validationTree->Branch("TrkStepPt", m_treeData->m_trk_pt, "trkstepPt[g4steps]/F");
84 m_validationTree->Branch("TrkStepEta", m_treeData->m_trk_eta, "trkstepEta[g4steps]/F");
85 m_validationTree->Branch("TrkStepTheta", m_treeData->m_trk_theta, "trkstepTheta[g4steps]/F");
86 m_validationTree->Branch("TrkStepPhi", m_treeData->m_trk_phi, "trkstepPhi[g4steps]/F");
87 m_validationTree->Branch("TrkStepX", m_treeData->m_trk_x, "trkstepX[g4steps]/F");
88 m_validationTree->Branch("TrkStepY", m_treeData->m_trk_y, "trkstepY[g4steps]/F");
89 m_validationTree->Branch("TrkStepZ", m_treeData->m_trk_z, "trkstepZ[g4steps]/F");
90 m_validationTree->Branch("TrkStepLocX", m_treeData->m_trk_lx, "trkstepLX[g4steps]/F");
91 m_validationTree->Branch("TrkStepLocY", m_treeData->m_trk_ly, "trkstepLY[g4steps]/F");
92 m_validationTree->Branch("TrkStepTX0", m_treeData->m_trk_tX0, "trkstepTX0[g4steps]/F");
93 m_validationTree->Branch("TrkAccumX0", m_treeData->m_trk_accX0, "trkstepAccTX0[g4steps]/F");
94 m_validationTree->Branch("TrkStepT", m_treeData->m_trk_t, "trkstepTX[g4steps]/F");
95 m_validationTree->Branch("TrkStepX0", m_treeData->m_trk_X0, "trkstepX0[g4steps]/F");
96
97 m_validationTree->Branch("ActsStepStatus",m_treeData->m_acts_status, "actsstepStatus[g4steps]/I");
98 m_validationTree->Branch("ActsVolumeId", m_treeData->m_acts_volumeID,"actsvolumeid[g4steps]/I");
99 m_validationTree->Branch("ActsStepPt", m_treeData->m_acts_pt, "actsstepPt[g4steps]/F");
100 m_validationTree->Branch("ActsStepEta", m_treeData->m_acts_eta, "actsstepEta[g4steps]/F");
101 m_validationTree->Branch("ActsStepTheta", m_treeData->m_acts_theta, "actsstepTheta[g4steps]/F");
102 m_validationTree->Branch("ActsStepPhi", m_treeData->m_acts_phi, "actsstepPhi[g4steps]/F");
103 m_validationTree->Branch("ActsStepX", m_treeData->m_acts_x, "actsstepX[g4steps]/F");
104 m_validationTree->Branch("ActsStepY", m_treeData->m_acts_y, "actsstepY[g4steps]/F");
105 m_validationTree->Branch("ActsStepZ", m_treeData->m_acts_z, "actsstepZ[g4steps]/F");
106 m_validationTree->Branch("ActsStepTX0", m_treeData->m_acts_tX0, "actsstepTX0[g4steps]/F");
107 m_validationTree->Branch("ActsAccumX0", m_treeData->m_acts_accX0, "actsstepAccTX0[g4steps]/F");
108 m_validationTree->Branch("ActsStepT", m_treeData->m_acts_t, "actsstepTX[g4steps]/F");
109 m_validationTree->Branch("ActsStepX0", m_treeData->m_acts_X0, "actsstepX0[g4steps]/F");
110
111 // now register the Tree
112 SmartIF<ITHistSvc> tHistSvc{service("THistSvc")};
113 if (!tHistSvc){
114 ATH_MSG_ERROR( "Could not find Hist Service -> Switching ValidationMode Off !" );
116 }
117 if ((tHistSvc->regTree(m_validationTreeFolder, m_validationTree)).isFailure()) {
118 ATH_MSG_ERROR( "Could not register the validation Tree -> Switching ValidationMode Off !" );
120 }
121
122 ATH_MSG_INFO("initialize() successful" );
123 return StatusCode::SUCCESS;
124}
125
127{
128 return StatusCode::SUCCESS;
129}
130
132{
133 m_treeData->m_t_x = 0.;
134 m_treeData->m_t_y = 0.;
135 m_treeData->m_t_z = 0.;
136 m_treeData->m_t_theta = 0.;
137 m_treeData->m_t_eta = 0.;
138 m_treeData->m_t_phi = 0.;
139 m_treeData->m_t_p = 0.;
140 m_treeData->m_t_charge = 0.;
141 m_treeData->m_t_pdg = 0;
142 m_treeData->m_g4_steps = 0;
143 m_tX0Cache = 0.;
146 m_tX0CacheActs = 0.;
147 m_tX0CacheATLAS = 0.;
148}
149
150void ActsGeantFollowerHelper::trackParticle(const G4ThreeVector& pos,
151 const G4ThreeVector& mom,
152 int pdg, double charge,
153 float t, float X0, bool isSensitive)
154{
155 // const EventContext ctx;
156 const EventContext &ctx = Gaudi::Hive::currentContext();
157 const ActsTrk::GeometryContext &gctx = m_trackingGeometryTool->getGeometryContext(ctx);
158 auto trackingGeometry = m_trackingGeometryTool->trackingGeometry();
159 // construct the initial parameters
160 Amg::Vector3D npos(pos.x(),pos.y(),pos.z());
161 Amg::Vector3D nmom(mom.x(),mom.y(),mom.z());
162
163 // Use the G4 pdgId as the particle hypothesis
164 Trk::ParticleHypothesis particleHypo = m_pdgToParticleHypothesis.convert(m_treeData->m_t_pdg, m_treeData->m_t_charge);
165
166 if(m_treeData->m_g4_steps == 0 && m_tNonSensitiveCache == 0){
167 ATH_MSG_INFO("Initial step ... preparing event cache.");
168 m_treeData->m_t_x = pos.x();
169 m_treeData->m_t_y = pos.y();
170 m_treeData->m_t_z = pos.z();
171 m_treeData->m_t_theta = mom.theta();
172 m_treeData->m_t_eta = mom.eta();
173 m_treeData->m_t_phi = mom.phi();
174 m_treeData->m_t_p = mom.mag();
175 m_treeData->m_t_charge = charge;
176 m_treeData->m_t_pdg = pdg;
177 m_treeData->m_g4_steps = -1;
178 m_tX0Cache = 0.;
179 m_tX0CacheActs = 0.;
181
182 std::shared_ptr<Acts::PerigeeSurface> surface =
183 Acts::Surface::makeShared<Acts::PerigeeSurface>(
184 npos);
185
186
187 float mass = Trk::ParticleMasses::mass[particleHypo] * Acts::UnitConstants::MeV;
188
189 Acts::Vector4 actsStart(pos.x(),pos.y(),pos.z(),0);
190 Acts::Vector3 dir = nmom.normalized();
191 Acts::ParticleHypothesis hypothesis{Acts::makeAbsolutePdgParticle(static_cast<Acts::PdgParticle>(pdg)),
192 mass,
193 Acts::AnyCharge{static_cast<float>(charge)}};
194 m_actsParameterCache = Acts::GenericBoundTrackParameters<Acts::ParticleHypothesis>::create(
195 gctx.context(), surface, actsStart, dir, charge/(mom.mag()/1000), std::nullopt, hypothesis)
196 .value();
197 }
198
199 // Store material in cache
200 float tX0 = X0 > 10e-5f ? t/X0 : 0.f;
203 if (!isSensitive)
204 {
205 return;
206 }
207
208 // jumping over inital step
209 m_treeData->m_g4_steps = (m_treeData->m_g4_steps == -1) ? 0 : m_treeData->m_g4_steps;
210
211 if (!m_parameterCache){
212 ATH_MSG_WARNING("No Parameters available. Bailing out.");
213 return;
214 }
215
216 if ( m_treeData->m_g4_steps >= MAXPROBES) {
217 ATH_MSG_WARNING("Maximum number of " << MAXPROBES << " reached, step is ignored.");
218 return;
219 }
220 // parameters of the G4 step point
221 Trk::CurvilinearParameters* g4Parameters = new Trk::CurvilinearParameters(npos, nmom, m_treeData->m_t_charge);
222 // destination surface
223 const Trk::PlaneSurface& destinationSurface = g4Parameters->associatedSurface();
224 // extrapolate to the destination surface
229 // call the extrapolation engine
230 auto eCodeSteps = m_extrapolationEngine->extrapolate(ecc, &destinationSurface);
231 Trk::TrackParameters *trkParameters = ecc.endParameters;
232 float X0ATLAS = ecc.materialX0;
233
234 if(eCodeSteps.code != 2 ){
235 ATH_MSG_ERROR("Error in the Extrapolator Engine, skip the current step");
236 return;
237 }
238
239 // create a Acts::Surface that correspond to the Trk::Surface
240 auto destinationSurfaceActs = Acts::CurvilinearSurface(destinationSurface.center(), destinationSurface.normal()).planeSurface();
241 std::optional<Acts::BoundTrackParameters> actsParameters = m_actsExtrapolator->propagate(ctx,
243 *destinationSurfaceActs,
244 Acts::Direction::Forward(),
245 std::numeric_limits<double>::max());
246
247 float X0Acts = m_actsExtrapolator->propagationSteps(ctx,
249 *destinationSurfaceActs,
250 Acts::Direction::Forward(),
251 std::numeric_limits<double>::max()).second.materialInX0;
252
253 if(not actsParameters.has_value()){
254 ATH_MSG_ERROR("Error in the Acts extrapolation, skip the current step");
255 return;
256 }
257 int volID = trackingGeometry->lowestTrackingVolume(gctx.context(), actsParameters->position(gctx.context()))->geometryId().volume();
258
259 // fill the geant information and the trk information
260 m_treeData->m_g4_pt[m_treeData->m_g4_steps] = mom.mag()/std::cosh(mom.eta());
261 m_treeData->m_g4_eta[m_treeData->m_g4_steps] = mom.eta();
262 m_treeData->m_g4_theta[m_treeData->m_g4_steps] = mom.theta();
263 m_treeData->m_g4_phi[m_treeData->m_g4_steps] = mom.phi();
264 m_treeData->m_g4_x[m_treeData->m_g4_steps] = pos.x();
265 m_treeData->m_g4_y[m_treeData->m_g4_steps] = pos.y();
266 m_treeData->m_g4_z[m_treeData->m_g4_steps] = pos.z();
267
269 m_treeData->m_g4_tX0[m_treeData->m_g4_steps] = m_tX0NonSensitiveCache;
270 m_treeData->m_g4_accX0[m_treeData->m_g4_steps] = m_tX0Cache;
271 m_treeData->m_g4_t[m_treeData->m_g4_steps] = m_tNonSensitiveCache;
273
274 m_treeData->m_trk_status[m_treeData->m_g4_steps] = trkParameters ? 1 : 0;
275 m_treeData->m_trk_pt[m_treeData->m_g4_steps] = trkParameters ? trkParameters->pT() : 0.;
276 m_treeData->m_trk_eta[m_treeData->m_g4_steps] = trkParameters ? trkParameters->momentum().eta() : 0.;
277 m_treeData->m_trk_theta[m_treeData->m_g4_steps] = trkParameters ? trkParameters->momentum().theta() : 0.;
278 m_treeData->m_trk_phi[m_treeData->m_g4_steps] = trkParameters ? trkParameters->momentum().phi() : 0.;
279 m_treeData->m_trk_x[m_treeData->m_g4_steps] = trkParameters ? trkParameters->position().x() : 0.;
280 m_treeData->m_trk_y[m_treeData->m_g4_steps] = trkParameters ? trkParameters->position().y() : 0.;
281 m_treeData->m_trk_z[m_treeData->m_g4_steps] = trkParameters ? trkParameters->position().z() : 0.;
282 m_treeData->m_trk_lx[m_treeData->m_g4_steps] = trkParameters ? trkParameters->parameters()[Trk::locX] : 0.;
283 m_treeData->m_trk_ly[m_treeData->m_g4_steps] = trkParameters ? trkParameters->parameters()[Trk::locY] : 0.;
284 // Incremental extrapolation, the extrapolation correspond to one step
285 if(m_extrapolateIncrementally || m_treeData->m_g4_steps == 0){
286 float tATLAS = (trkParameters->position() - m_parameterCache->position()).norm();
287 m_tX0CacheATLAS += X0ATLAS;
288 m_treeData->m_trk_tX0[m_treeData->m_g4_steps] = X0ATLAS;
289 m_treeData->m_trk_accX0[m_treeData->m_g4_steps] = m_tX0CacheATLAS;
290 m_treeData->m_trk_t[m_treeData->m_g4_steps] = tATLAS;
291 m_treeData->m_trk_X0[m_treeData->m_g4_steps] = tATLAS/X0ATLAS;
292 }
293 // Extrapolation perform from the start, step varaible need to be computed by comparing to the last extrapolation.
294 else{
295 Amg::Vector3D previousPos(m_treeData->m_trk_x[m_treeData->m_g4_steps-1],
296 m_treeData->m_trk_y[m_treeData->m_g4_steps-1],
297 m_treeData->m_trk_z[m_treeData->m_g4_steps-1]);
298 float tATLAS = (trkParameters->position() - previousPos).norm();
299 m_treeData->m_trk_tX0[m_treeData->m_g4_steps] = X0ATLAS - m_treeData->m_trk_accX0[m_treeData->m_g4_steps-1] ;
300 m_treeData->m_trk_accX0[m_treeData->m_g4_steps] = X0ATLAS;
301 m_treeData->m_trk_t[m_treeData->m_g4_steps] = tATLAS;
302 m_treeData->m_trk_X0[m_treeData->m_g4_steps] = tATLAS/m_treeData->m_trk_tX0[m_treeData->m_g4_steps];
303 }
304
305 m_treeData->m_acts_status[m_treeData->m_g4_steps] = actsParameters ? 1 : 0;
306 m_treeData->m_acts_volumeID[m_treeData->m_g4_steps] = actsParameters ? volID : 0;
307 m_treeData->m_acts_pt[m_treeData->m_g4_steps] = actsParameters ? actsParameters->transverseMomentum()*1000 : 0.;
308 m_treeData->m_acts_eta[m_treeData->m_g4_steps] = actsParameters ? actsParameters->momentum().eta() : 0.;
309 m_treeData->m_acts_theta[m_treeData->m_g4_steps] = actsParameters ? actsParameters->momentum().theta() : 0.;
310 m_treeData->m_acts_phi[m_treeData->m_g4_steps] = actsParameters ? actsParameters->momentum().phi() : 0.;
311 m_treeData->m_acts_x[m_treeData->m_g4_steps] = actsParameters ? actsParameters->position(gctx.context()).x() : 0.;
312 m_treeData->m_acts_y[m_treeData->m_g4_steps] = actsParameters ? actsParameters->position(gctx.context()).y() : 0.;
313 m_treeData->m_acts_z[m_treeData->m_g4_steps] = actsParameters ? actsParameters->position(gctx.context()).z() : 0.;
314 // Incremental extrapolation, the extrapolation correspond to one step
315 if(m_extrapolateIncrementally || m_treeData->m_g4_steps == 0){
316 float tActs = (actsParameters->position(gctx.context()) - m_actsParameterCache->position(gctx.context())).norm();
317 m_tX0CacheActs += X0Acts;
318 m_treeData->m_acts_tX0[m_treeData->m_g4_steps] = X0Acts;
319 m_treeData->m_acts_accX0[m_treeData->m_g4_steps] = m_tX0CacheActs;
320 m_treeData->m_acts_t[m_treeData->m_g4_steps] = tActs;
321 m_treeData->m_acts_X0[m_treeData->m_g4_steps] = tActs/X0Acts;
322 }
323 // Extrapolation perform from the start, step varaible need to be computed by comparing to the last extrapolation.
324 else{
325 Acts::Vector3 previousPos(m_treeData->m_acts_x[m_treeData->m_g4_steps-1],
326 m_treeData->m_acts_y[m_treeData->m_g4_steps-1],
327 m_treeData->m_acts_z[m_treeData->m_g4_steps-1]);
328 float tActs = (actsParameters->position(gctx.context()) - previousPos).norm();
329 m_treeData->m_acts_tX0[m_treeData->m_g4_steps] = X0Acts - m_treeData->m_acts_accX0[m_treeData->m_g4_steps-1] ;
330 m_treeData->m_acts_accX0[m_treeData->m_g4_steps] = X0Acts;
331 m_treeData->m_acts_t[m_treeData->m_g4_steps] = tActs;
332 m_treeData->m_acts_X0[m_treeData->m_g4_steps] = tActs/m_treeData->m_acts_tX0[m_treeData->m_g4_steps];
333 }
334
335 // update the parameters if needed/configured
336 if (m_extrapolateIncrementally && trkParameters && actsParameters) {
337 delete m_parameterCache;
338 m_actsParameterCache.reset();
339 m_parameterCache = trkParameters;
340 m_actsParameterCache = actsParameters;
341 }
342 // delete cache and increment
343 delete g4Parameters;
344 destinationSurfaceActs.reset();
347 ++m_treeData->m_g4_steps;
348}
349
351{
352 if (m_tX0Cache != 0)
353 {
354 // fill the validation tree
355 m_validationTree->Fill();
356 delete m_parameterCache;
357 m_actsParameterCache.reset();
358 }
359}
#define MAXPROBES
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_WARNING(x)
double charge(const T &p)
Definition AtlasPID.h:997
std::string m_validationTreeFolder
stream/folder to for the TTree to be written out
virtual StatusCode finalize() override
std::string m_validationTreeName
validation tree name - to be acessed by this from root
ToolHandle< ActsTrk::IExtrapolationTool > m_actsExtrapolator
Trk::PdgToParticleHypothesis m_pdgToParticleHypothesis
std::string m_validationTreeDescription
validation tree description - second argument in TTree
TTree * m_validationTree
Root Validation Tree.
ToolHandle< Trk::IExtrapolationEngine > m_extrapolationEngine
virtual void trackParticle(const G4ThreeVector &pos, const G4ThreeVector &mom, int pdg, double charge, float t, float X0, bool isSensitive) override
std::unique_ptr< TreeData > m_treeData
Trk::TrackParameters * m_parameterCache
virtual void endEvent() override
std::optional< Acts::BoundTrackParameters > m_actsParameterCache
Gaudi::Property< bool > m_extrapolateIncrementally
PublicToolHandle< ActsTrk::ITrackingGeometryTool > m_trackingGeometryTool
virtual void beginEvent() override
ActsGeantFollowerHelper(const std::string &, const std::string &, const IInterface *)
virtual StatusCode initialize() override
Acts::GeometryContext context() const
virtual const S & associatedSurface() const override final
Access to the Surface method.
templated class as an input-output object of the extrapolation, only public members,...
void addConfigurationMode(ExtrapolationMode::eMode em)
add a configuration mode
double materialX0
collected material so far in units of X0
T * endParameters
by pointer - are newly created and can be optionally 0
void setParticleHypothesis(const ParticleHypothesis &hypo)
set ParticleHypothesis
const Amg::Vector3D & momentum() const
Access method for the momentum.
const Amg::Vector3D & position() const
Access method for the position.
double pT() const
Access method for transverse momentum.
Class for a planaer rectangular or trapezoidal surface in the ATLAS detector.
virtual const Amg::Vector3D & normal() const
Returns the normal vector of the Surface (i.e.
const Amg::Vector3D & center() const
Returns the center position of the Surface.
Eigen::Matrix< double, 3, 1 > Vector3D
constexpr double mass[PARTICLEHYPOTHESES]
the array of masses
CurvilinearParametersT< TrackParametersDim, Charged, PlaneSurface > CurvilinearParameters
@ locY
local cartesian
Definition ParamDefs.h:38
@ locX
Definition ParamDefs.h:37
ParticleHypothesis
Enumeration for Particle hypothesis respecting the interaction with material.
ParametersBase< TrackParametersDim, Charged > TrackParameters