14 #include "GaudiKernel/EventContext.h"
23 #include "GeoModelKernel/GeoTube.h"
26 #include "Acts/ActsVersion.hpp"
27 #include "Acts/Geometry/Blueprint.hpp"
28 #include "Acts/Geometry/ContainerBlueprintNode.hpp"
29 #include "Acts/Geometry/CylinderVolumeBounds.hpp"
30 #include "Acts/Geometry/CylinderVolumeBuilder.hpp"
31 #include "Acts/Geometry/CylinderVolumeHelper.hpp"
32 #include "Acts/Geometry/ITrackingVolumeBuilder.hpp"
33 #include "Acts/Geometry/LayerArrayCreator.hpp"
34 #include "Acts/Geometry/LayerCreator.hpp"
35 #include "Acts/Geometry/SurfaceArrayCreator.hpp"
36 #include "Acts/Geometry/TrackingGeometry.hpp"
37 #include "Acts/Geometry/TrackingGeometryBuilder.hpp"
38 #include "Acts/Geometry/TrackingVolume.hpp"
39 #include "Acts/Geometry/TrackingVolumeArrayCreator.hpp"
40 #include "Acts/Utilities/Logger.hpp"
41 #include "Acts/Definitions/Units.hpp"
42 #include "Acts/Geometry/PassiveLayerBuilder.hpp"
43 #include <Acts/Plugins/Json/JsonMaterialDecorator.hpp>
44 #include <Acts/Plugins/Json/MaterialMapJsonConverter.hpp>
45 #include <Acts/Surfaces/PlanarBounds.hpp>
46 #include <Acts/Surfaces/AnnulusBounds.hpp>
47 #include <Acts/Surfaces/DiscSurface.hpp>
48 #include <Acts/Surfaces/LineSurface.hpp>
49 #include <Acts/Surfaces/RectangleBounds.hpp>
50 #include <Acts/Visualization/ObjVisualization3D.hpp>
62 #include <Acts/Utilities/AxisDefinitions.hpp>
67 using namespace Acts::UnitLiterals;
72 m_detStore(
"StoreGateSvc/DetectorStore",
name),
84 return StatusCode::FAILURE;
94 m_autoRetrieveTools =
false;
95 m_checkToolDeps =
false;
98 << Acts::VersionMajor <<
"." << Acts::VersionMinor <<
"."
99 << Acts::VersionPatch <<
" [" << Acts::CommitHash <<
"]");
104 ATH_MSG_INFO(
"Configured to build " << buildSubdet.size()
105 <<
" subdetectors:");
106 for (
const auto &
s : buildSubdet) {
111 if (buildSubdet.find(
"Pixel") != buildSubdet.end()) {
114 if (buildSubdet.find(
"SCT") != buildSubdet.end()) {
117 if (buildSubdet.find(
"TRT") != buildSubdet.end()) {
121 if (buildSubdet.find(
"ITkPixel") != buildSubdet.end()) {
124 if (buildSubdet.find(
"ITkStrip") != buildSubdet.end()) {
127 if (buildSubdet.find(
"HGTD") != buildSubdet.end()) {
139 ATH_MSG_FATAL(
"Consistency check for ITk inner pixel barrel passive layer construction failed. Please check your inputs! ");
140 return StatusCode::FAILURE;
145 ATH_MSG_FATAL(
"Consistency check for ITk outer pixel barrel passive layer construction failed. Please check your inputs! ");
146 return StatusCode::FAILURE;
151 ATH_MSG_FATAL(
"Consistency check for ITk strip barrel passive layer construction failed. Please check your inputs! ");
152 return StatusCode::FAILURE;
158 ATH_MSG_INFO(
"Using Blueprint API for geometry construction");
164 using enum Acts::AxisDirection;
166 std::vector<ActsTrk::IBlueprintNodeBuilder*> ptrBuilders;
168 std::back_inserter(ptrBuilders),
169 [](ToolHandle<ActsTrk::IBlueprintNodeBuilder>&
b) { return b.get(); });
173 Acts::Experimental::Blueprint::Config
cfg;
174 cfg.envelope[AxisZ] = {20_mm, 20_mm};
175 cfg.envelope[AxisR] = {0_mm, 20_mm};
177 auto blueprint = std::make_unique<Acts::Experimental::Blueprint>(
cfg);
179 auto&
root = blueprint->addCylinderContainer(
"Detector", AxisZ);
181 std::shared_ptr<Acts::Experimental::BlueprintNode> currentTop{
nullptr};
183 for (
auto&
builder : ptrBuilders) {
188 root.addChild(std::move(currentTop));
194 Acts::ObjVisualization3D vis;
196 {.visible =
false}, {.visible =
true});
197 vis.write(
"blueprint_sensitive.obj");
201 {.visible =
false}, {.visible =
false});
202 vis.write(
"blueprint_volume.obj");
206 {.visible =
true}, {.visible =
false});
207 vis.write(
"blueprint_portals.obj");
212 return StatusCode::SUCCESS;
217 Acts::LayerArrayCreator::Config lacCfg;
218 auto layerArrayCreator = std::make_shared<const Acts::LayerArrayCreator>(
221 Acts::TrackingVolumeArrayCreator::Config tvcCfg;
222 auto trackingVolumeArrayCreator =
223 std::make_shared<const Acts::TrackingVolumeArrayCreator>(
226 Acts::CylinderVolumeHelper::Config cvhConfig;
227 cvhConfig.layerArrayCreator = layerArrayCreator;
228 cvhConfig.trackingVolumeArrayCreator = trackingVolumeArrayCreator;
230 auto cylinderVolumeHelper =
231 std::make_shared<const Acts::CylinderVolumeHelper>(
234 Acts::TrackingGeometryBuilder::Config tgbConfig;
235 tgbConfig.trackingVolumeHelper = cylinderVolumeHelper;
238 std::shared_ptr<const Acts::IMaterialDecorator> matDeco =
nullptr;
241 if (matFileFullPath.empty()) {
243 return StatusCode::FAILURE;
245 ATH_MSG_INFO(
"Configured to use material input: " << matFileFullPath);
247 if (matFileFullPath.find(
".json") != std::string::npos) {
249 Acts::MaterialMapJsonConverter::Config jsonGeoConvConfig;
251 matDeco = std::make_shared<const Acts::JsonMaterialDecorator>(
254 tgbConfig.materialDecorator = matDeco;
257 std::array<double, 2> sctECEnvelopeZ{20_mm, 20_mm};
262 tgbConfig.trackingVolumeBuilders.push_back([&](
const auto &gctx,
266 Acts::CylinderVolumeBuilder::Config bpvConfig =
269 Acts::CylinderVolumeBuilder beamPipeVolumeBuilder {
272 return beamPipeVolumeBuilder.trackingVolume(gctx, inner);
279 if (buildSubdet.count(
"Pixel") > 0) {
280 tgbConfig.trackingVolumeBuilders.push_back([&](
const auto &gctx,
285 auto lb = std::make_shared<ActsLayerBuilder>(
287 Acts::CylinderVolumeBuilder::Config cvbConfig;
288 cvbConfig.layerEnvelopeR = {3_mm, 3_mm};
289 cvbConfig.layerEnvelopeZ = 1_mm;
290 cvbConfig.trackingVolumeHelper = cylinderVolumeHelper;
291 cvbConfig.volumeName =
"Pixel";
292 cvbConfig.layerBuilder =
lb;
295 Acts::CylinderVolumeBuilder cvb(
298 return cvb.trackingVolume(gctx, inner);
303 if (buildSubdet.count(
"ITkPixel") > 0) {
304 tgbConfig.trackingVolumeBuilders.push_back(
305 [&](
const auto &gctx,
const auto &inner,
const auto &) {
309 cfg.doEndcapLayerMerging =
true;
313 auto lb = std::make_shared<ActsLayerBuilder>(
316 Acts::CylinderVolumeBuilder::Config cvbConfig;
317 cvbConfig.layerEnvelopeR = {5_mm, 5_mm};
318 cvbConfig.layerEnvelopeZ = 1_mm;
319 cvbConfig.trackingVolumeHelper = cylinderVolumeHelper;
320 cvbConfig.volumeName =
"ITkPixelInner";
321 cvbConfig.layerBuilder =
lb;
324 Acts::CylinderVolumeBuilder cvb(
328 return cvb.trackingVolume(gctx, inner);
331 tgbConfig.trackingVolumeBuilders.push_back(
332 [&](
const auto &gctx,
const auto &inner,
const auto &) {
336 cfg.doEndcapLayerMerging =
false;
340 auto lb = std::make_shared<ActsLayerBuilder>(
343 Acts::CylinderVolumeBuilder::Config cvbConfig;
344 cvbConfig.layerEnvelopeR = {5_mm, 5_mm};
345 cvbConfig.layerEnvelopeZ = 1_mm;
346 cvbConfig.trackingVolumeHelper = cylinderVolumeHelper;
347 cvbConfig.volumeName =
"ITkPixelOuter";
348 cvbConfig.layerBuilder =
lb;
349 cvbConfig.buildToRadiusZero =
false;
350 cvbConfig.checkRingLayout =
true;
351 cvbConfig.ringTolerance = 10_mm;
353 Acts::CylinderVolumeBuilder cvb(
357 return cvb.trackingVolume(gctx, inner);
362 if (buildSubdet.count(
"ITkStrip") > 0) {
363 tgbConfig.trackingVolumeBuilders.push_back(
364 [&](
const auto &gctx,
const auto &inner,
const auto &) {
371 auto lb = std::make_shared<ActsLayerBuilder>(
374 Acts::CylinderVolumeBuilder::Config cvbConfig;
375 cvbConfig.layerEnvelopeR = {5_mm, 5_mm};
376 cvbConfig.layerEnvelopeZ = 1_mm;
377 cvbConfig.trackingVolumeHelper = cylinderVolumeHelper;
378 cvbConfig.volumeName =
"ITkStrip";
379 cvbConfig.layerBuilder =
lb;
380 cvbConfig.buildToRadiusZero =
383 Acts::CylinderVolumeBuilder cvb(
387 return cvb.trackingVolume(gctx, inner);
391 bool buildSCT = buildSubdet.count(
"SCT") > 0;
392 bool buildTRT = buildSubdet.count(
"TRT") > 0;
394 if (buildSCT && buildTRT) {
396 tgbConfig.trackingVolumeBuilders.push_back(
397 [&](
const auto &gctx,
const auto &inner,
const auto &) {
400 cfg.endcapEnvelopeZ = sctECEnvelopeZ;
401 auto sct_lb = std::make_shared<ActsLayerBuilder>(
407 *cylinderVolumeHelper, inner);
410 }
else if (buildSCT) {
411 tgbConfig.trackingVolumeBuilders.push_back(
412 [&](
const auto &gctx,
const auto &inner,
const auto &) {
415 lbCfg.endcapEnvelopeZ = sctECEnvelopeZ;
416 auto lb = std::make_shared<ActsLayerBuilder>(
420 Acts::CylinderVolumeBuilder::Config cvbConfig;
421 cvbConfig.layerEnvelopeR = {5_mm, 5_mm};
422 cvbConfig.layerEnvelopeZ = 2_mm;
423 cvbConfig.trackingVolumeHelper = cylinderVolumeHelper;
424 cvbConfig.volumeName =
"SCT";
425 cvbConfig.layerBuilder =
lb;
426 cvbConfig.buildToRadiusZero =
false;
428 Acts::CylinderVolumeBuilder cvb(
432 return cvb.trackingVolume(gctx, inner);
434 }
else if (buildTRT) {
435 tgbConfig.trackingVolumeBuilders.push_back(
436 [&](
const auto &gctx,
const auto &inner,
const auto &) {
438 Acts::CylinderVolumeBuilder::Config cvbConfig;
439 cvbConfig.layerEnvelopeR = {5_mm, 5_mm};
440 cvbConfig.layerEnvelopeZ = 2_mm;
441 cvbConfig.trackingVolumeHelper = cylinderVolumeHelper;
442 cvbConfig.volumeName =
"TRT";
443 cvbConfig.layerBuilder =
lb;
444 cvbConfig.buildToRadiusZero =
false;
446 Acts::CylinderVolumeBuilder cvb(
450 return cvb.trackingVolume(gctx, inner);
455 if(buildSubdet.count(
"HGTD") > 0) {
456 tgbConfig.trackingVolumeBuilders.push_back(
457 [&](
const auto &gctx,
const auto &inner,
const auto &) {
459 Acts::CylinderVolumeBuilder::Config cvbConfig;
460 cvbConfig.layerEnvelopeR = {5_mm, 5_mm};
461 cvbConfig.layerEnvelopeZ = 1_mm;
462 cvbConfig.trackingVolumeHelper = cylinderVolumeHelper;
463 cvbConfig.volumeName =
"HGTD";
464 cvbConfig.layerBuilder =
lb;
465 cvbConfig.buildToRadiusZero =
false;
467 Acts::CylinderVolumeBuilder cvb(
471 return cvb.trackingVolume(gctx, inner);
477 tgbConfig.trackingVolumeBuilders.push_back(
478 [&](
const auto &gctx,
const auto &inner,
const auto &) {
484 tgbConfig.trackingVolumeBuilders.push_back(
485 [&](
const auto &gctx,
const auto &inner,
const auto &) {
490 ATH_MSG_ERROR(
"Encountered error when building Acts tracking geometry");
492 return StatusCode::FAILURE;
495 auto trackingGeometryBuilder =
496 std::make_shared<const Acts::TrackingGeometryBuilder>(
505 ATH_MSG_ERROR(
"No ACTS tracking geometry was built. Cannot proceeed");
506 return StatusCode::FAILURE;
511 ATH_MSG_INFO(
"Running extra consistency check! (this is SLOW)");
513 ATH_MSG_ERROR(
"Consistency check has failed! Geometry is not consistent");
514 return StatusCode::FAILURE;
518 ATH_MSG_INFO(
"Acts TrackingGeometry construction completed");
520 return StatusCode::SUCCESS;
526 std::vector<Acts::Vector2> localPoints;
529 std::uniform_real_distribution<> dist(0.0, 1.0);
531 std::optional<std::ofstream>
os;
535 throw std::runtime_error{
"Failed to open consistency check output file"};
540 (*os) <<
"geo_id,vol_id,lay_id,sen_id,type,acts_loc0,acts_loc1,acts_inside,trk_loc0,trk_loc1,trk_inside,x,y,z,g2l_loc0,g2l_loc1,trk_x,trk_y,trk_z" << std::endl;
543 localPoints.emplace_back(dist(
gen), dist(
gen));
548 size_t nTotalSensors = 0;
549 std::array<size_t,3> nInconsistent{0,0,0};
550 size_t nMismatchedCenters = 0;
551 size_t nMismatchedNormals = 0;
555 auto isApprox = [](
auto&
a,
auto&
b) ->
bool {
556 return ((
a -
b).array().abs() < 1
e-5).
all();
562 const auto* actsDetElem =
dynamic_cast<const ActsDetectorElement*
>(surface->associatedDetectorElement());
563 if(actsDetElem ==
nullptr) {
569 if(siDetElem ==
nullptr) {
573 const auto* regSurface =
dynamic_cast<const Acts::RegularSurface*
>(surface);
574 const auto& trkSurface = siDetElem->
surface();
575 if(regSurface ==
nullptr) {
581 Acts::Vector3 center{regSurface->center(gctx)};
583 if (
dynamic_cast<const Acts::AnnulusBounds *
>(&surface->bounds()))
588 center.head<2>() = trkCenter.head<2>();
591 if(!isApprox(trkCenter, center)) {
593 if (
auto idHelper = siDetElem->getIdHelper())
595 trkName = idHelper->show_to_string(siDetElem->identify());
598 << surface->geometryId()
599 <<
" center (" << center[0] <<
',' << center[1] <<
',' << center[2]
600 <<
") does not match Trk surface " << trkName
601 <<
" center (" << trkCenter[0] <<
',' << trkCenter[1] <<
',' << trkCenter[2] <<
')');
602 nMismatchedCenters++;
606 const auto* lineSurface =
dynamic_cast<const Acts::LineSurface*
>(surface);
607 if(lineSurface ==
nullptr) {
608 Acts::Vector3
norm{regSurface->normal(gctx, regSurface->center(gctx))};
610 if(!isApprox(trkNorm,
norm)) {
612 if (
auto idHelper = siDetElem->getIdHelper())
614 trkName = idHelper->show_to_string(siDetElem->identify());
617 << surface->geometryId()
618 <<
" normal (" <<
norm[0] <<
',' <<
norm[1] <<
',' <<
norm[2]
619 <<
") does not match Trk surface " << trkName
620 <<
" normal (" << trkNorm[0] <<
',' << trkNorm[1] <<
',' << trkNorm[2] <<
')');
621 nMismatchedNormals++;
626 auto doPoints = [&](
unsigned int type,
const Acts::Vector2& loc) -> std::array<bool,3> {
632 bool locg2lOk =
false;
633 auto locTrkRes = trkSurface.globalToLocal(glb);
635 locTrk = locTrkRes.value();
636 glbTrk = trkSurface.localToGlobal(locTrk);
639 if (locg2lRes.ok()) {
641 locg2l = locg2lRes.value();
645 auto gId = surface->geometryId();
648 <<
"," << gId.volume()
649 <<
"," << gId.layer()
650 <<
"," << gId.sensitive()
654 <<
"," << surface->insideBounds(loc)
657 <<
"," << trkSurface.insideBounds(locTrk)
669 return {surface->insideBounds(loc) == trkSurface.insideBounds(locTrk),
670 locg2lOk ? isApprox(loc, locg2l) :
true,
671 locTrkRes ? isApprox(glb, glbTrk) :
true};
677 std::array<bool,3> allOk{
true,
true,
true};
678 if(
const auto* bounds =
dynamic_cast<const Acts::PlanarBounds*
>(&surface->bounds()); bounds) {
681 const Acts::RectangleBounds& boundingBox = bounds->boundingBox();
682 Acts::Vector2
min = boundingBox.min().array() - envelope;
683 Acts::Vector2
max = boundingBox.max().array() + envelope;
684 Acts::Vector2 diag =
max -
min;
686 for(
const auto& testPoint : localPoints) {
687 Acts::Vector2 loc =
min.array() + (testPoint.array() * diag.array());
688 auto pointOk = doPoints(0, loc);
689 for (
size_t i=0;
i<pointOk.size(); ++
i) {
698 else if(
const auto* bounds =
dynamic_cast<const Acts::AnnulusBounds*
>(&surface->bounds()); bounds) {
702 std::vector<Acts::Vector2> vertices = bounds->vertices(5);
704 Acts::Vector2
max{std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest()};
705 for (
const auto& vtx : vertices) {
706 min =
min.array().min(vtx.array());
707 max =
max.array().max(vtx.array());
709 min.array() -= envelope;
710 max.array() += envelope;
711 Acts::Vector2 diag =
max -
min;
713 for(
const auto& testPoint : localPoints) {
714 Acts::Vector2 locXY =
min.array() + (testPoint.array() * diag.array());
715 Acts::Vector2 locPC =
dynamic_cast<const Acts::DiscSurface&
>(*surface).localCartesianToPolar(locXY);
717 auto pointOk = doPoints(1, locPC);
718 for (
size_t i=0;
i<pointOk.size(); ++
i) {
731 for (
size_t i=0;
i<allOk.size(); ++
i) {
739 ATH_MSG_INFO(
"Total number of sensors : " << nTotalSensors);
740 ATH_MSG_INFO(
"Number of sensors with mismatched centers : " << nMismatchedCenters);
741 ATH_MSG_INFO(
"Number of sensors with mismatched normals : " << nMismatchedNormals);
742 ATH_MSG_INFO(
"Number of sensors with inconsistent inside: " << nInconsistent[0]);
743 ATH_MSG_INFO(
"Number of sensors with inconsistent g2l : " << nInconsistent[1]);
744 ATH_MSG_INFO(
"Number of sensors with inconsistent l2g : " << nInconsistent[2]);
749 std::shared_ptr<const Acts::TrackingGeometry>
756 std::shared_ptr<const Acts::ILayerBuilder>
760 std::string managerName =
manager->getName();
761 auto matcher = [](
const Acts::GeometryContext & ,
762 Acts::AxisDirection ,
const Acts::Surface * ,
763 const Acts::Surface *
764 ) ->
bool {
return false; };
766 Acts::SurfaceArrayCreator::Config sacCfg;
767 sacCfg.surfaceMatcher = matcher;
768 sacCfg.doPhiBinningOptimization =
false;
770 auto surfaceArrayCreator = std::make_shared<Acts::SurfaceArrayCreator>(
773 Acts::LayerCreator::Config lcCfg;
774 lcCfg.surfaceArrayCreator = surfaceArrayCreator;
775 auto layerCreator = std::make_shared<Acts::LayerCreator>(
781 cfg.layerCreator = layerCreator;
783 return std::make_shared<const ActsStrawLayerBuilder>(
787 std::shared_ptr<const Acts::ILayerBuilder>
791 std::string managerName =
manager->getName();
792 auto matcher = [](
const Acts::GeometryContext & ,
793 Acts::AxisDirection ,
const Acts::Surface * ,
794 const Acts::Surface *
795 ) ->
bool {
return false; };
797 Acts::SurfaceArrayCreator::Config sacCfg;
798 sacCfg.surfaceMatcher = matcher;
799 sacCfg.doPhiBinningOptimization =
false;
801 auto surfaceArrayCreator = std::make_shared<Acts::SurfaceArrayCreator>(
804 Acts::LayerCreator::Config lcCfg;
805 lcCfg.surfaceArrayCreator = surfaceArrayCreator;
806 auto layerCreator = std::make_shared<Acts::LayerCreator>(
812 cfg.layerCreator = layerCreator;
814 return std::make_shared<const ActsHGTDLayerBuilder>(
820 using enum Acts::AxisDirection;
822 std::string managerName =
manager->getName();
824 std::shared_ptr<const Acts::ILayerBuilder> gmLayerBuilder;
825 auto matcher = [](
const Acts::GeometryContext & ,
826 Acts::AxisDirection aDir,
const Acts::Surface *aS,
827 const Acts::Surface *bS) ->
bool {
829 aS->associatedDetectorElement());
831 bS->associatedDetectorElement());
832 if ((not
a) or (not
b)) {
833 throw std::runtime_error(
834 "Cast of surface associated element to ActsDetectorElement failed "
835 "in ActsTrackingGeometrySvc::makeVolumeBuilder");
843 if (idA.
bec() != idB.
bec())
846 if (aDir == AxisPhi) {
865 Acts::SurfaceArrayCreator::Config sacCfg;
866 sacCfg.surfaceMatcher = matcher;
868 auto surfaceArrayCreator = std::make_shared<Acts::SurfaceArrayCreator>(
871 Acts::LayerCreator::Config lcCfg;
872 lcCfg.surfaceArrayCreator = surfaceArrayCreator;
873 auto layerCreator = std::make_shared<Acts::LayerCreator>(
877 cfg.surfaceMatcher = matcher;
881 throw std::invalid_argument(
"Number of barrel material bin counts != 2");
884 cfg.barrelMaterialBins = {brlBins.at(0), brlBins.at(1)};
887 throw std::invalid_argument(
"Number of endcap material bin counts != 2");
890 cfg.endcapMaterialBins = {ecBins.at(0), ecBins.at(1)};
895 cfg.layerCreator = layerCreator;
905 std::shared_ptr<Acts::TrackingVolume>
907 const Acts::GeometryContext &gctx,
const Acts::ILayerBuilder &sct_lb,
908 const Acts::ILayerBuilder &trt_lb,
const Acts::CylinderVolumeHelper &cvh,
909 const std::shared_ptr<const Acts::TrackingVolume> &pixel) {
912 Acts::CylinderVolumeBuilder::Config cvbCfg;
913 Acts::CylinderVolumeBuilder cvb(
917 Acts::VolumeConfig sctNegEC =
918 cvb.analyzeContent(gctx, sct_lb.negativeLayers(gctx), {});
920 Acts::VolumeConfig sctPosEC =
921 cvb.analyzeContent(gctx, sct_lb.positiveLayers(gctx), {});
923 Acts::VolumeConfig sctBrl =
924 cvb.analyzeContent(gctx, sct_lb.centralLayers(gctx), {});
927 Acts::VolumeConfig trtNegEC =
928 cvb.analyzeContent(gctx, trt_lb.negativeLayers(gctx), {});
930 Acts::VolumeConfig trtPosEC =
931 cvb.analyzeContent(gctx, trt_lb.positiveLayers(gctx), {});
933 Acts::VolumeConfig trtBrl =
934 cvb.analyzeContent(gctx, trt_lb.centralLayers(gctx), {});
938 double absZMinEC =
std::min(std::abs(trtNegEC.zMax), std::abs(trtPosEC.zMin));
939 double absZMaxEC =
std::max(std::abs(trtNegEC.zMin), std::abs(trtPosEC.zMax));
941 trtNegEC.zMin = -absZMaxEC;
942 trtNegEC.zMax = -absZMinEC;
943 trtPosEC.zMin = absZMinEC;
944 trtPosEC.zMax = absZMaxEC;
946 using CVBBV = Acts::CylinderVolumeBounds::BoundValues;
949 bool isSCTSmallerInZ =
false;
951 ATH_MSG_VERBOSE(
"Shrinking SCT in R (and maybe in increase size in Z) to fit around Pixel");
952 auto pixelBounds =
dynamic_cast<const Acts::CylinderVolumeBounds *
>(
953 &
pixel->volumeBounds());
954 double sctNegECzMin =
std::min(sctNegEC.zMin, -pixelBounds->get(CVBBV::eHalfLengthZ));
955 double sctPosECzMax =
std::max(sctPosEC.zMax, pixelBounds->get(CVBBV::eHalfLengthZ));
957 ATH_MSG_VERBOSE(
"- SCT +-EC.rMin: " << sctNegEC.rMin <<
" -> " << pixelBounds->get(CVBBV::eMaxR));
958 ATH_MSG_VERBOSE(
"- SCT BRL.rMin: " << sctBrl.rMin <<
" -> " << pixelBounds->get(CVBBV::eMaxR));
959 ATH_MSG_VERBOSE(
"- SCT EC.zMin: " << sctNegEC.zMin <<
" -> " << sctNegECzMin);
960 ATH_MSG_VERBOSE(
"- SCT EC.zMax: " << sctPosEC.zMax <<
" -> " << sctPosECzMax);
962 sctNegEC.rMin = pixelBounds->get(CVBBV::eMaxR);
963 sctPosEC.rMin = pixelBounds->get(CVBBV::eMaxR);
964 sctBrl.rMin = pixelBounds->get(CVBBV::eMaxR);
966 isSCTSmallerInZ = sctPosEC.zMax < pixelBounds->get(CVBBV::eHalfLengthZ);
968 sctNegEC.zMin = sctNegECzMin;
969 sctPosEC.zMax = sctPosECzMax;
979 << sctNegEC.toString());
980 ATH_MSG_VERBOSE(
"- SCT::Barrel: " << sctBrl.layers.size() <<
" layers, "
981 << sctBrl.toString());
984 << sctPosEC.toString());
989 << trtNegEC.toString());
990 ATH_MSG_VERBOSE(
"- TRT::Barrel: " << trtBrl.layers.size() <<
" layers, "
991 << trtBrl.toString());
994 << trtPosEC.toString());
998 sctBrl.zMax = (sctBrl.zMax + sctPosEC.zMin) / 2.;
999 sctBrl.zMin = -sctBrl.zMax;
1003 trtBrl.zMin = sctBrl.zMin;
1004 trtBrl.zMax = sctBrl.zMax;
1007 trtNegEC.zMin = sctNegEC.zMin;
1008 trtPosEC.zMax = sctPosEC.zMax;
1011 trtNegEC.zMax = trtBrl.zMin;
1012 sctNegEC.zMax = trtBrl.zMin;
1013 trtPosEC.zMin = trtBrl.zMax;
1014 sctPosEC.zMin = trtBrl.zMax;
1017 sctBrl.rMax = trtBrl.rMin;
1018 sctNegEC.rMax = trtNegEC.rMin;
1019 sctPosEC.rMax = trtPosEC.rMin;
1022 trtNegEC.rMax = trtBrl.rMax;
1023 trtPosEC.rMax = trtBrl.rMax;
1025 ATH_MSG_VERBOSE(
"Dimensions after synchronization between SCT and TRT");
1029 << sctNegEC.toString());
1030 ATH_MSG_VERBOSE(
"- SCT::Barrel: " << sctBrl.layers.size() <<
" layers, "
1031 << sctBrl.toString());
1034 << sctPosEC.toString());
1039 << trtNegEC.toString());
1040 ATH_MSG_VERBOSE(
"- TRT::Barrel: " << trtBrl.layers.size() <<
" layers, "
1041 << trtBrl.toString());
1044 << trtPosEC.toString());
1046 auto makeTVol = [&](
const auto &vConf,
const auto &
name) {
1047 return cvh.createTrackingVolume(gctx, vConf.layers, {},
1049 vConf.rMin, vConf.rMax, vConf.zMin,
1054 auto tvSctNegEC = makeTVol(sctNegEC,
"SCT::NegativeEndcap");
1055 auto tvSctBrl = makeTVol(sctBrl,
"SCT::Barrel");
1056 auto tvSctPosEC = makeTVol(sctPosEC,
"SCT::PositiveEndcap");
1058 auto tvTrtNegEC = makeTVol(trtNegEC,
"TRT::NegativeEndcap");
1059 auto tvTrtBrl = makeTVol(trtBrl,
"TRT::Barrel");
1060 auto tvTrtPosEC = makeTVol(trtPosEC,
"TRT::PositiveEndcap");
1064 cvh.createContainerTrackingVolume(gctx, {tvSctNegEC, tvTrtNegEC});
1066 cvh.createContainerTrackingVolume(gctx, {tvSctPosEC, tvTrtPosEC});
1067 auto barrel = cvh.createContainerTrackingVolume(gctx, {tvSctBrl, tvTrtBrl});
1072 cvh.createContainerTrackingVolume(gctx, {negEC,
barrel, posEC});
1077 auto containerBounds =
dynamic_cast<const Acts::CylinderVolumeBounds *
>(
1078 &container->volumeBounds());
1079 auto pixelBounds =
dynamic_cast<const Acts::CylinderVolumeBounds *
>(
1080 &
pixel->volumeBounds());
1081 std::vector<std::shared_ptr<Acts::TrackingVolume>> noVolumes;
1083 if(!isSCTSmallerInZ) {
1085 auto posGap = cvh.createGapTrackingVolume(
1088 pixelBounds->get(CVBBV::eMinR), pixelBounds->get(CVBBV::eMaxR),
1089 pixelBounds->get(CVBBV::eHalfLengthZ),
1090 containerBounds->get(CVBBV::eHalfLengthZ),
1093 "Pixel::PositiveGap");
1094 auto negGap = cvh.createGapTrackingVolume(
1097 pixelBounds->get(CVBBV::eMinR), pixelBounds->get(CVBBV::eMaxR),
1098 -containerBounds->get(CVBBV::eHalfLengthZ),
1099 -pixelBounds->get(CVBBV::eHalfLengthZ),
1102 "Pixel::NegativeGap");
1105 cvh.createContainerTrackingVolume(gctx, {negGap,
pixel, posGap});
1108 cvh.createContainerTrackingVolume(gctx, {
pixelContainer, container});
1113 cvh.createContainerTrackingVolume(gctx, {
pixel, container});
1122 ATH_MSG_DEBUG(
"Populate the alignment store with all detector elements");
1123 unsigned int nElements = 0;
1125 const auto *detElem =
dynamic_cast<const IDetectorElement *
>(srf->associatedDetectorElement());
1131 ATH_MSG_DEBUG(
"Populated with " << nElements <<
" elements");
1136 Acts::CylinderVolumeBuilder::Config
1138 std::shared_ptr<const Acts::CylinderVolumeHelper> cvh)
const {
1148 Acts::Transform3 beamPipeTransform;
1149 beamPipeTransform.setIdentity();
1151 beamPipeTransform = Acts::Translation3(beamPipeTopVolume->getX().translation());
1153 double beamPipeRadius = 20;
1155 const GeoLogVol* beamPipeLogVolume = beamPipeTopVolume->getLogVol();
1156 const GeoTube* beamPipeTube =
nullptr;
1159 if (beamPipeLogVolume ==
nullptr) {
1161 throw std::runtime_error(
"Beam pip volume has no log volume");
1164 beamPipeTube =
dynamic_cast<const GeoTube*
>(beamPipeLogVolume->getShape());
1165 if (beamPipeTube ==
nullptr){
1167 throw std::runtime_error{
"BeamPipeLogVolume was not of type GeoTube"};
1170 for(
unsigned int i=0;
i<beamPipeTopVolume->getNChildVols();
i++) {
1172 if(beamPipeTopVolume->getNameOfChildVol(
i) ==
"SectionC03"){
1174 PVConstLink childTopVolume = beamPipeTopVolume->getChildVol(
i);
1175 const GeoLogVol* childLogVolume = childTopVolume->getLogVol();
1176 const GeoTube* childTube =
nullptr;
1178 if (childLogVolume){
1179 childTube =
dynamic_cast<const GeoTube*
>(childLogVolume->getShape());
1181 beamPipeRadius = 0.5 * (childTube->getRMax()+childTube->getRMin());
1190 ATH_MSG_VERBOSE(
"BeamPipe constructed from Database: translation (yes) - radius "
1191 << ( beamPipeTube ?
"(yes)" :
"(no)") <<
" - r = " << beamPipeRadius );
1195 Acts::CylinderVolumeBuilder::Config
cfg;
1197 Acts::PassiveLayerBuilder::Config bplConfig;
1198 bplConfig.layerIdentification =
"BeamPipe";
1199 bplConfig.centralLayerRadii = {beamPipeRadius * 1_mm};
1200 bplConfig.centralLayerHalflengthZ = {3000_mm};
1201 bplConfig.centralLayerThickness = {1_mm};
1202 auto beamPipeBuilder = std::make_shared<const Acts::PassiveLayerBuilder>(
1206 cfg.trackingVolumeHelper = cvh;
1207 cfg.volumeName =
"BeamPipe";
1208 cfg.layerBuilder = beamPipeBuilder;
1209 cfg.layerEnvelopeR = {1_mm, 1_mm};
1210 cfg.buildToRadiusZero =
true;