ATLAS Offline Software
Loading...
Searching...
No Matches
TrkDetDescr/TrkDetDescrAlgs/src/MaterialValidation.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// MaterialValidation.cxx, (c) ATLAS Detector Software
8
9// Amg
11// Trk
12#include "MaterialValidation.h"
14#include "TrkGeometry/Layer.h"
20
21// test
23
24// Gaudi Units
25#include "GaudiKernel/SystemOfUnits.h"
26
27
32
33
35{
36
37 // Get the TrackingGeometry from StoreGate
39
40 if ( (m_materialMapper.retrieve()).isFailure() )
41 ATH_MSG_WARNING("Could not retrieve MaterialMapper");
42
43 // initialize the random generators
44 m_flatDist = new Rndm::Numbers(randSvc(), Rndm::Flat(0.,1.));
45 return StatusCode::SUCCESS;
46}
47
48
49StatusCode Trk::MaterialValidation::execute(const EventContext& /*ctx*/)
50{
51 ATH_MSG_VERBOSE( "MaterialValidation execute() start ================================================" );
52
53 // create the random direction - flat in eta
54 double eta = m_etaMin + (m_etaMax-m_etaMin)*m_flatDist->shoot();
55 double theta = 2.*atan(exp(-eta));
56 double phi = M_PI * ( 2*m_flatDist->shoot() - 1.);
57 m_accTinX0 = 0;
58
59 // get the position and riection from the random numbers
60 Amg::Vector3D position(0.,0.,0.);
61 Amg::Vector3D direction(sin(theta)*cos(phi),sin(theta)*sin(phi), cos(theta));
62
63 ATH_MSG_DEBUG("[>] Start mapping event with phi | eta = " << phi << " | " << direction.eta());
64
65 // find the start TrackingVolume
66 const Trk::TrackingVolume* sVolume = trackingGeometry().lowestTrackingVolume(position);
67 const Trk::TrackingVolume* nVolume = sVolume;
68 while (nVolume ) {
70 position = paB.first;
71 nVolume = paB.second;
72 }
73 ATH_MSG_DEBUG("[<] Finishing event with collected path [X0] = " << m_accTinX0);
74 return StatusCode::SUCCESS;
75}
76
80{
81 // get the entry layers -----------------------------------------------------------
82 std::map<double, Trk::AssociatedMaterial> collectedMaterial;
83
84 // all boundaries found --- proceed
86
87 ATH_MSG_DEBUG("[>>] Entering Volume: " << tvol.volumeName() << "- at " << Amg::toString(position));
88
90
92 // A : collect all hit layers
93 auto layerIntersections = tvol.materialLayersOrdered<Trk::NeutralCurvilinearParameters>(nullptr,nullptr,cvp,Trk::alongMomentum);
94 // loop over the layers
95 for (auto& lCandidate : layerIntersections ) {
96 // get the layer
97 const Trk::Layer* layer = lCandidate.object;
98 double pathLength = lCandidate.intersection.pathLength;
99 // get the associate material
100 if (layer->layerMaterialProperties()){
101 // take it from the global position
102 const Trk::MaterialProperties* mprop = layer->layerMaterialProperties()->fullMaterial(lCandidate.intersection.position);
103 if (mprop){
104 double stepLength = mprop->thickness()*fabs(layer->surfaceRepresentation().pathCorrection(lCandidate.intersection.position,direction));
105 collectedMaterial[pathLength] = Trk::AssociatedMaterial(lCandidate.intersection.position, mprop, stepLength, &tvol, layer);
106 }
107 }
108 }
109 // B : collect all boundary layers, start from last hit layer
110 Amg::Vector3D lastPosition = !collectedMaterial.empty() ? collectedMaterial.rbegin()->second.materialPosition() : (position + direction.unit());
111 Trk::NeutralCurvilinearParameters lcp(lastPosition,direction,0.);
112 // boundary surfaces
114 if (!boundaryIntersections.empty()){
115 // by definition is the first one
116 lastPosition = boundaryIntersections.begin()->intersection.position;
117 const Trk::BoundarySurface<Trk::TrackingVolume>* bSurfaceTV = boundaryIntersections.begin()->object;
118 const Trk::Surface& bSurface = bSurfaceTV->surfaceRepresentation();
119 // get the path lenght to it
120 if (bSurface.materialLayer() && bSurface.materialLayer()->layerMaterialProperties()){
121 const Trk::MaterialProperties* mprop = bSurface.materialLayer()->layerMaterialProperties()->fullMaterial(lastPosition);
122 double pathLength = (lastPosition-position).mag();
123 if (mprop){
124 double stepLength = mprop->thickness()*fabs(bSurface.pathCorrection(lastPosition,direction));
125 collectedMaterial[pathLength] = Trk::AssociatedMaterial(lastPosition, mprop, stepLength, &tvol, bSurface.materialLayer());
126 } else
127 collectedMaterial[pathLength] = Trk::AssociatedMaterial(lastPosition, &tvol, bSurface.materialLayer());
128 }
129 // set the new volume
130 const Trk::TrackingVolume* naVolume = bSurfaceTV->attachedVolume(lastPosition, direction, Trk::alongMomentum);
131 pab = Trk::PositionAtBoundary(lastPosition,naVolume);
132 } else
133 pab = Trk::PositionAtBoundary(lastPosition,0);
134 } else {
135 std::map<double, std::pair<const Trk::Layer*, Amg::Vector3D> > intersectedLayers;
136
137 // Process the contained layers if they exist
138 const Trk::LayerArray* layerArray = tvol.confinedLayers();
139 if (layerArray) {
140 // display output
141 std::span<Trk::Layer const * const> layers = layerArray->arrayObjects();
142 auto layIter = layers.begin();
143 auto layIterE = layers.end();
144 for ( ; layIter != layIterE; ++layIter){
145 if ( (*layIter)->layerMaterialProperties() ){
146 Trk::Intersection lsIntersection = (*layIter)->surfaceRepresentation().straightLineIntersection(position, direction, true, true);
147 if (lsIntersection.valid){
148 intersectedLayers[lsIntersection.pathLength] = std::pair<const Trk::Layer*, Amg::Vector3D>(*layIter,lsIntersection.position);
149 // get & record the material
150 // - the position on the surface
151 Amg::Vector3D mposition = (*layIter)->surfaceRepresentation().transform().inverse()*lsIntersection.position;
152 const Trk::MaterialProperties* mprop = (*layIter)->layerMaterialProperties()->fullMaterial(mposition);
153 if (mprop) {
154 double stepLength = mprop->thickness()*fabs((*layIter)->surfaceRepresentation().pathCorrection(lsIntersection.position,direction));
155 collectedMaterial[lsIntersection.pathLength] = Trk::AssociatedMaterial(lsIntersection.position, mprop, stepLength, &tvol, (*layIter));
156 } else
157 collectedMaterial[lsIntersection.pathLength] = Trk::AssociatedMaterial(lsIntersection.position, &tvol, (*layIter));
158
159 ATH_MSG_VERBOSE("[>>>>] record material hit at layer with index " << (*layIter)->layerIndex().value() << " - at " << Amg::toString(lsIntersection.position) );
160 if (mprop)
161 ATH_MSG_VERBOSE("[>>>>] MaterialProperties are " << (*mprop) );
162 else
163 ATH_MSG_VERBOSE("[>>>>] No MaterialProperties found." );
164 }
165 }
166 }
167 }
168
169 // material for confined layers collected, now go to boundary
170
171 // update the position to the last one
172 Amg::Vector3D lastPosition = !intersectedLayers.empty() ? (*(--(intersectedLayers.end()))).second.second : position;
173
174 std::map<double, Trk::VolumeExit > volumeExits;
175 // now find the exit point
176 const auto & bSurfaces = tvol.boundarySurfaces();
177 for (size_t ib = 0; ib < bSurfaces.size(); ++ib){
178 // omit positions on the surface
179 if ( !bSurfaces[ib]->surfaceRepresentation().isOnSurface(lastPosition, true, 0.1, 0.1) ){
180 Trk::Intersection evIntersection = bSurfaces[ib]->surfaceRepresentation().straightLineIntersection(lastPosition, direction, true, true);
181 ATH_MSG_VERBOSE("[>>>>] boundary surface intersection / validity :" << Amg::toString(evIntersection.position) << " / " << evIntersection.valid);
182 ATH_MSG_VERBOSE("[>>>>] with path length = " << evIntersection.pathLength );
183 if (evIntersection.valid){
184 // next attached Tracking Volume
185 const Trk::TrackingVolume* naVolume = bSurfaces[ib]->attachedVolume(evIntersection.position, direction, Trk::alongMomentum);
186 // put it into the map
187 volumeExits[evIntersection.pathLength] = Trk::VolumeExit(naVolume, &(bSurfaces[ib]->surfaceRepresentation()), evIntersection.position);
188 // volume exit
189 ATH_MSG_VERBOSE("[>>>>] found volume exit - at " << Amg::toString(evIntersection.position) );
190 }
191 } else
192 ATH_MSG_VERBOSE("[>>>>] starting position is on surface ! " );
193 }
194 // prepare the boundary
195 if (!volumeExits.empty()){
196 // get the first entry in the map: closest next volume
197 VolumeExit closestVolumeExit = (*volumeExits.begin()).second;
198 // check if the volume exit boundary has material attached
199 const Trk::Surface* bSurface = closestVolumeExit.bSurface;
200 if ( bSurface && bSurface->materialLayer() && bSurface->materialLayer()->layerMaterialProperties()){
201 ATH_MSG_VERBOSE("[>>>>] The boundary surface has an associated layer, collect material from there");
202 const Trk::MaterialProperties* mprop = bSurface->materialLayer()->layerMaterialProperties()->fullMaterial(closestVolumeExit.vExit);
203 double pathToExit = (closestVolumeExit.vExit-lastPosition).mag();
204 if (mprop){
205 double stepLength = mprop->thickness()*fabs(bSurface->pathCorrection(closestVolumeExit.vExit,direction));
206 collectedMaterial[pathToExit] = Trk::AssociatedMaterial(closestVolumeExit.vExit, mprop, stepLength, &tvol, bSurface->materialLayer());
207 } else
208 collectedMaterial[pathToExit] = Trk::AssociatedMaterial(closestVolumeExit.vExit, &tvol, bSurface->materialLayer());
209 }
210 //
211 if (closestVolumeExit.nVolume != &tvol && closestVolumeExit.nVolume) {
212 ATH_MSG_VERBOSE("[>>>>] Next Volume: " << closestVolumeExit.nVolume->volumeName() << " - at " << Amg::toString(closestVolumeExit.vExit) );
213 // return for further navigation
214 pab = Trk::PositionAtBoundary(closestVolumeExit.vExit,closestVolumeExit.nVolume);
215 }
216 } else {
217 ATH_MSG_VERBOSE( "[>>>>] No exit found from Volume '" << tvol.volumeName() << "' - starting radius = " << lastPosition.perp() );
218 const Trk::CylinderVolumeBounds* cvb = dynamic_cast<const Trk::CylinderVolumeBounds*>(&(tvol.volumeBounds()));
219 if (cvb)
220 ATH_MSG_VERBOSE( "[>>>>] Volume outer radius = " << cvb->outerRadius() );
221 }
222
223 }
224 // finally collect the material
225 ATH_MSG_DEBUG("[>>>] Collecting materials from "<< collectedMaterial.size() << " layers");
226 // provide the material to the material mapper
227 auto cmIter = collectedMaterial.begin();
228 auto cmIterE = collectedMaterial.end();
229 for ( ; cmIter != cmIterE; ++cmIter ){
230 m_materialMapper->recordMaterialHit(cmIter->second, cmIter->second.materialPosition());
231 m_accTinX0 += cmIter->second.steplengthInX0();
232 int layerIndex = cmIter->second.associatedLayer() ? cmIter->second.associatedLayer()->layerIndex().value() : 0;
233 ATH_MSG_DEBUG("[>>>] Accumulate pathLength/X0 on layer with index " << layerIndex << " - t/X0 (total so far) = " << cmIter->second.steplengthInX0() << " (" << m_accTinX0 << ")");
234 if (layerIndex){
235 std::string surfaceType =
236 cmIter->second.associatedLayer()->surfaceRepresentation().type() ==
238 ? "Cylinder at radius = "
239 : "Disc at z-position = ";
240 std::string layerType =
241 cmIter->second.associatedLayer()->surfaceArray() ? "Active "
242 : "Passive ";
243 double rz =
244 cmIter->second.associatedLayer()->surfaceRepresentation().type() ==
246 ? cmIter->second.associatedLayer()
247 ->surfaceRepresentation()
248 .bounds()
249 .r()
250 : cmIter->second.associatedLayer()
251 ->surfaceRepresentation()
252 .center()
253 .z();
254 ATH_MSG_DEBUG(" " << layerType << surfaceType << rz);
255 }
256 ATH_MSG_DEBUG(" Distance to origin is " << cmIter->second.materialPosition().mag() );
257 }
258
259 // return what you have
260 return pab;
261
262}
263
264
265
267{
268 ATH_MSG_INFO( "MaterialValidation finalize()" );
269 return StatusCode::SUCCESS;
270}
271
273 std::stringstream msg;
274 msg << "Failed to get conditions data " << m_trackingGeometryReadKey.key() << ".";
275 throw std::runtime_error(msg.str());
276}
277
278
#define M_PI
Scalar eta() const
pseudorapidity method
Scalar mag() const
mag method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
static Double_t rz
It is used in the Mapping process ( using MaterialSteps ), the validation and recostruction ( using M...
virtual std::span< T *const > arrayObjects()=0
Return all objects of the Array non-const we can still modify the T.
Description of a BoundarySurface inside the tracking realm, it extends the Surface description to mak...
virtual const Tvol * attachedVolume(const TrackParameters &parms, PropDirection dir) const =0
Get the next Volume depending on the TrackParameters and the requested direction.
virtual const Surface & surfaceRepresentation() const =0
The Surface Representation of this.
Bounds for a cylindrical Volume, the decomposeToSurfaces method creates a vector of up to 6 surfaces:
double outerRadius() const
This method returns the outer radius.
virtual const MaterialProperties * fullMaterial(const Amg::Vector3D &gp) const =0
Return method for full material description of the Layer.
Base Class for a Detector Layer in the Tracking realm.
Definition Layer.h:72
const LayerMaterialProperties * layerMaterialProperties() const
getting the LayerMaterialProperties including full/pre/post update
Material with information about thickness of material.
float thickness() const
Return the thickness in mm.
StatusCode finalize()
standard Athena-Algorithm method
Gaudi::Property< bool > m_runNativeNavigation
validate the native TG navigation
PositionAtBoundary collectMaterialAndExit(const Trk::TrackingVolume &tvol, const Amg::Vector3D &position, const Amg::Vector3D &direction)
ToolHandle< IMaterialMapper > m_materialMapper
Mapper and Inspector.
Rndm::Numbers * m_flatDist
Random generator for flat distribution.
SG::ReadCondHandleKey< TrackingGeometry > m_trackingGeometryReadKey
StatusCode execute(const EventContext &ctx)
standard Athena-Algorithm method
StatusCode initialize()
standard Athena-Algorithm method
Abstract Base Class for tracking surfaces.
Definition Surface.h:79
virtual double pathCorrection(const Amg::Vector3D &pos, const Amg::Vector3D &mom) const
the pathCorrection for derived classes with thickness - it reflects if the direction projection is po...
const Trk::MaterialLayer * materialLayer() const
return the material Layer
Full Volume description used in Tracking, it inherits from Volume to get the geometrical structure,...
const LayerArray * confinedLayers() const
Return the subLayer array.
std::vector< LayerIntersection< T > > materialLayersOrdered(const Layer *sLayer, const Layer *eLayer, const T &parameters, PropDirection pDir=alongMomentum, const BoundaryCheck &bchk=true, bool resolveSubSurfaces=false) const
Return the material layers ordered based on straight line intersections:
std::vector< std::shared_ptr< BoundarySurface< TrackingVolume > > > & boundarySurfaces()
Method to return the BoundarySurfaces.
const std::string & volumeName() const
Returns the VolumeName - for debug reason, might be depreciated later.
std::vector< BoundaryIntersection< T > > boundarySurfacesOrdered(const T &parameters, PropDirection pDir=alongMomentum, bool startOffBoundary=false) const
Returns the boundary surfaces ordered in probability to hit them based on straight line intersection.
const VolumeBounds & volumeBounds() const
returns the volumeBounds()
Definition Volume.h:96
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Eigen::Matrix< double, 3, 1 > Vector3D
@ alongMomentum
BinnedArray< Layer > LayerArray
simply for the eye
std::pair< Amg::Vector3D, const Trk::TrackingVolume * > PositionAtBoundary
const Amg::Vector3D & direction() const
Method to retrieve the direction at the Intersection.
@ theta
Definition ParamDefs.h:66
@ phi
Definition ParamDefs.h:75
CurvilinearParametersT< NeutralParametersDim, Neutral, PlaneSurface > NeutralCurvilinearParameters
const Amg::Vector3D & position() const
Method to retrieve the position of the Intersection.
Amg::Vector3D position