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