Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:08:51

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
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   // Blue print construction for the tracking geometry
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   // Add the station nodes as static cylidner nodes
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   /** Assume a station paradigm. MDT multilayers and complementary strip
0078    * detectors are residing under a common parent node representing a muon
0079    * station envelope. Group the passed boxes under by their parent */
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;  // skip boxes that do not match the station name
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   // Create a vector to hold the chambers
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       // add the sensitives (tubes) in the constructed tracking volume
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   // Create the barrel node with the attached cylinder volume
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   // create the bluprint nodes for the chambers and add them as children to the
0153   // cylinder barrel node
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 }  // namespace ActsExamples