8 #include "Acts/Geometry/BlueprintNode.hpp"
9 #include "Acts/Geometry/StaticBlueprintNode.hpp"
10 #include "Acts/Geometry/CylinderVolumeBounds.hpp"
11 #include <Acts/Geometry/ContainerBlueprintNode.hpp>
12 #include "Acts/Geometry/MultiWireVolumeBuilder.hpp"
13 #include "Acts/Surfaces/TrapezoidBounds.hpp"
14 #include "Acts/Material/HomogeneousSurfaceMaterial.hpp"
15 #include <Acts/Geometry/MaterialDesignatorBlueprintNode.hpp>
16 #include <Acts/Geometry/GeometryIdentifierBlueprintNode.hpp>
17 #include <Acts/Geometry/VolumeAttachmentStrategy.hpp>
18 #include "Acts/Geometry/VolumeResizeStrategy.hpp"
19 #include <Acts/Geometry/TrackingVolume.hpp>
20 #include <Acts/Geometry/TrapezoidVolumeBounds.hpp>
21 #include <Acts/Surfaces/PlaneSurface.hpp>
22 #include <Acts/Plugins/GeoModel/GeoModelMaterialConverter.hpp>
23 #include <Acts/Visualization/ObjVisualization3D.hpp>
30 #include "GeoModelValidation/GeoMaterialHelper.h"
34 constexpr std::size_t s_muonBarrelId = 30;
35 constexpr std::size_t s_muonEndcapAId = 31;
36 constexpr std::size_t s_muonEndcapCId = 32;
37 constexpr std::size_t s_muonEndcapMiddleAId = 33;
38 constexpr std::size_t s_muonEndcapMiddleCId = 34;
45 return StatusCode::SUCCESS;
51 std::variant<MuonChamberSet, MuonSectorSet> elements;
52 std::variant<MuonChamberSet, MuonSectorSet> barrelStations, endcapAStations, endcapCStations, endcapMiddleAStations, endcapMiddleCStations;
60 std::visit([&](
auto& elems) {
61 using SetType = std::decay_t<decltype(elems)>;
64 SetType barrel, endcapA, endcapC, endcapMiddleA, endcapMiddleC;
66 for (
const auto& element : elems) {
70 barrel.insert(element);
72 endcapA.insert(element);
74 endcapC.insert(element);
76 endcapMiddleA.insert(element);
78 endcapMiddleC.insert(element);
81 <<
" not assigned to any station!");
86 barrelStations = std::move(barrel);
87 endcapAStations = std::move(endcapA);
88 endcapCStations = std::move(endcapC);
89 endcapMiddleAStations= std::move(endcapMiddleA);
90 endcapMiddleCStations= std::move(endcapMiddleC);
95 auto muonNode = std::make_shared<Acts::Experimental::CylinderContainerBlueprintNode>(
"MuonNode", Acts::AxisDirection::AxisZ);
97 Acts::VolumeBoundFactory boundsFactory{};
99 auto barrelNode =
buildMuonNode(gctx, barrelStations,
"BI_BM_BO_EE_EI",Acts::GeometryIdentifier().withVolume(s_muonBarrelId), boundsFactory);
100 auto endcapANode =
buildMuonNode(gctx, endcapAStations,
"EO_A", Acts::GeometryIdentifier().withVolume(s_muonEndcapAId), boundsFactory);
101 auto endcapCNode =
buildMuonNode(gctx, endcapCStations,
"EO_C", Acts::GeometryIdentifier().withVolume(s_muonEndcapCId), boundsFactory);
102 auto endcapMiddleANode =
buildMuonNode(gctx, endcapMiddleAStations,
"EM_A", Acts::GeometryIdentifier().withVolume(s_muonEndcapMiddleAId), boundsFactory);
103 auto endcapMiddleCNode =
buildMuonNode(gctx, endcapMiddleCStations,
"EM_C", Acts::GeometryIdentifier().withVolume(s_muonEndcapMiddleCId), boundsFactory);
107 barrelNode->addChild(std::move(childNode));
110 muonNode->addChild(std::move(barrelNode));
111 muonNode->addChild(std::move(endcapANode));
112 muonNode->addChild(std::move(endcapCNode));
113 muonNode->addChild(std::move(endcapMiddleANode));
114 muonNode->addChild(std::move(endcapMiddleCNode));
120 template<
typename MuonElementsSet>
121 std::shared_ptr<Acts::Experimental::StaticBlueprintNode>
123 const Acts::GeometryContext& gctx,
124 const MuonElementsSet& elements,
125 const std::string&
name,
126 const Acts::GeometryIdentifier&
id,
127 Acts::VolumeBoundFactory& boundsFactory)
const {
130 std::vector<std::string> stationNames;
132 std::vector<std::shared_ptr<Acts::Experimental::StaticBlueprintNode>> nodes;
134 double innerRadius = 0.0;
135 double outerRadius = std::numeric_limits<double>::lowest();
136 double maxZ = std::numeric_limits<double>::lowest();
141 std::visit([&](
const auto& elems){
143 for(
const auto& element : elems){
145 std::string volName = element->identString();
147 auto vol = std::make_unique<Acts::TrackingVolume>(
154 vol->addSurface(std::move(material));
156 Acts::GeometryIdentifier chId =
id.withLayer(chamberId++);
157 vol->assignGeometryId(chId);
159 std::pair<std::vector<staticNodePtr>,std::vector<surfacePtr>> innerStructure =
getSensitiveElements(*context, *element, chId, boundsFactory);
161 for(
auto& surface: innerStructure.second){
162 vol->addSurface(surface);
166 for(
const auto& surface: vol->boundarySurfaces()){
167 const auto& surfaceRepr = surface->surfaceRepresentation();
168 const Acts::Polyhedron& polyhedron = surfaceRepr.polyhedronRepresentation(gctx);
181 Acts::ObjVisualization3D
helper;
182 vol->visualize(
helper, gctx, {.visible =
true},
183 {.visible =
true}, {.visible =
true});
184 helper.write(volName +
".obj");
188 auto node = std::make_shared<Acts::Experimental::StaticBlueprintNode>(std::move(vol));
189 for(
auto& childNode : innerStructure.first){
190 node->addChild(std::move(childNode));
196 nodes.emplace_back(std::move(
node));
200 double halfLengthZ = 0.5 * std::abs(maxZ - minZ);
209 auto bounds = boundsFactory.makeBounds<Acts::CylinderVolumeBounds>(innerRadius, outerRadius, halfLengthZ);
210 auto volume = std::make_unique<Acts::TrackingVolume>(
trf, bounds,
name);
211 volume->assignGeometryId(
id);
212 auto muonNode = std::make_shared<Acts::Experimental::StaticBlueprintNode>(std::move(volume));
215 std::ranges::for_each(nodes, [&muonNode](
auto&
node) {
216 muonNode->addChild(std::move(
node));
222 std::pair<std::vector<staticNodePtr>, std::vector<surfacePtr>>
226 const Acts::GeometryIdentifier& chId,
227 Acts::VolumeBoundFactory& boundsFactory)
const {
229 std::vector<staticNodePtr> readoutVolumes;
230 std::vector<surfacePtr> readoutSurfaces;
231 Acts::GeometryIdentifier::Value mdtId{1};
235 std::vector<surfacePtr> detSurfaces = readoutEle->getSurfaces();
236 switch(readoutEle->detectorType()){
242 const Amg::Vector3D toChamber = element.globalToLocalTrans(gctx)*mdtReadoutEle->center(gctx);
243 const Acts::Transform3 mdtTransform = element.localToGlobalTrans(gctx) *
Amg::getTranslate3D(toChamber);
246 Acts::Experimental::MultiWireVolumeBuilder::Config mwCfg;
248 mwCfg.mlSurfaces = detSurfaces;
249 mwCfg.transform = mdtTransform;
251 auto mdtBounds = boundsFactory.makeBounds<Acts::TrapezoidVolumeBounds>(
parameters.shortHalfX,
254 mwCfg.bounds = mdtBounds;
255 using BoundsV = Acts::TrapezoidVolumeBounds::BoundValues;
256 mwCfg.binning = {{{Acts::AxisDirection::AxisY, Acts::AxisBoundaryType::Bound,
257 -mdtBounds->get(BoundsV::eHalfLengthY),
258 mdtBounds->get(BoundsV::eHalfLengthY),
259 static_cast<std::size_t
>(std::lround(2 * mdtBounds->get(BoundsV::eHalfLengthY) /
parameters.tubePitch))}, 2
u},
260 {{Acts::AxisDirection::AxisZ, Acts::AxisBoundaryType::Bound,
261 -mdtBounds->get(BoundsV::eHalfLengthZ),
262 mdtBounds->get(BoundsV::eHalfLengthZ),
263 static_cast<std::size_t
>(std::lround(2 * mdtBounds->get(BoundsV::eHalfLengthZ) /
parameters.tubePitch))}, 1
u}};
264 Acts::Experimental::MultiWireVolumeBuilder mdtBuilder{mwCfg};
265 std::unique_ptr<Acts::TrackingVolume> mdtVolume = mdtBuilder.buildVolume();
267 mdtVolume->assignGeometryId(chId.withExtra(mdtId++));
269 std::shared_ptr<Acts::Experimental::StaticBlueprintNode> mdtNode = std::make_shared<Acts::Experimental::StaticBlueprintNode>(std::move(mdtVolume));
270 mdtNode->setNavigationPolicyFactory(mdtBuilder.createNavigationPolicyFactory());
271 readoutVolumes.push_back(std::move(mdtNode));
280 readoutSurfaces.insert(readoutSurfaces.end(), std::make_move_iterator(detSurfaces.begin()),
281 std::make_move_iterator(detSurfaces.end()));
292 return std::make_pair(std::move(readoutVolumes), std::move(readoutSurfaces));
297 std::shared_ptr<Acts::Surface>
299 const T& element)
const {
301 const float thickness = element.halfZ() * 2;
302 PVConstLink parentVolume = element.readoutEles().front()->getMaterialGeom()->getParent();
303 GeoModelTools::GeoMaterialHelper geoMaterialHelper;
304 std::pair<GeoModelTools::GeoMaterialPtr, double> geoMaterials = geoMaterialHelper.collectMaterial(parentVolume);
306 const Acts::Material aMat = Acts::GeoModel::geoMaterialConverter(*geoMaterials.first);
308 auto constPtr = element.surface().getSharedPtr();
310 auto ptr = std::const_pointer_cast<Acts::Surface>(constPtr);
312 Acts::MaterialSlab slab{aMat, thickness};
313 std::shared_ptr<Acts::HomogeneousSurfaceMaterial> material = std::make_shared<Acts::HomogeneousSurfaceMaterial>(slab);
314 ptr->assignSurfaceMaterial(material);
322 auto stationSide = element.side();
323 bool matchesName = std::ranges::any_of(stationIndex.begin(), stationIndex.end(), [&](
const auto&
n){
324 return stationIdx == n;
328 return matchesName && etaSignCorrect;