ATLAS Offline Software
Loading...
Searching...
No Matches
TRT_LayerBuilderImpl.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
7//Trk
17// GeoPrimitives
19// InDetDD
25
26namespace {
27 template<class T>
28 class PtrVectorWrapper
29 {
30 public:
31 PtrVectorWrapper()
32 : m_ptr(new std::vector<T*>)
33 {}
34
35 ~PtrVectorWrapper()
36 {
37 if (m_ptr) {
38 for (const T* elm : *m_ptr) {
39 delete elm;
40 }
41 m_ptr->clear();
42 }
43 }
44 std::vector<T*>& operator*() { return *m_ptr; }
45 const std::vector<const T*>& operator*() const { return *m_ptr; }
46
47 std::vector<T*>* operator->() { return m_ptr.get(); }
48 const std::vector<const T*>* operator->() const { return m_ptr.get(); }
49
50 std::vector<T*>* release() { return m_ptr.release(); }
51
52 private:
53 std::unique_ptr<std::vector<T*>> m_ptr;
54 };
55
56}
57
58// constructor
59InDet::TRT_LayerBuilderImpl::TRT_LayerBuilderImpl(const std::string& t, const std::string& n, const IInterface* p) :
60 AthAlgTool(t,n,p)
61{
62}
63
64
65std::unique_ptr<const std::vector<Trk::CylinderLayer*> >
67 ATH_MSG_DEBUG( "Building cylindrical layers for the TRT " );
68 PtrVectorWrapper<Trk::CylinderLayer> barrelLayers;
69
70 // get Numerology and Id HElper
71 const InDetDD::TRT_Numerology* trtNums = trtContainer->getTRTNumerology();
72
73 // get the TRT ID Helper
74 const TRT_ID* trtIdHelper = nullptr;
75 if (detStore()->retrieve(trtIdHelper, "TRT_ID").isFailure()) {
76 ATH_MSG_ERROR("Could not get TRT ID helper");
77 return nullptr;
78 }
79
80 int nBarrelRings = trtNums->getNBarrelRings();
81 int nBarrelPhiSectors = trtNums->getNBarrelPhi();
82 double layerPhiStep = 2*M_PI/nBarrelPhiSectors;
83
84 int nTotalBarrelLayers = 0;
85
86 // get the overall dimensions
87 double rMin = 10e10;
88 double rMax = 0.;
89
90 double layerZmax = 0.;
91 double layerZmin = 10e10;
92
93 // pre-loop for overall layer numbers & some ordering ---------------------------------------
94 for (int ring=0; ring < nBarrelRings; ring++) {
95 // the number of barrel layers
96 int nBarrelLayers = trtNums->getNBarrelLayers(ring);
97 nTotalBarrelLayers += nBarrelLayers;
98 // loop over layers
99 for (int layer=0; layer < nBarrelLayers; layer++){
100 for (int phisec=0; phisec <nBarrelPhiSectors; ++phisec)
101 {
102 for (int iposneg=0; iposneg<2; ++iposneg){
103 // get the element
104 const InDetDD::TRT_BarrelElement* trtbar = trtContainer->getBarrelDetElement(iposneg, ring, phisec, layer); // TODO share this line
105
106 // get overall dimensions only one time
107 const Trk::PlaneSurface* elementSurface = dynamic_cast<const Trk::PlaneSurface*>(&(trtbar->surface()));
108 if (!elementSurface) {
109 ATH_MSG_WARNING( "elementSurface: dynamic_cast to Trk::PlaneSurface failed - skipping ... ring/layer/phisec/iposneg = " << ring << "/" << layer << "/" << phisec << "/" << iposneg );
110 continue;
111 }
112 const Trk::RectangleBounds* elementBounds = dynamic_cast<const Trk::RectangleBounds*>(&(trtbar->bounds()));
113 if (!elementBounds) {
114 ATH_MSG_WARNING( "elementBounds: dynamic_cast to Trk::RectangleBounds failed - skipping ... ring/layer/phisec/iposneg = " << ring << "/" << layer << "/" << phisec << "/" << iposneg );
115 continue;
116 }
117 double elementZcenter = (elementSurface->center()).z();
118 double elementZmin = std::abs(elementZcenter - elementBounds->halflengthY());
119 double elementZmax = std::abs(elementZcenter + elementBounds->halflengthY());
120 // take what you need
121 takeSmaller(layerZmin, elementZmin); takeBigger(layerZmax, elementZmax);
122 // get the radial dimensions
123 double currentR = trtbar->center().perp();
124 takeSmallerBigger(rMin,rMax,currentR);
125 }
126 }
127 }
128 }
129
130 if (nTotalBarrelLayers==0) {
131 ATH_MSG_WARNING( "nTotalBarrelLayers = 0 ... aborting and returning 0 !" );
132 return nullptr;
133 }
134
135 // calculate delta(R) steps and delta(R)
136 double rDiff = std::abs(rMax-rMin);
137 double rStep = rDiff/(m_modelBarrelLayers+1);
138 double layerHalflength = layerZmax;
139
140 // prepare the material
141 if ( std::abs(rDiff) <= 0.1 ) {
142 return nullptr;
143 }
144
145 // fix the positions where the layers are - these are used for the model geometry and the complex geometry ---------------
146 std::vector<double> layerRadii;
147 layerRadii.reserve(m_modelBarrelLayers);
148 for (unsigned int ilay = 1; ilay <= m_modelBarrelLayers; ++ilay)
149 layerRadii.push_back(rMin+ilay*rStep-0.5*m_layerThickness);
150 // these are the layer iterators
151 auto layerRadiusIter = layerRadii.begin();
152 auto layerRadiusIterEnd = layerRadii.end();
153
154 // (A) model geometry section
156
157 ATH_MSG_VERBOSE( " -> " << layerRadii.size() << " cylindrical barrel layers between " << rMin << " and " << rMax << " ( at step "<< rStep << " )");
158
159 // create the layers
160 for ( ; layerRadiusIter != layerRadiusIterEnd; ++layerRadiusIter ) {
161 // ----- prepare the BinnedLayerMaterial -----------------------------------------------------
162 Trk::BinnedLayerMaterial* layerMaterial = nullptr;
163 // -- material with 1D binning
164 Trk::BinUtility layerBinUtility1DZ(m_barrelLayerBinsZ,-layerHalflength, layerHalflength, Trk::open, Trk::binZ);
165 if (m_barrelLayerBinsPhi==1u){
166 // no binning in phi
167 layerMaterial =new Trk::BinnedLayerMaterial(layerBinUtility1DZ);
168 } else { // -- material with 2D binning : Rphi*Z optimized for cylinder layer
169 Trk::BinUtility layerBinUtility2DRPhiZ(m_barrelLayerBinsPhi,
170 -(*layerRadiusIter)*M_PI,
171 (*layerRadiusIter)*M_PI,
174 layerBinUtility2DRPhiZ += layerBinUtility1DZ;
175 layerMaterial =new Trk::BinnedLayerMaterial(layerBinUtility2DRPhiZ);
176 }
177 // Barrel layers are centered around (0,0,0) by definition
178 barrelLayers->push_back(
179 new Trk::CylinderLayer(std::make_shared<Trk::CylinderBounds>(
180 *layerRadiusIter, layerHalflength),
181 *layerMaterial, m_layerThickness));
182 ATH_MSG_VERBOSE(" --> Creating a layer at radius : " << *layerRadiusIter);
183 delete layerMaterial;
184 }
185 } else {
186
187 // (B) complex geometry section
188 float nMaterialLayerStep = 1.*nTotalBarrelLayers/m_modelBarrelLayers;
189 // complex geo should build same # of mat. layers as model geo; counter to check this:
190 unsigned int cMaterialLayerCount = 0;
191 // inclusive layer counter over all rings, used to determine mat. layer position
192 unsigned int cLayer=0;
193
194 // loop over rings
195 ATH_MSG_VERBOSE("TRT Barrel has " << nBarrelRings << " rings.");
196
197 for (int ring=0; ring < nBarrelRings; ring++){
198
199 int nBarrelLayers = trtNums->getNBarrelLayers(ring);
200 ATH_MSG_VERBOSE("-> Ring " << ring << " has " << nBarrelLayers << " barrel layers.");
201 // loop over layers
202 for (int layer=0; layer < nBarrelLayers; layer++){
203
204 // ----------------------------------------------------------------------------------
205 ATH_MSG_VERBOSE("--> Layer " << layer << " is being built with " << nBarrelPhiSectors << " secors in phi.");
206
207 // increase inclusive layer counter for next material layer
208 ++cLayer;
209
210 // set layer dimensions radius
211 double layerRadius = 0.;
212 double layerRadiusMin = 10e10;
213 double layerRadiusMax = 0.;
214 double layerPhiMin = 10.;
215 double layerPhiMax = -10;
216
217 // per phi sector we make a 2D binnin in phi-z
218 std::vector< std::pair<Trk::BinnedArray2D<Trk::Surface>, Amg::Vector3D > > layerSectorArrays;
219 Amg::Vector3D layerSectorPosition(0.,0.,0.);
220
221 // the sector approaching surfaces
222 std::vector< std::pair< std::shared_ptr<const Trk::ApproachSurfaces>, Amg::Vector3D > > layerApproachSurfaces;
223
224 // layer sector arrays
225 for (int phisec=0; phisec < nBarrelPhiSectors; phisec++){
226 // ----------------------------------------------------------------------------------
227 ATH_MSG_VERBOSE("---> Sector " << phisec << " gahtering the details.");
228 // -------------- a phi sector (expands in +/- z) -----------------------------------
229
230 // order the straws onto layers
231 std::vector< Trk::SurfaceOrderPosition > strawsPerPhiSecLayer;
232 // get the min an max phi, the min and max z
233 double phiMin = 10.;
234 double phiMax = -10.;
235 // sector stuff
236 int sectorStraws = 0;
237 // positive and negative sector
238 for (int posneg=0; posneg<2; ++posneg){
239 // sort the elements
240 const InDetDD::TRT_BarrelElement* currentElement = trtContainer->getBarrelDetElement(posneg, ring, phisec, layer); // TODO share this line
241 // get overall dimensions only one time
242 const Trk::PlaneSurface* elementSurface = dynamic_cast<const Trk::PlaneSurface*>(&(currentElement->surface()));
243 if (!elementSurface) {
244 ATH_MSG_WARNING( "elementSurface: dynamic_cast to Trk::PlaneSurface failed - skipping ... ring/layer/phisec/posneg = " << ring << "/" << layer << "/" << phisec << "/" << posneg );
245 continue;
246 }
247
248 // create teh approach surfaces --------------------------------------------------------------------------------------------------
249 // getTransformFromRotTransl(Amg::RotationMatrix3D rot, Amg::Vector3D transl_vec )
251 const Amg::Transform3D& elementTransform = elementSurface->transform();
252 const Amg::Vector3D& elementCenter = elementSurface->center();
253 const Amg::Vector3D& elementNormal = elementSurface->normal();
254 Amg::RotationMatrix3D elementRotation = elementTransform.rotation();
255 // outer / inner
256 Amg::Vector3D outerCenter(elementCenter+(0.5*m_layerThickness+m_layerStrawRadius)*elementNormal);
257 Amg::Vector3D innerCenter(elementCenter-(0.5*m_layerThickness+m_layerStrawRadius)*elementNormal);
258
259 // assign the layer sector position for the straw array ordering
260 layerSectorPosition = elementSurface->center();
261
262 // now register the two surfaces
263 aSurfaces->push_back(new Trk::PlaneSurface(Amg::Transform3D(Amg::getTransformFromRotTransl(elementRotation, innerCenter))));
264 aSurfaces->push_back(new Trk::PlaneSurface(Amg::Transform3D(Amg::getTransformFromRotTransl(elementRotation, outerCenter))));
265
266 // now register it to for building the array
267 layerApproachSurfaces.emplace_back( std::shared_ptr<const Trk::ApproachSurfaces>(aSurfaces),elementCenter);
268 // screen output
269 ATH_MSG_VERBOSE("---> Sector " << phisec << " - posneg - " << posneg << " - with central phi = " << elementSurface->center().phi() );
270 // sector phi centers
271 takeSmallerBigger(layerPhiMin,layerPhiMax,elementSurface->center().phi());
272
273 // loop over straws, fill them and find the phi boundaries
274 for (unsigned int istraw=0; istraw<currentElement->nStraws(); ++istraw)
275 {
276 Identifier strawId = trtIdHelper->straw_id(currentElement->identify(), istraw);
277 const Trk::Surface* currentStraw = &(currentElement->surface(strawId));
278 // get the phi values
279 double currentPhi = currentStraw->center().phi();
280 if (phisec == m_barrelSectorAtPiBoundary && currentPhi < 0.){
281 currentPhi = M_PI + currentPhi;
282 currentPhi += M_PI;
283 }
284 // the layer radius
285 takeSmallerBigger(layerRadiusMin,layerRadiusMax,currentStraw->center().perp());
286 takeSmallerBigger(phiMin, phiMax, currentPhi);
287 // make the ordering position
288 Amg::Vector3D strawOrderPos(currentStraw->center());
289 /*
290 * The above line was using the nodel (not delete option for the old shared object
291 * now that SharedObject is a shared_ptr typedef do the same with empty deleter
292 */
293 // Something like
294 // std::shared_ptr<Trk::Surface> =
295 // std::make_shared<Trk::Surface>(.....)) could be fine
296 //
297 // As things are now
298 // 1) Notice that basically we couple the DetElement owned
299 // surface to the Tracking Geometry passing a no-op deleter
300 // (no delete happens) to the shared_ptr(SharedObject is
301 // typedef of shared_ptr)
302 // 2) The const_cast here make the
303 // code non MT safe. For now we handle this by being careful
304 // on lifetimes and non-re-entrant TG construction.
305 std::shared_ptr<Trk::Surface> sharedSurface(const_cast<Trk::Surface*>(currentStraw),
307 strawsPerPhiSecLayer.emplace_back(sharedSurface, strawOrderPos);
308 // and record
309 ++sectorStraws;
310 } // loop over straws done
311 } // loop over posneg done
312 // show the phiMin/phiMax to the screen
313 // prepare the
314 // fix to CID 24918
315 if (!sectorStraws) {
316 return nullptr;
317 }
318 double deltaPhi = (phiMax-phiMin);
319 double phiStep = deltaPhi/(0.5*sectorStraws-1);
320 ATH_MSG_VERBOSE("---> Sector " << phisec << " - with " << 0.5*sectorStraws << " straws - straw phiMin/phiMax (step) = " << phiMin << " / " << phiMax << " (" << phiStep << ")");
321 // phi min / phi max
322 phiMin -= 0.5*phiStep;
323 phiMax += 0.5*phiStep;
324 // correct for the +pi/-pi module
325 // now create the BinUtility
326 //coverity[DIVIDE_BY_ZERO:FALSE]
327 auto layerStrawPhiZUtility = Trk::BinUtility(sectorStraws/2,phiMin,phiMax,Trk::open, Trk::binPhi);
328 layerStrawPhiZUtility += Trk::BinUtility(2,-layerZmax, layerZmax, Trk::open, Trk::binZ);
329 // create the 2D BinnedArray
330 Trk::BinnedArray2D<Trk::Surface> layerStrawPhiSector(strawsPerPhiSecLayer,layerStrawPhiZUtility);
331 ATH_MSG_VERBOSE("---> Sector " << phisec << " - BinnedArray for straws prepared for " << strawsPerPhiSecLayer.size() << " straws.");
332 // fill the array
333 layerSectorArrays.emplace_back(std::move(layerStrawPhiSector), layerSectorPosition);
334 // ---------------- enf of phi sector ----------------------------------------------------
335 } // loop over PhiSectors done
336
337 // build the mean of the layer Radius
338 layerRadius = 0.5*(layerRadiusMin+layerRadiusMax)+0.5*m_layerStrawRadius;
339
340 bool assignMaterial = false;
341 if (cLayer==(unsigned)int((cMaterialLayerCount+1)*nMaterialLayerStep)) {
342 assignMaterial = true;
343 ++cMaterialLayerCount;
344 ATH_MSG_VERBOSE( "--> Creating a material+straw layer at radius : " << layerRadius );
345 } else
346 ATH_MSG_VERBOSE( "--> Creating a straw layer at radius : " << layerRadius );
347
348 // now order the plane layers to sit on cylindrical layers
349 auto barrelLayerBounds = std::make_shared<Trk::CylinderBounds>(layerRadius, layerHalflength);
350
351 // ---- correct phi -------------------------------------------------------------------
352 ATH_MSG_VERBOSE(" prepare approach description with " << nBarrelPhiSectors << " barrel sectors.");
353 ATH_MSG_VERBOSE(" min phi / max phi detected : " << layerPhiMin << " / " << layerPhiMax );
354 double layerPhiMinCorrected = layerPhiMin-0.5*layerPhiStep;
355 double layerPhiMaxCorrected = layerPhiMax+0.5*layerPhiStep;
356 // catch if the minPhi falls below M_PI
357 if (layerPhiMinCorrected < -M_PI){
358 layerPhiMinCorrected += layerPhiStep;
359 layerPhiMaxCorrected += layerPhiStep;
360 }
361 ATH_MSG_VERBOSE(" min phi / max phi corrected : " << layerPhiMinCorrected << " / " << layerPhiMaxCorrected );
362
363 // the sector surfaces
364 auto layerSectorBinUtility = Trk::BinUtility(nBarrelPhiSectors,layerPhiMinCorrected,layerPhiMaxCorrected,Trk::closed,Trk::binPhi);
365 auto strawArray = std::make_unique<Trk::BinnedArrayArray2D<Trk::Surface>>(std::move(layerSectorArrays), layerSectorBinUtility );
366
367 ATH_MSG_VERBOSE("--> Layer " << layer << " has been built with " << strawArray->arrayObjects().size() << " straws.");
368
369 // ApproachDescriptor
370 // build a BinUtility for the ApproachDescritptor
371 auto aDescriptorBinUtility = Trk::BinUtility(nBarrelPhiSectors,layerPhiMinCorrected,layerPhiMaxCorrected,Trk::closed,Trk::binPhi);
372 aDescriptorBinUtility += Trk::BinUtility(2,-layerHalflength,layerHalflength,Trk::open, Trk::binZ);
373
374 auto aDescriptorBinnedArray = std::make_unique<Trk::BinnedArray2D<const Trk::ApproachSurfaces>> (layerApproachSurfaces, aDescriptorBinUtility);
375
376 // build an approach surface
377 auto approachSurface = std::make_unique<Trk::CylinderSurface>(
378 std::make_shared<Trk::CylinderBounds>(*barrelLayerBounds));
380 std::move(aDescriptorBinnedArray), std::move(approachSurface));
381
382 // do not give every layer material properties
383 if (assignMaterial) {
384 // ----- prepare the BinnedLayerMaterial -----------------------------------------------------
385 Trk::BinnedLayerMaterial* layerMaterial = nullptr;
386 // -- material with 1D binning
387 Trk::BinUtility layerBinUtilityZ(m_barrelLayerBinsZ, -layerHalflength, layerHalflength, Trk::open, Trk::binZ );
388 if (m_barrelLayerBinsPhi==1u){
389 layerMaterial =new Trk::BinnedLayerMaterial(layerBinUtilityZ);
390 } else { // -- material with 2D binning: RPhiZ binning
391 Trk::BinUtility layerBinUtilityRPhiZ(m_barrelLayerBinsPhi,
392 -layerRadius*M_PI, layerRadius*M_PI,
395 layerBinUtilityRPhiZ += layerBinUtilityZ;
396 layerMaterial =new Trk::BinnedLayerMaterial(layerBinUtilityRPhiZ);
397 }
398
399 barrelLayers->push_back(new Trk::CylinderLayer(barrelLayerBounds,
400 std::move(strawArray),
401 *layerMaterial,
403 std::make_unique<InDet::TRT_OverlapDescriptor>(trtIdHelper),
404 aDescritpor));
405 delete layerMaterial;
406
407 } else
408 barrelLayers->push_back(new Trk::CylinderLayer(barrelLayerBounds,
409 std::move(strawArray),
411 std::make_unique<InDet::TRT_OverlapDescriptor>(trtIdHelper),
412 aDescritpor));
413 } // loop over layers
414 } // loop over rings
415
416 ATH_MSG_VERBOSE(" Built number of TRT barrel material layers: " << cMaterialLayerCount);
417 // In Complex geo # of material layers should match the expected # of layers,
418 // else a mis-match in layer and material map index occurs.
419 // This mis-match will results layers getting incorrect material properties.
420 if (cMaterialLayerCount!=m_modelBarrelLayers) {
421 ATH_MSG_WARNING(" Complex geo built incorrect # of TRT barrel material layers: "
422 << cMaterialLayerCount << " / " << m_modelBarrelLayers);
423 }
424 }// complex geometry
425
426 // return what you have
427 return std::unique_ptr<const std::vector<Trk::CylinderLayer*> > (barrelLayers.release());
428}
429
430
431std::unique_ptr<const std::vector<Trk::DiscLayer*> >
433{
434 ATH_MSG_DEBUG( "Building disc-like layers for the TRT " );
435
436 const InDetDD::TRT_Numerology* trtNums = trtContainer->getTRTNumerology();
437 // get the TRT ID Helper
438 const TRT_ID* trtIdHelper = nullptr;
439 if (detStore()->retrieve(trtIdHelper, "TRT_ID").isFailure()) {
440 ATH_MSG_ERROR("Could not get TRT ID helper");
441 return nullptr;
442 }
443 unsigned int nEndcapWheels = trtNums->getNEndcapWheels();
444 unsigned int nEndcapPhiSectors = trtNums->getNEndcapPhi();
445
446 // total layer numbers
447 int numTotalLayers = 0;
448
449 // zMin / zMax
450 double zMin = 10e10;
451 double zMax = 0.;
452
453 const Trk::DiscBounds* sectorDiscBounds = nullptr;
454
455 // preloop for overall numbers
456 for (unsigned int iwheel=0; iwheel<nEndcapWheels; ++iwheel)
457 {
458 unsigned int nEndcapLayers = trtNums->getNEndcapLayers(iwheel);
459 numTotalLayers += nEndcapLayers;
460 for (unsigned int ilayer = 0; ilayer<nEndcapLayers; ++ilayer){
461 const InDetDD::TRT_EndcapElement* sectorDiscElement = trtContainer->getEndcapDetElement(0, iwheel, ilayer, 0); // TODO share this line
462
463 // get a reference element for dimensions
464 if (!sectorDiscBounds){
465 sectorDiscBounds = dynamic_cast<const Trk::DiscBounds*>(&(sectorDiscElement->bounds()));
466 }
467
468 double currentZ = std::abs(sectorDiscElement->center().z());
469 takeSmallerBigger(zMin,zMax,currentZ);
470 }
471 }
472 if (numTotalLayers==0) {
473 ATH_MSG_WARNING( "numTotalLayers = 0 ... aborting and returning 0 !" );
474 return nullptr;
475 }
476
477 if (!sectorDiscBounds) {
478 ATH_MSG_WARNING( "fullDiscBounds do not exist ... aborting and returning 0 !" );
479 return nullptr;
480 }
481 auto fullDiscBounds = std::make_unique<Trk::DiscBounds>(sectorDiscBounds->rMin(), sectorDiscBounds->rMax());
482
483 PtrVectorWrapper<Trk::DiscLayer> endcapLayers;
484
485 // the BinUtility for the material
486 std::unique_ptr<Trk::BinnedLayerMaterial> layerMaterial;
487 // -- material with 1D binning
488 Trk::BinUtility layerBinUtilityR(m_endcapLayerBinsR,
489 fullDiscBounds->rMin(),
490 fullDiscBounds->rMax(),
491 Trk::open,
492 Trk::binR);
493 if (m_barrelLayerBinsPhi==1u)
494 layerMaterial = std::make_unique<Trk::BinnedLayerMaterial>(layerBinUtilityR);
495 else { // -- material with 2D binning
496 Trk::BinUtility layerBinUtilityPhi(m_barrelLayerBinsPhi,
497 -M_PI, M_PI,
500 // make it rPhi now
501 layerBinUtilityR += layerBinUtilityPhi;
502 layerMaterial = std::make_unique<Trk::BinnedLayerMaterial>(layerBinUtilityR);
503 }
504
505 // global geometry statistics
506 double zDiff = std::abs(zMax-zMin);
507 double zStep = zDiff/(m_modelEndcapLayers+1);
508
509 // loop for surface ordering
510 int maxendcaps=2;
511 if (m_endcapConly) maxendcaps=1;
512
513 for (int iposneg=0; iposneg<maxendcaps; ++iposneg){
514
515 // fill the positions of the disc layers
516 std::vector<double> zPositions;
517 zPositions.reserve(m_modelEndcapLayers);
518
519 double stepdir = iposneg ? 1. : -1.;
520 double zStart = stepdir*zMin;
521
522 ATH_MSG_VERBOSE( " -> Creating " << m_modelEndcapLayers << " disc-layers on each side between "
523 << zMin << " and " << zMax << " ( at step "<< zStep << " )");
524
525 // take a different modelling for the layers - use these layers for the model geometry and the real geometry
526 for (unsigned int izpos = 1; izpos <= m_modelEndcapLayers; ++izpos){
527 zPositions.push_back(zStart + stepdir * double(izpos) * zStep - 0.5 * m_layerThickness);
528 }
529
530 std::vector<double>::const_iterator zPosIter = zPositions.begin();
531 std::vector<double>::const_iterator zPosIterEnd = zPositions.end();
532
533 // (a) simplified geometry
534 if (m_modelGeometry){
535 // build the layers actually
536 for ( ; zPosIter != zPosIterEnd; ++zPosIter){
537 ATH_MSG_VERBOSE( " --> Creating a layer at z pos : " << (*zPosIter) );
538 Amg::Transform3D zPosTrans =
539 Amg::Transform3D(Amg::Translation3D(0., 0., (*zPosIter)));
540 endcapLayers->push_back(new Trk::DiscLayer(zPosTrans,
541 std::make_shared<Trk::DiscBounds>(*fullDiscBounds),
542 *layerMaterial,
544 }
545
546 } else {
547 // (b) complex geometry
548 float nMaterialLayerStep = 1.*numTotalLayers/m_modelEndcapLayers;
549 // inclusive layer counter over all wheels
550 unsigned int cLayer = 0;
551 // complex geo should build same # of mat. layers as model geo; counter to check this:
552 unsigned int cMaterialLayerCount = 0;
553
554 // complex geometry - needs a little bit of joggling
555 for (unsigned int iwheel=0; iwheel<nEndcapWheels; ++iwheel)
556 {
557 // do the loop per side
558 unsigned int nEndcapLayers = trtNums->getNEndcapLayers(iwheel);
559 for (unsigned int ilayer = 0; ilayer < nEndcapLayers; ++ilayer){
560
561 // increase inclusive layer counter for next material layer
562 ++cLayer;
563
564 // count the straws;
565 int numberOfStraws = 0;
566
567 // check if dynamic cast worked
568 // get a reference element for dimensions
569 const InDetDD::TRT_EndcapElement* sectorDiscElement = trtContainer->getEndcapDetElement(iposneg, iwheel, ilayer, 0); // TODO share this line
570
571 // take the position, but not the rotation (the rotation has to be standard)
572 Amg::Vector3D fullDiscPosition(sectorDiscElement->surface().transform().translation());
573 double discZ = fullDiscPosition.z();
574
575 // check if we need to build a straw layer or not
576 bool assignMaterial = false;
577 if (cLayer == (unsigned)int((cMaterialLayerCount+1)*nMaterialLayerStep)) {
578 assignMaterial = true;
579 ++cMaterialLayerCount;
580 ATH_MSG_VERBOSE( "--> Creating a material+straw layer at z-pos : " << discZ );
581 } else {
582 ATH_MSG_VERBOSE( "--> Creating a straw layer at z-pos : " << discZ );
583 }
584
585 // order the straws onto layers
586 std::vector< Trk::SurfaceOrderPosition > strawPerEndcapLayer;
587
588 // the layer thickness - for approaching surfaces
589 double zMin = 10e10;
590 double zMax = -10e10;
591
592 for (unsigned int iphisec=0; iphisec<nEndcapPhiSectors; ++iphisec){
593 ATH_MSG_VERBOSE("Building sector " << iphisec << " of endcap wheel " << iwheel );
594 const InDetDD::TRT_EndcapElement* currentElement = trtContainer->getEndcapDetElement(iposneg, iwheel, ilayer, iphisec); // TODO share this line
595 unsigned int nstraws = currentElement->nStraws();
596 for (unsigned int istraw=0; istraw<nstraws; istraw++){
597 Identifier strawId = trtIdHelper->straw_id(currentElement->identify(), istraw);
598 const Trk::Surface* currentStraw = &(currentElement->surface(strawId));
599 Amg::Vector3D strawOrderPos(currentStraw->center());
600 // get the z position
601 double zPos = currentStraw->center().z();
602 takeSmaller(zMin,zPos);
603 takeBigger(zMax,zPos);
604 // Something like
605 // std::shared_ptr<Trk::Surface> =
606 // std::make_shared<Trk::Surface>(currentElement)) could be fine
607 //
608 // As things are now
609 // 1) Notice that basically we couple the DetElement owned
610 // surface to the Tracking Geometry passing a no-op deleter
611 // (no delete happens) to the shared_ptr(SharedObject is
612 // typedef of shared_ptr)
613 // 2) The const_cast here make the
614 // code non MT safe. For now we handle this by being careful
615 // on lifetimes and non-re-entrant TG construction.
616 std::shared_ptr<Trk::Surface> sharedSurface(const_cast<Trk::Surface*>(currentStraw),
617 [](Trk::Surface*) {});
618 strawPerEndcapLayer.emplace_back(sharedSurface, strawOrderPos);
619 ++numberOfStraws;
620 }
621 }
622 // fix to CID 11326
623 if (!numberOfStraws){
624 return nullptr;
625 }
626 auto currentBinUtility = Trk::BinUtility(numberOfStraws, -M_PI, M_PI, Trk::closed, Trk::binPhi);
627 auto strawArray = std::make_unique<Trk::BinnedArray1D<Trk::Surface>>(strawPerEndcapLayer, currentBinUtility);
628 Trk::DiscLayer* currentLayer = nullptr;
629
630 // redefine the discZ
631 discZ = 0.5*(zMin+zMax);
632 Amg::Transform3D fullDiscTransform = Amg::Transform3D(Amg::Translation3D(0.,0.,discZ));
633
634 ATH_MSG_VERBOSE("TRT Disc being build at z Position " << discZ << " ( from " << zMin << " / " << zMax << " )");
635
636 // create the approach offset
637 auto aSurfaces = std::make_unique<Trk::ApproachSurfaces>();
638 // get the position of the approach surfaces
639 const Amg::Vector3D aspPosition(0.,0.,zMin-m_layerStrawRadius);
640 const Amg::Vector3D asnPosition(0.,0.,zMax+m_layerStrawRadius);
641
642 // create new surfaces
643 Amg::Transform3D asnTransform = Amg::Transform3D(Amg::Translation3D(asnPosition));
644 Amg::Transform3D aspTransform = Amg::Transform3D(Amg::Translation3D(aspPosition));
645 // order in an optimised way for collision direction
646 if (discZ > 0.){
647 aSurfaces->push_back( new Trk::DiscSurface(asnTransform, std::make_shared<Trk::DiscBounds>(*fullDiscBounds)));
648 aSurfaces->push_back( new Trk::DiscSurface(aspTransform, std::make_shared<Trk::DiscBounds>(*fullDiscBounds)) );
649 } else {
650 aSurfaces->push_back( new Trk::DiscSurface(aspTransform, std::make_shared<Trk::DiscBounds>(*fullDiscBounds)) );
651 aSurfaces->push_back( new Trk::DiscSurface(asnTransform, std::make_shared<Trk::DiscBounds>(*fullDiscBounds)) );
652 }
653 // approach descriptor
654 Trk::ApproachDescriptor* aDescriptor = new Trk::ApproachDescriptor(std::move(aSurfaces),false);
655
656 // do not give every layer material properties
657 if (assignMaterial)
658 currentLayer = new Trk::DiscLayer(fullDiscTransform,
659 std::make_shared<Trk::DiscBounds>(*fullDiscBounds),
660 std::move(strawArray),
661 *layerMaterial,
663 std::make_unique<InDet::TRT_OverlapDescriptor>(trtIdHelper),
664 aDescriptor);
665 else if (!m_modelGeometry)
666 currentLayer = new Trk::DiscLayer(fullDiscTransform,
667 std::make_shared<Trk::DiscBounds>(*fullDiscBounds),
668 std::move(strawArray),
670 std::make_unique<InDet::TRT_OverlapDescriptor>(trtIdHelper),
671 aDescriptor);
672
673 if (currentLayer) endcapLayers->push_back(currentLayer);
674 } // end of layer loop
675 } // end of wheel loop
676
677 ATH_MSG_VERBOSE(" Built # of TRT material layers: " << cMaterialLayerCount << "in ispos: " << iposneg << "ring");
678 // # of material layers should match the expected # of layers,
679 // else a mis-match in layer and material map index occurs.
680 // This mis-match will results layers getting incorrect material properties.
681 if (cMaterialLayerCount != m_modelEndcapLayers) {
682 ATH_MSG_WARNING(" Built incorrect # of TRT material layers: "
683 << cMaterialLayerCount << " / " << m_modelEndcapLayers << "in ispos" << iposneg << "ring" );
684 }
685
686 } // model/real geometry
687 } // end of posneg loop
688
689 return std::unique_ptr<const std::vector<Trk::DiscLayer*> > (endcapLayers.release());
690}
#define M_PI
Scalar deltaPhi(const MatrixBase< Derived > &vec) const
#define ATH_MSG_ERROR(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
#define takeSmaller(current, test)
#define takeSmallerBigger(cSmallest, cBiggest, test)
#define takeBigger(current, test)
This is an Identifier helper class for the TRT subdetector.
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
const ServiceHandle< StoreGateSvc > & detStore() const
Extended TRT_BaseElement to describe a TRT readout element, this is a planar layer with n ( order of ...
unsigned int nStraws() const
Number of straws in the element.
virtual const Trk::SurfaceBounds & bounds() const override final
Straw layer bounds.
virtual Identifier identify() const override final
identifier of this detector element:
virtual const Trk::Surface & surface() const override final
Element Surface: access to the Surface (straw layer).
virtual const Amg::Vector3D & center() const override final
Element Surface: center of a straw layer.
Class to hold different TRT detector elements structures.
const TRT_EndcapElement * getEndcapDetElement(unsigned int positive, unsigned int wheelIndex, unsigned int strawLayerIndex, unsigned int phiIndex) const
const TRT_BarrelElement * getBarrelDetElement(unsigned int positive, unsigned int moduleIndex, unsigned int phiIndex, unsigned int strawLayerIndex) const
const TRT_Numerology * getTRTNumerology() const
Extended class of a TRT_BaseElement to describe a readout elment in the endcap.
Helper class to organize the straw elements on TRT readout elements.
unsigned int getNEndcapWheels() const
unsigned int getNEndcapPhi() const
unsigned int getNBarrelPhi() const
unsigned int getNBarrelRings() const
unsigned int getNBarrelLayers(unsigned int iMod) const
unsigned int getNEndcapLayers(unsigned int iWheel) const
UnsignedIntegerProperty m_endcapLayerBinsR
Bins for the Endcap material - in r.
DoubleProperty m_layerThickness
modelled layer thickness
std::unique_ptr< const std::vector< Trk::CylinderLayer * > > cylindricalLayersImpl(const InDetDD::TRT_DetElementContainer *trtContainer) const
UnsignedIntegerProperty m_modelEndcapLayers
model endcap layers with material
BooleanProperty m_endcapConly
Only build the endcapC.
UnsignedIntegerProperty m_barrelLayerBinsPhi
Bins for the Barrel material - in phi.
TRT_LayerBuilderImpl(const std::string &, const std::string &, const IInterface *)
AlgTool style constructor.
std::unique_ptr< const std::vector< Trk::DiscLayer * > > discLayersImpl(const InDetDD::TRT_DetElementContainer *trtContainer) const
UnsignedIntegerProperty m_modelBarrelLayers
model barrel layers with material
IntegerProperty m_barrelSectorAtPiBoundary
this is the barrel Sector where +pi/-pi is within
BooleanProperty m_registerStraws
register the straws
BooleanProperty m_modelGeometry
Build the geometry with model layers.
double m_layerStrawRadius
straw radius
UnsignedIntegerProperty m_barrelLayerBinsZ
Bins for the Barrel material - in z.
This is an Identifier helper class for the TRT subdetector.
Definition TRT_ID.h:84
Identifier straw_id(int barrel_ec, int phi_module, int layer_or_wheel, int straw_layer, int straw) const
Three ways of getting id for a single straw:
Definition TRT_ID.h:583
Class to decide and return which approaching surface to be taken.
just implement the delete on the objects
A generic symmetric BinUtility, for fully symmetric binning in terms of binning grid and binning type...
Definition BinUtility.h:39
Avoiding a map search, the templated BinnedArray class can help ordereing geometrical objects by prov...
It extends the LayerMaterialProperties base class.
Class to describe a cylindrical detector layer for tracking, it inhertis from both,...
Class to describe the bounds for a planar DiscSurface.
Definition DiscBounds.h:44
double rMax() const
This method returns outer radius.
double rMin() const
This method returns inner radius.
Class to describe a disc-like detector layer for tracking, it inhertis from both, Layer base class an...
Definition DiscLayer.h:45
Class for a DiscSurface in the ATLAS detector.
Definition DiscSurface.h:54
Class for a planaer rectangular or trapezoidal surface in the ATLAS detector.
Bounds for a rectangular, planar surface.
double halflengthY() const
for consitant naming
Abstract Base Class for tracking surfaces.
Definition Surface.h:79
virtual const Amg::Vector3D & normal() const
Returns the normal vector of the Surface (i.e.
const Amg::Transform3D & transform() const
Returns HepGeom::Transform3D by reference.
const Amg::Vector3D & center() const
Returns the center position of the Surface.
static std::string release
Definition computils.h:50
Eigen::Matrix< double, 3, 3 > RotationMatrix3D
Amg::Transform3D getTransformFromRotTransl(Amg::RotationMatrix3D rot, Amg::Vector3D transl_vec)
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
Eigen::Translation< double, 3 > Translation3D
unsigned long long T
const auto do_not_delete
@ open
Definition BinningType.h:40
@ closed
Definition BinningType.h:41
@ binR
Definition BinningType.h:50
@ binPhi
Definition BinningType.h:51
@ binRPhi
Definition BinningType.h:52
@ binZ
Definition BinningType.h:49