ATLAS Offline Software
Loading...
Searching...
No Matches
TrackingVolume.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6// TrackingVolume.cxx, (b) ATLAS Detector software
8
10// Gaudi Kernel
11#include "GaudiKernel/MsgStream.h"
12// Trk
16#include "TrkGeometry/Layer.h"
22//
33//
38#include "TrkSurfaces/Surface.h"
39//
42//
45// CLHEP
47#include <utility>
48
49// constructor: 1 a)
51 std::unique_ptr<Amg::Transform3D> htrans,
52 std::shared_ptr<VolumeBounds> volbounds,
53 std::unique_ptr<LayerArray> subLayers,
54 std::unique_ptr<TrackingVolumeArray> subVolumes,
55 const std::string& volumeName)
56 : Volume(std::move(htrans), std::move(volbounds))
57 , Material()
59 , m_confinedLayers(std::move(subLayers))
60 , m_confinedVolumes(std::move(subVolumes))
62{
66}
67
68// constructor: 2 a)
70 const Material& matprop,
71 std::unique_ptr<LayerArray> subLayers,
72 std::unique_ptr<TrackingVolumeArray> subVolumes,
73 const std::string& volumeName)
74 : Volume(volume)
75 , Material(matprop)
76 , m_confinedLayers(std::move(subLayers))
77 , m_confinedVolumes(std::move(subVolumes))
79{
83}
84
85// constructor: 3 a)
87 std::unique_ptr<Amg::Transform3D> htrans,
88 std::shared_ptr<VolumeBounds> volbounds,
89 const Material& matprop,
90 std::unique_ptr<LayerArray> subLayers,
91 std::unique_ptr<TrackingVolumeArray> subVolumes,
92 const std::string& volumeName)
93 : Volume(std::move(htrans), std::move(volbounds))
94 , Material(matprop)
95 , m_confinedLayers(std::move(subLayers))
96 , m_confinedVolumes(std::move(subVolumes))
98{
102}
103
104// 1 b)
106 std::unique_ptr<Amg::Transform3D> htrans,
107 std::shared_ptr<VolumeBounds> volbounds,
108 const Material& matprop,
109 std::unique_ptr<std::vector<DetachedTrackingVolume*>> detachedSubVolumes,
110 const std::string& volumeName)
111 : Volume(std::move(htrans), std::move(volbounds))
112 , Material(matprop)
113 , m_confinedDetachedVolumes(std::move(detachedSubVolumes))
115{
117}
118
119// 2 b)
121 const Volume& volume,
122 const Material& matprop,
123 std::unique_ptr<std::vector<DetachedTrackingVolume*>> detachedSubVolumes,
124 const std::string& volumeName)
125 : Volume(volume)
126 , Material(matprop)
127 , m_confinedDetachedVolumes(std::move(detachedSubVolumes))
129{
131}
132
133// 1 d)
135 std::unique_ptr<Amg::Transform3D> htrans,
136 std::shared_ptr<VolumeBounds> volbounds,
137 const Material& matprop,
138 std::unique_ptr<const std::vector<TrackingVolume*>> unorderedSubVolumes,
139 const std::string& volumeName)
140 : Volume(std::move(htrans), std::move(volbounds))
141 , Material(matprop)
142 , m_confinedDenseVolumes(std::move(unorderedSubVolumes))
144{
146}
147
148// 2 d)
150 const Volume& volume,
151 const Material& matprop,
152 std::unique_ptr<const std::vector<TrackingVolume*>> unorderedSubVolumes,
153 const std::string& volumeName)
154 : Volume(volume)
155 , Material(matprop)
156 , m_confinedDenseVolumes(std::move(unorderedSubVolumes))
158{
160}
161
162// 1 c)
164 std::unique_ptr<Amg::Transform3D> htrans,
165 std::shared_ptr<VolumeBounds> volbounds,
166 const Material& matprop,
167 std::unique_ptr<const std::vector<Layer*>> layers,
168 const std::string& volumeName)
169 : Volume(std::move(htrans), std::move(volbounds))
170 , Material(matprop)
171 , m_confinedArbitraryLayers(std::move(layers))
173{
175}
176
177// 2 c)
179 const Material& matprop,
180 std::unique_ptr<const std::vector<Layer*>> layers,
181 const std::string& volumeName)
182 : Volume(volume)
183 , Material(matprop)
184 , m_confinedArbitraryLayers(std::move(layers))
186{
188}
189
190// 1 d)
192 std::unique_ptr<Amg::Transform3D> htrans,
193 std::shared_ptr<VolumeBounds> volbounds,
194 std::unique_ptr<const std::vector<Layer*>> layers,
195 std::unique_ptr<const std::vector<TrackingVolume*>> unorderedSubVolumes,
196 const Material& matprop,
197 const std::string& volumeName)
198 : Volume(std::move(htrans), std::move(volbounds))
199 , Material(matprop)
200 , m_confinedDenseVolumes(std::move(unorderedSubVolumes))
201 , m_confinedArbitraryLayers(std::move(layers))
203{
205}
206
207// 2 d)
209 const Volume& volume,
210 std::unique_ptr<const std::vector<Layer*>> layers,
211 std::unique_ptr<const std::vector<TrackingVolume*>> unorderedSubVolumes,
212 const Material& matprop,
213 const std::string& volumeName)
214 : Volume(volume)
215 , Material(matprop)
216 , m_confinedDenseVolumes(std::move(unorderedSubVolumes))
217 , m_confinedArbitraryLayers(std::move(layers))
219{
221}
222
225 : Volume(trVol, transform)
226 , Material(trVol)
229 , m_name(trVol.m_name)
230 , m_colorCode(trVol.m_colorCode)
231{
232 // createBoundarySurfaces
233 m_boundarySurfaces.reserve(trVol.boundarySurfaces().size());
234 const Trk::TrackingVolume* in = nullptr;
235 const Trk::TrackingVolume* out = nullptr;
236 for (size_t ib = 0; ib < trVol.boundarySurfaces().size(); ib++) {
237 in = trVol.boundarySurfaces()[ib]->insideVolume() == &trVol ? this : nullptr;
238 out = in == nullptr ? this : nullptr;
239 const Trk::CylinderSurface* cyl =
240 dynamic_cast<const Trk::CylinderSurface*>(trVol.boundarySurfaces()[ib]);
241 const Trk::DiscSurface* dis =
242 dynamic_cast<const Trk::DiscSurface*>(trVol.boundarySurfaces()[ib]);
243 const Trk::PlaneSurface* pla =
244 dynamic_cast<const Trk::PlaneSurface*>(trVol.boundarySurfaces()[ib]);
246 dynamic_cast<const Trk::SubtractedCylinderSurface*>(
247 trVol.boundarySurfaces()[ib]);
248 const Trk::SubtractedPlaneSurface* spla =
249 dynamic_cast<const Trk::SubtractedPlaneSurface*>(
250 trVol.boundarySurfaces()[ib]);
251 if (scyl) {
252 m_boundarySurfaces.push_back(
254 } else if (spla) {
255 m_boundarySurfaces.push_back(
257 } else if (cyl) {
258 m_boundarySurfaces.push_back(
259 std::make_shared<Trk::BoundaryCylinderSurface<Trk::TrackingVolume>>(in, out, *cyl, transform));
260 } else if (dis) {
261 m_boundarySurfaces.push_back(
262 std::make_shared<Trk::BoundaryDiscSurface<Trk::TrackingVolume>>(in, out, *dis, transform));
263 } else if (pla) {
264 m_boundarySurfaces.push_back(
265 std::make_shared<Trk::BoundaryPlaneSurface<Trk::TrackingVolume>>(in, out, *pla, transform));
266 }
267 }
268
269 // confined layers
271 if (confinedLayers) {
272 std::span<Trk::Layer const* const> layers = confinedLayers->arrayObjects();
273 std::vector<std::shared_ptr<Trk::Layer>> layerOrder;
274 layerOrder.reserve(layers.size());
275 for (const auto *layer : layers) {
276 const Trk::PlaneLayer* lay = dynamic_cast<const Trk::PlaneLayer*>(layer);
277 if (lay) {
278 Trk::PlaneLayer* newlay = new Trk::PlaneLayer(*lay, transform);
279 layerOrder.push_back(std::shared_ptr<Trk::Layer>(newlay));
280 }
281 }
282 const Trk::NavBinnedArray1D<Trk::Layer>* confLays =
284 if (confLays) {
285 m_confinedLayers = std::make_unique<Trk::NavBinnedArray1D<Trk::Layer>>(
286 *confLays,
287 std::vector<std::shared_ptr<Trk::Layer>>(layerOrder),
288 transform);
289 }
290 }
291
292 // confined 'unordered' layers
295 if (!confinedArbitraryLayers.empty()) {
296 // clone & apply the transform
297 std::vector<Trk::Layer*> uLayers;
298 uLayers.reserve(confinedArbitraryLayers.size());
299 for (const auto *confinedArbitraryLayer : confinedArbitraryLayers) {
300 const Trk::SubtractedPlaneLayer* slayer =
301 dynamic_cast<const Trk::SubtractedPlaneLayer*>(
302 confinedArbitraryLayer);
303 const Trk::SubtractedCylinderLayer* sclayer =
304 dynamic_cast<const Trk::SubtractedCylinderLayer*>(
305 confinedArbitraryLayer);
306 const Trk::PlaneLayer* layer =
307 dynamic_cast<const Trk::PlaneLayer*>(confinedArbitraryLayer);
308 const Trk::CylinderLayer* clayer =
309 dynamic_cast<const Trk::CylinderLayer*>(confinedArbitraryLayer);
310
311 if (slayer) {
312 Trk::SubtractedPlaneLayer* lay = new Trk::SubtractedPlaneLayer(*slayer, transform);
313 uLayers.push_back(lay);
314 } else if (layer) {
315 Trk::PlaneLayer* lay = new Trk::PlaneLayer(*layer, transform);
316 uLayers.push_back(lay);
317 } else if (sclayer) {
318 Trk::SubtractedCylinderLayer* lay = new Trk::SubtractedCylinderLayer(*sclayer, transform);
319 uLayers.push_back(lay);
320 } else if (clayer) {
321 Trk::CylinderLayer* lay = new Trk::CylinderLayer(*clayer, transform);
322 uLayers.push_back(lay);
323 }
324 }
325 m_confinedArbitraryLayers = std::make_unique<std::vector<Trk::Layer*>>(uLayers);
326 }
327
328 // confined volumes
329 const Trk::BinnedArray<Trk::TrackingVolume>* confinedVolumes =
330 trVol.confinedVolumes();
331 if (confinedVolumes) {
332 // retrieve array objects and apply the transform
333 std::span<Trk::TrackingVolume const * const > volumes =
334 confinedVolumes->arrayObjects();
335 std::vector<std::shared_ptr<Trk::TrackingVolume>> volOrder;
336 volOrder.reserve(volumes.size());
337 for (const auto *volume : volumes) {
338 Trk::TrackingVolume* vol = new Trk::TrackingVolume(*volume, transform);
339 volOrder.push_back(std::shared_ptr<TrackingVolume>(vol));
340 }
343 confinedVolumes);
344 if (confVols)
345 m_confinedVolumes = std::make_unique<Trk::NavBinnedArray1D<Trk::TrackingVolume>>(
346 *confVols,
347 std::vector<std::shared_ptr<Trk::TrackingVolume>>(volOrder),
348 transform);
349 }
350
351 // confined unordered volumes
353 trVol.confinedDenseVolumes();
354 if (!confinedDenseVolumes.empty()) {
355 std::vector<Trk::TrackingVolume*> newVol;
356 newVol.reserve(confinedDenseVolumes.size());
357 // retrieve array objects and apply the transform
358 for (const auto *confinedDenseVolume : confinedDenseVolumes) {
359 Trk::TrackingVolume* vol = new Trk::TrackingVolume(*confinedDenseVolume, transform);
360 newVol.push_back(vol);
361 }
362 m_confinedDenseVolumes = std::make_unique<const std::vector<Trk::TrackingVolume*>>(newVol);
363 }
364}
365
367{
368 //We need to clean the elements we own from the vectors
370 for (auto * confinedDenseVolume : *m_confinedDenseVolumes){
371 delete confinedDenseVolume;
372 }
373 }
375 for (auto * confinedArbitraryLayer : *m_confinedArbitraryLayers){
376 delete confinedArbitraryLayer;
377 }
378 }
379}
380
381const Trk::Layer*
383{
384 // confined layers
385 if (m_confinedLayers){
386 return (confinedLayers()->object(gp));
387 }
388 // confined arbitrary
390 for (auto* confinedArbitraryLayer : *m_confinedArbitraryLayers){
391 if (confinedArbitraryLayer->isOnLayer(gp)){
392 return confinedArbitraryLayer;
393 }
394 }
395 }
396 return nullptr;
397}
398
401{
402 // confined layers
403 if (m_confinedLayers){
404 return (confinedLayers()->object(gp));
405 }
406 // confined arbitrary
408 for (auto * confinedArbitraryLayer : *m_confinedArbitraryLayers){
409 if (confinedArbitraryLayer->isOnLayer(gp)){
410 return confinedArbitraryLayer;
411 }
412 }
413 }
414 return nullptr;
415}
416
417const Trk::Layer*
419 const Amg::Vector3D& mom,
420 bool associatedResult,
421 bool skipNavLayer) const
422{
423 const Trk::Layer* nextLayer = nullptr;
424 if (m_confinedLayers){
425 nextLayer = (confinedLayers()->nextObject(gp, mom, associatedResult));
426 }
427 // forward it in this case
428 if (!skipNavLayer){
429 return nextLayer;
430 }
431 // if only material or layers
432 if (nextLayer &&
433 (nextLayer->layerMaterialProperties() || nextLayer->surfaceArray())){
434 return nextLayer;
435 }
436 // try to get the next layer that has either material or sub surfaces
437 while (nextLayer && (!(nextLayer->layerMaterialProperties()) &&
438 !(nextLayer->surfaceArray()))){
439 nextLayer = (confinedLayers()->nextObject(gp, mom, associatedResult));
440 }
441 return nextLayer;
442}
443
446 const Amg::Vector3D& dir,
447 PropDirection pDir,
448 const BoundaryCheck& bchk) const
449{
450 // the layer candidates to check
451 std::vector<const Layer*> layerCandidates;
452
453 // ---------------- BOUNDARY LAYER SECTION (only for mapping) ----------
454 if (pDir == mappingMode) {
455 const auto& bSurfaces = boundarySurfaces();
456 for (size_t ib = 0; ib < bSurfaces.size(); ++ib) {
457 if (bSurfaces[ib]->surfaceRepresentation().materialLayer()){
458 layerCandidates.push_back(bSurfaces[ib]->surfaceRepresentation().materialLayer());
459 }
460 }
461 }
462 // ---------------- CONFINED LAYER SECTION --------------
463 if (m_confinedLayers) {
464 // the associated layer
465 const Trk::Layer* assocLayer = associatedLayer(gp);
466 const Trk::Layer* previousMatLayer = nullptr;
467 const Trk::Layer* nextMatLayer = nullptr;
468 // if the associated layer is a navigation layer - get the previous and next
469 // from this one
470 const Trk::NavigationLayer* navLayer =
471 dynamic_cast<const Trk::NavigationLayer*>(assocLayer);
472 if (navLayer) {
473 // get previous / next
474 previousMatLayer = navLayer->previousLayer();
475 nextMatLayer = navLayer->nextLayer();
476 if (previousMatLayer){
477 layerCandidates.push_back(previousMatLayer);
478 }
479 if (nextMatLayer){
480 layerCandidates.push_back(nextMatLayer);
481 }
482 } else{
483 layerCandidates.push_back(assocLayer);
484 }
485 }
486 // --- solve for the layer candidates ---------------------
487 //
488 Trk::Intersection laySurfIntersection(Amg::Vector3D(0., 0., 0.), 10e10, false);
489 // layer candidates found - continue
490 if (!layerCandidates.empty()) {
491 const Layer* cLayer = nullptr;
492 // iterate through and chose
493 for (auto& lcIter : layerCandidates) {
494 // only the forceFwd solution is possible here
495 bool forceDir = (pDir == alongMomentum || pDir == oppositeMomentum);
496 double dirScalor = (pDir == oppositeMomentum) ? -1. : 1.;
497 // get the intersection soltuion
499 (*lcIter).surfaceRepresentation().straightLineIntersection(
500 gp, dirScalor * dir, forceDir, bchk);
501 if (sfI.valid &&
502 (sfI.pathLength * sfI.pathLength) <
503 (laySurfIntersection.pathLength * laySurfIntersection.pathLength)) {
504 laySurfIntersection = sfI;
505 cLayer = lcIter;
506 }
507 }
508 // now return the pair: in case of a valid intersection, or if no mapping
509 // mode is chosen
510 if (cLayer){
512 laySurfIntersection,
513 cLayer,
514 &(cLayer->surfaceRepresentation()),
515 nullptr,
516 pDir);
517 }
518 }
519 // mapping mode chosen, but no valid intersection yet
520 const Trk::TrackingVolume* nVolume = nextVolume(gp, dir, pDir);
521
522 // forward the next Volume solution or a 0 solution
523 return (nVolume && nVolume != this)
524 ? nVolume->closestMaterialLayer(gp, dir, pDir, bchk)
526 laySurfIntersection, nullptr, nullptr, nullptr, pDir);
527}
528
531{
533 return (m_confinedVolumes->object(gp));
534 }
535
537 for (auto *confinedDetachedVolume : *m_confinedDetachedVolumes) {
538 if (confinedDetachedVolume->trackingVolume()->inside(gp, 0.001)){
539 return confinedDetachedVolume->trackingVolume();
540 }
541 }
542 }
543
545 for (auto *confinedDenseVolume : *m_confinedDenseVolumes){
546 if (confinedDenseVolume->inside(gp, 0.001)){
547 return confinedDenseVolume;
548 }
549 }
550 }
551
552 return this;
553}
554
557{
559 return (m_confinedVolumes->object(gp));
560 }
561
563 for (auto *confinedDetachedVolume : *m_confinedDetachedVolumes) {
564 if (confinedDetachedVolume->trackingVolume()->inside(gp, 0.001)){
565 return confinedDetachedVolume->trackingVolume();
566 }
567 }
568 }
569
571 for (auto * confinedDenseVolume : *m_confinedDenseVolumes){
572 if (confinedDenseVolume->inside(gp, 0.001)){
573 return confinedDenseVolume;
574 }
575 }
576 }
577
578 return this;
579}
580
581
584 const Amg::Vector3D& dir,
585 Trk::PropDirection pDir) const
586{
587 // get the boundary surfaces & intersect them
588 const Trk::TrackingVolume* nVolume = nullptr;
589 // fix the direction once
590 bool forceDir = (pDir == Trk::alongMomentum || pDir == Trk::oppositeMomentum);
591 double dirScalor = (pDir == Trk::oppositeMomentum) ? -1. : 1.;
592 Amg::Vector3D cDir = dirScalor * dir;
593 double pathLength = 10e10;
594 // now loop through the and find the closest
595 const auto& bSurfaces = boundarySurfaces();
596 for (size_t ib = 0; ib < bSurfaces.size(); ++ib) {
597 // get the intersection soltuion
599 bSurfaces[ib]->surfaceRepresentation().straightLineIntersection(
600 gp, cDir, forceDir, true);
601 if (sfI.valid &&
602 (sfI.pathLength * sfI.pathLength) < (pathLength * pathLength)) {
603 // assign the next Volume
604 Trk::PropDirection attachedDir =
606 pathLength = sfI.pathLength;
607 nVolume = bSurfaces[ib]->attachedVolume(gp, cDir, attachedDir);
608 }
609 }
610 return nVolume;
611}
612
615 const Amg::Vector3D& mom) const
616{
618 return (m_confinedVolumes->nextObject(gp, mom));
619 }
620 return this;
621}
622
623std::vector<const Trk::DetachedTrackingVolume*>
625 double tol) const
626{
627 auto currVols = std::vector<const Trk::DetachedTrackingVolume*>();
628
631 if (!detVols.empty()) {
632 for (const auto *detVol : detVols) {
633 if (detVol->trackingVolume()->inside(gp, tol)){
634 currVols.push_back(detVol);
635 }
636 }
637 }
638 return currVols;
639}
640
641void
643 int& offset)
644{
645 // the offset gets increased internally
646 // the static layers first
647 // ------------------------------------------------------------------
648 if (m_confinedLayers) {
649 std::span<Trk::Layer* const> layers = confinedLayers()->arrayObjects();
650 for (Trk::Layer* layerptr : layers) {
651 // only index the material layers & only those that have not yet been
652 // singed
653 if (layerptr && layerptr->layerIndex().value() < 0) {
654 // sign only those with material properties - rest goes to 0
655 Trk::LayerIndex layIndex =
656 layerptr->layerMaterialProperties()
658 int(geoSig) * TRKDETDESCR_GEOMETRYSIGNATUREWEIGHT + (++offset))
659 : Trk::LayerIndex(0);
660 // now register the index
661 layerptr->registerLayerIndex(layIndex);
662 }
663 }
664 }
665
666 // the boundary surface layer
667 auto& bSurfaces = boundarySurfaces();
668 for (const auto& bsIter : bSurfaces) {
670 if (mLayer && mLayer->layerIndex().value() < 0.) {
672 int(geoSig) * TRKDETDESCR_GEOMETRYSIGNATUREWEIGHT + (++offset));
673 mLayer->registerLayerIndex(layIndex);
674 }
675 }
676
677 // step down the hierarchy to the contained volumes and index those
678 // ------------------------
679 if (confinedVolumes()) {
680 std::span<Trk::TrackingVolume* const > volumes = confinedVolumes()->arrayObjects();
681 for (const auto& volumesIter : volumes) {
682 if (volumesIter)
683 volumesIter->indexContainedStaticLayers(geoSig, offset);
684 }
685 }
686}
687
688void
690 int& offset)
691{
692 // the offset gets increased internally
693 // the static layers first and check if they have surfaces with material
694 // layers that need index
695 if (m_confinedLayers) {
696 std::span<Trk::Layer * const> layers = confinedLayers()->arrayObjects();
697 for (Trk::Layer* layerIter : layers) {
698 // only index the material layers & only those that have not yet been
699 // singed
700 if (layerIter) {
701 Trk::SurfaceArray* surfArray = layerIter->surfaceArray();
702 if (surfArray) {
703 std::span<Trk::Surface * const> layerSurfaces = surfArray->arrayObjects();
704 // loop over the surfaces - there can be 0 entries
705 for (Trk::Surface* const laySurf : layerSurfaces) {
706 Trk::MaterialLayer* materialLayer = laySurf ? laySurf->materialLayer() : nullptr;
707 if (materialLayer && materialLayer->layerIndex().value() < 0) {
708 // sign only those with material properties - rest goes to 0
709 Trk::LayerIndex layIndex =
710 materialLayer->layerMaterialProperties()
711 ? Trk::LayerIndex(int(geoSig) *
713 (++offset))
714 : Trk::LayerIndex(0);
715 // now register the index
716 materialLayer->registerLayerIndex(layIndex);
717 }
718 }
719 }
720 }
721 }
722 }
723
724 // step down the hierarchy to the contained volumes and index those
725 // ------------------------
726 if (confinedVolumes()) {
727 std::span<Trk::TrackingVolume * const> volumes = confinedVolumes()->arrayObjects();
728 for (Trk::TrackingVolume* volumesIter : volumes) {
729 if (volumesIter)
730 volumesIter->indexContainedMaterialLayers(geoSig, offset);
731 }
732 }
733}
734
735void
737{
738 // assume the scaling factor refers to the volume scaling
739 float flin = pow(fact, 0.33);
740 // average X0
741 double invX0 = X0 > 0. ? 1. / X0 : 0.;
742 double sum_invX0 = invX0 + flin / mprop.X0;
743 X0 = 1. / sum_invX0;
744 // average L0
745 double invL0 = L0 > 0. ? 1. / L0 : 0.;
746 double sum_invL0 = invL0 + flin / mprop.L0;
747 L0 = 1. / sum_invL0;
748 // add density
749 float rho1 = rho;
750 rho += fact * mprop.rho;
751 // averageZ
752 float n1 = Z > 0. ? rho1 / Z : 0.;
753 float n2 = fact * mprop.rho / mprop.Z;
754 Z = rho / (n1 + n2);
755 // averageA
756 n1 = A > 0. ? rho1 / A : 0.;
757 n2 = fact * mprop.rho / mprop.A;
758 A = rho / (n1 + n2);
759 // zOverAtimesRho
760 zOaTr = Z / A * rho;
761 // mean energy loss (linear scaling)
762 dEdX += flin * mprop.dEdX;
763}
764
765void
767 Trk::GeometryType geotype)
768{
769 // never overwrite what is already signed, that's a crime
771 m_geometrySignature = geosign;
772 }
773 m_geometryType = geotype;
774
775 // confined volumes
777 if (confVolumes) {
778 std::span<Trk::TrackingVolume* const> volumes =
779 confVolumes->arrayObjects();
780 for (const auto& volumesIter : volumes){
781 if (volumesIter){
782 volumesIter->sign(geosign, geotype);
783 }
784 }
785 }
786 // same procedure for the detached volumes
789 if (!confDetachedVolumes.empty()) {
790 for (const auto& volumesIter : confDetachedVolumes) {
791 if (volumesIter) {
792 volumesIter->sign(geosign, geotype);
793 }
794 }
795 }
796 // confined dense volumes
799 if (!confDenseVolumes.empty()) {
800 for (const auto& volumesIter : confDenseVolumes) {
801 if (volumesIter) {
802 volumesIter->sign(geosign, geotype);
803 }
804 }
805 }
806}
807
808std::vector<std::shared_ptr<Trk::BoundarySurface<Trk::TrackingVolume>>>&
813
820
823{
824 return (std::as_const(m_boundarySurfaces)[oa]).get();
825}
826
827void
829{
830 // prepare the BoundarySurfaces
832 std::vector<std::shared_ptr<Trk::BoundarySurface<Trk::TrackingVolume>>>();
833 // transform Surfaces To BoundarySurfaces
834 std::vector<std::unique_ptr<Trk::Surface>> surfaces =
836 auto surfIter = surfaces.begin();
837
838 // counter to flip the inner/outer position for Cylinders
839 unsigned int sfCounter = 0;
840 unsigned int sfNumber = surfaces.size();
841
842 // memory optimisation
843 m_boundarySurfaces.reserve(sfNumber + 1);
844
845 // identify Subtracted/CombinedVolumes
846 const Trk::SubtractedVolumeBounds* subtrVol =
847 dynamic_cast<const Trk::SubtractedVolumeBounds*>(
849 const Trk::CombinedVolumeBounds* combVol =
850 dynamic_cast<const Trk::CombinedVolumeBounds*>(
852 bool subtr = (subtrVol) ? 1 : 0;
853 bool comb = (combVol) ? 1 : 0;
854
855 if (!subtr && !comb) {
857 dynamic_cast<const Trk::SimplePolygonBrepVolumeBounds*>(
859
860 for (; surfIter != surfaces.end(); ++surfIter) {
861 sfCounter++;
862
863 Trk::TrackingVolume* in = this;
864 Trk::TrackingVolume* out = nullptr;
865
866 // ST update: subtracted surfaces may appear in 'simple' volumes
867 // (SimplePolygonBrep...)
868 const Trk::SubtractedPlaneSurface* spsf =
869 dynamic_cast<const Trk::SubtractedPlaneSurface*>((*surfIter).get());
870 const Trk::PlaneSurface* psf =
871 dynamic_cast<const Trk::PlaneSurface*>((*surfIter).get());
872 if (spsf) {
873 if (spbVol && sfCounter == 1) {
874 in = nullptr;
875 out = this;
876 }
877 m_boundarySurfaces.push_back(
879 in, out, *spsf));
880 continue;
881 }
882 if (psf) {
883 m_boundarySurfaces.push_back(
884 std::make_shared<Trk::BoundaryPlaneSurface<Trk::TrackingVolume>>(in, out, *psf));
885 continue;
886 }
887
888 const Trk::DiscSurface* dsf =
889 dynamic_cast<const Trk::DiscSurface*>((*surfIter).get());
890 if (dsf) {
891 m_boundarySurfaces.push_back(
892 std::make_shared<Trk::BoundaryDiscSurface<Trk::TrackingVolume>>(in, out, *dsf));
893 continue;
894 }
895
897 dynamic_cast<const Trk::SubtractedCylinderSurface*>((*surfIter).get());
898 const Trk::CylinderSurface* csf =
899 dynamic_cast<const Trk::CylinderSurface*>((*surfIter).get());
900 if (scsf) {
901 Trk::TrackingVolume* inner =
902 (sfCounter == 4 && sfNumber > 3) ? nullptr : this;
903 Trk::TrackingVolume* outer = (inner) ? nullptr : this;
904 m_boundarySurfaces.push_back(
905 std::make_shared<Trk::BoundarySubtractedCylinderSurface<Trk::TrackingVolume>>(inner, outer, *scsf));
906 continue;
907 }
908 if (csf) {
909 Trk::TrackingVolume* inner =
910 (sfCounter == 4 && sfNumber > 3) ? nullptr : this;
911 Trk::TrackingVolume* outer = (inner) ? nullptr : this;
912 m_boundarySurfaces.push_back(
914 inner, outer, *csf));
915 continue;
916 }
917 }
918
919 } else {
920 const std::vector<bool> bOrient =
921 subtrVol ? subtrVol->boundsOrientation() : combVol->boundsOrientation();
922
923 for (; surfIter != surfaces.end(); ++surfIter) {
924 Trk::TrackingVolume* in = bOrient[sfCounter] ? this : nullptr;
925 Trk::TrackingVolume* out = bOrient[sfCounter] ? nullptr : this;
926 sfCounter++;
927
928 const Trk::SubtractedPlaneSurface* psf =
929 dynamic_cast<const Trk::SubtractedPlaneSurface*>((*surfIter).get());
930 if (psf) {
931 m_boundarySurfaces.push_back(
933 in, out, *psf));
934 continue;
935 }
936
938 dynamic_cast<const Trk::SubtractedCylinderSurface*>((*surfIter).get());
939 if (csf) {
940 m_boundarySurfaces.push_back(
942 in, out, *csf));
943 continue;
944 }
945 }
946 }
947}
948
949void
951{
952 // check whether there's a static array
953 if (m_confinedLayers) {
954 // BinUtility
955 const Trk::BinUtility* binUtility = m_confinedLayers->binUtility();
956 if (binUtility) {
957 if (binUtility->binningValue() == Trk::binR){
958 m_layerAttemptsCalculator = std::make_unique<Trk::CylinderLayerAttemptsCalculator>(1, 5);
959 }
960 if (binUtility->binningValue() == Trk::binZ){
961 m_layerAttemptsCalculator = std::make_unique<Trk::DiscLayerAttemptsCalculator>(1, 5);
962 }
963 }
964 }
965}
966
968{
969 if (m_confinedLayers) {
970 std::span<Trk::Layer* const> layers = m_confinedLayers->arrayObjects();
971 // forward loop
972 const Trk::Layer* lastLayer = nullptr;
973 std::span<Trk::Layer* const>::iterator layerIter = layers.begin();
974 for (; layerIter != layers.end(); ++layerIter) {
975 if (*layerIter) {
976 // register the layers
977 (**layerIter).setBinUtility(confinedLayers()->binUtility()
978 ? confinedLayers()->binUtility()
979 : nullptr);
980 (**layerIter).setPreviousLayer(lastLayer);
981 // register the volume
982 (**layerIter).encloseTrackingVolume(*this);
983 }
984 lastLayer = (*layerIter);
985 }
986 // backward loop
987 lastLayer = nullptr;
988 layerIter = layers.end();
989 --layerIter;
990 for (;; --layerIter) {
991 if (*layerIter) {
992 (**layerIter).setNextLayer(lastLayer);
993 }
994 lastLayer = (*layerIter);
995 if (layerIter == layers.begin()) {
996 break;
997 }
998 }
999 }
1000}
1001
1002const Trk::LayerArray*
1004{
1005 const Trk::LayerArray* checkoutLayers = m_confinedLayers.get();
1006 return checkoutLayers;
1007}
1008
1009void
1011{
1012 m_outsideGlueVolumes.store(std::unique_ptr<Trk::GlueVolumesDescriptor>(gvd));
1013}
1014
1017{
1018 if (!m_outsideGlueVolumes) {
1019 m_outsideGlueVolumes.store(std::make_unique<Trk::GlueVolumesDescriptor>());
1020 }
1021 return (*m_outsideGlueVolumes);
1022}
1023
1026{
1027 if (!m_outsideGlueVolumes) {
1028 m_outsideGlueVolumes.set(std::make_unique<Trk::GlueVolumesDescriptor>());
1029 }
1030 return (*m_outsideGlueVolumes);
1031}
1032
1033void
1035{
1036 if (m_transform) {
1037 Amg::Transform3D transf = shift * (*m_transform);
1038 this->m_transform = std::make_unique<Amg::Transform3D>(transf);
1039 } else {
1040 this->m_transform = std::make_unique<Amg::Transform3D>(shift);
1041 }
1042 this->m_center = (m_transform->translation());
1043}
1044
1045const Trk::Layer*
1047 const Amg::Vector3D& dir,
1048 const Trk::Layer& first,
1049 const Trk::Layer& second)
1050{
1051 // use the distance solution for assigning the layer
1052 Trk::DistanceSolution distSolToPrevious =
1053 first.surfaceRepresentation().straightLineDistanceEstimate(pos, dir);
1054 Trk::DistanceSolution distSolToNext =
1055 second.surfaceRepresentation().straightLineDistanceEstimate(pos, dir);
1056 // find out which one
1057 return (distSolToPrevious.absClosest() < distSolToNext.absClosest()
1058 ? &first
1059 : &second);
1060}
1061
1062void
1064{
1065
1066 this->moveVolume(transform);
1067
1068 // confined 'ordered' layers
1070 if (confLayers)
1071 for (Trk::Layer* clayIter : confLayers->arrayObjects()){
1072 clayIter->moveLayer(transform);
1073 }
1074
1075 // confined 'unordered' layers
1076 Trk::ArraySpan<Trk::Layer* const> confArbLayers =
1078 if (!confArbLayers.empty()){
1079 for (Trk::Layer* calayIter : confArbLayers){
1080 calayIter->moveLayer(transform);
1081 }
1082 }
1083
1084 // confined volumes
1086 if (confVolumes){
1087 // retrieve array objects and apply the transform
1088 for (Trk::TrackingVolume* cVolumesIter : confVolumes->arrayObjects()){
1089 (cVolumesIter)->moveTV(transform);
1090 }
1091 }
1092
1093 // confined unordered volumes
1095 if (!confDenseVolumes.empty())
1096 // retrieve array objects and apply the transform
1097 for (Trk::TrackingVolume* cVolumesIter : confDenseVolumes){
1098 cVolumesIter->moveTV(transform);
1099 }
1100}
1101
1102void
1103Trk::TrackingVolume::synchronizeLayers(MsgStream& msgstream, double envelope)
1104{
1105 // case a : Layers exist
1107 if (confLayers) {
1108 for (Trk::Layer* clay : confLayers->arrayObjects())
1109 if (clay) {
1110 if (clay->surfaceRepresentation().type() ==
1112 !(center().isApprox(clay->surfaceRepresentation().center()))) {
1113 clay->resizeAndRepositionLayer(volumeBounds(), center(), envelope);
1114 } else {
1115 clay->resizeLayer(volumeBounds(), envelope);
1116 }
1117 } else
1118 msgstream << MSG::WARNING
1119 << " ---> found 0 pointer to layer in Volume [ "
1120 << volumeName() << " ], indicates problem." << endmsg;
1121 }
1122 // case b : container volume -> step down
1124 if (confVolumes) {
1125 for (const auto& cVolumesIter : confVolumes->arrayObjects())
1126 cVolumesIter->synchronizeLayers(msgstream, envelope);
1127 }
1128}
1129
1130void
1131Trk::TrackingVolume::compactify(size_t& cSurfaces, size_t& tSurfaces)
1132{
1133 // confined 'ordered' layers
1135 if (confLayers) {
1136 std::span<Trk::Layer* const> layers = confLayers->arrayObjects();
1137 for (const auto& clayIter : layers) {
1138 if (&(*clayIter) != nullptr){
1139 clayIter->compactify(cSurfaces, tSurfaces);
1140 }
1141 else{
1142 std::cout << "WARNING: Attempt to compactify nullptr layer in volume : "
1143 << volumeName() << std::endl;
1144 }
1145 }
1146 }
1147 // confined 'unordered' layers
1149 if (!confArbLayers.empty()) {
1150 for (const auto& calayIter : confArbLayers) {
1151 if (calayIter != nullptr) {
1152 calayIter->compactify(cSurfaces, tSurfaces);
1153 } else {
1154 std::cout << "WARNING: Attempt to compactify nullptr layer."
1155 << std::endl;
1156 }
1157 }
1158 }
1159 // confined volumes
1161 if (confVolumes) {
1162 std::span<Trk::TrackingVolume* const> volumes =
1163 confVolumes->arrayObjects();
1164 for (const auto& cVolumesIter : volumes) {
1165 cVolumesIter->compactify(cSurfaces, tSurfaces);
1166 }
1167 }
1168 // confined unordered volumes
1170 if (!confDenseVolumes.empty()){
1171 for (const auto& cVolumesIter : (confDenseVolumes)) {
1172 cVolumesIter->compactify(cSurfaces, tSurfaces);
1173 }
1174 }
1175
1176 // detached volumes if any
1178 for (const auto& cdVolumesIter : (*m_confinedDetachedVolumes)) {
1179 cdVolumesIter->compactify(cSurfaces, tSurfaces);
1180 }
1181 }
1182}
1183
1184void
1186{
1187 msg << "[[ Trk::TrackingVolume ]] called: " << volumeName() << std::endl;
1188 msg << '\t' << '\t' << "# position (x,y,z) : " << center().x() << ", "
1189 << center().y() << ", " << center().z() << std::endl;
1190 msg << '\t' << '\t' << "# bounds : " << volumeBounds() << endmsg;
1191}
1192
#define endmsg
#define TRKDETDESCR_GEOMETRYSIGNATUREWEIGHT
Definition LayerIndex.h:19
constexpr int pow(int base, int exp) noexcept
A generic symmetric BinUtility, for fully symmetric binning in terms of binning grid and binning type...
Definition BinUtility.h:39
BinningValue binningValue(size_t ba=0) const
The type/value of the binning.
Definition BinUtility.h:230
Binned Array for avoiding map searches/.
Definition BinnedArray.h:36
virtual std::span< T *const > arrayObjects()=0
Return all objects of the Array non-const we can still modify the T.
The BoundaryCheck class allows to steer the way surface boundaries are used for inside/outside checks...
BoundaryCylinderSurface description inside the tracking realm, Extends the Surface description to mak...
BoundaryDiscSurface description inside the tracking realm, it extends the DiscSurface description to ...
BoundaryPlaneSurface description inside the tracking realm, it extends the PlaneSurface description t...
BoundarySubtractedCylinderSurface description inside the tracking realm, it extends the Surface descr...
BoundarySubtractedPlaneSurface description inside the tracking realm, it extends the SubtractedPlaneS...
Description of a BoundarySurface inside the tracking realm, it extends the Surface description to mak...
Bounds for a generic combined volume, the decomposeToSurfaces method creates a vector of n surfaces (...
const std::vector< bool > & boundsOrientation() const
This method returns bounds orientation.
Class for a CylinderSurface in the ATLAS detector.
Class for a DiscSurface in the ATLAS detector.
Definition DiscSurface.h:54
Access to distance solutions.
double absClosest() const
Absolute Distance to closest solution.
Descriptor class to hold GlueVolumes of a TrackingGeometry object.
LayerIndex for the identification of layers in a simplified detector geometry of Cylinders and Discs.
Definition LayerIndex.h:37
int value() const
layerIndex expressed in an integer
Definition LayerIndex.h:71
Base Class for a Detector Layer in the Tracking realm.
Definition Layer.h:72
virtual const Surface & surfaceRepresentation() const =0
Transforms the layer into a Surface representation for extrapolation.
const Layer * previousLayer(bool skipNavLayer=false) const
getting what's stored to be the previous Layer, boolean to skip navigation layers
Definition Layer.cxx:141
const Layer * nextLayer(const Amg::Vector3D &gp, const Amg::Vector3D &udir) const
getting the next/previous Layer if registered - unit for direction vector required
Definition Layer.cxx:161
const LayerMaterialProperties * layerMaterialProperties() const
getting the LayerMaterialProperties including full/pre/post update
void registerLayerIndex(const LayerIndex &lIdx)
const LayerIndex & layerIndex() const
get the layerIndex
A material layer is a simple helper class to attach material information to a boundary surface.
virtual const Surface & surfaceRepresentation() const override=0
Transforms the layer into a Surface representation for extrapolation.
A common object to be contained by.
Definition Material.h:117
Material()
Default Constructor needed for POOL.
Definition Material.h:130
Avoiding a map search, the templated BinnedArray class can help ordereing geometrical objects by prov...
Class to be used for gaps in Volumes as a navigational link.
Class to describe a planar detector layer for tracking, it inhertis from both, Layer base class and P...
Definition PlaneLayer.h:40
Class for a planaer rectangular or trapezoidal surface in the ATLAS detector.
Bounds for the exact transcript of the GeoSimplePolygonBrep; volume defined by combination of symm....
Class for a cylinder subtracted/shared surface in the ATLAS detector.
Class for a planar subtracted/shared surface in the ATLAS detector.
Bounds for a generic subtracted volume, the decomposeToSurfaces method creates a vector of n surfaces...
const std::vector< bool > & boundsOrientation() const
This method returns bounds orientation.
Abstract Base Class for tracking surfaces.
const Trk::MaterialLayer * materialLayer() const
return the material Layer
Full Volume description used in Tracking, it inherits from Volume to get the geometrical structure,...
const LayerArray * confinedLayers() const
Return the subLayer array.
const TrackingVolume * nextVolume(const Amg::Vector3D &gp, const Amg::Vector3D &dir, PropDirection pDir=alongMomentum) const
Return the next volume along the navigation stream.
LayerIntersection< Amg::Vector3D > closestMaterialLayer(const Amg::Vector3D &gp, const Amg::Vector3D &dir, PropDirection pDir=alongMomentum, const BoundaryCheck &bchk=true) const
Return the closest layer with material description.
void moveTV(Amg::Transform3D &transform)
move the Tracking Volume
void indexContainedMaterialLayers(GeometrySignature geoSig, int &offset)
reIndex the material layers of the TrackingVolume
const TrackingVolume * nextSubVolume(const Amg::Vector3D &gp, const Amg::Vector3D &dir) const
Return the next sub Volume if existing, returns THIS if no subVolume exists.
std::unique_ptr< LayerAttemptsCalculator > m_layerAttemptsCalculator
defines how the Extrapolator propagates through this
TrackingVolume()=default
Default Constructor.
const Layer * associatedLayer(const Amg::Vector3D &gp) const
Return the associated Layer.
unsigned int m_colorCode
Color code for displaying.
const LayerArray * checkoutConfinedLayers() const
Return the subLayerarray including the ownership.
const TrackingVolumeArray * confinedVolumes() const
Return the subLayer array.
std::vector< const DetachedTrackingVolume * > assocDetachedSubVolumes(const Amg::Vector3D &gp, double tol) const
Return the associated detached subvolumes.
std::unique_ptr< const std::vector< TrackingVolume * > > m_confinedDenseVolumes
Additionally, Unordered Layers inside the Volume (we own the elements)
const TrackingVolume * associatedSubVolume(const Amg::Vector3D &gp) const
Return the associated sub Volume, returns THIS if no subVolume exists.
void indexContainedStaticLayers(GeometrySignature geoSig, int &offset)
reIndex the static layers of the TrackingVolume
std::vector< std::shared_ptr< BoundarySurface< TrackingVolume > > > & boundarySurfaces()
Method to return the BoundarySurfaces.
const std::string & volumeName() const
Returns the VolumeName - for debug reason, might be depreciated later.
std::unique_ptr< const std::vector< DetachedTrackingVolume * > > m_confinedDetachedVolumes
Additionally, Unordered subvolumes (we own the elements)
std::unique_ptr< LayerArray > m_confinedLayers
Array of Volumes inside the Volume.
const Layer * nextLayer(const Amg::Vector3D &gp, const Amg::Vector3D &mom, bool asres=true, bool skipNavLayer=false) const
Return the next Layer if existing, NULL if no next layer corresponds.
std::unique_ptr< TrackingVolumeArray > m_confinedVolumes
Detached subvolumes.
std::string m_name
Volume name for debug reasons.
void registerOutsideGlueVolumes(GlueVolumesDescriptor *gvd)
Register the outside glue volumes - ordering is in the TrackingVolume Frame:
void addMaterial(const Material &mat, float fact=1.)
add Material
void interlinkLayers()
Register Next - Previous for Layers, set volumelink.
void synchronizeLayers(MsgStream &msgstream, double envelope=1.)
method to synchronize the layers with potentially updated volume bounds:
void moveVolume(Amg::Transform3D &shift)
move Volume
CxxUtils::CachedUniquePtrT< GlueVolumesDescriptor > m_outsideGlueVolumes
provided the number of layer attempts
ArraySpan< DetachedTrackingVolume const *const > confinedDetachedVolumes() const
Return detached subVolumes - not the ownership.
void sign(GeometrySignature signat, GeometryType gtype=Static)
sign the volume - the geometry builder has to do that
void compactify(size_t &rSurfaces, size_t &tSurfaces)
compactify the memory usage in the event by setting ownership to TackingGeometry the referenced types...
const TrackingVolume * m_motherVolume
boundary Surfaces, they can be shared between volumes
std::vector< std::shared_ptr< BoundarySurface< TrackingVolume > > > m_boundarySurfaces
GeometryType m_geometryType
The Signature done by the GeometryBuilder.
void createLayerAttemptsCalculator()
Create Layer Attempts Caluclator.
std::unique_ptr< const std::vector< Layer * > > m_confinedArbitraryLayers
void screenDump(MsgStream &msg) const
GlueVolumesDescriptor & glueVolumesDescriptor()
const BoundarySurface< TrackingVolume > * boundarySurface(const ObjectAccessor::value_type &oa) const
Get the BoundarySurface to the appointed Accessor state.
static const Layer * closest(const Amg::Vector3D &pos, const Amg::Vector3D &dir, const Layer &first, const Layer &second)
Helper method - find closest of two layers.
ArraySpan< Layer const *const > confinedArbitraryLayers() const
Return the confined subLayer array.
void createBoundarySurfaces()
Create Boundary Surface.
ArraySpan< TrackingVolume const *const > confinedDenseVolumes() const
Return unordered subVolumes - not the ownership.
virtual ~TrackingVolume() override
Destructor.
GeometrySignature m_geometrySignature
virtual std::vector< std::unique_ptr< Trk::Surface > > decomposeToSurfaces(const Amg::Transform3D &transform)=0
Method to decompose the Bounds into Surfaces, the Volume can turn them into BoundarySurfaces.
Volume()=default
Defaults copies are special due ot unique ptr data member.
const Amg::Vector3D & center() const
returns the center of the volume
Definition Volume.h:90
const Amg::Transform3D & transform() const
Return methods for geometry transform.
Definition Volume.h:83
const VolumeBounds & volumeBounds() const
returns the volumeBounds()
Definition Volume.h:96
Amg::Vector3D m_center
center position of the surface
Definition Volume.h:79
std::unique_ptr< Amg::Transform3D > m_transform
Transform3D (optional)
Definition Volume.h:78
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
PropDirection
PropDirection, enum for direction of the propagation.
@ oppositeMomentum
@ alongMomentum
@ mappingMode
BinnedArray< Layer > LayerArray
simply for the eye
std::span< T > ArraySpan
BinnedArray< Surface > SurfaceArray
Definition Layer.h:40
FullIntersection< Layer, Surface, T > LayerIntersection
@ binR
Definition BinningType.h:50
@ binZ
Definition BinningType.h:49
STL namespace.
MsgStream & msg
Definition testRead.cxx:32