ATLAS Offline Software
Loading...
Searching...
No Matches
CylinderVolumeCreator.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6// CylinderVolumeCreator.cxx, (c) ATLAS Detector software
8
9// Trk include
21// Amg
24
25
26// constructor
27Trk::CylinderVolumeCreator::CylinderVolumeCreator(const std::string& t, const std::string& n, const IInterface* p)
28: AthAlgTool(t,n,p)
29{
30 declareInterface<ITrackingVolumeCreator>(this);
31}
32
33
34// the interface methods
36{
37
38 // Retrieve the layer array creator ----------------------------------------------------
39 if (m_layerArrayCreator.retrieve().isFailure())
40 {
41 ATH_MSG_FATAL( "Failed to retrieve tool " << m_layerArrayCreator );
42 return StatusCode::FAILURE;
43 } else
44 ATH_MSG_DEBUG( "Retrieved tool " << m_layerArrayCreator );
45
46
47 // Retrieve the volume array creator ----------------------------------------------------
48 if (m_trackingVolumeArrayCreator.retrieve().isFailure())
49 {
50 ATH_MSG_FATAL( "Failed to retrieve tool " << m_trackingVolumeArrayCreator );
51 return StatusCode::FAILURE;
52 } else
53 ATH_MSG_DEBUG( "Retrieved tool " << m_trackingVolumeArrayCreator );
54
55
56 // Retrieve the volume array creator ----------------------------------------------------
57 if (m_trackingVolumeHelper.retrieve().isFailure())
58 {
59 ATH_MSG_FATAL( "Failed to retrieve tool " << m_trackingVolumeHelper );
60 return StatusCode::FAILURE;
61 } else
62 ATH_MSG_DEBUG( "Retrieved tool " << m_trackingVolumeHelper );
63
64 ATH_MSG_DEBUG( "initialize() successful" );
65
66 return StatusCode::SUCCESS;
67}
68
71 const std::vector<Trk::Layer*>& layers,
72 Trk::Material& matprop,
73 Trk::VolumeBounds* volBounds,
74 Amg::Transform3D* transform,
75 const std::string& volumeName,
76 Trk::BinningType btype) const
77
78{
79
80 // the final one to build / sensitive Volume / Bounds
81 Trk::TrackingVolume* tVolume = nullptr;
82
83 // cases are:
84 // (1) volBounds && transform : use both information
85 // (2) volBounds && !transform : centered around 0, but with given bounds
86 // (3) !volBounds && transform : estimate size from layers, use transform
87 // (4) !volBounds && !transform : estimate size & translation from layers
88 Trk::CylinderVolumeBounds* cylinderBounds = nullptr;
89 // this is the implementation of CylinderVolumeCreator
90 if (volBounds) {
91 cylinderBounds = dynamic_cast<Trk::CylinderVolumeBounds*>(volBounds);
92 if (!cylinderBounds){
93 ATH_MSG_WARNING( "[!] Problem: given bounds were not cylindrical - return 0" );
94 return tVolume;
95 }
96 }
97 std::vector<Trk::CylinderLayer*> cylLayers;
98 cylLayers.reserve(layers.size());
99 std::vector<Trk::DiscLayer*> discLayers;
100 discLayers.reserve(layers.size());
101
102 // the raw data
103 double rMinRaw{0.};
104 double rMaxRaw{0.};
105 double zMinRaw{0.};
106 double zMaxRaw{0.};
107
108 // check the dimension and fill raw data
109 if (estimateAndCheckDimension(layers,
110 cylinderBounds,
111 transform,
112 cylLayers,
113 discLayers,
114 rMinRaw,rMaxRaw,
115 zMinRaw,zMaxRaw,
116 btype).isFailure()) {
117 ATH_MSG_WARNING( "[!] Problem with given dimensions - return 0 and delete provided objects" );
118 delete volBounds;
119 delete transform;
120 if (volBounds != cylinderBounds) {
121 delete cylinderBounds;
122 }
123 return tVolume;
124 }
125
126 // get the zMin/Max
127 double zMin = ( transform ? transform->translation().z() : 0. ) +
128 ( cylinderBounds ? -cylinderBounds->halflengthZ() : 0. );
129 double zMax = ( transform ? transform->translation().z() : 0. ) +
130 ( cylinderBounds ? cylinderBounds->halflengthZ() : 0. );
131
132 double rMin = 0.;
133 double rMax = 0.;
134
135 // overrule the zMin/zMax for biequidistant binning
136 if (btype == Trk::biequidistant) {
137 // set rMin/rMax and zMin/zMax
138 zMin = zMinRaw;
139 zMax = zMaxRaw;
140 rMin = rMinRaw;
141 rMax = rMaxRaw;
142 } else {
143 if (!cylinderBounds) {
144 ATH_MSG_WARNING( "[!] No cylindrical bounds given - return 0" );
145 return tVolume;
146 }
147 rMin = cylinderBounds->innerRadius();
148 rMax = cylinderBounds->outerRadius();
149 }
150
151 ATH_MSG_VERBOSE("Filling the layers into an appropriate layer array");
152 // create the Layer Array
153 std::unique_ptr<Trk::BinnedArray1D<Trk::Layer>> layerArray =
154 !cylLayers.empty() ? m_layerArrayCreator->cylinderLayerArray(
155 cylLayers, rMin, rMax, btype)
156 : m_layerArrayCreator->discLayerArray(
157 discLayers, zMin, zMax, btype);
158
159 // finally create the TrackingVolume
160 tVolume = new Trk::TrackingVolume(std::unique_ptr<Amg::Transform3D>(transform),
161 std::shared_ptr<Trk::CylinderVolumeBounds>(cylinderBounds),
162 matprop,
163 std::move(layerArray),
164 nullptr,
165 volumeName);
166 // screen output
167 ATH_MSG_VERBOSE( "Created cylindrical volume at z-position :" << tVolume->center().z() );
168 ATH_MSG_VERBOSE( " created bounds : " << tVolume->volumeBounds() );
169
170 // return the constructed TrackingVolume
171 return tVolume;
172}
173
176 const std::vector<Trk::Layer*>& layers,
177 Trk::Material& matprop,
178 double rMin,
179 double rMax,
180 double zMin,
181 double zMax,
182 const std::string& volumeName,
183 Trk::BinningType btype) const
184
185{
186 // that's what is needed
187 Trk::CylinderVolumeBounds* cBounds = nullptr;
188
189 // screen output
190 ATH_MSG_VERBOSE("Create cylindrical TrackingVolume '" << volumeName << "'.");
191 ATH_MSG_VERBOSE(" -> with given dimensions of (rMin/rMax/zMin/Max) = "
192 << rMin << " / " << rMax << " / " << zMin << " / " << zMax);
193
194 // check for consistency
195 if (zMin > zMax || rMin > rMax) {
196 ATH_MSG_WARNING("Inconsistent dimensions given :"
197 << ((zMin > zMax) ? " zMin > zMax (" : " rMin > rMax (")
198 << ((zMin > zMax) ? zMin : rMin) << " > "
199 << ((zMin > zMax) ? zMax : rMax) << " ) - return 0");
200 return nullptr;
201 }
202
203 // create a Amg::Transform3D and VolumeBounds out of the zMin/zMax
204 double halflengthZ = 0.5 * (zMax - zMin);
205 double zPosition = 0.5 * (zMin + zMax);
206 zPosition = fabs(zPosition) < 0.1 ? 0. : zPosition;
207
208 // now create the cylinder volume bounds
209 cBounds = rMin > 0.1 ? new Trk::CylinderVolumeBounds(rMin, rMax, halflengthZ)
210 : new Trk::CylinderVolumeBounds(rMax, halflengthZ);
211 // transform
212 Amg::Transform3D* transform =
213 (zPosition != 0) ? new Amg::Transform3D : nullptr;
214 if (transform)
215 (*transform) = Amg::Translation3D(0., 0., zPosition);
216
217 // call to the Bounds/Amg::Translation3D method
219 layers, matprop, cBounds, transform, volumeName, btype);
220}
221
224 double rMin,
225 double rMax,
226 double zMin,
227 double zMax,
228 unsigned int materialLayers,
229 bool cylinder,
230 const std::string& volumeName) const
231{
232
233 // screen output
234 ATH_MSG_VERBOSE( "Create cylindrical gap TrackingVolume '" << volumeName << "' with (rMin/rMax/zMin/Max) = ");
235 ATH_MSG_VERBOSE( '\t' << rMin << " / " << rMax << " / " << zMin << " / " << zMax );
236
237 // assing min/max
238 double min = cylinder ? rMin : zMin;
239 double max = cylinder ? rMax : zMax;
240
241 // create the layer r/z positions
242 std::vector<double> layerPositions;
243 layerPositions.reserve(materialLayers);
244 if (materialLayers > 1){
245 //double step = cylinder ? (max-min)/(materialLayers-1) : (max-min)/(materialLayers-1);
246 const double step=(max-min)/(materialLayers-1);
247 for (unsigned int il = 0; il < materialLayers; ++il)
248 layerPositions.push_back(min+il*step);
249 } else
250 layerPositions.push_back(0.5*(min+max));
251
252 // now call the main method
253 return createGapTrackingVolume(matprop,
254 rMin,
255 rMax,
256 zMin,
257 zMax,
258 layerPositions,
259 cylinder,
260 volumeName,
261 (layerPositions.size() == 1 ? Trk::arbitrary : Trk::biequidistant));
262
263}
264
267 Trk::Material& matprop,
268 double rMin,
269 double rMax,
270 double zMin,
271 double zMax,
272 const std::vector<double>& layerPositions,
273 bool cylinder,
274 const std::string& volumeName,
275 BinningType btype) const
276{
277
278 // screen output
279 ATH_MSG_VERBOSE("Create cylindrical gap TrackingVolume '"
280 << volumeName << "' with (rMin/rMax/zMin/Max) = ");
281 ATH_MSG_VERBOSE('\t' << rMin << " / " << rMax << " / " << zMin << " / "
282 << zMax);
283
284 // create the layers
285 std::vector<Trk::Layer*> layers;
286 layers.reserve(layerPositions.size());
287
288 std::vector<double>::const_iterator layerPropIter = layerPositions.begin();
289 std::vector<double>::const_iterator layerPropEnd = layerPositions.end();
290 for (; layerPropIter != layerPropEnd; ++layerPropIter) {
291 // create cylinder layers
292 if (cylinder) {
293 // take envelopes into account
294 double zMinLayer = zMin;
295 double zMaxLayer = zMax;
296 // create the layer
297 layers.push_back(createCylinderLayer(0.5 * (zMinLayer + zMaxLayer),
298 (*layerPropIter),
299 fabs(0.5 * (zMaxLayer - zMinLayer)),
303
304 } else {
305 // take the envelopes into account
306 double rMinLayer = rMin;
307 double rMaxLayer = rMax;
308 // create the layer
309 layers.push_back(createDiscLayer((*layerPropIter),
310 rMinLayer,
311 rMaxLayer,
315 }
316 }
317 // now call the createTrackingVolume() method
319 layers, matprop, rMin, rMax, zMin, zMax, volumeName, btype);
320}
321
324 const std::vector<Trk::TrackingVolume*>& volumes,
325 const Trk::Material& matprop,
326 const std::string& volumeName,
327 bool buildBoundaryLayers,
328 bool replaceBoundaryFace) const
329{
330 // check if you have more than one volume
331 if (volumes.size() <= (unsigned int)1) {
332 ATH_MSG_WARNING("None (only one) TrackingVolume given to create container "
333 "volume (min required: 2) - returning 0 ");
334 return nullptr;
335 }
336
337 // screen output
338 ATH_MSG_VERBOSE("[start] Creating container volume '"
339 << volumeName << "' with " << volumes.size()
340 << " sub volumes:");
341 // volumes need to be sorted in either r or z - both increasing
342 // set the iterator to the volumes, the first and the end
343 auto firstVolume = volumes.begin();
344 auto lastVolume = volumes.end();
345
346 for (unsigned int ivol = 0; firstVolume != lastVolume;
347 ++firstVolume, ++ivol) {
348 ATH_MSG_VERBOSE(" - volume ("
349 << ivol << ") is : " << (*firstVolume)->volumeName());
351 " at position : " << Amg::toString((*firstVolume)->center()));
352 ATH_MSG_VERBOSE(" with bounds : " << (*firstVolume)->volumeBounds());
353 }
354
355 // reset the iterator
356 firstVolume = volumes.begin();
357 --lastVolume; // set to the last volume
358
359 if (firstVolume == lastVolume) {
360 ATH_MSG_WARNING("Only one TrackingVolume given to create Top level volume "
361 "(min required: 2) - returning 0 ");
362 return nullptr;
363 }
364
365 // get the bounds
366 const Trk::CylinderVolumeBounds* firstVolumeBounds =
367 dynamic_cast<const Trk::CylinderVolumeBounds*>(
368 &((*firstVolume)->volumeBounds()));
369 const Trk::CylinderVolumeBounds* lastVolumeBounds =
370 dynamic_cast<const Trk::CylinderVolumeBounds*>(
371 &((*lastVolume)->volumeBounds()));
372 // check the dynamic cast
373 if (!firstVolumeBounds || !lastVolumeBounds) {
374 ATH_MSG_WARNING("VolumeBounds given are not of type: "
375 "Trk::CylinderVolumeBounds (required) - returning 0 ");
376 return nullptr;
377 }
378
379 // check whether it is a r-binned case or a z-binned case
380 bool rCase = fabs(firstVolumeBounds->innerRadius() -
381 lastVolumeBounds->innerRadius()) > 0.1;
382 // fill these ones depending on the rCase though assignment - no parsing at
383 // that stage
384 double zMin = 0.;
385 double zMax = 0.;
386 double rMin = 0.;
387 double rMax = 0.;
388 if (rCase) {
389 zMin = (*firstVolume)->center().z() - firstVolumeBounds->halflengthZ();
390 zMax = (*firstVolume)->center().z() + firstVolumeBounds->halflengthZ();
391 rMin = firstVolumeBounds->innerRadius();
392 rMax = lastVolumeBounds->outerRadius();
393 } else {
394 zMin = (*firstVolume)->center().z() - firstVolumeBounds->halflengthZ();
395 zMax = (*lastVolume)->center().z() + lastVolumeBounds->halflengthZ();
396 rMin = firstVolumeBounds->innerRadius();
397 rMax = firstVolumeBounds->outerRadius();
398 }
399
400 // estimate the z - position
401 double zPos = 0.5 * (zMin + zMax);
402 // create the HEP transform from the stuff known so far
403 std::unique_ptr<Amg::Transform3D> topVolumeTransform =
404 fabs(zPos) > 0.1 ? std::make_unique<Amg::Transform3D>(Amg::Translation3D(0., 0., zPos)) : nullptr;
405 // create the bounds from the information gathered so far
406 auto topVolumeBounds =
407 fabs(rMin) > 0.1
408 ? std::make_shared<Trk::CylinderVolumeBounds>(rMin, rMax, 0.5 * fabs(zMax - zMin))
409 : std::make_shared<Trk::CylinderVolumeBounds>(rMax, 0.5 * fabs(zMax - zMin));
410 // create the volume array to fill in
411 std::unique_ptr<Trk::BinnedArray<Trk::TrackingVolume>> volumeArray =
412 (rCase) ? m_trackingVolumeArrayCreator->cylinderVolumesArrayInR(volumes)
413 : m_trackingVolumeArrayCreator->cylinderVolumesArrayInZ(volumes);
414 if (!volumeArray) {
416 "Creation of TrackingVolume array did not succeed - returning 0 ");
417 return nullptr;
418 }
419
420 // we have the bounds and the volume array, create the volume
422 std::move(topVolumeTransform),
423 std::move(topVolumeBounds),
424 matprop,
425 nullptr,
426 std::move(volumeArray),
427 volumeName);
428
429 // glueing section
430 // --------------------------------------------------------------------------------------
432 *topVolume, rCase, buildBoundaryLayers, replaceBoundaryFace)
433 .isFailure()) {
435 "Problem with inter-glueing of TrackingVolumes (needed) - returning 0 ");
436 delete topVolume;
437 return nullptr;
438 }
439
441 "[ end ] return newly created container : " << topVolume->volumeName());
442
443 return topVolume;
444}
445
447StatusCode
449 const std::vector<Trk::Layer*>& layers,
450 Trk::CylinderVolumeBounds*& cylinderVolumeBounds,
451 Amg::Transform3D*& transform,
452 std::vector<Trk::CylinderLayer*>& cylinderLayers,
453 std::vector<Trk::DiscLayer*>& discLayers,
454 double& rMinClean,
455 double& rMaxClean,
456 double& zMinClean,
457 double& zMaxClean,
458 Trk::BinningType bType) const
459
460{
461 // check and bail out if no layers are given
462 if (layers.empty()) {
463 ATH_MSG_VERBOSE( "No layers given, you shouldn't use : "<< type() );
464 return StatusCode::FAILURE;
465 }
466
467 // some verbose output
468 ATH_MSG_VERBOSE( "Parsing the " << layers.size() << " layers to gather overall dimensions" );
469 if (cylinderVolumeBounds) ATH_MSG_VERBOSE( "Cylinder volume bounds are given." );
470
471 // prepare for parsing the layers
472 double layerRmin = 10e10;
473 double layerRmax = 0.;
474 double layerZmin = 10e10;
475 double layerZmax = -10e10;
476 bool radial = false;
477
478 rMinClean = 10e10;
479 rMaxClean = 0.;
480 zMinClean = 10e10;
481 zMaxClean = -10e10;
482
483 // find out what is there
484 for (auto *const layerIter : layers) {
485 //class is not thread safe due to this
486 // initialize
487 double currentRmin = 0.;
488 double currentRmax = 0.;
489 double currentZmin = 0.;
490 double currentZmax = 0.;
491 // dynamic cast the bounds either to CylinderBounds or DiscBounds
492 const Trk::CylinderBounds* cylBounds =
493 dynamic_cast<const Trk::CylinderBounds*>(&(layerIter->surfaceRepresentation()).bounds());
494 // cylinder bounds
495 if (cylBounds) {
496 radial = true;
497 // fill it into the cylinderLayer vector
498 cylinderLayers.push_back(dynamic_cast<Trk::CylinderLayer*>(layerIter));
499 // get the raw data
500 double currentR = cylBounds->r();
501 double centerZ = (layerIter->surfaceRepresentation()).center().z();
502 // check for min/max in the cylinder bounds case
503 if (bType == Trk::biequidistant){
504 currentRmin = currentR; currentRmax = currentR;
505 } else {
506 currentRmin = currentR-(0.5*(layerIter)->thickness());
507 currentRmax = currentR+(0.5*(layerIter)->thickness());
508 }
509 currentZmin = centerZ - cylBounds->halflengthZ();
510 currentZmax = centerZ + cylBounds->halflengthZ();
511 }
512 // dynamic cast to the DiscBounds
513 const Trk::DiscBounds* discBounds =
514 dynamic_cast<const Trk::DiscBounds*>(&(layerIter->surfaceRepresentation()).bounds());
515 if (discBounds) {
516 // fill it into the discLayer vector
517 discLayers.push_back(dynamic_cast<Trk::DiscLayer*>(layerIter));
518 // check for min/max in the cylinder bounds case
519 double centerZ = (layerIter->surfaceRepresentation()).center().z();
520 currentRmin = discBounds->rMin();
521 currentRmax = discBounds->rMax();
522 if (bType == Trk::biequidistant){
523 currentZmin = centerZ; currentZmax = centerZ;
524 } else {
525 currentZmin = centerZ - (0.5*(layerIter)->thickness());
526 currentZmax = centerZ + (0.5*(layerIter)->thickness());
527 }
528 }
529 // the raw data
530 rMinClean = std::min(rMinClean, currentRmin);
531 rMaxClean = std::max(rMaxClean, currentRmax);
532 zMinClean = std::min(zMinClean, currentZmin);
533 zMaxClean = std::max(zMaxClean, currentZmax);
534 // assign if they overrule the minima/maxima (with layers thicknesses)
535
536 layerRmin = std::min(layerRmin,currentRmin);
537 layerRmax = std::max(layerRmax, currentRmax);
538 layerZmin = std::min(layerZmin,currentZmin);
539 layerZmax = std::max(layerZmax, currentZmax);
540 }
541
542 // special for biequidistant binning - navigation layers are added before / after
543 if (bType == Trk::biequidistant){
544 if (radial){
545 double rStepHalf = 0.5*(layerRmax-layerRmin)/(layers.size()-1);
546 layerRmin -= rStepHalf;
547 layerRmax += rStepHalf;
548 } else {
549 double zStepHalf = 0.5*(layerZmax-layerZmin)/(layers.size()-1);
550 layerZmin -= zStepHalf;
551 layerZmax += zStepHalf;
552 }
553 }
554
555 ATH_MSG_VERBOSE( "Estimate/check CylinderVolumeBounds from/w.r.t. enclosed layers + envelope covers" );
556 // the z from the layers w and w/o envelopes
557 double zEstFromLayerEnv = 0.5*((layerZmax)+(layerZmin));
558 double halflengthFromLayer = 0.5*fabs((layerZmax)-(layerZmin));
559
560 bool concentric = (zEstFromLayerEnv*zEstFromLayerEnv < 0.001);
561
562 // no CylinderBounds and Translation given - make it
563 if (!cylinderVolumeBounds && !transform) {
564 // create the CylinderBounds from parsed layer inputs
565 cylinderVolumeBounds = new Trk::CylinderVolumeBounds(layerRmin,layerRmax,halflengthFromLayer);
566 // and the transform
567 transform = concentric ? new Amg::Transform3D : nullptr;
568 if (transform)
569 (*transform) = Amg::Translation3D(0.,0.,zEstFromLayerEnv);
570 } else if (cylinderVolumeBounds && !transform &&!concentric){
571 transform = new Amg::Transform3D;
572 (*transform) = Amg::Translation3D(0.,0.,zEstFromLayerEnv);
573 }
574 else if (transform && !cylinderVolumeBounds) {
575 // create the CylinderBounds from parsed layer inputs
576 double halflengthFromLayer = 0.5*fabs((layerZmax)-(layerZmin));
577 cylinderVolumeBounds = new Trk::CylinderVolumeBounds(layerRmin,
578 layerRmax,
579 halflengthFromLayer);
580 }
581
582 ATH_MSG_VERBOSE( " -> dimensions from layers (rMin/rMax/zMin/zMax) = "
583 << layerRmin << " / " << layerRmax << " / " << layerZmin << " / " << layerZmax );
584 double zFromTransform = transform ? transform->translation().z() : 0.;
585 ATH_MSG_VERBOSE( " -> while created bounds are (rMin/rMax/zMin/zMax) = "
586 << cylinderVolumeBounds->innerRadius() << " / " << cylinderVolumeBounds->outerRadius() << " / "
587 << zFromTransform-cylinderVolumeBounds->halflengthZ() << " / " << zFromTransform+cylinderVolumeBounds->halflengthZ() );
588
589
590 // both is NOW given --- check it -----------------------------
591 if (cylinderVolumeBounds) {
592 // only check
593 if (zFromTransform-cylinderVolumeBounds->halflengthZ() <= layerZmin &&
594 zFromTransform+cylinderVolumeBounds->halflengthZ() >= layerZmax &&
595 cylinderVolumeBounds->innerRadius() <= layerRmin &&
596 cylinderVolumeBounds->outerRadius() >= layerRmax)
597 return StatusCode::SUCCESS;
598 else {
599 ATH_MSG_WARNING( "Provided layers are not contained by volume ! Bailing out. " );
600 return StatusCode::FAILURE;
601 }
602 ATH_MSG_VERBOSE( "Created/Checked " << *cylinderVolumeBounds );
603 }
604
605
606 return StatusCode::SUCCESS;
607}
608
609
611 bool rBinned,
612 bool createBoundaryLayers,
613 bool replaceBoundaryFace) const
614{
615
616 ATH_MSG_VERBOSE( "Glue contained TrackingVolumes of container '" << tVolume.volumeName() << "'." );
617
618 // get the glueVolumes descriptor of the top volume to register the outside volumes
620
621 // so far we know that we can do that (private method)
622 std::span<Trk::TrackingVolume * const> volumes = tVolume.confinedVolumes()->arrayObjects();
623
624 // the needed iterators
625 auto tVolIter = volumes.begin();
626 auto tVolFirst = volumes.begin();
627 auto tVolLast = volumes.end(); --tVolLast;
628 auto tVolEnd = volumes.end();
629
630 // the glue volumes for the description
631 std::vector<Trk::TrackingVolume*> glueVolumesInnerTube;
632 std::vector<Trk::TrackingVolume*> glueVolumesOuterTube;
633 std::vector<Trk::TrackingVolume*> glueVolumesNegativeFace;
634 std::vector<Trk::TrackingVolume*> glueVolumesPositiveFace;
635
636 // volumes of increasing r
637 if (rBinned) {
638 // loop over the volumes -------------------------------
639 for ( ; tVolIter != tVolEnd; ) {
640 // screen output
641 ATH_MSG_VERBOSE("r-binning: Processing volume '" << (*tVolIter)->volumeName() << "'.");
642 // for the first one
643 if (tVolIter == tVolFirst)
644 addFaceVolumes((**tVolIter),Trk::tubeInnerCover,glueVolumesInnerTube);
645 // add this or the subvolumes to the negativeFace and positiveFace
646 addFaceVolumes((**tVolIter),Trk::negativeFaceXY,glueVolumesNegativeFace);
647 addFaceVolumes((**tVolIter),Trk::positiveFaceXY,glueVolumesPositiveFace);
648 if (tVolIter == tVolLast) {
649 addFaceVolumes((**tVolIter),Trk::tubeOuterCover,glueVolumesOuterTube);
650 ++tVolIter;
651 } else {
652 Trk::TrackingVolume* tVol1 = (*tVolIter);
653 Trk::TrackingVolume* tVol2 = (*(++tVolIter));
654 glueTrackingVolumes(*tVol1,Trk::tubeOuterCover, *tVol2, Trk::tubeInnerCover, createBoundaryLayers, replaceBoundaryFace);
655 }
656 }
657 } else {
658 // volumes in increasing z
659 // loop over the volumes
660 for ( ; tVolIter != tVolEnd; ) {
661 // screen output
662 ATH_MSG_VERBOSE("z-binning: Processing volume '" << (*tVolIter)->volumeName() << "'.");
663 if (tVolIter == tVolFirst)
664 addFaceVolumes((**tVolIter),Trk::negativeFaceXY,glueVolumesNegativeFace);
665 addFaceVolumes((**tVolIter),Trk::tubeInnerCover,glueVolumesInnerTube);
666 addFaceVolumes((**tVolIter),Trk::tubeOuterCover,glueVolumesOuterTube);
667 if (tVolIter == tVolLast) {
668 addFaceVolumes((**tVolIter),Trk::positiveFaceXY,glueVolumesPositiveFace);
669 ++tVolIter;
670 } else {
671 Trk::TrackingVolume* tVol1 = (*tVolIter);
672 Trk::TrackingVolume* tVol2 = (*(++tVolIter));
673 glueTrackingVolumes(*tVol1,Trk::positiveFaceXY,*tVol2,Trk::negativeFaceXY, createBoundaryLayers, replaceBoundaryFace);
674 }
675 }
676 }
677
678 // register it with the glueVolumeDescriptor
679 glueDescr.registerGlueVolumes(Trk::negativeFaceXY,glueVolumesNegativeFace);
680 glueDescr.registerGlueVolumes(Trk::positiveFaceXY,glueVolumesPositiveFace);
681 glueDescr.registerGlueVolumes(Trk::tubeInnerCover,glueVolumesInnerTube);
682 glueDescr.registerGlueVolumes(Trk::tubeOuterCover,glueVolumesOuterTube);
683
684 // return success
685 return StatusCode::SUCCESS;
686}
687
688
692 std::vector<Trk::TrackingVolume*>& vols) const
693{
694
695 ATH_MSG_VERBOSE( "Adding face volumes of face " << glueFace << " for the volume '" << tvol.volumeName() << "'." );
696 // retrieve the gluevolume descriptor
698 // if volumes are registered: take them
699 if (!gvDescriptor.glueVolumes(glueFace).empty()) {
700 // get the navigation level subvolumes
701 std::vector<Trk::TrackingVolume*>::const_iterator volIter = gvDescriptor.glueVolumes(glueFace).begin();
702 std::vector<Trk::TrackingVolume*>::const_iterator volEnd = gvDescriptor.glueVolumes(glueFace).end();
703 for ( ; volIter != volEnd; ++volIter){
704 ATH_MSG_VERBOSE( " -> adding volumes : " << (*volIter)->volumeName() );
705 vols.push_back(*volIter);
706 }
707 // screen output
708 ATH_MSG_VERBOSE( vols.size() << " navigation volumes registered as glue volumes." );
709 } else {
710 // the volume itself is on navigation level
711 ATH_MSG_VERBOSE( "Volume is on navigation level." );
712 vols.push_back(&tvol);
713 }
714}
715
716
720 Trk::TrackingVolume& tvolTwo,
722 bool createBoundaryLayers,
723 bool replaceBoundaryFace) const
724{
725
726 // get the two gluevolume descriptors
727 Trk::GlueVolumesDescriptor& gvDescriptorOne = tvolOne.glueVolumesDescriptor();
728 Trk::GlueVolumesDescriptor& gvDescriptorTwo = tvolTwo.glueVolumesDescriptor();
729
730 ATH_MSG_VERBOSE( "Glue method called with " << (replaceBoundaryFace ? "joint boundaries." : "individual boundaries." ) );
731
732 size_t volOneGlueVols = gvDescriptorOne.glueVolumes(faceOne).size();
733 ATH_MSG_VERBOSE( "GlueVolumeDescriptor of volume '" << tvolOne.volumeName() <<"' has "
734 << volOneGlueVols << " @ " << faceOne );
735 size_t volTwoGlueVols = gvDescriptorTwo.glueVolumes(faceTwo).size();
736 ATH_MSG_VERBOSE( "GlueVolumeDescriptor of volume '" << tvolTwo.volumeName() <<"' has "
737 << volTwoGlueVols << " @ " << faceTwo );
738
739 // they could still be a container though
740 TrackingVolume* glueVolOne = volOneGlueVols ?
741 gvDescriptorOne.glueVolumes(faceOne)[0] : &tvolOne;
742
743 TrackingVolume* glueVolTwo = volTwoGlueVols ?
744 gvDescriptorTwo.glueVolumes(faceTwo)[0] : &tvolTwo;
745
746 // check the cases
747 // (i) easy volume to volume
748 if ( volOneGlueVols <= 1 && volTwoGlueVols <= 1) {
749 // now glue it
750 ATH_MSG_VERBOSE( " glue : one[ "<< glueVolOne->volumeName() << " @ " << faceOne
751 << " ]-to-one[ "<< glueVolTwo->volumeName() << " @ " << faceTwo << " ]" );
752 m_trackingVolumeHelper->glueTrackingVolumes(*glueVolOne,
753 faceOne,
754 *glueVolTwo,
755 faceTwo,
756 createBoundaryLayers);
757 } else if (volOneGlueVols <= 1) { // (ii) one -> many
758 ATH_MSG_VERBOSE( " glue : one[ "<< glueVolOne->volumeName() << " @ " << faceOne
759 << " ]-to-many[ "<< tvolTwo.volumeName() << " @ " << faceTwo << " ]" );
760 m_trackingVolumeHelper->glueTrackingVolumes(*glueVolOne,
761 faceOne,
762 gvDescriptorTwo.glueVolumes(faceTwo),
763 faceTwo,
764 createBoundaryLayers,
765 replaceBoundaryFace);
766 } else if (volTwoGlueVols <= 1 ) { // (iii) many -> two
767 ATH_MSG_VERBOSE( " glue : many[ "<< tvolOne.volumeName() << " @ " << faceOne
768 << " ]-to-one[ "<< glueVolTwo->volumeName() << " @ " << faceTwo << " ]" );
769 m_trackingVolumeHelper->glueTrackingVolumes(*glueVolTwo,
770 faceTwo,
771 gvDescriptorOne.glueVolumes(faceOne),
772 faceOne,
773 createBoundaryLayers,
774 replaceBoundaryFace);
775 } else {
776 // (iv) glue array to array
777 ATH_MSG_VERBOSE( " glue : many[ "<< tvolOne.volumeName() << " @ " << faceOne
778 << " ]-to-many[ "<< tvolTwo.volumeName() << " @ " << faceTwo << " ]" );
779 m_trackingVolumeHelper->glueTrackingVolumes(gvDescriptorOne.glueVolumes(faceOne),
780 faceOne,
781 gvDescriptorTwo.glueVolumes(faceTwo),
782 faceTwo,
783 createBoundaryLayers,
784 replaceBoundaryFace);
785 } // end of case (iv)
786}
787
789 double r,
790 double halflengthZ,
791 double thickness,
792 int binsPhi,
793 int binsZ) const
794{
795 ATH_MSG_VERBOSE( "Creating a CylinderLayer at position " << z << " and radius " << r );
796 // prepare the material
797 Trk::BinnedLayerMaterial cylinderMaterial{};
798 // positioning
799 std::unique_ptr<Amg::Transform3D> transform =
800 (fabs(z) > 0.1) ? std::make_unique<Amg::Transform3D>(Amg::Translation3D(0., 0., z)) : nullptr;
801
802 // z-binning
803 Trk::BinUtility layerBinUtility(binsZ,z-halflengthZ,z+halflengthZ,Trk::open,Trk::binZ);
804 if (binsPhi==1){
805 // the BinUtility for the material
806 // ---------------------> create the layer material
807 cylinderMaterial = Trk::BinnedLayerMaterial(layerBinUtility);
808 ATH_MSG_VERBOSE( " -> Preparing the binned material with "
809 << binsZ << " bins in Z. ");
810
811 } else { // break the phi symmetry
812 // update the BinUtility: local position on Cylinder is rPhi, z
813 Trk::BinUtility layerBinUtilityRPhiZ(binsPhi,-r*M_PI,+r*M_PI,Trk::closed,Trk::binRPhi);
814 layerBinUtilityRPhiZ += layerBinUtility;
815 // ---------------------> create the layer material
816 cylinderMaterial = Trk::BinnedLayerMaterial(layerBinUtilityRPhiZ);
817
818 ATH_MSG_VERBOSE( " -> Preparing the binned material with "
819 << binsPhi << " / " << binsZ << " bins in R*phi / Z. ");
820 }
821 // bounds
822 auto cylinderBounds = std::make_shared<Trk::CylinderBounds>(r,halflengthZ);
823 // create the cylinder
824 Trk::CylinderLayer* cylinderLayer =
825 transform
826 ? new Trk::CylinderLayer(*transform, cylinderBounds,
827 cylinderMaterial, thickness, nullptr,
828 int(Trk::passive))
829 : new Trk::CylinderLayer(cylinderBounds, cylinderMaterial,
830 thickness, nullptr, int(Trk::passive));
831 // and return it
832 return cylinderLayer;
833}
834
835
837 double rMin,
838 double rMax,
839 double thickness,
840 int binsPhi,
841 int binsR) const
842{
843
844 ATH_MSG_VERBOSE( "Creating a DiscLayer at position " << z << " and rMin/rMax " << rMin << " / " << rMax);
845
846 // positioning
847 Amg::Transform3D transform =
848 fabs(z) > 0.1 ? Amg::Transform3D((Amg::Translation3D(0.,0.,z))) : Amg::Transform3D::Identity();
849
850 // R is the primary binning for the material
851 Trk::BinUtility layerBinUtility(binsR, rMin, rMax, Trk::open, Trk::binR);
852 if (binsPhi==1) {
853 ATH_MSG_VERBOSE( " -> Preparing the binned material with "
854 << binsR << " bins in R. ");
855 } else {
856 // also binning in phi chosen
857 layerBinUtility += Trk::BinUtility(binsPhi, -M_PI, M_PI, Trk::closed, Trk::binPhi);
858 ATH_MSG_VERBOSE( " -> Preparing the binned material with "
859 << binsPhi << " / " << binsR << " bins in phi / R. ");
860 }
861 // ---------------------> create the layer material
862 auto discMaterial = Trk::BinnedLayerMaterial(layerBinUtility);
863 // bounds
864 auto discBounds = std::make_shared<Trk::DiscBounds>(rMin,rMax);
865 // create the disc
866 Trk::DiscLayer* discLayer = new Trk::DiscLayer(transform, discBounds, discMaterial,
867 thickness, nullptr, int(Trk::passive));
868
869 // and return it
870 return discLayer;
871}
872
#define M_PI
#define ATH_MSG_FATAL(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
#define min(a, b)
Definition cfImp.cxx:40
#define max(a, b)
Definition cfImp.cxx:41
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
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.
It extends the LayerMaterialProperties base class.
Bounds for a cylindrical Surface.
virtual double r() const override final
This method returns the radius.
double halflengthZ() const
This method returns the halflengthZ.
Class to describe a cylindrical detector layer for tracking, it inhertis from both,...
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.
ToolHandle< ITrackingVolumeHelper > m_trackingVolumeHelper
CylinderLayer * createCylinderLayer(double z, double r, double halflength, double thickness, int binsPhi, int binsZ) const
Private method - helper method to save some code.
void glueTrackingVolumes(TrackingVolume &volumeOne, BoundarySurfaceFace faceOne, TrackingVolume &volumeTwo, BoundarySurfaceFace faceTwo, bool buildBoundaryLayers, bool replaceBoundaryFace=false) const
Private method - glue volume to the other – use trackingVolume helper.
void addFaceVolumes(TrackingVolume &tvol, Trk::BoundarySurfaceFace bsf, std::vector< Trk::TrackingVolume * > &vols) const
Private method - helper method not to duplicate code.
ToolHandle< ILayerArrayCreator > m_layerArrayCreator
< A Tool for coherent LayerArray creation
virtual TrackingVolume * createGapTrackingVolume(Material &matprop, double rMin, double rMax, double zMin, double zMax, unsigned int materialLayers, bool cylinder=true, const std::string &volumeName="UndefinedVolume") const override final
DiscLayer * createDiscLayer(double z, double rMin, double rMax, double thickness, int binsPhi, int binsR) const
Private method - helper method to save some code.
virtual TrackingVolume * createContainerTrackingVolume(const std::vector< TrackingVolume * > &volumes, const Material &matprop, const std::string &volumeName="UndefinedVolume", bool buildBoundaryLayers=false, bool replaceBoundaryFace=false) const override final
;
Gaudi::Property< int > m_passiveLayerRzBins
ToolHandle< ITrackingVolumeArrayCreator > m_trackingVolumeArrayCreator
TrackingVolume helper.
StatusCode interGlueTrackingVolume(TrackingVolume &tVolume, bool rBinned, bool buildBoundaryLayers, bool replaceBoundaryFace=false) const
Private method - interglue all volumes contained by a TrackingVolume and set the outside glue volumes...
CylinderVolumeCreator(const std::string &, const std::string &, const IInterface *)
Constructor.
Gaudi::Property< double > m_passiveLayerThickness
virtual StatusCode initialize() override
AlgTool initialize method.
Gaudi::Property< int > m_passiveLayerPhiBins
virtual TrackingVolume * createTrackingVolume(const std::vector< Layer * > &layers, Material &matprop, VolumeBounds *volBounds=0, Amg::Transform3D *transform=0, const std::string &volumeName="UndefinedVolume", BinningType btype=arbitrary) const override final
;
StatusCode estimateAndCheckDimension(const std::vector< Layer * > &layers, Trk::CylinderVolumeBounds *&cylBounds, Amg::Transform3D *&translation, std::vector< CylinderLayer * > &cylLayers, std::vector< DiscLayer * > &discLayers, double &rMinClean, double &rMaxClean, double &zMinClean, double &zMaxClean, BinningType bType=arbitrary) const
Private method - it estimates the CylinderBounds and Translation of layers, if given,...
Class to describe the bounds for a planar DiscSurface.
Definition DiscBounds.h:44
double rMax() const
This method returns outer radius.
double rMin() const
This method returns inner radius.
Class to describe a disc-like detector layer for tracking, it inhertis from both, Layer base class an...
Definition DiscLayer.h:45
Descriptor class to hold GlueVolumes of a TrackingGeometry object.
const std::vector< TrackingVolume * > & glueVolumes(BoundarySurfaceFace)
retrieve them again
void registerGlueVolumes(BoundarySurfaceFace, std::vector< TrackingVolume * > &)
register the volumes
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 TrackingVolumeArray * confinedVolumes() const
Return the subLayer array.
const std::string & volumeName() const
Returns the VolumeName - for debug reason, might be depreciated later.
GlueVolumesDescriptor & glueVolumesDescriptor()
Pure Absract Base Class for Volume bounds.
const Amg::Vector3D & center() const
returns the center of the volume
Definition Volume.h:90
const VolumeBounds & volumeBounds() const
returns the volumeBounds()
Definition Volume.h:96
int r
Definition globals.cxx:22
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Eigen::Affine3d Transform3D
Eigen::Translation< double, 3 > Translation3D
@ open
Definition BinningType.h:40
@ closed
Definition BinningType.h:41
BoundarySurfaceFace
Enum to describe the position of the BoundarySurface respectively to the frame orientatin of the volu...
@ z
global position (cartesian)
Definition ParamDefs.h:57
BinningType
, BinningOption & BinningAccess
Definition BinningType.h:31
@ biequidistant
Definition BinningType.h:33
@ arbitrary
Definition BinningType.h:34
@ binR
Definition BinningType.h:50
@ binPhi
Definition BinningType.h:51
@ binRPhi
Definition BinningType.h:52
@ binZ
Definition BinningType.h:49
@ passive
Definition Layer.h:47