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