ATLAS Offline Software
CaloTrackingGeometryBuilderImpl.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // Calo
7 // Trk
14 //
17 #include "TrkGeometry/DiscLayer.h"
23 //
24 #include "TrkSurfaces/DiscBounds.h"
29 //
30 #include <memory>
31 //
33 #include "GaudiKernel/SystemOfUnits.h"
34 
35 // constructor
37  const std::string& t, const std::string& n, const IInterface* p)
38  : AthAlgTool(t, n, p) {
39 }
40 
41 // destructor
43 
44 // Athena standard methods
45 // initialize
47 
48  // Retrieve the tracking volume array creator
49  // -------------------------------------------------
50  ATH_CHECK(m_trackingVolumeArrayCreator.retrieve());
51  ATH_MSG_INFO("Retrieved tool " << m_trackingVolumeArrayCreator);
52 
53  // Retrieve the second volume creator
54  if (m_buildMBTS) {
55  ATH_CHECK(m_trackingVolumeCreator.retrieve());
56  ATH_MSG_INFO("Retrieved tool " << m_trackingVolumeCreator);
57  };
58 
59  // Retrieve the volume builders
60  // -------------------------------------------------
61  ATH_CHECK(m_lArVolumeBuilder.retrieve());
62  ATH_MSG_INFO("Retrieved tool " << m_lArVolumeBuilder);
63 
64  // Retrieve the tracking volume helper
65  // -------------------------------------------------
66  ATH_CHECK(m_tileVolumeBuilder.retrieve());
67  ATH_MSG_INFO("Retrieved tool " << m_tileVolumeBuilder);
68 
69  ATH_MSG_INFO("initialize() succesful");
70 
71  return StatusCode::SUCCESS;
72 }
73 
74 std::unique_ptr<Trk::TrackingGeometry>
76  , const CaloDetDescrManager* caloDDM
77  , const GeoAlignmentStore* geoAlign) const {
78 
79  ATH_MSG_VERBOSE("Starting to build CaloTrackingGeometry ...");
80 
81  Trk::TrackingVolume* calorimeter = nullptr;
82 
83  // the key dimensions
84  RZPairVector keyDim;
85 
86  // the enclosed input volume (ID)
87  double enclosedInnerSectorHalflength = 0.;
88  double enclosedInnerSectorRadius = 0.;
89 
90  if (innerVol) {
91  ATH_MSG_VERBOSE("Got Inner Detector Volume: " << innerVol->volumeName());
92  innerVol->screenDump(msg(MSG::VERBOSE));
93 
94  // retrieve dimensions
95  const Trk::CylinderVolumeBounds* innerDetectorBounds =
96  dynamic_cast<const Trk::CylinderVolumeBounds*>(
97  &(innerVol->volumeBounds()));
98  if (!innerDetectorBounds)
99  std::abort();
100 
101  enclosedInnerSectorHalflength = innerDetectorBounds->halflengthZ();
102  enclosedInnerSectorRadius = innerDetectorBounds->outerRadius();
103 
104  keyDim.emplace_back(enclosedInnerSectorRadius, enclosedInnerSectorHalflength);
105  }
106  // get the dimensions from the envelope service
107  const RZPairVector& envelopeDefsIn =
108  m_enclosingEnvelopeSvc->getCaloRZBoundary();
109 
110  // find the max,max pair
111  unsigned int ii = 0;
112  for (unsigned int i = 0; i < envelopeDefsIn.size(); i++) {
113  if (envelopeDefsIn[i].second > envelopeDefsIn[ii].second)
114  ii = i;
115  else if (envelopeDefsIn[i].second == envelopeDefsIn[ii].second &&
116  envelopeDefsIn[i].first > envelopeDefsIn[ii].first)
117  ii = i;
118  }
119 
120  // find the sense of rotation
121  int irot = 1;
122  unsigned int inext = ii + 1;
123  if (inext == envelopeDefsIn.size())
124  inext = 0;
125  if (envelopeDefsIn[inext].second != envelopeDefsIn[ii].second) {
126  irot = -1;
127  inext = ii > 0 ? ii - 1 : envelopeDefsIn.size() - 1;
128  }
129 
130  // fill starting with upper low edge, end with upper high edge
131  RZPairVector envelopeDefs;
132  if (irot > 0) {
133  for (unsigned int i = inext; i < envelopeDefsIn.size(); i++)
134  envelopeDefs.push_back(envelopeDefsIn[i]);
135  if (inext > 0)
136  for (unsigned int i = 0; i <= inext - 1; i++)
137  envelopeDefs.push_back(envelopeDefsIn[i]);
138  } else {
139  int i = inext;
140  while (i >= 0) {
141  envelopeDefs.push_back(envelopeDefsIn[i]);
142  i = i - 1;
143  };
144  inext = envelopeDefsIn.size() - 1;
145  while (inext >= ii) {
146  envelopeDefs.push_back(envelopeDefsIn[inext]);
147  inext = inext - 1;
148  };
149  }
150 
151  double envEnclosingVolumeHalfZ = m_caloDefaultHalflengthZ;
152 
153  ATH_MSG_VERBOSE("Calo envelope definition retrieved:");
154  RZPairVector msCutouts;
155  for (unsigned int i = 0; i < envelopeDefs.size(); i++) {
156  ATH_MSG_VERBOSE("Rz pair:" << i << ":" << envelopeDefs[i].first << ","
157  << envelopeDefs[i].second);
158  if (std::abs(envelopeDefs[i].second) < envEnclosingVolumeHalfZ)
159  envEnclosingVolumeHalfZ = std::abs(envelopeDefs[i].second);
160  // ID dimensions : pick 1100 < R < 1200
161  if (envelopeDefs[i].first > 1100. && envelopeDefs[i].first < 1200. &&
162  envelopeDefs[i].second > 0.) {
163  // check that radial size of ID envelope fits
164  if (enclosedInnerSectorRadius != envelopeDefs[i].first)
165  ATH_MSG_INFO(
166  "Enclosed ID volume radius does not match ID envelope, adjusting "
167  "Calo.");
168  envEnclosingVolumeHalfZ = envelopeDefs[i].second;
169  if (!innerVol) {
170  enclosedInnerSectorRadius = envelopeDefs[i].first;
171  enclosedInnerSectorHalflength = envelopeDefs[i].second;
172  }
173  }
174  // collect outer cutouts, process those with |z| < 6785.mm ( this cut should
175  // be synchronized with MS default size,
176  // MS builder would crash for a longer input volume )
177  if (envelopeDefs[i].second > 0. && envelopeDefs[i].second < 6785. &&
178  (envelopeDefs[i].first > 1200. ||
179  envelopeDefs[i].second > envEnclosingVolumeHalfZ)) {
180  if (msCutouts.empty())
181  msCutouts.push_back(envelopeDefs[i]);
182  else {
183  RZPairVector::iterator envIter = msCutouts.begin();
184  while (envIter != msCutouts.end() &&
185  (*envIter).second < envelopeDefs[i].second)
186  ++envIter;
187  while (envIter != msCutouts.end() &&
188  (*envIter).second == envelopeDefs[i].second &&
189  (*envIter).first > envelopeDefs[i].first)
190  ++envIter;
191  msCutouts.insert(envIter, envelopeDefs[i]);
192  }
193  }
194  // end outer (MS) cutouts
195  }
196  if (msgLvl(MSG::VERBOSE)) {
197  for (unsigned int i = 0; i < msCutouts.size(); i++)
198  ATH_MSG_VERBOSE("MS cutouts to be processed by Calo:"
199  << i << ":" << msCutouts[i].first << ","
200  << msCutouts[i].second);
201  }
202 
203  // first member of msCutouts redefines the default central cylinder dimension
204  double caloDefaultRadius = m_caloDefaultRadius;
205  double caloDefaultHalflengthZ = m_caloDefaultHalflengthZ;
206 
207  if (!msCutouts.empty()) {
208  caloDefaultRadius = msCutouts[0].first;
209  caloDefaultHalflengthZ = msCutouts[0].second;
211  " Calo central cylinder dimensions adjusted using EnvelopeSvc:"
212  << m_caloDefaultRadius << "," << m_caloDefaultHalflengthZ);
213  }
214 
215  // create dummy ID if not built already
216 
217  if (!innerVol) {
218  auto idBounds = std::make_shared<Trk::CylinderVolumeBounds>(
219  enclosedInnerSectorRadius, enclosedInnerSectorHalflength);
220 
221  auto idTr = std::make_unique<Amg::Transform3D>(Trk::s_idTransform);
222 
223  innerVol =
224  new Trk::TrackingVolume(std::move(idTr), std::move(idBounds), m_caloMaterial, nullptr,
225  nullptr, "Calo::GapVolumes::DummyID");
226 
227  keyDim.emplace_back(enclosedInnerSectorRadius, enclosedInnerSectorHalflength);
228  }
229 
230  // BEAM PIPE
231  const RZPairVector& bpDefs = m_enclosingEnvelopeSvc->getBeamPipeRZBoundary();
232 
233  ATH_MSG_VERBOSE("BeamPipe envelope definition retrieved:");
234  RZPairVector bpCutouts;
235  for (unsigned int i = 0; i < bpDefs.size(); i++) {
236  ATH_MSG_VERBOSE("Rz pair:" << i << ":" << bpDefs[i].first << ","
237  << bpDefs[i].second);
238  // beam pipe within calo : pick 10. < R < 200; envEnclosingVolumeHalfZ =<
239  // z <= msCutouts.back().second;
240  if (bpDefs[i].first > 10. && bpDefs[i].first < 200. &&
241  bpDefs[i].second >= envEnclosingVolumeHalfZ &&
242  bpDefs[i].second <= msCutouts.back().second) {
243  bpCutouts.push_back(bpDefs[i]);
244  }
245  if (i > 0 && i < 4)
246  keyDim.push_back(bpDefs[i]);
247  }
248 
249  // no beam pipe within ID
250  // if (bpCutouts[0].second == envEnclosingVolumeHalfZ && bpCutouts[0].first >
251  // 0 ) bpCutouts[0].first=0.;
252  // last not needed
253  if (bpCutouts.size() > 1 &&
254  bpCutouts.back().second == bpCutouts[bpCutouts.size() - 2].second)
255  bpCutouts.erase(bpCutouts.end() - 1);
256  // end beam pipe envelope within Calo
257  for (unsigned int i = 0; i < bpCutouts.size(); i++)
258  ATH_MSG_VERBOSE("Beam pipe dimensions to be used by Calo:"
259  << i << ":" << bpCutouts[i].first << ","
260  << bpCutouts[i].second);
261 
262  keyDim.emplace_back(caloDefaultRadius, caloDefaultHalflengthZ);
263 
266 
267  // PART 1 : Liquid Argon Volumes
268  // ===========================================================================================
269  // get the Tracking Volumes from the LAr Builder
270  //
271  const std::vector<Trk::TrackingVolume*> lArVolumes =
272  m_lArVolumeBuilder->trackingVolumes(*caloDDM,geoAlign);
273 
274  ATH_MSG_INFO(lArVolumes.size()
275  << " volumes retrieved from " << m_lArVolumeBuilder.name());
276 
277  // LAr Barrel part
278  Trk::TrackingVolume* solenoid = lArVolumes[0];
279  Trk::TrackingVolume* solenoidlArPresamplerGap = lArVolumes[1];
280  Trk::TrackingVolume* lArBarrelPresampler = lArVolumes[2];
281  Trk::TrackingVolume* lArBarrel = lArVolumes[3];
282 
283  // LAr Positive Endcap part
284  Trk::TrackingVolume* lArPositiveMBTS = lArVolumes[4];
285  Trk::TrackingVolume* lArPositiveEndcap = lArVolumes[5];
286  Trk::TrackingVolume* lArPositiveHec = lArVolumes[6];
287  Trk::TrackingVolume* lArPositiveFcal = lArVolumes[7];
288  Trk::TrackingVolume* lArPositiveHecFcalCover = lArVolumes[8];
289  // LAr Negative Endcap part
290  Trk::TrackingVolume* lArNegativeMBTS = lArVolumes[9];
291  Trk::TrackingVolume* lArNegativeEndcap = lArVolumes[10];
292  Trk::TrackingVolume* lArNegativeHec = lArVolumes[11];
293  Trk::TrackingVolume* lArNegativeFcal = lArVolumes[12];
294  Trk::TrackingVolume* lArNegativeHecFcalCover = lArVolumes[13];
295  Trk::TrackingVolume* lArPosECPresampler = lArVolumes[14];
296  Trk::TrackingVolume* lArNegECPresampler = lArVolumes[15];
297 
298  // PART 2 : Tile Volumes
299  // ===========================================================================================
300  // get the Tracking Volumes from the Tile Builder
301  std::vector<Trk::TrackingVolume*> tileVolumes =
302  m_tileVolumeBuilder->trackingVolumes(*caloDDM,geoAlign);
303 
304  ATH_MSG_INFO(tileVolumes.size()
305  << " volumes retrieved from " << m_tileVolumeBuilder.name());
306  if (msgLvl(MSG::INFO)) {
307  ATH_MSG_INFO(
308  "--------------- detailed output "
309  "---------------------------------------------------------- ");
310  auto tileVolIter = tileVolumes.begin();
311  auto tileVolIterEnd = tileVolumes.end();
312  for (; tileVolIter != tileVolIterEnd;
313  (*tileVolIter)->screenDump(msg(MSG::VERBOSE)), ++tileVolIter)
314  ;
315  }
316 
317  // Tile Barrel part
318  Trk::TrackingVolume* tileCombined = tileVolumes[0];
319  // Tile Positive Extended Part
320  Trk::TrackingVolume* tilePositiveExtendedBarrel = tileVolumes[1];
321 
322  const Trk::CylinderVolumeBounds* ebBounds =
323  dynamic_cast<const Trk::CylinderVolumeBounds*>(
324  &(tilePositiveExtendedBarrel->volumeBounds()));
325 
326  double rTileMin = ebBounds ? ebBounds->innerRadius() : 2288.;
327  double zTileMin = ebBounds ? tilePositiveExtendedBarrel->center().z() -
328  ebBounds->halflengthZ()
329  : 3559.5;
330 
331  keyDim.emplace_back(rTileMin, zTileMin);
332  for (unsigned int i = 0; i < keyDim.size(); i++) {
333  ATH_MSG_VERBOSE("key dimensions:" << i << ":" << keyDim[i].first << ","
334  << keyDim[i].second);
335  }
336 
337  // The Bounds needed for the Gap Volume creation
338  const Trk::CylinderVolumeBounds* solenoidBounds =
339  dynamic_cast<const Trk::CylinderVolumeBounds*>(
340  &(solenoid->volumeBounds()));
341  if (!solenoidBounds){
342  std::abort();
343  }
344  const Trk::CylinderVolumeBounds* lArBarrelBounds =
345  dynamic_cast<const Trk::CylinderVolumeBounds*>(
346  &(lArBarrel->volumeBounds()));
347  if (!lArBarrelBounds){
348  std::abort();
349  }
350  const Trk::CylinderVolumeBounds* lArPositiveEndcapBounds =
351  dynamic_cast<const Trk::CylinderVolumeBounds*>(
352  &(lArPositiveEndcap->volumeBounds()));
353  if (!lArPositiveEndcapBounds){
354  std::abort();
355  }
356  const Trk::CylinderVolumeBounds* lArNegativeEndcapBounds =
357  dynamic_cast<const Trk::CylinderVolumeBounds*>(
358  &(lArNegativeEndcap->volumeBounds()));
359  if (!lArNegativeEndcapBounds){
360  std::abort();
361  }
362  const Trk::CylinderVolumeBounds* lArPositiveHecBounds =
363  dynamic_cast<const Trk::CylinderVolumeBounds*>(
364  &(lArPositiveHec->volumeBounds()));
365  if (!lArPositiveHecBounds){
366  std::abort();
367  }
368  const Trk::CylinderVolumeBounds* lArPositiveFcalBounds =
369  dynamic_cast<const Trk::CylinderVolumeBounds*>(
370  &(lArPositiveFcal->volumeBounds()));
371  if (!lArPositiveFcalBounds){
372  std::abort();
373  }
374  const Trk::CylinderVolumeBounds* lArNegativeFcalBounds =
375  dynamic_cast<const Trk::CylinderVolumeBounds*>(
376  &(lArNegativeFcal->volumeBounds()));
377  if (!lArNegativeFcalBounds){
378  std::abort();
379  }
380  const Trk::CylinderVolumeBounds* tileCombinedBounds =
381  dynamic_cast<const Trk::CylinderVolumeBounds*>(
382  &(tileCombined->volumeBounds()));
383  if (!tileCombinedBounds){
384  std::abort();
385  }
386 
387  // Create the gap volumes
388  // ======================================================================
389  Trk::TrackingVolume* lArTileCentralSectorGap = nullptr;
390 
391  Trk::TrackingVolume* lArPositiveSectorInnerGap = nullptr;
392  Trk::TrackingVolume* lArPositiveSectorOuterGap = nullptr;
393  Trk::TrackingVolume* lArPositiveSectorOuterGap0 = nullptr;
394  Trk::TrackingVolume* lArCentralPositiveGap = nullptr;
395 
396  Trk::TrackingVolume* lArNegativeSectorInnerGap = nullptr;
397  Trk::TrackingVolume* lArNegativeSectorOuterGap = nullptr;
398  Trk::TrackingVolume* lArNegativeSectorOuterGap0 = nullptr;
399  Trk::TrackingVolume* lArCentralNegativeGap = nullptr;
400 
401  Trk::TrackingVolume* trtSolenoidGap = nullptr;
402 
403  double caloPositiveOuterBoundary = tileCombinedBounds->halflengthZ();
404 
405  double lArPositiveOuterBoundary = lArPositiveFcal->center().z();
406  lArPositiveOuterBoundary += lArPositiveFcalBounds->halflengthZ();
407 
408  // No. 1
409  // building dense volume here
410  Trk::Material tilePositiveSectorInnerGapMaterial =
411  Trk::Material(58., 565., 30.7, 14.6, 0.0025);
412 
413  // calo sensitive volume outer radius/z extent defined (for example) here
414  float caloVolsOuterRadius = tileCombinedBounds->outerRadius();
415  float caloVolsExtendZ = caloPositiveOuterBoundary;
416 
418  // LAr InnerGap sector + beam pipe
419 
420  Trk::Material lArSectorInnerGapMaterial =
421  Trk::Material(361., 1370., 14.5, 7., 0.0009); // ???
422 
423  // create beam pipe volumes for InnerGap/MBTS and return their outer radius
424  float rInnerGapBP = 0.;
425  std::pair<Trk::TrackingVolume*, Trk::TrackingVolume*> innerGapBP =
426  createBeamPipeVolumes(
427  bpCutouts, keyDim[0].second,
428  // lArPositiveEndcap->center().z()-lArPositiveEndcapBounds->halflengthZ(),
429  keyDim.back().second, "InnerGap", rInnerGapBP);
430 
431  double z = 0.5 * (keyDim.back().second + keyDim[0].second);
432 
433  auto mbtsNegLayers = std::make_unique<std::vector<Trk::Layer*>>();
434  auto mbtsPosLayers = std::make_unique<std::vector<Trk::Layer*>>();
435 
436  if (lArPositiveMBTS && lArNegativeMBTS) {
437  // Disc
438  const Trk::CylinderVolumeBounds* mbtsBounds =
439  dynamic_cast<const Trk::CylinderVolumeBounds*>(
440  &(lArPositiveMBTS->volumeBounds()));
441  if (mbtsBounds && m_buildMBTS) {
442  float rmin = mbtsBounds->innerRadius();
443  float rmax = mbtsBounds->outerRadius();
444  // float d = mbtsBounds->halflengthZ();
445  auto dibo = std::make_shared<Trk::DiscBounds>(rmin, rmax);
446  // MBTS positions
447  Amg::Transform3D mbtsNegZpos =
448  Amg::Transform3D(Amg::Translation3D(lArNegativeMBTS->center()));
449  Amg::Transform3D mbtsPosZpos =
450  Amg::Transform3D(Amg::Translation3D(lArPositiveMBTS->center()));
451  // create the two Layers ( TODO: add trd surface subarray )
452  Trk::DiscLayer* mbtsNegLayer = new Trk::DiscLayer(
453  mbtsNegZpos, dibo,
454  // mbtsNegLayerSurfArray,
456  Trk::MaterialProperties(m_caloMaterial, 1.), 1.),
457  1.);
458  Trk::DiscLayer* mbtsPosLayer = new Trk::DiscLayer(
459  mbtsPosZpos, std::make_shared<Trk::DiscBounds>(*dibo),
460  // mbtsPosLayerSurfArray,
462  Trk::MaterialProperties(m_caloMaterial, 1.), 1.),
463  1. * Gaudi::Units::mm);
464 
465  mbtsNegLayers->push_back(mbtsNegLayer);
466  mbtsPosLayers->push_back(mbtsPosLayer);
467  }
468  }
469 
470  // building inner gap
471  auto lArG1Bounds = std::make_shared<Trk::CylinderVolumeBounds>(
472  rInnerGapBP,
473  // lArPositiveEndcapBounds->outerRadius(),
474  keyDim[0].first, 0.5 * (keyDim.back().second - keyDim[0].second));
475 
476  auto lArG1P =
477  std::make_unique<Amg::Transform3D>(Amg::Translation3D(Amg::Vector3D(0., 0., z)));
478  lArPositiveSectorInnerGap = new Trk::TrackingVolume(
479  std::move(lArG1P), std::make_shared<Trk::CylinderVolumeBounds>(*lArG1Bounds),
480  lArSectorInnerGapMaterial, std::move(mbtsPosLayers),
481  "Calo::GapVolumes::LAr::PositiveSectorInnerGap");
482 
483  auto lArG1N =
484  std::make_unique<Amg::Transform3D>(Amg::Translation3D(Amg::Vector3D(0., 0., -z)));
485  lArNegativeSectorInnerGap = new Trk::TrackingVolume(
486  std::move(lArG1N),
487  std::move(lArG1Bounds),
488  lArSectorInnerGapMaterial,
489  std::move(mbtsNegLayers), "Calo::GapVolumes::LAr::NegativeSectorInnerGap");
490 
491  // glue InnerGap with beam pipe volumes
492  Trk::TrackingVolume* positiveInnerGap = nullptr;
493  if (innerGapBP.first) {
494  std::vector<Trk::TrackingVolume*> volsInnerGap;
495  volsInnerGap.push_back(innerGapBP.first);
496  volsInnerGap.push_back(lArPositiveSectorInnerGap);
497  positiveInnerGap = m_trackingVolumeCreator->createContainerTrackingVolume(
498  volsInnerGap, m_caloMaterial, "Calo::Container::PositiveInnerGap");
499  } else
500  positiveInnerGap = lArPositiveSectorInnerGap;
501 
502  Trk::TrackingVolume* negativeInnerGap = nullptr;
503  if (innerGapBP.second) {
504  std::vector<Trk::TrackingVolume*> volsInnerGap;
505  volsInnerGap.push_back(innerGapBP.second);
506  volsInnerGap.push_back(lArNegativeSectorInnerGap);
507  negativeInnerGap = m_trackingVolumeCreator->createContainerTrackingVolume(
508  volsInnerGap, m_caloMaterial, "Calo::Container::NegativeInnerGap");
509  } else
510  negativeInnerGap = lArNegativeSectorInnerGap;
511 
512  // glue MBTS volumes with ID
513  std::vector<Trk::TrackingVolume*> inBufferVolumes;
514  inBufferVolumes.push_back(negativeInnerGap);
515  inBufferVolumes.push_back(innerVol);
516  inBufferVolumes.push_back(positiveInnerGap);
517 
518  Trk::TrackingVolume* inDetEnclosed =
519  m_trackingVolumeCreator->createContainerTrackingVolume(
520  inBufferVolumes, m_caloMaterial,
521  "Calo::Container::EnclosedInnerDetector");
522 
523  ATH_MSG_DEBUG(" Inner detector enclosed (MBTS volumes)");
524 
526  // LAr endcap sector including the beam pipe
527  // create beam pipe volumes for Endcap and return their outer radius
528  float rEndcapBP = 0.;
529  std::pair<Trk::TrackingVolume*, Trk::TrackingVolume*> endcapBP =
530  createBeamPipeVolumes(bpCutouts, keyDim.back().second,
531  lArPositiveEndcap->center().z() +
532  lArPositiveEndcapBounds->halflengthZ(),
533  "Endcap", rEndcapBP);
534 
535  // build lAr vessel around EC Presampler
536  const Trk::CylinderVolumeBounds* ecpBounds =
537  dynamic_cast<const Trk::CylinderVolumeBounds*>(
538  &(lArPosECPresampler->volumeBounds()));
539  if (!ecpBounds){
540  std::abort();
541  }
542 
543  float ecpHz = ecpBounds->halflengthZ();
544  float ecpRmin = ecpBounds->innerRadius();
545  float ecpRmax = ecpBounds->outerRadius();
546 
547  auto ecpPos = std::make_unique<Amg::Transform3D>(lArPosECPresampler->transform());
548  auto ecpNeg = std::make_unique<Amg::Transform3D>(lArNegECPresampler->transform());
549 
550  auto ecpUpBounds = std::make_shared<Trk::CylinderVolumeBounds>(ecpRmax, keyDim.back().first, ecpHz);
551  auto ecpDownBounds = std::make_shared<Trk::CylinderVolumeBounds>(rEndcapBP, ecpRmin, ecpHz);
552 
553  Trk::TrackingVolume* ecPresamplerCoverPos = new Trk::TrackingVolume(
554  std::make_unique<Amg::Transform3D>(*ecpPos), std::make_shared<Trk::CylinderVolumeBounds>(*ecpUpBounds),
555  m_Al, nullptr, nullptr,
556  "Calo::GapVolumes::LAr::PositiveECPresamplerCover");
557  Trk::TrackingVolume* ecPresamplerCoverNeg = new Trk::TrackingVolume(
558  std::make_unique<Amg::Transform3D>(*ecpNeg),
559  std::move(ecpUpBounds), m_Al, nullptr, nullptr,
560  "Calo::GapVolumes::LAr::NegativeECPresamplerCover");
561  Trk::TrackingVolume* ecPresamplerInnerPos = new Trk::TrackingVolume(
562  std::move(ecpPos), std::make_shared<Trk::CylinderVolumeBounds>(*ecpDownBounds),
563  m_Al, nullptr,
564  nullptr, "Calo::GapVolumes::LAr::PositiveECPresamplerInner");
565  Trk::TrackingVolume* ecPresamplerInnerNeg = new Trk::TrackingVolume(
566  std::move(ecpNeg),
567  std::move(ecpDownBounds),
568  m_Al, nullptr,
569  nullptr, "Calo::GapVolumes::LAr::NegativeECPresamplerInner");
570 
571  // glue EC presampler radially
572  std::vector<Trk::TrackingVolume*> volsECP;
573  volsECP.push_back(ecPresamplerInnerPos);
574  volsECP.push_back(lArPosECPresampler);
575  volsECP.push_back(ecPresamplerCoverPos);
576  Trk::TrackingVolume* positiveECP =
577  m_trackingVolumeCreator->createContainerTrackingVolume(
578  volsECP, m_caloMaterial, "Calo::Container::PositiveECPresamplerR");
579  std::vector<Trk::TrackingVolume*> volsECN;
580  volsECN.push_back(ecPresamplerInnerNeg);
581  volsECN.push_back(lArNegECPresampler);
582  volsECN.push_back(ecPresamplerCoverNeg);
583  Trk::TrackingVolume* negativeECP =
584  m_trackingVolumeCreator->createContainerTrackingVolume(
585  volsECN, m_caloMaterial, "Calo::Container::NegativeECPresamplerR");
586 
587  // add surrounding buffers
588  z = lArPosECPresampler->center().z() - ecpHz;
589  float z1 = lArPosECPresampler->center().z() + ecpHz;
590  float z2 =
591  lArPositiveEndcap->center().z() - lArPositiveEndcapBounds->halflengthZ();
592 
593  auto ecIPos = std::make_unique<Amg::Transform3D>(Amg::Translation3D(
594  Amg::Vector3D(0., 0., 0.5 * (z + keyDim.back().second))));
595 
596  auto ecINeg = std::make_unique<Amg::Transform3D>(Amg::Translation3D(
597  Amg::Vector3D(0., 0., -0.5 * (z + keyDim.back().second))));
598 
599  auto ecpIBounds = std::make_shared<Trk::CylinderVolumeBounds>(
600  rEndcapBP, keyDim.back().first, 0.5 * (z - keyDim.back().second));
601 
602  auto ecOPos = std::make_unique<Amg::Transform3D>(
603  Amg::Translation3D(Amg::Vector3D(0., 0., 0.5 * (z1 + z2))));
604 
605  auto ecONeg = std::make_unique<Amg::Transform3D>(
606  Amg::Translation3D(Amg::Vector3D(0., 0., -0.5 * (z1 + z2))));
607 
608  auto ecpOBounds = std::make_shared<Trk::CylinderVolumeBounds>(
609  rEndcapBP, keyDim.back().first, 0.5 * (z2 - z1));
610 
611  Trk::TrackingVolume* ecPresamplerInPos = new Trk::TrackingVolume(
612  std::move(ecIPos), std::make_shared<Trk::CylinderVolumeBounds>(*ecpIBounds),
613  m_Ar, nullptr, nullptr,
614  "Calo::GapVolumes::LAr::PositiveECPresamplerIn");
615  Trk::TrackingVolume* ecPresamplerInNeg = new Trk::TrackingVolume(
616  std::move(ecINeg), std::move(ecpIBounds),
617  m_Ar, nullptr, nullptr,
618  "Calo::GapVolumes::LAr::NegativeECPresamplerIn");
619  Trk::TrackingVolume* ecPresamplerOutPos = new Trk::TrackingVolume(
620  std::move(ecOPos), std::make_shared<Trk::CylinderVolumeBounds>(*ecpOBounds),
621  m_Ar, nullptr, nullptr,
622  "Calo::GapVolumes::LAr::PositiveECPresamplerOut");
623  Trk::TrackingVolume* ecPresamplerOutNeg = new Trk::TrackingVolume(
624  std::move(ecONeg), std::move(ecpOBounds),
625  m_Ar, nullptr, nullptr,
626  "Calo::GapVolumes::LAr::NegativeECPresamplerOut");
627 
628  // glue EC presampler in z
629  std::vector<Trk::TrackingVolume*> volECP;
630  volECP.push_back(ecPresamplerInPos);
631  volECP.push_back(positiveECP);
632  volECP.push_back(ecPresamplerOutPos);
633  Trk::TrackingVolume* positiveEP =
634  m_trackingVolumeCreator->createContainerTrackingVolume(
635  volECP, m_caloMaterial, "Calo::Container::PositiveECPresampler");
636  std::vector<Trk::TrackingVolume*> volECN;
637  volECN.push_back(ecPresamplerOutNeg);
638  volECN.push_back(negativeECP);
639  volECN.push_back(ecPresamplerInNeg);
640  Trk::TrackingVolume* negativeEP =
641  m_trackingVolumeCreator->createContainerTrackingVolume(
642  volECN, m_caloMaterial, "Calo::Container::NegativeECPresampler");
643 
644  // build lAr vessel around EMEC
645  ecpHz = lArPositiveEndcapBounds->halflengthZ();
646  ecpRmin = lArPositiveEndcapBounds->innerRadius();
647  ecpRmax = lArPositiveEndcapBounds->outerRadius();
648 
649  auto ecPos =
650  std::make_unique<Amg::Transform3D>(lArPositiveEndcap->transform());
651  auto ecNeg =
652  std::make_unique<Amg::Transform3D>(lArNegativeEndcap->transform());
653 
654  auto ecUpBounds =
655  std::make_shared<Trk::CylinderVolumeBounds>(ecpRmax, keyDim.back().first, ecpHz);
656  auto ecDownBounds =
657  std::make_shared<Trk::CylinderVolumeBounds>(rEndcapBP, ecpRmin, ecpHz);
658 
659  Trk::TrackingVolume* ecCoverPos = new Trk::TrackingVolume(
660  std::make_unique<Amg::Transform3D>(*ecPos),
661  std::make_shared<Trk::CylinderVolumeBounds>(*ecUpBounds),
662  m_Ar, nullptr, nullptr,
663  "Calo::GapVolumes::LAr::PositiveEndcapCover");
664  Trk::TrackingVolume* ecCoverNeg = new Trk::TrackingVolume(
665  std::make_unique<Amg::Transform3D>(*ecNeg),
666  std::move(ecUpBounds),
667  m_Ar, nullptr, nullptr,
668  "Calo::GapVolumes::LAr::NegativeEndcapCover");
669  Trk::TrackingVolume* ecInnerPos = new Trk::TrackingVolume(
670  std::move(ecPos), std::make_shared<Trk::CylinderVolumeBounds>(*ecDownBounds),
671  m_Al, nullptr,
672  nullptr, "Calo::GapVolumes::LAr::PositiveEndcapInner");
673  Trk::TrackingVolume* ecInnerNeg = new Trk::TrackingVolume(
674  std::move(ecNeg),
675  std::move(ecDownBounds),
676  m_Al, nullptr,
677  nullptr, "Calo::GapVolumes::LAr::NegativeEndcapInner");
678 
679  // glue EMEC radially
680  std::vector<Trk::TrackingVolume*> volsEC;
681  volsEC.push_back(ecInnerPos);
682  volsEC.push_back(lArPositiveEndcap);
683  volsEC.push_back(ecCoverPos);
684  Trk::TrackingVolume* positiveEC =
685  m_trackingVolumeCreator->createContainerTrackingVolume(
686  volsEC, m_caloMaterial, "Calo::Container::PositiveEndcapR");
687  std::vector<Trk::TrackingVolume*> volsEN;
688  volsEN.push_back(ecInnerNeg);
689  volsEN.push_back(lArNegativeEndcap);
690  volsEN.push_back(ecCoverNeg);
691  Trk::TrackingVolume* negativeEC =
692  m_trackingVolumeCreator->createContainerTrackingVolume(
693  volsEN, m_caloMaterial, "Calo::Container::NegativeEndcapR");
694 
695  // glue presampler with EMEC
696  std::vector<Trk::TrackingVolume*> volEEP;
697  volEEP.push_back(positiveEP);
698  volEEP.push_back(positiveEC);
699  Trk::TrackingVolume* positiveEEP =
700  m_trackingVolumeCreator->createContainerTrackingVolume(
701  volEEP, m_caloMaterial, "Calo::Container::PositiveEMEC");
702  std::vector<Trk::TrackingVolume*> volEEN;
703  volEEN.push_back(negativeEC);
704  volEEN.push_back(negativeEP);
705  Trk::TrackingVolume* negativeEEP =
706  m_trackingVolumeCreator->createContainerTrackingVolume(
707  volEEN, m_caloMaterial, "Calo::Container::NegativeEMEC");
708 
709  // glue EMEC sector with beam pipe volumes
710 
711  std::vector<Trk::TrackingVolume*> volsEndcapPos;
712  if (endcapBP.first)
713  volsEndcapPos.push_back(endcapBP.first);
714  volsEndcapPos.push_back(positiveEEP);
715 
716  std::unique_ptr<Trk::TrackingVolume> positiveEndcap(
717  m_trackingVolumeCreator->createContainerTrackingVolume(
718  volsEndcapPos, m_caloMaterial, "Calo::Container::PositiveEndcap"));
719 
720  std::vector<Trk::TrackingVolume*> volsEndcapNeg;
721  if (endcapBP.second)
722  volsEndcapNeg.push_back(endcapBP.second);
723  volsEndcapNeg.push_back(negativeEEP);
724 
725  std::unique_ptr<Trk::TrackingVolume> negativeEndcap(
726  m_trackingVolumeCreator->createContainerTrackingVolume(
727  volsEndcapNeg, m_caloMaterial, "Calo::Container::NegativeEndcap"));
728 
730  // Hec sector + beam pipe + lAr cover
731  // create beam pipe volumes for Hec and return their outer radius
732  float rHecBP = 0.;
733  std::pair<Trk::TrackingVolume*, Trk::TrackingVolume*> hecBP =
734  createBeamPipeVolumes(
735  bpCutouts,
736  lArPositiveHec->center().z() - lArPositiveHecBounds->halflengthZ(),
737  lArPositiveHec->center().z() + lArPositiveHecBounds->halflengthZ(),
738  "Hec", rHecBP);
739  // HecInnerGap (new gap volume )
740  Trk::Material lArHecInnerGapMaterial =
741  Trk::Material(390., 1223., 18., 9., 0.0014);
742 
743  // create the Bounds
744  auto lArHecInnerGapBounds =
745  std::make_shared<Trk::CylinderVolumeBounds>(rHecBP, lArPositiveHecBounds->innerRadius(),
746  lArPositiveHecBounds->halflengthZ());
747 
748  auto lArHecPos = std::make_unique<Amg::Transform3D>(
749  Amg::Translation3D(Amg::Vector3D(0., 0., lArPositiveHec->center().z())));
750  auto lArHecNeg = std::make_unique<Amg::Transform3D>(
751  Amg::Translation3D(Amg::Vector3D(0., 0., lArNegativeHec->center().z())));
752 
753  Trk::TrackingVolume* lArPositiveHecInnerGap = new Trk::TrackingVolume(
754  std::make_unique<Amg::Transform3D>(*lArHecPos),
755  lArHecInnerGapBounds, m_Al, nullptr, nullptr,
756  "Calo::GapVolumes::LAr::PositiveHecInnerGap");
757 
758  Trk::TrackingVolume* lArNegativeHecInnerGap = new Trk::TrackingVolume(
759  std::make_unique<Amg::Transform3D>(*lArHecNeg),
760  std::make_shared<Trk::CylinderVolumeBounds>(*lArHecInnerGapBounds),
761  m_Al, nullptr, nullptr,
762  "Calo::GapVolumes::LAr::NegativeHecInnerGap");
763  // create the Bounds
764  auto lArHecOuterGapBounds =
765  std::make_shared<Trk::CylinderVolumeBounds>(lArPositiveHecBounds->outerRadius(),
766  keyDim.back().first,
767  lArPositiveHecBounds->halflengthZ());
768 
769  Trk::TrackingVolume* lArPositiveHecOuterGap = new Trk::TrackingVolume(
770  std::move(lArHecPos), std::make_shared<Trk::CylinderVolumeBounds>(*lArHecOuterGapBounds),
771  m_Ar, nullptr,
772  nullptr, "Calo::GapVolumes::LAr::PositiveHecOuterGap");
773 
774  Trk::TrackingVolume* lArNegativeHecOuterGap = new Trk::TrackingVolume(
775  std::move(lArHecNeg),
776  std::move(lArHecOuterGapBounds), m_Ar,
777  nullptr, nullptr, "Calo::GapVolumes::LAr::NegativeHecOuterGap");
778 
779  // glue Hec sector with beam pipe volumes
780 
781  std::vector<Trk::TrackingVolume*> volsHecPos;
782  if (hecBP.first)
783  volsHecPos.push_back(hecBP.first);
784  volsHecPos.push_back(lArPositiveHecInnerGap);
785  volsHecPos.push_back(lArPositiveHec);
786  volsHecPos.push_back(lArPositiveHecOuterGap);
787 
788  std::unique_ptr<Trk::TrackingVolume> positiveHec(
789  m_trackingVolumeCreator->createContainerTrackingVolume(
790  volsHecPos, m_caloMaterial, "Calo::Container::PositiveHec"));
791 
792  std::vector<Trk::TrackingVolume*> volsHecNeg;
793  if (hecBP.second){
794  volsHecNeg.push_back(hecBP.second);
795  }
796  volsHecNeg.push_back(lArNegativeHecInnerGap);
797  volsHecNeg.push_back(lArNegativeHec);
798  volsHecNeg.push_back(lArNegativeHecOuterGap);
799 
800  std::unique_ptr<Trk::TrackingVolume> negativeHec(
801  m_trackingVolumeCreator->createContainerTrackingVolume(
802  volsHecNeg, m_caloMaterial, "Calo::Container::NegativeHec"));
803 
805  // Fcal sector + beam pipe + lAr cover
806 
807  // create beam pipe volumes for Fcal and return their outer radius
808  float rFcalBP = 0.;
809  std::pair<Trk::TrackingVolume*, Trk::TrackingVolume*> fcalBP =
810  createBeamPipeVolumes(
811  bpCutouts,
812  lArPositiveFcal->center().z() - lArPositiveFcalBounds->halflengthZ(),
813  lArPositiveFcal->center().z() + lArPositiveFcalBounds->halflengthZ(),
814  "Fcal", rFcalBP);
815  // FcalInnerGap (new gap volume )
816  // Trk::Material lArFcalInnerGapMaterial = Trk::Material(390.,
817  // 1223., 40.,18., 0.0014);
818 
819  if (rFcalBP > lArPositiveFcalBounds->innerRadius()) {
820  ATH_MSG_ERROR("PROBLEM : beam pipe collide with Fcal:"
821  << rFcalBP << ">" << lArPositiveFcalBounds->innerRadius()
822  << ", abort");
823  return nullptr;
824  }
825 
826  // create the Bounds
827  auto lArFcalInnerGapBounds =
828  std::make_shared<Trk::CylinderVolumeBounds>(rFcalBP,
829  lArPositiveFcalBounds->innerRadius(),
830  lArPositiveFcalBounds->halflengthZ());
831 
832  auto lArFcalPos = std::make_unique<Amg::Transform3D>(
833  Amg::Translation3D(Amg::Vector3D(0., 0., lArPositiveFcal->center().z())));
834  auto lArFcalNeg = std::make_unique<Amg::Transform3D>(
835  Amg::Translation3D(Amg::Vector3D(0., 0., lArNegativeFcal->center().z())));
836 
837  Trk::TrackingVolume* lArPositiveFcalInnerGap = new Trk::TrackingVolume(
838  std::make_unique<Amg::Transform3D>(*lArFcalPos),
839  std::make_shared<Trk::CylinderVolumeBounds>(*lArFcalInnerGapBounds),
840  m_Al, nullptr, nullptr,
841  "Calo::GapVolumes::LAr::PositiveFcalInnerGap");
842 
843  Trk::TrackingVolume* lArNegativeFcalInnerGap = new Trk::TrackingVolume(
844  std::make_unique<Amg::Transform3D>(*lArFcalNeg),
845  std::move(lArFcalInnerGapBounds), m_Al, nullptr,
846  nullptr, "Calo::GapVolumes::LAr::NegativeFcalInnerGap");
847 
848  // create the Bounds
849  auto lArFcalOuterGapBounds =
850  std::make_shared<Trk::CylinderVolumeBounds>(lArPositiveHecBounds->outerRadius(),
851  keyDim.back().first,
852  lArPositiveFcalBounds->halflengthZ());
853 
854  Trk::TrackingVolume* lArPositiveFcalOuterGap = new Trk::TrackingVolume(
855  std::move(lArFcalPos), std::make_shared<Trk::CylinderVolumeBounds>(*lArFcalOuterGapBounds),
856  m_Ar, nullptr, nullptr, "Calo::GapVolumes::LAr::PositiveFcalOuterGap");
857 
858  Trk::TrackingVolume* lArNegativeFcalOuterGap = new Trk::TrackingVolume(
859  std::move(lArFcalNeg), std::move(lArFcalOuterGapBounds), m_Ar,
860  nullptr, nullptr, "Calo::GapVolumes::LAr::NegativeFcalOuterGap");
861 
862  // glue Fcal sector with beam pipe volumes
863 
864  std::vector<Trk::TrackingVolume*> volsFcalPos;
865  if (fcalBP.first){
866  volsFcalPos.push_back(fcalBP.first);
867  }
868  volsFcalPos.push_back(lArPositiveFcalInnerGap);
869  volsFcalPos.push_back(lArPositiveFcal);
870  volsFcalPos.push_back(lArPositiveHecFcalCover);
871  volsFcalPos.push_back(lArPositiveFcalOuterGap);
872 
873  std::unique_ptr<Trk::TrackingVolume> positiveFcal(
874  m_trackingVolumeCreator->createContainerTrackingVolume(
875  volsFcalPos, m_caloMaterial, "Calo::Container::PositiveFcal"));
876 
877  std::vector<Trk::TrackingVolume*> volsFcalNeg;
878  if (fcalBP.second){
879  volsFcalNeg.push_back(fcalBP.second);
880  }
881  volsFcalNeg.push_back(lArNegativeFcalInnerGap);
882  volsFcalNeg.push_back(lArNegativeFcal);
883  volsFcalNeg.push_back(lArNegativeHecFcalCover);
884  volsFcalNeg.push_back(lArNegativeFcalOuterGap);
885 
886  std::unique_ptr<Trk::TrackingVolume> negativeFcal(
887  m_trackingVolumeCreator->createContainerTrackingVolume(
888  volsFcalNeg, m_caloMaterial, "Calo::Container::NegativeFcal"));
889 
891  // Outer endcap sector + beam pipe
892 
893  // create beam pipe volumes for Outer sector and return their outer radius
894  float rOutBP = 0.;
895  std::pair<Trk::TrackingVolume*, Trk::TrackingVolume*> outBP =
896  createBeamPipeVolumes(bpCutouts, lArPositiveOuterBoundary,
897  caloPositiveOuterBoundary, "Outer", rOutBP);
898 
899  Trk::Material lArSectorOuterGapMat =
900  Trk::Material(20.5, 723., 64., 28., 0.0084);
901 
902  auto lArSectorOuterG0Bounds =
903  std::make_shared<Trk::CylinderVolumeBounds>(
904  rOutBP, 430.,
905  // lArPositiveEndcapBounds->outerRadius(),
906  0.5 * (caloPositiveOuterBoundary - lArPositiveOuterBoundary));
907 
908  auto lArSectorOuterG1Bounds =
909  std::make_shared<Trk::CylinderVolumeBounds>(
910  430., keyDim.back().first,
911  // lArPositiveEndcapBounds->outerRadius(),
912  0.5 * (caloPositiveOuterBoundary - lArPositiveOuterBoundary));
913 
914  z = 0.5 * (caloPositiveOuterBoundary + lArPositiveOuterBoundary);
915 
916  auto lArSecOutG1P =
917  std::make_unique<Amg::Transform3D>(Amg::Translation3D(Amg::Vector3D(0., 0., z)));
918  auto lArSecOutG0P =
919  std::make_unique<Amg::Transform3D>(Amg::Translation3D(Amg::Vector3D(0., 0., z)));
920 
921  lArPositiveSectorOuterGap0 = new Trk::TrackingVolume(
922  std::move(lArSecOutG0P), std::make_shared<Trk::CylinderVolumeBounds>(*lArSectorOuterG0Bounds),
923  lArSectorOuterGapMat, nullptr,
924  nullptr, "Calo::GapVolumes::LAr::PositiveSectorOuterGap0");
925 
926  lArPositiveSectorOuterGap = new Trk::TrackingVolume(
927  std::move(lArSecOutG1P), std::make_shared<Trk::CylinderVolumeBounds> (*lArSectorOuterG1Bounds),
928  m_Ar, nullptr, nullptr,
929  "Calo::GapVolumes::LAr::PositiveSectorOuterGap");
930 
931  auto lArSecOutG1N =
932  std::make_unique<Amg::Transform3D>(Amg::Translation3D(Amg::Vector3D(0., 0., -z)));
933  auto lArSecOutG0N =
934  std::make_unique<Amg::Transform3D>(Amg::Translation3D(Amg::Vector3D(0., 0., -z)));
935 
936  lArNegativeSectorOuterGap0 =
937  new Trk::TrackingVolume(std::move(lArSecOutG0N),
938  std::move(lArSectorOuterG0Bounds),
939  lArSectorOuterGapMat, nullptr, nullptr,
940  "Calo::GapVolumes::LAr::NegativeSectorOuterGap0");
941 
942  lArNegativeSectorOuterGap = new Trk::TrackingVolume(
943  std::move(lArSecOutG1N),
944  std::move(lArSectorOuterG1Bounds),
945  m_Ar, nullptr,
946  nullptr, "Calo::GapVolumes::LAr::NegativeSectorOuterGap");
947 
948  // glue OuterGap with beam pipe volumes
949  std::vector<Trk::TrackingVolume*> volsOuterGapP;
950  if (outBP.first){
951  volsOuterGapP.push_back(outBP.first);
952  }
953  volsOuterGapP.push_back(lArPositiveSectorOuterGap0);
954  volsOuterGapP.push_back(lArPositiveSectorOuterGap);
955  std::unique_ptr<Trk::TrackingVolume> positiveOuterGap(
956  m_trackingVolumeCreator->createContainerTrackingVolume(
957  volsOuterGapP, m_caloMaterial, "Calo::Container::PositiveOuterGap"));
958 
959  std::vector<Trk::TrackingVolume*> volsOuterGapN;
960  if (outBP.second){
961  volsOuterGapN.push_back(outBP.second);
962  }
963  volsOuterGapN.push_back(lArNegativeSectorOuterGap0);
964  volsOuterGapN.push_back(lArNegativeSectorOuterGap);
965  std::unique_ptr<Trk::TrackingVolume> negativeOuterGap(
966  m_trackingVolumeCreator->createContainerTrackingVolume(
967  volsOuterGapN, m_caloMaterial, "Calo::Container::NegativeOuterGap"));
968 
969  ATH_MSG_DEBUG("Endcap volumes ready");
970 
971  // ++ (ii) lArNegativeSector
972  Trk::TrackingVolume* lArNegativeSector = nullptr;
973  // +++ has 4 sub volumes in Z
974  std::vector<Trk::TrackingVolume*> lArNegativeSectorVolumes;
975  // +++ (A) -> Outer sector
976  lArNegativeSectorVolumes.push_back(negativeOuterGap.release());
977  // +++ (B) -> Fcal sector
978  lArNegativeSectorVolumes.push_back(negativeFcal.release());
979  // +++ (C) -> Hec sector
980  lArNegativeSectorVolumes.push_back(negativeHec.release());
981  // +++ (D) -> Endcap sector
982  lArNegativeSectorVolumes.push_back(negativeEndcap.release());
983  // +++ all exists : create super volume (ii)
984  lArNegativeSector = m_trackingVolumeCreator->createContainerTrackingVolume(
985  lArNegativeSectorVolumes, m_caloMaterial,
986  "Calo::LAr::Container::NegativeSector");
987 
988  // ++ (ii) lArPositiveSector
989  Trk::TrackingVolume* lArPositiveSector = nullptr;
990  // +++ has 4 sub volumes in Z
991  std::vector<Trk::TrackingVolume*> lArPositiveSectorVolumes;
992  // +++ (A) -> Endcap sector
993  lArPositiveSectorVolumes.push_back(positiveEndcap.release());
994  // +++ (B) -> Hec sector
995  lArPositiveSectorVolumes.push_back(positiveHec.release());
996  // +++ (C) -> Fcal sector
997  lArPositiveSectorVolumes.push_back(positiveFcal.release());
998  // +++ (D) -> OuterGap
999  lArPositiveSectorVolumes.push_back(positiveOuterGap.release());
1000  // +++ all exists : create super volume (ii)
1001  lArPositiveSector = m_trackingVolumeCreator->createContainerTrackingVolume(
1002  lArPositiveSectorVolumes, m_caloMaterial,
1003  "Calo::LAr::Container::PositiveSector");
1004 
1006  // central LAr barrel
1007  //
1008  // solenoid gap
1009  auto trtSolGapBounds = std::make_shared<Trk::CylinderVolumeBounds>(
1010  keyDim[0].first, solenoidBounds->innerRadius(),
1011  solenoidBounds->halflengthZ());
1012 
1013  // solenoid gap is not completely empty
1014  Trk::Material solGapMat(535., 2871., 18.6, 9.1, 0.00038);
1015 
1016  trtSolenoidGap =
1017  new Trk::TrackingVolume(nullptr, std::move(trtSolGapBounds), solGapMat, nullptr,
1018  nullptr, "Calo::GapVolumes::SolenoidGap");
1019 
1020  auto lArTileCentralG1Bounds =
1021  std::make_shared<Trk::CylinderVolumeBounds>(lArBarrelBounds->outerRadius(),
1022  tileCombinedBounds->innerRadius(),
1023  lArBarrelBounds->halflengthZ());
1024 
1025  lArTileCentralSectorGap = new Trk::TrackingVolume(
1026  nullptr, std::move(lArTileCentralG1Bounds), m_Ar, nullptr, nullptr,
1027  "Calo::GapVolumes::LArTileCentralSectorGap");
1028 
1029  Trk::TrackingVolume* lArCentralBarrelSector = nullptr;
1030  // ++ has 6 sub volumes in R
1031  std::vector<Trk::TrackingVolume*> lArCentralBarrelSectorVolumes;
1032  // ++++ (a) -> solenoid gap
1033  lArCentralBarrelSectorVolumes.push_back(trtSolenoidGap);
1034  // ++++ (b) -> solenoid (exists already)
1035  lArCentralBarrelSectorVolumes.push_back(solenoid);
1036  // ++++ (c) -> solenoidlArPresamplerGap (exists already)
1037  lArCentralBarrelSectorVolumes.push_back(solenoidlArPresamplerGap);
1038  // ++++ (d) -> lArBarrelPresampler (exists already)
1039  lArCentralBarrelSectorVolumes.push_back(lArBarrelPresampler);
1040  // ++++ (e) -> lArBarrel (exists already)
1041  lArCentralBarrelSectorVolumes.push_back(lArBarrel);
1042  // ++++ (f) -> lArTile gap
1043  lArCentralBarrelSectorVolumes.push_back(lArTileCentralSectorGap);
1044  // ++++ all sub volumes exist: build the super volume
1045  lArCentralBarrelSector =
1046  m_trackingVolumeCreator->createContainerTrackingVolume(
1047  lArCentralBarrelSectorVolumes, m_caloMaterial,
1048  "Calo::Containers::LAr::CentralBarrelSector", false, true);
1050  // side buffers
1051  // the Tile Crack volume (TileGap3, enum 17) inserted here
1052  // binned material for Crack : steering in binEta
1053  // TODO turn into 2D binned array
1054  std::vector<Trk::IdentifiedMaterial> matCrack;
1055  // layer material can be adjusted here
1056  int baseID = Trk::GeometrySignature(Trk::Calo) * 1000 + 17;
1057  matCrack.emplace_back(std::make_shared<Trk::Material>(m_Scint), baseID);
1058  matCrack.emplace_back(std::make_shared<Trk::Material>(m_caloMaterial), -1);
1059  matCrack.emplace_back(std::make_shared<Trk::Material>(m_Al), -1);
1060  //
1061  double etadist;
1062  // if TileGap3 goes above 1.6 in eta - it's RUN3 geometry
1063  int nbins =
1064  (caloDDM->is_in(1.65, 0.0, CaloCell_ID::TileGap3, etadist)) ? 6 : 3;
1065  auto bun = Trk::BinUtility(nbins, -1.8, -1.2, Trk::open, Trk::binEta);
1066  auto bup = Trk::BinUtility(nbins, 1.2, 1.8, Trk::open, Trk::binEta);
1067  // array of indices
1068  std::vector<std::vector<size_t>> indexP;
1069  std::vector<std::vector<size_t>> indexN;
1070  // binned material for LAr : layer depth per eta bin
1071  std::vector<Trk::BinUtility> layDN(bun.bins());
1072  std::vector<Trk::BinUtility> layUP(bup.bins());
1073  double crackZ1 = 3532.;
1074  double crackZ2 = 3540.;
1075  // construct bin utilities
1076  std::vector<float> steps;
1077  for (unsigned int i = 0; i < bup.bins(); i++) {
1078  steps.clear();
1079  std::vector<size_t> indx;
1080  indx.clear();
1081  steps.push_back(crackZ1);
1082  indx.push_back(i < bup.bins() - 1 ? 0 : 1);
1083  steps.push_back(crackZ2);
1084  indx.push_back(2);
1085  steps.push_back(keyDim.back().second);
1087  layUP[i] = zBU;
1088  indexP.push_back(indx);
1089  }
1090 
1091  const Trk::BinnedMaterial crackBinPos(m_crackMaterial, bup, layUP, indexP,
1092  matCrack);
1093 
1094  auto crackBoundsPos = std::make_shared<Trk::CylinderVolumeBounds>(
1095  keyDim[0].first, tileCombinedBounds->innerRadius(),
1096  0.5 * (keyDim.back().second - crackZ1));
1097  z = 0.5 * (keyDim.back().second + crackZ1);
1098  auto crackPosTransform =
1099  std::make_unique<Amg::Transform3D>(Amg::Translation3D(Amg::Vector3D(0., 0., z)));
1100 
1102  std::move(crackPosTransform), crackBoundsPos, crackBinPos, 17,
1103  "Calo::Detectors::Tile::CrackPos");
1104 
1105  for (unsigned int i = 0; i < bun.bins(); i++) {
1106  steps.clear();
1107  std::vector<size_t> indx;
1108  indx.clear();
1109  steps.push_back(-keyDim.back().second);
1110  indx.push_back(2);
1111  steps.push_back(-crackZ2);
1112  indx.push_back(i > 0 ? 0 : 1);
1113  steps.push_back(-crackZ1);
1115  layDN[i] = zBU;
1116  indexN.push_back(indx);
1117  }
1118 
1119  const Trk::BinnedMaterial crackBinNeg(m_crackMaterial, bun, layDN, indexN, matCrack);
1120 
1121  auto crackNegTransform =
1122  std::make_unique<Amg::Transform3D>(Amg::Translation3D(Amg::Vector3D(0., 0., -z)));
1123 
1125  std::move(crackNegTransform),
1126  std::make_shared<Trk::CylinderVolumeBounds>(*crackBoundsPos), crackBinNeg, 17,
1127  "Calo::Detectors::Tile::CrackNeg");
1129 
1130  auto lArCentralG1Bounds = std::make_shared<Trk::CylinderVolumeBounds>(
1131  keyDim[0].first, tileCombinedBounds->innerRadius(),
1132  0.5 * (crackZ1 - lArBarrelBounds->halflengthZ()));
1133 
1134  z = 0.5 * (crackZ1 + lArBarrelBounds->halflengthZ());
1135  auto lArCentralG1P =
1136  std::make_unique<Amg::Transform3D>(Amg::Translation3D(Amg::Vector3D(0., 0., z)));
1137 
1138  lArCentralPositiveGap = new Trk::TrackingVolume(
1139  std::move(lArCentralG1P),
1140  std::make_shared<Trk::CylinderVolumeBounds>(*lArCentralG1Bounds), m_Ar, nullptr, nullptr,
1141  "Calo::GapVolumes::LArCentralPositiveGap");
1142 
1143  auto lArCentralG1N =
1144  std::make_unique<Amg::Transform3D>(Amg::Translation3D(Amg::Vector3D(0., 0., -z)));
1145 
1146  lArCentralNegativeGap = new Trk::TrackingVolume(
1147  std::move(lArCentralG1N),
1148  std::move(lArCentralG1Bounds),
1149  m_Ar, nullptr,
1150  nullptr, "Calo::GapVolumes::LArCentralNegativeGap");
1151 
1152  // glue laterally
1153  Trk::TrackingVolume* lArCentralSector = nullptr;
1154  // ++ has 5 sub volumes in z
1155  std::vector<Trk::TrackingVolume*> lArCentralSectorVolumes;
1156  // ++++ (a) -> negative crack
1157  lArCentralSectorVolumes.push_back(crackNeg);
1158  // ++++ (b) -> negative gap
1159  lArCentralSectorVolumes.push_back(lArCentralNegativeGap);
1160  // ++++ (c) -> central barrel
1161  lArCentralSectorVolumes.push_back(lArCentralBarrelSector);
1162  // ++++ (d) -> positive gap
1163  lArCentralSectorVolumes.push_back(lArCentralPositiveGap);
1164  // ++++ (e) -> positive crack
1165  lArCentralSectorVolumes.push_back(crackPos);
1166  // ++++ all sub volumes exist: build the super volume
1167  lArCentralSector = m_trackingVolumeCreator->createContainerTrackingVolume(
1168  lArCentralSectorVolumes, m_caloMaterial,
1169  "Calo::Containers::LAr::CentralSector");
1170 
1171  // glue with ID sector
1172  Trk::TrackingVolume* caloCentralSector = nullptr;
1173  // ++ has 2 sub volumes in R
1174  std::vector<Trk::TrackingVolume*> caloCentralSectorVolumes;
1175  // ++++ (a) -> ID sector
1176  caloCentralSectorVolumes.push_back(inDetEnclosed);
1177  // ++++ (b) -> LAr sector
1178  caloCentralSectorVolumes.push_back(lArCentralSector);
1179  // ++++ all sub volumes exist: build the super volume
1180  caloCentralSector = m_trackingVolumeCreator->createContainerTrackingVolume(
1181  caloCentralSectorVolumes, m_caloMaterial,
1182  "Calo::Containers::CaloCentralSector");
1183 
1185 
1186  // glue laterally with endcaps
1187  Trk::TrackingVolume* lArCombined = nullptr;
1188  // ++ has 3 sub volumes in z
1189  std::vector<Trk::TrackingVolume*> lArCombinedVolumes;
1190  // ++++ (a) -> negative endcap
1191  lArCombinedVolumes.push_back(lArNegativeSector);
1192  // ++++ (b) -> barrel
1193  lArCombinedVolumes.push_back(caloCentralSector);
1194  // ++++ (a) -> positive endcap
1195  lArCombinedVolumes.push_back(lArPositiveSector);
1196  // ++++ all sub volumes exist: build the super volume
1197  lArCombined = m_trackingVolumeCreator->createContainerTrackingVolume(
1198  lArCombinedVolumes, m_caloMaterial, "Calo::Containers::LAr::Combined");
1199 
1200  // glue with LAr sector
1201  Trk::TrackingVolume* caloCombined = nullptr;
1202  // ++ has 2 sub volumes in R
1203  std::vector<Trk::TrackingVolume*> caloVolumes;
1204  // ++++ (a) -> LAr sector
1205  caloVolumes.push_back(lArCombined);
1206  // ++++ (b) -> Tile sector
1207  caloVolumes.push_back(tileCombined);
1208  // ++++ all sub volumes exist: build the super volume
1209  caloCombined = m_trackingVolumeCreator->createContainerTrackingVolume(
1210  caloVolumes, m_caloMaterial, "Calo::Containers::CombinedCalo");
1211 
1213 
1214  // build the radial buffer volume to synchronize the radial envelope
1215  // dimensions
1216  Trk::TrackingVolume* centralBuffer = nullptr;
1217  Trk::TrackingVolume* ecPosBuffer = nullptr;
1218  Trk::TrackingVolume* ecNegBuffer = nullptr;
1219 
1220  if (caloVolsOuterRadius > caloDefaultRadius) {
1222  "Calo volumes exceeds envelope radius: adjusting envelope "
1223  "(de-synchronizing...)");
1224  caloDefaultRadius = caloVolsOuterRadius;
1225  }
1226 
1227  if (caloVolsOuterRadius < caloDefaultRadius) {
1229  "Build radial buffer to synchronize the boundaries in between R "
1230  << caloVolsOuterRadius << " and " << caloDefaultRadius);
1231 
1232  auto centralSynBounds = std::make_shared<Trk::CylinderVolumeBounds>(
1233  caloVolsOuterRadius, caloDefaultRadius, caloVolsExtendZ);
1234  centralBuffer = new Trk::TrackingVolume(
1235  nullptr, std::move(centralSynBounds), m_caloMaterial, nullptr, nullptr,
1236  "Calo::GapVolumes::EnvelopeBuffer");
1237  }
1238 
1239  if (caloVolsExtendZ < caloDefaultHalflengthZ) {
1241  "Build longitudinal buffers to synchronize the boundaries in between Z "
1242  << caloVolsExtendZ << " and " << caloDefaultHalflengthZ);
1243 
1244  auto endcapSynBounds = std::make_shared<Trk::CylinderVolumeBounds>(
1245  0., caloDefaultRadius,
1246  0.5 * (caloDefaultHalflengthZ - caloVolsExtendZ));
1247  // endcap buffers not empty
1248  Trk::Material ecBuffMat(53. / 0.38, 355. / 0.38, 20., 10.,
1249  0.0053 * pow(0.38, 3));
1250 
1251  float zPos = 0.5 * (caloDefaultHalflengthZ + caloVolsExtendZ);
1252  ecPosBuffer = new Trk::TrackingVolume(
1253  std::make_unique<Amg::Transform3D>(Amg::Translation3D(Amg::Vector3D(0., 0., zPos))),
1254  std::make_shared<Trk::CylinderVolumeBounds>(*endcapSynBounds),
1255  m_Ar, nullptr, nullptr,
1256  "Calo::GapVolumes::PosECBuffer");
1257 
1258  ecNegBuffer = new Trk::TrackingVolume(
1259  std::make_unique<Amg::Transform3D>(Amg::Translation3D(Amg::Vector3D(0., 0., -zPos))),
1260  std::move(endcapSynBounds), m_Ar, nullptr, nullptr,
1261  "Calo::GapVolumes::NegECBuffer");
1262  }
1263 
1265  "All gap volumes for the Calorimeter created. Starting to build Volume "
1266  "Hiearchy.");
1267 
1269 
1270  ATH_MSG_VERBOSE("Resolve MS cutouts:");
1271 
1272  // resolve number of additional cutout volumes
1273  int nCutVol = 0;
1274  std::vector<float> zCutStep;
1275  std::vector<float> rCutStep;
1276  if (msCutouts.size() > 1) {
1277  zCutStep.push_back(msCutouts[0].second);
1278  rCutStep.push_back(msCutouts[0].first);
1279  for (unsigned int i = 1; i < msCutouts.size(); i++) {
1280  if (msCutouts[i].second == zCutStep.back())
1281  rCutStep.push_back(msCutouts[i].first);
1282  else
1283  zCutStep.push_back(msCutouts[i].second);
1284  }
1285  nCutVol = zCutStep.size() - 1;
1286  }
1287  if (nCutVol > 0)
1288  ATH_MSG_VERBOSE(nCutVol << " MS cutout volume(s) required ");
1289 
1290  std::vector<Trk::TrackingVolume*> forwardCutoutVols;
1291  std::vector<Trk::TrackingVolume*> backwardCutoutVols;
1292 
1293  // cutout region not empty
1294  std::vector<Trk::Material> cutOutMat;
1295  cutOutMat.emplace_back(19.9, 213., 50., 23.,
1296  0.0065); // 3.5 Fe + 1 Ar : verify
1297  cutOutMat.push_back(m_caloMaterial);
1298  // cutOutMat.push_back(Trk::Material(18.74, 200.9, 52.36, 24.09, 0.0069));
1299 
1300  if (nCutVol > 0) {
1301  // loop over zCutStep, rCutStep[0] gives the fixed outer radius, rCutStep[i]
1302  // the cutout radius for ith volume
1303  float rout = rCutStep[0];
1304  float zlow = zCutStep[0];
1305  for (unsigned int i = 1; i < zCutStep.size(); i++) {
1306  float zup = zCutStep[i];
1307  float rcut = rCutStep[i];
1308  std::stringstream ss;
1309  ss << i;
1310  // get beam pipe volumes
1311  float rCutOutBP = 0.;
1312  std::pair<Trk::TrackingVolume*, Trk::TrackingVolume*> cutOutBP =
1313  createBeamPipeVolumes(bpCutouts, zlow, zup, "CutOuts" + ss.str(),
1314  rCutOutBP);
1315 
1316  // build inner part ( -> Calo )
1317  unsigned int mindex = i > 1 ? 1 : i;
1318 
1319  auto cutInBounds =
1320  std::make_shared<Trk::CylinderVolumeBounds>(rCutOutBP, rcut, 0.5 * (zup - zlow));
1321  Trk::TrackingVolume* caloInPos = new Trk::TrackingVolume(
1322  std::make_unique<Amg::Transform3D>(
1323  Amg::Translation3D(Amg::Vector3D(0., 0., 0.5 * (zup + zlow)))),
1324  std::make_shared<Trk::CylinderVolumeBounds>(*cutInBounds),
1325  cutOutMat[mindex], nullptr, nullptr,
1326  "Calo::GapVolumes::CaloPositiveCutIn" + ss.str());
1327  Trk::TrackingVolume* caloInNeg = new Trk::TrackingVolume(
1328  std::make_unique<Amg::Transform3D>(
1329  Amg::Translation3D(Amg::Vector3D(0., 0., -0.5 * (zup + zlow)))),
1330  std::move(cutInBounds),
1331  cutOutMat[mindex], nullptr, nullptr,
1332  "Calo::GapVolumes::CaloNegativeCutIn" + ss.str());
1333  // build cutout ( -> MS ) : geometry signature needs to be resolved later
1334  // : follow naming convention
1335  auto cutOutBounds = std::make_shared<Trk::CylinderVolumeBounds>(rcut, rout, 0.5 * (zup - zlow));
1336  Trk::TrackingVolume* caloOutPos = new Trk::TrackingVolume(
1337  std::make_unique<Amg::Transform3D>(
1338  Amg::Translation3D(Amg::Vector3D(0., 0., 0.5 * (zup + zlow)))),
1339  std::make_shared<Trk::CylinderVolumeBounds>(*cutOutBounds), m_caloMaterial, nullptr, nullptr,
1340  "Muon::GapVolumes::CaloPositiveCutOut" + ss.str());
1341  Trk::TrackingVolume* caloOutNeg = new Trk::TrackingVolume(
1342  std::make_unique<Amg::Transform3D>(
1343  Amg::Translation3D(Amg::Vector3D(0., 0., -0.5 * (zup + zlow)))),
1344  std::move(cutOutBounds),
1345  m_caloMaterial, nullptr, nullptr,
1346  "Muon::GapVolumes::CaloNegativeCutOut" + ss.str());
1347 
1348  // sign
1349  caloOutPos->sign(Trk::MS);
1350  caloOutNeg->sign(Trk::MS);
1351 
1352  // glue radially and save for final gluing
1353  std::vector<Trk::TrackingVolume*> cvPos;
1354  cvPos.push_back(cutOutBP.first);
1355  cvPos.push_back(caloInPos);
1356  cvPos.push_back(caloOutPos);
1357  Trk::TrackingVolume* cutOutPos =
1358  m_trackingVolumeCreator->createContainerTrackingVolume(
1359  cvPos, m_caloMaterial,
1360  "Calo::GapVolumes::CaloPositiveCutoutVolume" + ss.str());
1361  forwardCutoutVols.push_back(cutOutPos);
1362  //
1363  std::vector<Trk::TrackingVolume*> cvNeg;
1364  cvNeg.push_back(cutOutBP.second);
1365  cvNeg.push_back(caloInNeg);
1366  cvNeg.push_back(caloOutNeg);
1367  Trk::TrackingVolume* cutOutNeg =
1368  m_trackingVolumeCreator->createContainerTrackingVolume(
1369  cvNeg, m_caloMaterial,
1370  "Calo::GapVolumes::CaloNegativeCutoutVolume" + ss.str());
1371  backwardCutoutVols.insert(backwardCutoutVols.begin(), cutOutNeg);
1372 
1373  zlow = zup;
1374  }
1375  }
1376 
1378 
1379  if (!centralBuffer) { //(XX)
1380  // all volumes exist : create the super volume at top level
1381  calorimeter = caloCombined;
1382 
1383  } else { //(X)
1384 
1385  std::vector<Trk::TrackingVolume*> envRVols;
1386  envRVols.push_back(caloCombined);
1387  envRVols.push_back(centralBuffer);
1388 
1389  // add cutouts - final step
1390  if (!forwardCutoutVols.empty() || ecNegBuffer) {
1391 
1392  Trk::TrackingVolume* caloRVolume =
1393  m_trackingVolumeCreator->createContainerTrackingVolume(
1394  envRVols, m_caloMaterial, "Calo::Containers::CombinedRCalo");
1395  std::vector<Trk::TrackingVolume*> envZVols;
1396  envZVols.reserve(backwardCutoutVols.size());
1397  for (auto& backwardCutoutVol : backwardCutoutVols)
1398  envZVols.push_back(backwardCutoutVol);
1399  if (ecNegBuffer)
1400  envZVols.push_back(ecNegBuffer);
1401  envZVols.push_back(caloRVolume);
1402  if (ecPosBuffer)
1403  envZVols.push_back(ecPosBuffer);
1404  for (auto& forwardCutoutVol : forwardCutoutVols)
1405  envZVols.push_back(forwardCutoutVol);
1406 
1407  calorimeter = m_trackingVolumeCreator->createContainerTrackingVolume(
1408  envZVols, m_caloMaterial, m_exitVolume);
1409 
1410  } else { // if no cutouts or endcap buffers, this is the top calo volume
1411 
1412  calorimeter = m_trackingVolumeCreator->createContainerTrackingVolume(
1413  envRVols, m_caloMaterial, m_exitVolume);
1414  }
1415  }
1416 
1418  "TrackingVolume 'Calorimeter' built successfully. Wrap it in "
1419  "TrackingGeometry.");
1420 
1421  auto caloTrackingGeometry = std::make_unique<Trk::TrackingGeometry>(calorimeter);
1422 
1423  if (msgLvl(MSG::VERBOSE) && caloTrackingGeometry){
1424  caloTrackingGeometry->printVolumeHierarchy(msg(MSG::VERBOSE));
1425  }
1426 
1427  if (m_indexStaticLayers && caloTrackingGeometry){
1428  caloTrackingGeometry->indexStaticLayers(signature());
1429  }
1430 
1431  return caloTrackingGeometry;
1432 }
1433 
1435  Trk::LayerIndexSampleMap& licsMap,
1436  const std::vector<CaloCell_ID::CaloSample>& ccid, const Trk::TrackingVolume& vol,
1437  int side) const {
1438 
1439  ATH_MSG_VERBOSE("[+] Registering layers of TrackingVolume '"
1440  << vol.volumeName() << "' in LayerIndex/CaloCell_ID map");
1441 
1442  // get the confined Layers from the TrackingVolume
1443  const Trk::LayerArray* confinedLayers = vol.confinedLayers();
1444  if (!confinedLayers)
1445  return;
1446 
1447  std::span<Trk::Layer const* const> layerObjects =
1448  confinedLayers->arrayObjects();
1450  layerObjects.begin();
1452  layerObjects.end();
1453 
1454  // now pick out the material layers (and skip the navigation ones)
1455  std::vector<const Trk::Layer*> materialLayers;
1456  for (; layerObjIter != layerObjEnd; ++layerObjIter)
1457  if ((*layerObjIter)->layerMaterialProperties())
1458  materialLayers.push_back((*layerObjIter));
1459 
1460  unsigned int matLaySize = materialLayers.size();
1461  unsigned int ccidSize = ccid.size();
1462 
1463  ATH_MSG_VERBOSE("[+] Found " << matLaySize << " material layers ( "
1464  << ccidSize << " CaloSample ids )");
1465  if (matLaySize != ccidSize)
1466  return;
1467 
1468  // everything's fine for side > 0
1469  if (side > 0) {
1470  // match 1-to-1
1471  std::vector<const Trk::Layer*>::const_iterator layerIt = materialLayers.begin();
1472  std::vector<const Trk::Layer*>::const_iterator layerItEnd = materialLayers.end();
1473  std::vector<CaloCell_ID::CaloSample>::const_iterator ccidIt = ccid.begin();
1474  std::vector<CaloCell_ID::CaloSample>::const_iterator ccidItEnd = ccid.end();
1475 
1476  for (; layerIt != layerItEnd && ccidIt != ccidItEnd; ++layerIt, ++ccidIt)
1477  licsMap.insert(std::make_pair((*layerIt)->layerIndex(), int(*ccidIt)));
1478 
1479  } else {
1480  // the order needs to be reversed, because TG has z-ordering positive
1481  // defined
1482 
1483  std::vector<CaloCell_ID::CaloSample>::const_iterator ccidIt = ccid.begin();
1484  std::vector<CaloCell_ID::CaloSample>::const_iterator ccidItEnd = ccid.end();
1485 
1486  for (; ccidIt != ccidItEnd; ++ccidIt, --matLaySize)
1487  licsMap.insert(std::make_pair(
1488  (materialLayers[matLaySize - 1])->layerIndex(), int(*ccidIt)));
1489  }
1490 }
1491 
1492 std::pair<Trk::TrackingVolume*, Trk::TrackingVolume*>
1494  const RZPairVector& bpCutouts, float zmin, float zmax,
1495  const std::string& name, float& outerRadius) const {
1496  outerRadius = 0.;
1497 
1498  // beam pipe thickness along the z distance
1499  if (bpCutouts.empty()) {
1500  return std::pair<Trk::TrackingVolume*, Trk::TrackingVolume*>(0, 0);
1501  }
1502 
1503  RZPairVector dim;
1504  dim.emplace_back(bpCutouts[0].first, zmin);
1505  float rOut = bpCutouts[0].first;
1506  for (const auto& bpCutout : bpCutouts) {
1507  if (bpCutout.second <= dim[0].second)
1508  dim[0].first = bpCutout.first;
1509  else if (bpCutout.second <= zmax)
1510  dim.push_back(bpCutout);
1511  if (bpCutout.second <= zmax)
1512  rOut = bpCutout.first;
1513  }
1514 
1515  if (dim.back().second < zmax)
1516  dim.emplace_back(rOut, zmax);
1517 
1518  if (dim.size() == 2) { // simple case
1519 
1520  outerRadius = dim[0].first;
1521 
1522  auto bpBounds =
1523  std::make_shared<Trk::CylinderVolumeBounds>(0., outerRadius, 0.5 * (zmax - zmin));
1524 
1525  auto bpPos = std::make_unique<Amg::Transform3D>(
1526  Amg::Translation3D(Amg::Vector3D(0., 0., 0.5 * (zmin + zmax))));
1527 
1528  Trk::TrackingVolume* bpVolPos =
1529  new Trk::TrackingVolume(std::move(bpPos),
1530  std::make_shared<Trk::CylinderVolumeBounds>(*bpBounds),
1531  m_caloMaterial, nullptr,
1532  nullptr, "BeamPipe::Positive" + name);
1533 
1534  auto bpNeg = std::make_unique<Amg::Transform3D>(
1535  Amg::Translation3D(Amg::Vector3D(0., 0., -0.5 * (zmin + zmax))));
1536 
1537  Trk::TrackingVolume* bpVolNeg = new Trk::TrackingVolume(
1538  std::move(bpNeg),
1539  std::move(bpBounds),
1540  m_caloMaterial, nullptr, nullptr,
1541  "BeamPipe::Negative" + name);
1542 
1543  // geometry signature
1544  bpVolPos->sign(Trk::BeamPipe);
1545  bpVolNeg->sign(Trk::BeamPipe);
1546 
1547  return std::pair<Trk::TrackingVolume*, Trk::TrackingVolume*>(bpVolPos,
1548  bpVolNeg);
1549  }
1550 
1551  // cutout included
1552 
1553  outerRadius = dim[0].first;
1554 
1555  // find rMax
1556  for (unsigned int i = 1; i < dim.size(); i++)
1557  if (dim[i].first > outerRadius)
1558  outerRadius = dim[i].first;
1559 
1560  // loop over z sections, prepare volumes for gluing
1561  std::vector<Trk::TrackingVolume*> posVols;
1562 
1563  for (unsigned int i = 0; i < dim.size() - 1; i++) {
1564 
1565  if (dim[i].second == dim[i + 1].second)
1566  continue;
1567 
1568  // beam pipe volume
1569  auto bpBounds = std::make_shared<Trk::CylinderVolumeBounds>(
1570  0., dim[i].first, 0.5 * (dim[i + 1].second - dim[i].second));
1571 
1572  auto bpPos = std::make_unique<Amg::Transform3D>(Amg::Translation3D(
1573  Amg::Vector3D(0., 0., 0.5 * (dim[i + 1].second + dim[i].second))));
1574 
1575  auto bpPB = std::make_unique<Amg::Transform3D>(*bpPos);
1576 
1577  Trk::TrackingVolume* bpVolPos =
1578  new Trk::TrackingVolume(std::move(bpPos),std::move(bpBounds), m_caloMaterial, nullptr,
1579  nullptr, "BeamPipe::Positive" + name);
1580  bpVolPos->sign(Trk::BeamPipe);
1581 
1582  Trk::TrackingVolume* bpVolGap = nullptr;
1583  if (dim[i].first < outerRadius) {
1584  auto bpGB = std::make_shared<Trk::CylinderVolumeBounds>(
1585  dim[i].first, outerRadius, 0.5 * (dim[i + 1].second - dim[i].second));
1586 
1587  bpVolGap = new Trk::TrackingVolume(std::move(bpPB), std::move(bpGB), m_caloMaterial,
1588  nullptr, nullptr,
1589  "Calo::GapVolumes::Positive" + name);
1590  }
1591 
1592  Trk::TrackingVolume* bpSector = bpVolPos;
1593 
1594  if (bpVolGap) {
1595  std::vector<Trk::TrackingVolume*> gapVols;
1596  gapVols.push_back(bpVolPos);
1597  gapVols.push_back(bpVolGap);
1598  bpSector = m_trackingVolumeCreator->createContainerTrackingVolume(
1599  gapVols, m_caloMaterial, "Calo::Container::PositiveBPSector" + name);
1600  }
1601  posVols.push_back(bpSector);
1602  }
1603 
1604  Trk::TrackingVolume* bpPosSector =
1605  m_trackingVolumeCreator->createContainerTrackingVolume(
1606  posVols, m_caloMaterial, "Calo::Container::PositiveBP" + name);
1607 
1608  // loop over z sections, prepare volumes for gluing
1609  std::vector<Trk::TrackingVolume*> negVols;
1610 
1611  for (unsigned int i = 0; i < dim.size() - 1; i++) {
1612 
1613  float zmax2 = -1. * (dim[i].second);
1614  float zmin2 = -1. * (dim[i + 1].second);
1615 
1616  if (zmin2 == zmax2)
1617  continue;
1618 
1619  // beam pipe volume
1620  auto bpBounds = std::make_shared<Trk::CylinderVolumeBounds>(0., dim[i].first, 0.5 * (zmax2 - zmin2));
1621 
1622  auto bpNeg = std::make_unique<Amg::Transform3D>(
1623  Amg::Translation3D(Amg::Vector3D(0., 0., 0.5 * (zmin2 + zmax2))));
1624 
1625  Trk::TrackingVolume* bpVolNeg =
1626  new Trk::TrackingVolume(std::make_unique<Amg::Transform3D>(*bpNeg),
1627  std::move(bpBounds), m_caloMaterial, nullptr,
1628  nullptr, "BeamPipe::Negative" + name);
1629  bpVolNeg->sign(Trk::BeamPipe);
1630 
1631  Trk::TrackingVolume* bpVolGap =
1632  dim[i].first < outerRadius
1633  ? new Trk::TrackingVolume(
1634  std::move(bpNeg),
1635  std::make_shared<Trk::CylinderVolumeBounds>(dim[i].first, outerRadius,
1636  0.5 * (zmax2 - zmin2)),
1637  m_caloMaterial, nullptr, nullptr,
1638  "Calo::GapVolumes::Negative" + name)
1639  : nullptr;
1640 
1641  Trk::TrackingVolume* bpSector = bpVolNeg;
1642 
1643  if (bpVolGap) {
1644  std::vector<Trk::TrackingVolume*> gapVols;
1645  gapVols.push_back(bpVolNeg);
1646  gapVols.push_back(bpVolGap);
1647  bpSector = m_trackingVolumeCreator->createContainerTrackingVolume(
1648  gapVols, m_caloMaterial, "Calo::Container::NegativeBPSector" + name);
1649  }
1650 
1651  if (negVols.empty())
1652  negVols.push_back(bpSector);
1653  else
1654  negVols.insert(negVols.begin(), bpSector);
1655  }
1656 
1657  Trk::TrackingVolume* bpNegSector =
1658  m_trackingVolumeCreator->createContainerTrackingVolume(
1659  negVols, m_caloMaterial, "Calo::Container::NegativeBP" + name);
1660 
1661  return std::pair<Trk::TrackingVolume*, Trk::TrackingVolume*>(bpPosSector,
1662  bpNegSector);
1663 }
1664 
BinnedMaterial.h
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
TrapezoidBounds.h
GeoAlignmentStore
Ensure that the extensions for the Vector3D are properly loaded.
Definition: GeoAlignmentStore.h:24
yodamerge_tmp.dim
dim
Definition: yodamerge_tmp.py:239
python.SystemOfUnits.mm
float mm
Definition: SystemOfUnits.py:98
DiscBounds.h
PowhegControl_ttHplus_NLO.ss
ss
Definition: PowhegControl_ttHplus_NLO.py:83
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
MaterialProperties.h
RZPairVector
std::vector< RZPair > RZPairVector
Definition: RZPair.h:18
Trk::binZ
@ binZ
Definition: BinningType.h:49
PixelAthClusterMonAlgCfg.zmin
zmin
Definition: PixelAthClusterMonAlgCfg.py:169
Calo::CaloTrackingGeometryBuilderImpl::initialize
virtual StatusCode initialize() override
AlgTool initailize method.
Definition: CaloTrackingGeometryBuilderImpl.cxx:46
BinnedArray.h
Calo::CaloTrackingGeometryBuilderImpl::createTrackingGeometry
std::unique_ptr< Trk::TrackingGeometry > createTrackingGeometry(Trk::TrackingVolume *innerVol, const CaloDetDescrManager *caloDDM, const GeoAlignmentStore *geoAlign) const
TrackingGeometry Interface method.
Definition: CaloTrackingGeometryBuilderImpl.cxx:75
Trk::BinnedMaterial
Definition: BinnedMaterial.h:31
BinUtility.h
python.SystemOfUnits.second
float second
Definition: SystemOfUnits.py:135
DiscLayer.h
VolumeBounds.h
HomogeneousLayerMaterial.h
BinnedArray1D1D.h
Calo::CaloTrackingGeometryBuilderImpl::registerInLayerIndexCaloSampleMap
void registerInLayerIndexCaloSampleMap(Trk::LayerIndexSampleMap &licsMAp, const std::vector< CaloCell_ID::CaloSample > &ccid, const Trk::TrackingVolume &vol, int side=1) const
method to establish a link between the LayerIndex and the CaloCell_ID in an associative container
Definition: CaloTrackingGeometryBuilderImpl.cxx:1434
Trk::binEta
@ binEta
Definition: BinningType.h:54
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
CaloTrackingGeometryBuilderImpl.h
Trk::Calo
@ Calo
Definition: GeometrySignature.h:28
CaloCell_ID_FCS::TileGap3
@ TileGap3
Definition: FastCaloSim_CaloCell_ID.h:36
ILayerArrayCreator.h
Trk::BeamPipe
@ BeamPipe
Definition: GeometrySignature.h:27
Trk::LayerIndexSampleMap
std::map< Trk::LayerIndex, int > LayerIndexSampleMap
Definition: LayerIndexSampleMap.h:29
TRT::Hit::side
@ side
Definition: HitInfo.h:83
Trk::MS
@ MS
Definition: GeometrySignature.h:29
Trk::TrackingVolume::confinedLayers
const LayerArray * confinedLayers() const
Return the subLayer array.
Calo::CaloTrackingGeometryBuilderImpl::~CaloTrackingGeometryBuilderImpl
virtual ~CaloTrackingGeometryBuilderImpl()
Destructor.
GeometryStatics.h
CylinderVolumeBounds.h
Trk::GeometrySignature
GeometrySignature
Definition: GeometrySignature.h:24
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:209
beamspotman.steps
int steps
Definition: beamspotman.py:503
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
Calo::CaloTrackingGeometryBuilderImpl::createBeamPipeVolumes
std::pair< Trk::TrackingVolume *, Trk::TrackingVolume * > createBeamPipeVolumes(const RZPairVector &bpCutouts, float, float, const std::string &, float &) const
method to build enclosed beam pipe volumes
Definition: CaloTrackingGeometryBuilderImpl.cxx:1493
lumiFormat.i
int i
Definition: lumiFormat.py:85
z
#define z
beamspotman.n
n
Definition: beamspotman.py:729
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
Trk::CylinderVolumeBounds::halflengthZ
double halflengthZ() const
This method returns the halflengthZ.
Definition: CylinderVolumeBounds.h:207
PixelAthClusterMonAlgCfg.zmax
zmax
Definition: PixelAthClusterMonAlgCfg.py:169
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
Trk::Volume::center
const Amg::Vector3D & center() const
returns the center of the volume
Definition: Volume.h:90
Trk::DiscLayer
Definition: DiscLayer.h:45
Trk::BinnedArray::arrayObjects
virtual std::span< T *const > arrayObjects()=0
Return all objects of the Array non-const we can still modify the T.
Trk::BinUtility
Definition: BinUtility.h:39
Trk::CylinderVolumeBounds
Definition: CylinderVolumeBounds.h:70
IOVInfiniteRange.h
Trk::TrackingVolume::volumeName
const std::string & volumeName() const
Returns the VolumeName - for debug reason, might be depreciated later.
GlueVolumesDescriptor.h
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
Trk::CylinderVolumeBounds::outerRadius
double outerRadius() const
This method returns the outer radius.
Definition: CylinderVolumeBounds.h:191
Trk::Volume::transform
const Amg::Transform3D & transform() const
Return methods for geometry transform.
Definition: Volume.h:83
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
SCT_CalibAlgs::nbins
@ nbins
Definition: SCT_CalibNumbers.h:10
CaloDetDescrManager_Base::is_in
bool is_in(double eta, double phi, CaloCell_ID::CaloSample sample, double &etadist) const
return true if direction eta,phi crosses ANY of the corresponding descriptors
Definition: CaloDetDescrManager.cxx:1348
Trk::open
@ open
Definition: BinningType.h:40
IDynamicLayerCreator.h
Trk::MaterialProperties
Definition: MaterialProperties.h:40
TrackingVolume.h
CaloDetDescrManager
This class provides the client interface for accessing the detector description information common to...
Definition: CaloDetDescrManager.h:473
python.Constants.INFO
int INFO
Definition: Control/AthenaCommon/python/Constants.py:15
Trk::CylinderVolumeBounds::innerRadius
double innerRadius() const
This method returns the inner radius.
Definition: CylinderVolumeBounds.h:187
Calo::CaloTrackingGeometryBuilderImpl::CaloTrackingGeometryBuilderImpl
CaloTrackingGeometryBuilderImpl(const std::string &, const std::string &, const IInterface *)
Constructor.
Definition: CaloTrackingGeometryBuilderImpl.cxx:36
Trk::TrackingVolume::sign
void sign(GeometrySignature signat, GeometryType gtype=Static)
sign the volume - the geometry builder has to do that
Definition: TrackingVolume.cxx:766
DeMoScan.first
bool first
Definition: DeMoScan.py:534
Amg::Translation3D
Eigen::Translation< double, 3 > Translation3D
Definition: GeoPrimitives.h:44
Trk::Volume::volumeBounds
const VolumeBounds & volumeBounds() const
returns the volumeBounds()
Definition: Volume.h:96
DiscSurface.h
TrackingGeometry.h
Trk::Material
Definition: Material.h:117
python.Constants.VERBOSE
int VERBOSE
Definition: Control/AthenaCommon/python/Constants.py:13
Trk::BinnedArray
Definition: BinnedArray.h:36
AthAlgTool
Definition: AthAlgTool.h:26
Trk::HomogeneousLayerMaterial
Definition: HomogeneousLayerMaterial.h:53
pow
constexpr int pow(int base, int exp) noexcept
Definition: ap_fixedTest.cxx:15
Trk::TrackingVolume
Definition: TrackingVolume.h:119
Material
@ Material
Definition: MaterialTypes.h:8
AlignableTrackingVolume.h
python.AutoConfigFlags.msg
msg
Definition: AutoConfigFlags.py:7
Trk::TrackingVolume::screenDump
void screenDump(MsgStream &msg) const
Definition: TrackingVolume.cxx:1185
Trk::AlignableTrackingVolume
Definition: AlignableTrackingVolume.h:36