ATLAS Offline Software
Loading...
Searching...
No Matches
MaterialValidation.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2022 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"
21
22// test
24
25// Gaudi Units
26#include "GaudiKernel/SystemOfUnits.h"
27
28
29Trk::MaterialValidation::MaterialValidation(const std::string& name, ISvcLocator* pSvcLocator)
30: AthAlgorithm(name,pSvcLocator) ,
31 m_materialMapper("Trk::MaterialMapper/MappingMaterialMapper"),
33 m_flatDist(nullptr),
34 m_etaMin(-3.),
35 m_etaMax(3.),
37 m_accTinX0(0)
38{
39
40 // ---------------------- The Material Mapping -------------------------- //
41 // the toolhandle of the MaterialMapper to be used
42 declareProperty("MaterialMapper" , m_materialMapper);
43 declareProperty("MaximumMappingEvents" , m_maxMaterialValidationEvents);
44 // ---------------------- Range setup ----------------------------------- //
45 declareProperty("MinEta" , m_etaMin);
46 declareProperty("MaxEta" , m_etaMax);
47 // ---------------------- Native navigation ----------------------------- //
48 declareProperty("NativeNavigation" , m_runNativeNavigation);
49}
50
55
56
58{
59
60 // Get the TrackingGeometry from StoreGate
62
63 if ( (m_materialMapper.retrieve()).isFailure() )
64 ATH_MSG_WARNING("Could not retrieve MaterialMapper");
65
66 // initialize the random generators
67 m_flatDist = new Rndm::Numbers(randSvc(), Rndm::Flat(0.,1.));
68 return StatusCode::SUCCESS;
69}
70
71
73{
74 ATH_MSG_VERBOSE( "MaterialValidation execute() start ================================================" );
75
76 // create the random direction - flat in eta
77 double eta = m_etaMin + (m_etaMax-m_etaMin)*m_flatDist->shoot();
78 double theta = 2.*atan(exp(-eta));
79 double phi = M_PI * ( 2*m_flatDist->shoot() - 1.);
80 m_accTinX0 = 0;
81
82 // get the position and riection from the random numbers
83 Amg::Vector3D position(0.,0.,0.);
84 Amg::Vector3D direction(sin(theta)*cos(phi),sin(theta)*sin(phi), cos(theta));
85
86 ATH_MSG_DEBUG("[>] Start mapping event with phi | eta = " << phi << " | " << direction.eta());
87
88 // find the start TrackingVolume
89 const Trk::TrackingVolume* sVolume = trackingGeometry().lowestTrackingVolume(position);
90 const Trk::TrackingVolume* nVolume = sVolume;
91 while (nVolume ) {
92 Trk::PositionAtBoundary paB = collectMaterialAndExit(*nVolume, position, direction);
93 position = paB.first;
94 nVolume = paB.second;
95 }
96 ATH_MSG_DEBUG("[<] Finishing event with collected path [X0] = " << m_accTinX0);
97 return StatusCode::SUCCESS;
98}
99
101 const Amg::Vector3D& position,
102 const Amg::Vector3D& direction)
103{
104 // get the entry layers -----------------------------------------------------------
105 std::map<double, Trk::AssociatedMaterial> collectedMaterial;
106
107 // all boundaries found --- proceed
108 Trk::PositionAtBoundary pab(position, 0);
109
110 ATH_MSG_DEBUG("[>>] Entering Volume: " << tvol.volumeName() << "- at " << Amg::toString(position));
111
112 Trk::NeutralCurvilinearParameters cvp(position,direction,0.);
113
115 // A : collect all hit layers
116 auto layerIntersections = tvol.materialLayersOrdered<Trk::NeutralCurvilinearParameters>(nullptr,nullptr,cvp,Trk::alongMomentum);
117 // loop over the layers
118 for (auto& lCandidate : layerIntersections ) {
119 // get the layer
120 const Trk::Layer* layer = lCandidate.object;
121 double pathLength = lCandidate.intersection.pathLength;
122 // get the associate material
123 if (layer->layerMaterialProperties()){
124 // take it from the global position
125 const Trk::MaterialProperties* mprop = layer->layerMaterialProperties()->fullMaterial(lCandidate.intersection.position);
126 if (mprop){
127 double stepLength = mprop->thickness()*fabs(layer->surfaceRepresentation().pathCorrection(lCandidate.intersection.position,direction));
128 collectedMaterial[pathLength] = Trk::AssociatedMaterial(lCandidate.intersection.position, mprop, stepLength, &tvol, layer);
129 }
130 }
131 }
132 // B : collect all boundary layers, start from last hit layer
133 Amg::Vector3D lastPosition = !collectedMaterial.empty() ? collectedMaterial.rbegin()->second.materialPosition() : (position + direction.unit());
134 Trk::NeutralCurvilinearParameters lcp(lastPosition,direction,0.);
135 // boundary surfaces
137 if (!boundaryIntersections.empty()){
138 // by definition is the first one
139 lastPosition = boundaryIntersections.begin()->intersection.position;
140 const Trk::BoundarySurface<Trk::TrackingVolume>* bSurfaceTV = boundaryIntersections.begin()->object;
141 const Trk::Surface& bSurface = bSurfaceTV->surfaceRepresentation();
142 // get the path lenght to it
143 if (bSurface.materialLayer() && bSurface.materialLayer()->layerMaterialProperties()){
144 const Trk::MaterialProperties* mprop = bSurface.materialLayer()->layerMaterialProperties()->fullMaterial(lastPosition);
145 double pathLength = (lastPosition-position).mag();
146 if (mprop){
147 double stepLength = mprop->thickness()*fabs(bSurface.pathCorrection(lastPosition,direction));
148 collectedMaterial[pathLength] = Trk::AssociatedMaterial(lastPosition, mprop, stepLength, &tvol, bSurface.materialLayer());
149 } else
150 collectedMaterial[pathLength] = Trk::AssociatedMaterial(lastPosition, &tvol, bSurface.materialLayer());
151 }
152 // set the new volume
153 const Trk::TrackingVolume* naVolume = bSurfaceTV->attachedVolume(lastPosition, direction, Trk::alongMomentum);
154 pab = Trk::PositionAtBoundary(lastPosition,naVolume);
155 } else
156 pab = Trk::PositionAtBoundary(lastPosition,0);
157 } else {
158 std::map<double, std::pair<const Trk::Layer*, Amg::Vector3D> > intersectedLayers;
159
160 // Process the contained layers if they exist
161 const Trk::LayerArray* layerArray = tvol.confinedLayers();
162 if (layerArray) {
163 // display output
164 std::span<Trk::Layer const * const> layers = layerArray->arrayObjects();
165 auto layIter = layers.begin();
166 auto layIterE = layers.end();
167 for ( ; layIter != layIterE; ++layIter){
168 if ( (*layIter)->layerMaterialProperties() ){
169 Trk::Intersection lsIntersection = (*layIter)->surfaceRepresentation().straightLineIntersection(position, direction, true, true);
170 if (lsIntersection.valid){
171 intersectedLayers[lsIntersection.pathLength] = std::pair<const Trk::Layer*, Amg::Vector3D>(*layIter,lsIntersection.position);
172 // get & record the material
173 // - the position on the surface
174 Amg::Vector3D mposition = (*layIter)->surfaceRepresentation().transform().inverse()*lsIntersection.position;
175 const Trk::MaterialProperties* mprop = (*layIter)->layerMaterialProperties()->fullMaterial(mposition);
176 if (mprop) {
177 double stepLength = mprop->thickness()*fabs((*layIter)->surfaceRepresentation().pathCorrection(lsIntersection.position,direction));
178 collectedMaterial[lsIntersection.pathLength] = Trk::AssociatedMaterial(lsIntersection.position, mprop, stepLength, &tvol, (*layIter));
179 } else
180 collectedMaterial[lsIntersection.pathLength] = Trk::AssociatedMaterial(lsIntersection.position, &tvol, (*layIter));
181
182 ATH_MSG_VERBOSE("[>>>>] record material hit at layer with index " << (*layIter)->layerIndex().value() << " - at " << Amg::toString(lsIntersection.position) );
183 if (mprop)
184 ATH_MSG_VERBOSE("[>>>>] MaterialProperties are " << (*mprop) );
185 else
186 ATH_MSG_VERBOSE("[>>>>] No MaterialProperties found." );
187 }
188 }
189 }
190 }
191
192 // material for confined layers collected, now go to boundary
193
194 // update the position to the last one
195 Amg::Vector3D lastPosition = !intersectedLayers.empty() ? (*(--(intersectedLayers.end()))).second.second : position;
196
197 std::map<double, Trk::VolumeExit > volumeExits;
198 // now find the exit point
199 const auto & bSurfaces = tvol.boundarySurfaces();
200 for (size_t ib = 0; ib < bSurfaces.size(); ++ib){
201 // omit positions on the surface
202 if ( !bSurfaces[ib]->surfaceRepresentation().isOnSurface(lastPosition, true, 0.1, 0.1) ){
203 Trk::Intersection evIntersection = bSurfaces[ib]->surfaceRepresentation().straightLineIntersection(lastPosition, direction, true, true);
204 ATH_MSG_VERBOSE("[>>>>] boundary surface intersection / validity :" << Amg::toString(evIntersection.position) << " / " << evIntersection.valid);
205 ATH_MSG_VERBOSE("[>>>>] with path length = " << evIntersection.pathLength );
206 if (evIntersection.valid){
207 // next attached Tracking Volume
208 const Trk::TrackingVolume* naVolume = bSurfaces[ib]->attachedVolume(evIntersection.position, direction, Trk::alongMomentum);
209 // put it into the map
210 volumeExits[evIntersection.pathLength] = Trk::VolumeExit(naVolume, &(bSurfaces[ib]->surfaceRepresentation()), evIntersection.position);
211 // volume exit
212 ATH_MSG_VERBOSE("[>>>>] found volume exit - at " << Amg::toString(evIntersection.position) );
213 }
214 } else
215 ATH_MSG_VERBOSE("[>>>>] starting position is on surface ! " );
216 }
217 // prepare the boundary
218 if (!volumeExits.empty()){
219 // get the first entry in the map: closest next volume
220 VolumeExit closestVolumeExit = (*volumeExits.begin()).second;
221 // check if the volume exit boundary has material attached
222 const Trk::Surface* bSurface = closestVolumeExit.bSurface;
223 if ( bSurface && bSurface->materialLayer() && bSurface->materialLayer()->layerMaterialProperties()){
224 ATH_MSG_VERBOSE("[>>>>] The boundary surface has an associated layer, collect material from there");
225 const Trk::MaterialProperties* mprop = bSurface->materialLayer()->layerMaterialProperties()->fullMaterial(closestVolumeExit.vExit);
226 double pathToExit = (closestVolumeExit.vExit-lastPosition).mag();
227 if (mprop){
228 double stepLength = mprop->thickness()*fabs(bSurface->pathCorrection(closestVolumeExit.vExit,direction));
229 collectedMaterial[pathToExit] = Trk::AssociatedMaterial(closestVolumeExit.vExit, mprop, stepLength, &tvol, bSurface->materialLayer());
230 } else
231 collectedMaterial[pathToExit] = Trk::AssociatedMaterial(closestVolumeExit.vExit, &tvol, bSurface->materialLayer());
232 }
233 //
234 if (closestVolumeExit.nVolume != &tvol && closestVolumeExit.nVolume) {
235 ATH_MSG_VERBOSE("[>>>>] Next Volume: " << closestVolumeExit.nVolume->volumeName() << " - at " << Amg::toString(closestVolumeExit.vExit) );
236 // return for further navigation
237 pab = Trk::PositionAtBoundary(closestVolumeExit.vExit,closestVolumeExit.nVolume);
238 }
239 } else {
240 ATH_MSG_VERBOSE( "[>>>>] No exit found from Volume '" << tvol.volumeName() << "' - starting radius = " << lastPosition.perp() );
241 const Trk::CylinderVolumeBounds* cvb = dynamic_cast<const Trk::CylinderVolumeBounds*>(&(tvol.volumeBounds()));
242 if (cvb)
243 ATH_MSG_VERBOSE( "[>>>>] Volume outer radius = " << cvb->outerRadius() );
244 }
245
246 }
247 // finally collect the material
248 ATH_MSG_DEBUG("[>>>] Collecting materials from "<< collectedMaterial.size() << " layers");
249 // provide the material to the material mapper
250 auto cmIter = collectedMaterial.begin();
251 auto cmIterE = collectedMaterial.end();
252 for ( ; cmIter != cmIterE; ++cmIter ){
253 m_materialMapper->recordMaterialHit(cmIter->second, cmIter->second.materialPosition());
254 m_accTinX0 += cmIter->second.steplengthInX0();
255 int layerIndex = cmIter->second.associatedLayer() ? cmIter->second.associatedLayer()->layerIndex().value() : 0;
256 ATH_MSG_DEBUG("[>>>] Accumulate pathLength/X0 on layer with index " << layerIndex << " - t/X0 (total so far) = " << cmIter->second.steplengthInX0() << " (" << m_accTinX0 << ")");
257 if (layerIndex){
258 std::string surfaceType =
259 cmIter->second.associatedLayer()->surfaceRepresentation().type() ==
261 ? "Cylinder at radius = "
262 : "Disc at z-position = ";
263 std::string layerType =
264 cmIter->second.associatedLayer()->surfaceArray() ? "Active "
265 : "Passive ";
266 double rz =
267 cmIter->second.associatedLayer()->surfaceRepresentation().type() ==
269 ? cmIter->second.associatedLayer()
270 ->surfaceRepresentation()
271 .bounds()
272 .r()
273 : cmIter->second.associatedLayer()
274 ->surfaceRepresentation()
275 .center()
276 .z();
277 ATH_MSG_DEBUG(" " << layerType << surfaceType << rz);
278 }
279 ATH_MSG_DEBUG(" Distance to origin is " << cmIter->second.materialPosition().mag() );
280 }
281
282 // return what you have
283 return pab;
284
285}
286
287
288
290{
291 ATH_MSG_INFO( "MaterialValidation finalize()" );
292 return StatusCode::SUCCESS;
293}
294
296 std::stringstream msg;
297 msg << "Failed to get conditions data " << m_trackingGeometryReadKey.key() << ".";
298 throw std::runtime_error(msg.str());
299}
300
301
#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
AthAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
Constructor with parameters:
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
MsgStream & msg() const
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.
int m_maxMaterialValidationEvents
limit the number of validation records to avoid 2G files
StatusCode finalize()
standard Athena-Algorithm method
~MaterialValidation()
Default Destructor.
const TrackingGeometry & trackingGeometry() const
StatusCode execute()
standard Athena-Algorithm method
PositionAtBoundary collectMaterialAndExit(const Trk::TrackingVolume &tvol, const Amg::Vector3D &position, const Amg::Vector3D &direction)
ToolHandle< IMaterialMapper > m_materialMapper
Mapper and Inspector.
MaterialValidation(const std::string &name, ISvcLocator *pSvcLocator)
Standard Athena-Algorithm Constructor.
Rndm::Numbers * m_flatDist
Random generator for flat distribution.
double m_etaMax
eta boundary
SG::ReadCondHandleKey< TrackingGeometry > m_trackingGeometryReadKey
StatusCode initialize()
standard Athena-Algorithm method
bool m_runNativeNavigation
validate the native TG navigation
void throwFailedToGetTrackingGeometry() const
double m_etaMin
eta boundary
double m_accTinX0
accumulated t in X0
Abstract Base Class for tracking surfaces.
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
@ theta
Definition ParamDefs.h:66
@ phi
Definition ParamDefs.h:75
CurvilinearParametersT< NeutralParametersDim, Neutral, PlaneSurface > NeutralCurvilinearParameters
Amg::Vector3D position
const Trk::Surface * bSurface
Amg::Vector3D vExit
const Trk::TrackingVolume * nVolume