ATLAS Offline Software
Loading...
Searching...
No Matches
HGTD_LayerBuilderCond.cxx
Go to the documentation of this file.
1
2/*
3 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
4*/
5
7// HGTD_LayerBuilderCond.cxx, (c) ATLAS Detector software
9
12
13//HGTD include
18
19// Trk inlcude
28#include "TrkSurfaces/Surface.h"
29// STL
30#include <map>
31
32// constructor
33HGTD_LayerBuilderCond::HGTD_LayerBuilderCond(const std::string& t, const std::string& n, const IInterface* p) :
34 base_class(t,n,p),
35 m_hgtdMgr(nullptr),
36 m_hgtdHelper(nullptr),
38 m_identification("HGTD"),
39 m_rBins(50),
40 m_phiBins(100),
41 m_discEnvelopeR(50.),
42 m_discThickness(0.2),
44{
45 // general steering
46 declareProperty("SetLayerAssociation" , m_setLayerAssociation);
47 // identification
48 declareProperty("Identification" , m_identification);
49 // set some parameters
50 declareProperty("DiscMaterialBinsR" , m_rBins);
51 declareProperty("DiscMaterialBinsPhi" , m_phiBins);
52 declareProperty("DiscEnvelope" , m_discEnvelopeR);
53 declareProperty("DiscThickness" , m_discThickness);
54 // validation
55 declareProperty("RunValidation" , m_runGeometryValidation);
56}
57
58// destructor
60
61// Athena standard methods
62// initialize
64{
65
66 ATH_MSG_DEBUG( "initialize()" );
67 // get HGTD Detector Description Manager and HGTD Helper
68 ATH_CHECK(detStore()->retrieve(m_hgtdMgr, "HGTD"));
69 ATH_CHECK(detStore()->retrieve(m_hgtdHelper, "HGTD_ID"));
70
71 // get HGTD detector element collection
72 ATH_CHECK(m_HGTD_ReadKey.initialize());
73
74 return StatusCode::SUCCESS;
75}
76
77
79{
81 if (*readHandle==nullptr) {
82 ATH_MSG_ERROR("Null pointer to the read conditions object of " << m_HGTD_ReadKey.key());
83 }
84 return readHandle;
85}
86
87
89std::unique_ptr<const std::vector<Trk::DiscLayer*> >
90HGTD_LayerBuilderCond::discLayers(const EventContext& ctx,
92{
93 ATH_MSG_DEBUG( "calling HGTD_LayerBuilderCond::discLayers()" );
94
95 // sanity check for HGTD Helper
96 if (!m_hgtdHelper){
97 ATH_MSG_ERROR("HGTD Detector Manager or ID Helper could not be retrieved - giving up.");
98 return nullptr;
99 }
100
101 // get general layout
103 if(*readHandle == nullptr){
104 return nullptr;
105 }
106 whandle.addDependency (readHandle);
107
108 const InDetDD::HGTD_DetectorElementCollection* readCdo{*readHandle};
110
111 // loop on all modules (selecting only one endcap side)
112 // and evaluates the number of discs
113 // assuming you have the same number of modules on both sides
114 int nlayers = 0;
115 for (; hgtdDetIter != readCdo->end(); ++hgtdDetIter){
116 Identifier currentId((*hgtdDetIter)->identify());
117 // skipping negative side
118 if (m_hgtdHelper->endcap(currentId)<0) continue;
119 if (m_hgtdHelper->layer(currentId)>nlayers)
120 nlayers++;
121 }
122 // adding one layer offset
123 nlayers+=1;
124
125 ATH_MSG_DEBUG( "Configured to build " << nlayers << " *2 disc-like layers (+ additional support layers)." );
126
127 // prepare the vectors
128 std::vector<float> discZpos(2*nlayers,0.);
129 std::vector< std::vector<Trk::SurfaceOrderPosition> > discSurfaces(2*nlayers, std::vector<Trk::SurfaceOrderPosition>());
130
131 int hgtdModules = 0;
132 int sumCheckhgtdModules = 0;
133 unsigned int currentlayer = 0;
134 float maxRmax = -std::numeric_limits<float>::max();
135 float minRmin = std::numeric_limits<float>::max();
136
137 // get the missing dimensions by loop over DetElements
138 hgtdDetIter = readCdo->begin();
139 for (; hgtdDetIter != readCdo->end(); ++hgtdDetIter){
140 // take it - if
141 // a) you have a detector element ... protection
142 if ( (*hgtdDetIter) ) {
143 // get the identifier
144 Identifier currentId((*hgtdDetIter)->identify());
145
146 ATH_MSG_DEBUG("Element : " << m_hgtdHelper->endcap(currentId) << "/"
147 << m_hgtdHelper->layer(currentId) << "/"
148 << m_hgtdHelper->eta_module(currentId) << "/"
149 << m_hgtdHelper->phi_module(currentId));
150
151 // increase the counter of HGTD modules
152 hgtdModules++;
153
154 // parse all z positions for the mean value of the discs
155 float currentZ = (*hgtdDetIter)->center().z();
156 //calculate current layer and current disk from it
157 currentlayer = m_hgtdHelper->layer(currentId);
158 // adding the numbe of layers per side as offset
159 currentlayer += currentZ > 0. ? nlayers : 0;
160 ATH_MSG_DEBUG( " ---- layer: " << currentlayer );
161
162 // evaluate the z-position per layer
163 // all modules on the same HGTD layer have the same z
164 discZpos[currentlayer] = currentZ;
165
166 // evaluate the r-extension per layer
167 float currentRmin = (*hgtdDetIter)->rMin();
168 float currentRmax = (*hgtdDetIter)->rMax();
169 ATH_MSG_DEBUG( " ---- rmin/rmax: " << currentRmin << "/" << currentRmax );
170 if (maxRmax<currentRmax)
171 maxRmax = currentRmax;
172 if (minRmin>currentRmin)
173 minRmin = currentRmin;
174
175 // fill the elements for the layers into the surface arrays
176 // get the center position
177 const Amg::Vector3D& orderPosition = (*hgtdDetIter)->center();
178
179
180 // Register the chosen side in the object array
181 //
182 // Passing a no-op deleter (no delete happens)
183 // This line can be problematic
184 // 1. We couple the DetElement owned surface to the Tracking Geometry.
185 // The lifetime is not controlled by the geometry.
186 // For now we need to be careful on how we schedule these as we do not
187 // want to end up with dangling ptr.
188 // 2. We modiy the payload (see const_cast).
189 // NOTE !!! We can avoid these if we can clone and not "share".
190 // Or if we have also created the layer and attached them
191 // to the surfaces when the Det Elements are created.
192 // Aka run this Layer Builder as part of the DetElement creation.
193 Trk::Surface* mutableSurace = const_cast<Trk::Surface*>(&((*hgtdDetIter)->surface()));
194 std::shared_ptr<Trk::Surface> sharedSurface(mutableSurace,[](Trk::Surface*) {});
195 //
196 Trk::SurfaceOrderPosition surfaceOrder(sharedSurface, orderPosition);
197
198 discSurfaces[currentlayer].push_back(surfaceOrder);
199
200 } else if (!(*hgtdDetIter))
201 ATH_MSG_WARNING("Not valid pointer to HGTD Detector element... something wrong with the Id dictionary?");
202 }
203
204 // adding some envelope
205 maxRmax += m_discEnvelopeR;
206 minRmin -= m_discEnvelopeR;
207
208 // construct the layers
209 auto discLayers = std::make_unique<std::vector<Trk::DiscLayer*> >();
210
211 double thickness = m_discThickness;
212
213 int discCounter = 0;
214 for (auto& thisDiscZpos : discZpos) {
215 // screen output
216 ATH_MSG_DEBUG( "Building a DiscLayer: " );
217 ATH_MSG_DEBUG( " -> At Z - Position : " << thisDiscZpos );
218 ATH_MSG_DEBUG( " -> With Thickness : " << thickness << " i- ncludes envelope tolerance : " << m_discEnvelopeR );
219 ATH_MSG_DEBUG( " -> With Rmin/Rmax (est) : " << minRmin << " / " << maxRmax );
220
221 ATH_MSG_DEBUG( "... creating binned array ... ");
222
223 std::vector<float> rBins = {minRmin};
224 std::vector<std::vector<float>> phiBins = {{}};
225
226 evaluateBestBinning(discSurfaces[discCounter], rBins, maxRmax, phiBins);
227
228 // Build the BinUtilities using the bins defined at construction
229 // the extension is provided in the previous loop
230 auto BinUtilityR = Trk::BinUtility(rBins, Trk::open, Trk::binR);
231 auto subBinUtilitiesPhi = std::vector<Trk::BinUtility>();
232 ATH_MSG_DEBUG("BinUtilityR --> " << BinUtilityR );
233
234 for (unsigned int bin = 0; bin < rBins.size()-1; bin++) {
235 auto BinUtilityY = Trk::BinUtility(phiBins.at(bin), Trk::closed, Trk::binPhi);
236 subBinUtilitiesPhi.push_back(BinUtilityY);
237 ATH_MSG_DEBUG(bin << ") BinUtilityPhi --> " << BinUtilityY );
238 }
239
240 // prepare the binned array, it can be with one to several rings
241 auto currentBinnedArray =
242 std::make_unique<Trk::BinnedArray1D1D<Trk::Surface>>(
243 discSurfaces[discCounter], BinUtilityR, subBinUtilitiesPhi);
244
245 ATH_MSG_DEBUG( "... done!" );
246
247 int discSurfacesNum = (discSurfaces[discCounter]).size();
248
249 ATH_MSG_DEBUG( "Constructed BinnedArray for DiscLayer with "<< discSurfacesNum << " SubSurfaces." );
250
251 // always run the geometry validation to catch flaws
253 // checking for :
254 // - empty surface bins
255 // - doubly filled bins
256 std::map< const Trk::Surface*,Amg::Vector3D > uniqueSurfaceMap;
257 std::map< const Trk::Surface*,Amg::Vector3D >::iterator usmIter = uniqueSurfaceMap.end();
258 // check the registered surfaces in the binned array
259 std::span<Trk::Surface * const> arraySurfaces = currentBinnedArray->arrayObjects();
260 size_t dsumCheckSurfaces = 0;
261 double lastPhi = 0.;
262 for (const auto & asurfIter : arraySurfaces){
263 if ( asurfIter ) {
264 ++dsumCheckSurfaces;
265 usmIter = uniqueSurfaceMap.find(asurfIter);
266 lastPhi = asurfIter->center().phi();
267 if (usmIter != uniqueSurfaceMap.end()) {
268 ATH_MSG_WARNING("Non-unique surface found with eta/phi = "
269 << asurfIter->center().eta() << " / "
270 << asurfIter->center().phi());
271 } else {
272 uniqueSurfaceMap[asurfIter] = asurfIter->center();
273 }
274 } else {
275 ATH_MSG_WARNING("Zero-pointer in array detected in this ring, last "
276 "valid phi value was = "
277 << lastPhi << " --> discCounter: " << discCounter);
278 }
279 }
280 sumCheckhgtdModules += dsumCheckSurfaces;
281 }
282
283 // get the layer material from the helper method
284 const Trk::LayerMaterialProperties& layerMaterial = discLayerMaterial(minRmin,maxRmax);
285
287 Amg::Transform3D activeLayerTransform ;
288 activeLayerTransform = Amg::Translation3D(0.,0.,thisDiscZpos);
289
290 auto activeLayerBounds = std::make_shared<Trk::DiscBounds>(minRmin, maxRmax);
291
292 auto olDescriptor = std::make_unique<HGTD_OverlapDescriptor>(
293 currentBinnedArray.get(), rBins, phiBins);
294
295 // register the layer to the surfaces
296 std::span<Trk::Surface * const> layerSurfaces = currentBinnedArray->arrayObjects();
297 // layer creation; deletes currentBinnedArray in baseclass 'Layer' upon destruction
298 // activeLayerTransform deleted in 'Surface' baseclass
299 Trk::DiscLayer* activeLayer = new Trk::DiscLayer(activeLayerTransform,
300 activeLayerBounds,
301 std::move(currentBinnedArray),
302 layerMaterial,
303 thickness,
304 std::move(olDescriptor));
305
306 registerSurfacesToLayer(layerSurfaces,*activeLayer);
307 discLayers->push_back(activeLayer);
308 // increase the disc counter by one
309 ++discCounter;
310 }
311
312 //
313 ATH_MSG_DEBUG( hgtdModules << " HGTD Modules parsed for Disc Layer dimensions." );
315 ATH_MSG_DEBUG( sumCheckhgtdModules << " HGTD Modules filled in Disc Layer Arrays." );
316 if ( hgtdModules-sumCheckhgtdModules )
317 ATH_MSG_WARNING( hgtdModules-sumCheckhgtdModules << " Modules not registered properly in binned array." );
318 }
319
320 // sort the vector
321 Trk::DiscLayerSorterZ zSorter;
322 std::sort(discLayers->begin(), discLayers->end(), zSorter);
323
324 return discLayers;
325}
326
328{
329 Trk::BinUtility layerBinUtilityR(m_rBins, rMin, rMax, Trk::open, Trk::binR);
330 Trk::BinUtility layerBinUtilityPhi(m_phiBins, -M_PI, M_PI, Trk::closed, Trk::binPhi);
331 layerBinUtilityR += layerBinUtilityPhi;
332 return Trk::BinnedLayerMaterial(layerBinUtilityR);
333}
334
335void HGTD_LayerBuilderCond::registerSurfacesToLayer(std::span<Trk::Surface * const>& layerSurfaces, const Trk::Layer& lay) const
336{
337 if (!m_setLayerAssociation) return;
338 // register the surfaces to the layer
339 for (const auto & surfaces : layerSurfaces) {
340 if (surfaces) {
341 // register the current surfaces
342 (*surfaces).associateLayer(lay);
343 }
344 }
345}
346
347void HGTD_LayerBuilderCond::evaluateBestBinning(std::vector<Trk::SurfaceOrderPosition>& surfaces,
348 std::vector<float>& rBins, float& maxRadius,
349 std::vector<std::vector<float>>& phiBins)
350{
351 // get all the centers (r,phi), as you want to play with them
352 std::vector < std::pair< float, float> > centers = {};
353 centers.reserve(surfaces.size());
354 for ( auto& orderedSurface : surfaces) {
355 centers.emplace_back(orderedSurface.second.perp(), orderedSurface.second.phi());
356 }
357
358 // sorting the centers accordingly to r
359 std::sort(centers.begin(), centers.end(),
360 [](const std::pair< float, float>& a, const std::pair< float, float>& b) -> bool {
361 return a.first < b.first;
362 });
363
364 // at the beginning use a fine binning in phi
365 // it is updated later to fit the amount of surfaces
366 // once you have defined a bin in radius
367 int bins = 100;
368 float step = 2*M_PI/float(bins);
369 std::vector<float> finerBinning = {};
370 finerBinning.reserve(bins);
371
372 for (int bin = 0; bin<=bins; bin++) {
373 finerBinning.push_back(-M_PI+step*bin);
374 }
375
376 // use this vector to save the indices and
377 // guess when you have to add
378 // an additional bin in r
379 std::vector<int> phiIndices = {};
380 std::vector<float> tmpRadii = {};
381
382 for (auto& center : centers) {
383 float phi = center.second;
384 const auto boundVal = std::lower_bound(finerBinning.begin(), finerBinning.end(), phi);
385 int phiIndex = std::distance(finerBinning.begin(), boundVal);
386 // if the element fits in the given r bin, add it,
387 // otherwise reset the indices and start a new r bin
388 if (std::find(phiIndices.begin(), phiIndices.end(), phiIndex)==phiIndices.end()) {
389 phiIndices.push_back(phiIndex);
390 tmpRadii.push_back(center.first);
391 } else {
392 phiIndices.clear();
393 for (unsigned int index = (tmpRadii.size()-1); index>0; index--) {
394 auto& prevRadius = tmpRadii.at(index);
395 if ( std::abs(prevRadius - center.first)<1e-5 ) {
396 const auto boundVal = std::lower_bound(finerBinning.begin(), finerBinning.end(), phi);
397 int phiIndex = std::distance(finerBinning.begin(), boundVal);
398 phiIndices.push_back(phiIndex);
399 continue;
400 } else {
401 float r = 0.5*(prevRadius+center.first);
402 rBins.push_back(r);
403 tmpRadii = {prevRadius};
404 break;
405 }
406 }
407 }
408 }
409
410 rBins.push_back(maxRadius);
411
412 // now we have the best binning in r and want to
413 // map the centers accordingly to this
414 std::vector< std::vector < float > > binnedCenters = {{}};
415
416 for (auto& center : centers) {
417 float r = center.first;
418 float phi = center.second;
419 const auto boundVal = std::lower_bound(rBins.begin(), rBins.end(), r);
420 int rIndex = std::distance(rBins.begin(), boundVal);
421 if (int(binnedCenters.size())<rIndex)
422 binnedCenters.push_back({phi});
423 else
424 binnedCenters.back().push_back(phi);
425 }
426
427 // now that we have the centers binned in r, we evaluate the best
428 // bin in phi for each of those bins
429 bool isFirst = true;
430 for (auto& centersInBin : binnedCenters) {
431 // sorting the centers accordingly to phi_bins
432 std::sort(centersInBin.begin(), centersInBin.end());
433 if (isFirst) {
434 phiBins.back().push_back(-M_PI);
435 isFirst=false;
436 } else phiBins.push_back({-M_PI});
437 for (unsigned int index = 0; index<(centersInBin.size()-1); index++) {
438 float phi = 0.5*(centersInBin.at(index)+centersInBin.at(index+1));
439 phiBins.back().push_back(phi);
440 }
441 }
442
443 }
#define M_PI
Scalar phi() const
phi method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
static Double_t a
static const std::vector< std::string > bins
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
virtual StatusCode initialize() override
AlgTool initialize method.
int m_phiBins
set the number of bins
bool m_setLayerAssociation
Set Layer Association.
bool m_runGeometryValidation
run geometry validation
float m_discEnvelopeR
set disc envelope
float m_discThickness
set disc thickness
virtual std::unique_ptr< const std::vector< Trk::DiscLayer * > > discLayers(const EventContext &ctx, SG::WriteCondHandle< Trk::TrackingGeometry > &whandle) const override final
LayerBuilder interface method - returning Endcap-like layers.
SG::ReadCondHandle< InDetDD::HGTD_DetectorElementCollection > retrieveHGTDdetElements(const EventContext &ctx) const
helper method to construct HGTD materia
void registerSurfacesToLayer(std::span< Trk::Surface *const > &surfaces, const Trk::Layer &layer) const
HGTD_LayerBuilderCond(const std::string &, const std::string &, const IInterface *)
AlgTool style constructor.
virtual ~HGTD_LayerBuilderCond()
Destructor.
int m_rBins
set the number of bins
const HGTD_ID * m_hgtdHelper
HGTD Id Helper.
std::string m_identification
string identification
const HGTD_DetectorManager * m_hgtdMgr
the HGTD Detector Manager
static void evaluateBestBinning(std::vector< Trk::SurfaceOrderPosition > &surfaces, std::vector< float > &rBins, float &maxRadius, std::vector< std::vector< float > > &phiBins)
SG::ReadCondHandleKey< InDetDD::HGTD_DetectorElementCollection > m_HGTD_ReadKey
const Trk::BinnedLayerMaterial discLayerMaterial(double rMin, double rMax) const
layer association
void addDependency(const EventIDRange &range)
A generic symmetric BinUtility, for fully symmetric binning in terms of binning grid and binning type...
Definition BinUtility.h:39
It extends the LayerMaterialProperties base class.
simple helper function to allow sorting of DiscLayers in z
Definition DiscLayer.h:152
Class to describe a disc-like detector layer for tracking, it inhertis from both, Layer base class an...
Definition DiscLayer.h:45
This virtual base class encapsulates the logics to build pre/post/full update material for Layer stru...
Base Class for a Detector Layer in the Tracking realm.
Definition Layer.h:72
Abstract Base Class for tracking surfaces.
int r
Definition globals.cxx:22
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
Eigen::Translation< double, 3 > Translation3D
DataVector< HGTD_DetectorElement > HGTD_DetectorElementCollection
std::pair< std::shared_ptr< Surface >, Amg::Vector3D > SurfaceOrderPosition
@ open
Definition BinningType.h:40
@ closed
Definition BinningType.h:41
@ binR
Definition BinningType.h:50
@ binPhi
Definition BinningType.h:51
Definition index.py:1
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.