File indexing completed on 2025-08-05 08:08:51
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "ActsExamples/GeoModelDetector/GeoModelMuonMockupBuilder.hpp"
0010
0011 #include "Acts/Definitions/Units.hpp"
0012 #include "Acts/Geometry/Blueprint.hpp"
0013 #include "Acts/Geometry/ContainerBlueprintNode.hpp"
0014 #include "Acts/Geometry/CylinderVolumeBounds.hpp"
0015 #include "Acts/Geometry/GeometryContext.hpp"
0016 #include "Acts/Geometry/TrackingVolume.hpp"
0017 #include "Acts/Geometry/TrapezoidVolumeBounds.hpp"
0018 #include "Acts/Geometry/VolumeAttachmentStrategy.hpp"
0019 #include "Acts/Utilities/AxisDefinitions.hpp"
0020 #include "Acts/Utilities/MathHelpers.hpp"
0021
0022 #include "GeoModelKernel/throwExcept.h"
0023
0024 using namespace Acts::UnitLiterals;
0025
0026 namespace ActsExamples {
0027
0028 GeoModelMuonMockupBuilder::GeoModelMuonMockupBuilder(
0029 const Config& cfg, std::unique_ptr<const Acts::Logger> logger)
0030 : m_cfg(cfg), m_logger(std::move(logger)) {}
0031
0032 std::unique_ptr<const Acts::TrackingGeometry>
0033 GeoModelMuonMockupBuilder::trackingGeometry(
0034 const Acts::GeometryContext& gctx) const {
0035 ConvertedVolList_t boundingBoxes = m_cfg.volumeBoxFPVs;
0036
0037
0038 Acts::Experimental::Blueprint::Config bpCfg;
0039 bpCfg.envelope[Acts::AxisDirection::AxisZ] = {20_mm, 20_mm};
0040 bpCfg.envelope[Acts::AxisDirection::AxisR] = {5008.87000_mm, 12_mm};
0041 Acts::Experimental::Blueprint root{bpCfg};
0042 auto& cyl = root.addCylinderContainer("MuonMockupBarrelContainer",
0043 Acts::AxisDirection::AxisR);
0044 cyl.setAttachmentStrategy(Acts::VolumeAttachmentStrategy::Gap);
0045 cyl.setResizeStrategy(Acts::VolumeResizeStrategy::Gap);
0046
0047 if (boundingBoxes.empty()) {
0048 throw std::invalid_argument(
0049 "GeoModelMuonMockupBuilder() -- No converted bounding boxes in the "
0050 "configuration - provide volumes "
0051 "(e.g from the GeModelDetectorObjectFactory) ");
0052 }
0053
0054
0055 std::size_t layerId = 1;
0056
0057 for (const auto& str : m_cfg.stationNames) {
0058 auto geoIdNode = Acts::GeometryIdentifier().withLayer(layerId);
0059 ++layerId;
0060 auto node = buildBarrelNode(boundingBoxes, str, *m_cfg.volumeBoundFactory,
0061 geoIdNode);
0062 cyl.addChild(std::move(node));
0063 }
0064
0065 auto trackingGeometry = root.construct({}, gctx, *m_logger);
0066
0067 return trackingGeometry;
0068 }
0069
0070 std::shared_ptr<Acts::Experimental::StaticBlueprintNode>
0071 GeoModelMuonMockupBuilder::buildBarrelNode(
0072 const ConvertedVolList_t& boundingBoxes, const std::string& name,
0073 Acts::VolumeBoundFactory& boundFactory,
0074 const Acts::GeometryIdentifier& geoId) const {
0075 using enum Acts::TrapezoidVolumeBounds::BoundValues;
0076
0077
0078
0079
0080 std::map<const GeoVPhysVol*, ConvertedVolList_t> commonStations{};
0081 for (const auto& box : boundingBoxes) {
0082 ACTS_VERBOSE("Test whether " << box.name << " contains '" << name
0083 << "' as substring");
0084 if (box.name.find(name) == std::string::npos) {
0085 continue;
0086 }
0087 auto parent = box.fullPhysVol->getParent().get();
0088
0089 if (parent == nullptr) {
0090 throw std::domain_error("buildBarrelNode() No parent found for " + name);
0091 }
0092 commonStations[parent].push_back(box);
0093 }
0094
0095 std::vector<std::unique_ptr<Acts::TrackingVolume>> volChambers;
0096
0097 if (commonStations.empty()) {
0098 throw std::invalid_argument("No barrel stations could be found.");
0099 }
0100 volChambers.reserve(commonStations.size());
0101 std::size_t stationNum = 1;
0102 double maxZ = std::numeric_limits<double>::lowest();
0103 for (const auto& [parentPhysVol, childrenTrkVols] : commonStations) {
0104 std::shared_ptr<Acts::Volume> parentVolume = Acts::GeoModel::convertVolume(
0105 Acts::GeoModel::volumePosInSpace(parentPhysVol),
0106 parentPhysVol->getLogVol()->getShape(), boundFactory);
0107
0108 auto chamberVolume = std::make_unique<Acts::TrackingVolume>(
0109 *parentVolume, name + "Chamber_" + std::to_string(stationNum));
0110 chamberVolume->assignGeometryId(geoId.withVolume(stationNum));
0111 ++stationNum;
0112 ACTS_VERBOSE("Boundaries of the chamber volume: "
0113 << chamberVolume->boundarySurfaces().size());
0114
0115 std::size_t childVol = 1;
0116 for (const auto& child : childrenTrkVols) {
0117 auto trVol =
0118 std::make_unique<Acts::TrackingVolume>(*child.volume, child.name);
0119 trVol->assignGeometryId(geoId.withVolume(stationNum).withExtra(childVol));
0120 ++childVol;
0121
0122
0123 for (const auto& surface : child.surfaces) {
0124 trVol->addSurface(surface);
0125 }
0126
0127 chamberVolume->addVolume(std::move(trVol));
0128 }
0129 volChambers.push_back(std::move(chamberVolume));
0130 maxZ = std::max(
0131 maxZ, volChambers.back()->center().z() +
0132 volChambers.back()->volumeBounds().values()[eHalfLengthY]);
0133 }
0134
0135 const Acts::Vector3& cent{volChambers.front()->center()};
0136 double rmincyl =
0137 Acts::fastHypot(cent.x(), cent.y()) -
0138 volChambers.front()->volumeBounds().values()[eHalfLengthXnegY];
0139 double rmaxcyl = Acts::fastHypot(
0140 rmincyl +
0141 2 * volChambers.front()->volumeBounds().values()[eHalfLengthXnegY],
0142 volChambers.front()->volumeBounds().values()[eHalfLengthXposY]);
0143 double halfZ = maxZ;
0144
0145
0146 auto barrelNode = std::make_shared<Acts::Experimental::StaticBlueprintNode>(
0147 std::make_unique<Acts::TrackingVolume>(
0148 Acts::Transform3::Identity(),
0149 std::make_shared<Acts::CylinderVolumeBounds>(rmincyl, rmaxcyl, halfZ),
0150 name + "_Barrel"));
0151
0152
0153
0154 for (auto& chamber : volChambers) {
0155 auto chamberNode =
0156 std::make_shared<Acts::Experimental::StaticBlueprintNode>(
0157 std::move(chamber));
0158 barrelNode->addChild(std::move(chamberNode));
0159 }
0160
0161 return barrelNode;
0162 }
0163
0164 }