ATLAS Offline Software
Loading...
Searching...
No Matches
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//
23//
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 // -------------------------------------------------
51 ATH_MSG_INFO("Retrieved tool " << m_trackingVolumeArrayCreator);
52
53 // Retrieve the second volume creator
54 if (m_buildMBTS) {
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 // -------------------------------------------------
67 ATH_MSG_INFO("Retrieved tool " << m_tileVolumeBuilder);
68
69 ATH_MSG_INFO("initialize() succesful");
70
71 return StatusCode::SUCCESS;
72}
73
74std::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)
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:"
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)) {
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 =
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,
457 1.);
458 Trk::DiscLayer* mbtsPosLayer = new Trk::DiscLayer(
459 mbtsPosZpos, std::make_shared<Trk::DiscBounds>(*dibo),
460 // mbtsPosLayerSurfArray,
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
660 std::make_unique<Amg::Transform3D>(*ecPos),
661 std::make_shared<Trk::CylinderVolumeBounds>(*ecUpBounds),
662 m_Ar, nullptr, nullptr,
663 "Calo::GapVolumes::LAr::PositiveEndcapCover");
665 std::make_unique<Amg::Transform3D>(*ecNeg),
666 std::move(ecUpBounds),
667 m_Ar, nullptr, nullptr,
668 "Calo::GapVolumes::LAr::NegativeEndcapCover");
670 std::move(ecPos), std::make_shared<Trk::CylinderVolumeBounds>(*ecDownBounds),
671 m_Al, nullptr,
672 nullptr, "Calo::GapVolumes::LAr::PositiveEndcapInner");
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 =
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 =
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));
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());
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();
1449 std::span<Trk::Layer const* const>::iterator layerObjIter =
1450 layerObjects.begin();
1451 std::span<Trk::Layer const* const>::iterator layerObjEnd =
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
1492std::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
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
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_DEBUG(x)
static Double_t ss
std::vector< RZPair > RZPairVector
Definition RZPair.h:18
#define z
constexpr int pow(int base, int exp) noexcept
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
bool msgLvl(const MSG::Level lvl) const
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
This class provides the client interface for accessing the detector description information common to...
BooleanProperty m_indexStaticLayers
forces robust indexing for layers
PublicToolHandle< Trk::ITrackingVolumeCreator > m_trackingVolumeCreator
Volume Builder for the Liquid Argon Calorimeter.
std::unique_ptr< Trk::TrackingGeometry > createTrackingGeometry(Trk::TrackingVolume *innerVol, const CaloDetDescrManager *caloDDM, const GeoAlignmentStore *geoAlign) const
TrackingGeometry Interface method.
StringProperty m_exitVolume
name of the Calo container
DoubleProperty m_caloDefaultHalflengthZ
the halflength in z if not built from
PublicToolHandle< Trk::ICaloTrackingVolumeBuilder > m_lArVolumeBuilder
Volume Builder for the Tile Calorimeter.
virtual StatusCode initialize() override
AlgTool initailize method.
std::pair< Trk::TrackingVolume *, Trk::TrackingVolume * > createBeamPipeVolumes(const RZPairVector &bpCutouts, float, float, const std::string &, float &) const
method to build enclosed beam pipe volumes
DoubleProperty m_caloDefaultRadius
the radius if not built from GeoModel
CaloTrackingGeometryBuilderImpl(const std::string &, const std::string &, const IInterface *)
Constructor.
virtual ~CaloTrackingGeometryBuilderImpl()
Destructor.
Trk::GeometrySignature signature() const
The unique signature.
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
PublicToolHandle< Trk::ITrackingVolumeArrayCreator > m_trackingVolumeArrayCreator
Second helper for volume creation.
ServiceHandle< IEnvelopeDefSvc > m_enclosingEnvelopeSvc
BooleanProperty m_buildMBTS
MBTS like detectors.
PublicToolHandle< Trk::ICaloTrackingVolumeBuilder > m_tileVolumeBuilder
Material properties.
Ensure that the extensions for the Vector3D are properly loaded.
Base Class for a navigation object (active) in the Calo realm.
A generic symmetric BinUtility, for fully symmetric binning in terms of binning grid and binning type...
Definition BinUtility.h:39
virtual std::span< T *const > arrayObjects()=0
Return all objects of the Array non-const we can still modify the T.
for description of non-homogenous dense volumes
Bounds for a cylindrical Volume, the decomposeToSurfaces method creates a vector of up to 6 surfaces:
double innerRadius() const
This method returns the inner radius.
double halflengthZ() const
This method returns the halflengthZ.
double outerRadius() const
This method returns the outer radius.
Class to describe a disc-like detector layer for tracking, it inhertis from both, Layer base class an...
Definition DiscLayer.h:45
It extends the LayerMaterialProperties base class.
Material with information about thickness of material.
A common object to be contained by.
Definition Material.h:117
Full Volume description used in Tracking, it inherits from Volume to get the geometrical structure,...
const LayerArray * confinedLayers() const
Return the subLayer array.
const std::string & volumeName() const
Returns the VolumeName - for debug reason, might be depreciated later.
void sign(GeometrySignature signat, GeometryType gtype=Static)
sign the volume - the geometry builder has to do that
void screenDump(MsgStream &msg) const
const Amg::Vector3D & center() const
returns the center of the volume
Definition Volume.h:90
const Amg::Transform3D & transform() const
Return methods for geometry transform.
Definition Volume.h:83
const VolumeBounds & volumeBounds() const
returns the volumeBounds()
Definition Volume.h:96
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
Eigen::Translation< double, 3 > Translation3D
static const Amg::Transform3D s_idTransform
idendity transformation
BinnedArray< Layer > LayerArray
simply for the eye
@ open
Definition BinningType.h:40
std::map< Trk::LayerIndex, int > LayerIndexSampleMap
@ binEta
Definition BinningType.h:54
@ binZ
Definition BinningType.h:49
MsgStream & msg
Definition testRead.cxx:32