ATLAS Offline Software
Loading...
Searching...
No Matches
MuonBlueprintNodeBuilder.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7#include "Acts/Geometry/BlueprintNode.hpp"
8#include "Acts/Geometry/StaticBlueprintNode.hpp"
9#include "Acts/Geometry/CylinderVolumeBounds.hpp"
10#include <Acts/Geometry/ContainerBlueprintNode.hpp>
11#include "Acts/Geometry/MultiWireVolumeBuilder.hpp"
12#include "Acts/Surfaces/TrapezoidBounds.hpp"
13#include "Acts/Material/HomogeneousSurfaceMaterial.hpp"
14#include <Acts/Geometry/MaterialDesignatorBlueprintNode.hpp>
15#include <Acts/Geometry/GeometryIdentifierBlueprintNode.hpp>
16#include <Acts/Geometry/VolumeAttachmentStrategy.hpp>
17#include "Acts/Geometry/VolumeResizeStrategy.hpp"
18#include <Acts/Geometry/TrackingVolume.hpp>
19#include <Acts/Geometry/TrapezoidVolumeBounds.hpp>
20#include <Acts/Geometry/CuboidVolumeBounds.hpp>
21#include <Acts/Geometry/DiamondVolumeBounds.hpp>
22#include <Acts/Surfaces/PlaneSurface.hpp>
23#include <Acts/Surfaces/CylinderSurface.hpp>
24#include <Acts/Surfaces/DiscSurface.hpp>
25#include "Acts/Surfaces/RadialBounds.hpp"
26#include <ActsPlugins/GeoModel/GeoModelMaterialConverter.hpp>
27#include <Acts/Visualization/ObjVisualization3D.hpp>
28#include <Acts/Visualization/GeometryView3D.hpp>
29
34
35#include "GeoModelValidation/GeoMaterialHelper.h"
36
37using namespace Acts::UnitLiterals;
38namespace {
39
40 //Muon System IDs
41 constexpr std::size_t s_muonBarrelId = 30;
42 constexpr std::size_t s_muonEndcapAId = 31;
43 constexpr std::size_t s_muonEndcapCId = 32;
44 constexpr std::size_t s_muonEndcapMiddleAId = 33;
45 constexpr std::size_t s_muonEndcapMiddleCId = 34;
46
47 //helper function to flag a chamber or a sector as BIS78
48 bool isBIS78(const MuonGMR4::MuonReadoutElement* element){
49 Muon::MuonStationIndex::ChIndex chamberIdx = element->chamberIndex();
50 return chamberIdx == Muon::MuonStationIndex::ChIndex::BIS && std::abs(element->stationEta())>=7;
51 }
52
53}
54
55
56namespace ActsTrk {
57
59 ATH_CHECK(detStore()->retrieve(m_detMgr));
60 return StatusCode::SUCCESS;
61 }
62
63
64std::shared_ptr<Acts::Experimental::BlueprintNode> MuonBlueprintNodeBuilder::buildBlueprintNode(const Acts::GeometryContext& gctx, std::shared_ptr<Acts::Experimental::BlueprintNode>&& childNode) {
65
66EnvelopeSet_t elements;
67EnvelopeSet_t barrelStations, endcapOuterAStations, endcapOuterCStations,
68 endcapMiddleAStations, endcapMiddleCStations;
69
70if (m_useSectors) {
71 elements = m_detMgr->getAllSectors();
72} else {
73 elements = m_detMgr->getAllChambers();
74}
75
76std::visit([&](auto& elems) {
77 using SetType = std::decay_t<decltype(elems)>;
78
79 // Initialize station containers of the same type
80 SetType barrel, endcapA, endcapC, endcapMiddleA, endcapMiddleC;
81
82 for (const auto& element : elems) {
83 if (isElementInTheStation(*element,
84 {StIdx::BI, StIdx::BM, StIdx::BO, StIdx::BE, StIdx::EE, StIdx::EI},
86 barrel.push_back(element);
87 } else if (isElementInTheStation(*element, {StIdx::EO}, EndcapSide::A)) {
88 endcapA.push_back(element);
89 } else if (isElementInTheStation(*element, {StIdx::EO}, EndcapSide::C)) {
90 endcapC.push_back(element);
91 } else if (isElementInTheStation(*element, {StIdx::EM}, EndcapSide::A)) {
92 endcapMiddleA.push_back(element);
93 } else if (isElementInTheStation(*element, {StIdx::EM}, EndcapSide::C)) {
94 endcapMiddleC.push_back(element);
95 } else {
96 ATH_MSG_WARNING("Element " << element->identString()
97 << " not assigned to any station!");
98 }
99 }
100
101 // Assign back into the outer variants
102 barrelStations = std::move(barrel);
103 endcapOuterAStations = std::move(endcapA);
104 endcapOuterCStations = std::move(endcapC);
105 endcapMiddleAStations = std::move(endcapMiddleA);
106 endcapMiddleCStations = std::move(endcapMiddleC);
107}, elements);
108
109 // Top level node for the Muon system
110auto muonNode = std::make_shared<Acts::Experimental::CylinderContainerBlueprintNode>("MuonNode", Acts::AxisDirection::AxisZ);
111
112Acts::VolumeBoundFactory boundsFactory{};
113auto barrelNode = buildMuonNode(gctx, barrelStations, "BI_BM_BO_EE_EI", Acts::GeometryIdentifier().withVolume(s_muonBarrelId), boundsFactory, {ChIdx::BIS, ChIdx::BML, ChIdx::BOL,
114 ChIdx::EIS, ChIdx::EIL});
115auto endcapANode = buildMuonNode(gctx, endcapOuterAStations, "EO_A", Acts::GeometryIdentifier().withVolume(s_muonEndcapAId), boundsFactory);
116auto endcapCNode = buildMuonNode(gctx, endcapOuterCStations, "EO_C", Acts::GeometryIdentifier().withVolume(s_muonEndcapCId), boundsFactory);
117auto endcapMiddleANode = buildMuonNode(gctx, endcapMiddleAStations, "EM_A", Acts::GeometryIdentifier().withVolume(s_muonEndcapMiddleAId), boundsFactory, {ChIdx::EML, ChIdx::EMS});
118auto endcapMiddleCNode = buildMuonNode(gctx, endcapMiddleCStations, "EM_C", Acts::GeometryIdentifier().withVolume(s_muonEndcapMiddleCId), boundsFactory, {ChIdx::EML, ChIdx::EMS});
119
120//Add to the muon barrel child node (e.g calo or Itk) - if existed
121if(childNode){
122 barrelNode->addChild(std::move(childNode));
123}
124muonNode->addChild(std::move(barrelNode));
125muonNode->addChild(std::move(endcapANode));
126muonNode->addChild(std::move(endcapCNode));
127muonNode->addChild(std::move(endcapMiddleANode));
128muonNode->addChild(std::move(endcapMiddleCNode));
129
130return muonNode;
131
132}
133
134std::shared_ptr<Acts::Experimental::StaticBlueprintNode>
135MuonBlueprintNodeBuilder::buildMuonNode(const Acts::GeometryContext& gctx,
136 const EnvelopeSet_t& elements,
137 const std::string& name,
138 const Acts::GeometryIdentifier& id,
139 Acts::VolumeBoundFactory& boundsFactory,
140 const std::vector<ChIdx>& passiveStationIds) const {
141
142 const ActsTrk::GeometryContext* context = gctx.get<const ActsTrk::GeometryContext* >();
143 std::vector<std::string> stationNames;
144
145 std::vector<std::shared_ptr<Acts::Experimental::StaticBlueprintNode>> nodes;
146
147 double innerRadius{0.0};
148 double outerRadius{std::numeric_limits<double>::lowest()};
149 double maxZ{std::numeric_limits<double>::lowest()};
150 double minZ{std::numeric_limits<double>::max()};
151 int chamberId = 1;
152 std::vector<std::shared_ptr<Acts::Surface>> passiveSurfaces;
153
154 std::visit([&](const auto& elems){
155
156 using SetType = std::decay_t<decltype(elems)>;
157 std::unordered_map<unsigned int, SetType> elementsPerStation;
158
159 for(const auto& element : elems){
160 auto vol = std::make_unique<Acts::TrackingVolume>(*element->boundingVolume(*context),
161 element->identString());
162 // //the chamber geometry id
163 Acts::GeometryIdentifier chId = id.withLayer(chamberId++);
164 vol->assignGeometryId(chId);
165 std::pair<std::vector<staticNodePtr>,std::vector<surfacePtr>> innerStructure = getSensitiveElements(*context, *element, chId, boundsFactory);
166 for(auto& surface: innerStructure.second){
167 vol->addSurface(surface);
168 }
169 //calculate the bounds of the cylinder container
170 for(const auto& surface: vol->volumeBounds().orientedSurfaces(vol->localToGlobalTransform(gctx))) {
171 const auto& surfaceRepr = (*surface.surface);
172 const Acts::Polyhedron& polyhedron = surfaceRepr.polyhedronRepresentation(gctx);
173 const Amg::Vector3D& center = surfaceRepr.center(gctx);
174
175 maxZ = std::max(maxZ, center.z());
176 minZ = std::min(minZ, center.z());
177
178 // Outer radius needs to be treated differently due to curvature of cylindrical surface
179 for(const Amg::Vector3D& vertex: polyhedron.vertices){
180 outerRadius = std::max(outerRadius, vertex.perp());
181 }
182 }
183 std::shared_ptr<Acts::Experimental::StaticBlueprintNode> node;
184 const bool isSingleMdt =
185 (element->readoutEles().size() == 1 &&
186 element->readoutEles().front()->detectorType() == DetectorType::Mdt);
187
188 if (isSingleMdt) {
189 // Take ownership of the single existing node
190 node = std::move(innerStructure.first.front());
191 } else {
192 node = std::make_shared<Acts::Experimental::StaticBlueprintNode>(std::move(vol));
193 for (auto& childNode : innerStructure.first) {
194 node->addChild(std::move(childNode));
195 }
196 innerStructure.first.clear();
197 }
198 if (!node) {
199 THROW_EXCEPTION("No blueprint node constructed");
200 }
201 nodes.emplace_back(std::move(node));
202 //keep the elements of the stations we want to assign passive material surfaces
203
204 if(!Acts::rangeContainsValue(passiveStationIds, element->chamberIndex())){
205 continue;
206 }
207
208 DetIdx detIdx = Muon::MuonStationIndex::toDetectorRegionIndex(element->chamberIndex(), element->side());
209 elementsPerStation[Muon::MuonStationIndex::regionChamberHash(detIdx, element->chamberIndex())].push_back(element);
210 }
211 //construct the surfaces we want to map passive material on
212 passiveSurfaces = getPassiveMaterialSurfaces(gctx, std::move(elementsPerStation));
213
214 }, elements);
215
216 double halfLengthZ = 0.5 * std::abs(maxZ - minZ);
217 ATH_MSG_DEBUG("Inner radius: " << innerRadius<<", outer radius: " << outerRadius
218 <<", max Z: " << maxZ<<", min Z: " << minZ<<", half length Z: " << halfLengthZ);
219
220 Amg::Transform3D trf = Amg::getTranslateZ3D(halfLengthZ + minZ);
221
222 auto bounds = boundsFactory.makeBounds<Acts::CylinderVolumeBounds>(innerRadius, outerRadius, halfLengthZ);
223 auto volume = std::make_unique<Acts::TrackingVolume>(trf, bounds, name);
224 volume->assignGeometryId(id);
225
226 //put the passive material surfaces into the volume
227 std::ranges::for_each(passiveSurfaces, [&volume](auto& surf){
228 volume->addSurface(surf);
229 });
230
231 auto muonNode = std::make_shared<Acts::Experimental::StaticBlueprintNode>(std::move(volume));
232 ATH_MSG_DEBUG("There are " << nodes.size() << " nodes");
233 std::ranges::for_each(nodes, [&muonNode](auto& node) {
234 muonNode->addChild(std::move(node));
235 });
236 return muonNode;
237 }
238
239template<typename T>
242 const T& element,
243 const Acts::GeometryIdentifier& chId,
244 Acts::VolumeBoundFactory& boundsFactory) const
245 requires(std::is_same_v<T, MuonGMR4::Chamber> || std::is_same_v<T, MuonGMR4::SpectrometerSector>){
246
247 std::vector<staticNodePtr> readoutVolumes;
248 std::vector<surfacePtr> readoutSurfaces;
249 Acts::GeometryIdentifier::Value mdtId{1};
250
251 for (const MuonGMR4::MuonReadoutElement* readoutEle : element.readoutEles()) {
252
253 std::vector<surfacePtr> detSurfaces = readoutEle->getSurfaces();
254 switch(readoutEle->detectorType()){
255 case DetectorType::Mdt: {
256 const auto* mdtReadoutEle = static_cast<const MuonGMR4::MdtReadoutElement*>(readoutEle);
257 const MuonGMR4::MdtReadoutElement::parameterBook& parameters{mdtReadoutEle->getParameters()};
258
259 // get the transform to the sector's frame
260 const Amg::Vector3D toChamber = element.globalToLocalTransform(gctx)*mdtReadoutEle->center(gctx);
261 Acts::Transform3 mdtTransform = element.localToGlobalTransform(gctx) * Amg::getTranslate3D(toChamber);
262
263 // create the MDT multilayer volume with the dedicated builder
264 Acts::Experimental::MultiWireVolumeBuilder::Config mwCfg;
265 mwCfg.name = m_detMgr->idHelperSvc()->toStringDetEl(mdtReadoutEle->identify());
266 mwCfg.mlSurfaces = detSurfaces;
267 mwCfg.transform = mdtTransform;
268
269 //special treatment of BIS78 MDT multilayer
270 //use different shape because of clashes with EIL chambers
271 std::shared_ptr<Acts::VolumeBounds> mdtBounds{nullptr};
272 if(isBIS78(mdtReadoutEle) && mdtReadoutEle->multilayer() == 2){
273
274 //find the minimum and the maximum tube length (x dimension of the diamond bounds)
275 std::vector<double> tubeLengths;
276 tubeLengths.reserve(mdtReadoutEle->numTubesInLay());
277 for(std::size_t tube = 1; tube < mdtReadoutEle->numTubesInLay(); ++tube){
279 double tubeLength = mdtReadoutEle->tubeLength(tubeHash);
280 tubeLengths.push_back(tubeLength);
281 }
282 auto [minX,maxX] = std::ranges::minmax_element(tubeLengths);
283 int nSmallTubes = std::count_if(tubeLengths.begin(), tubeLengths.end(), [minX](double length){
284 return std::abs(*minX-length) < Acts::s_epsilon;
285 });
286
287 //create the diamond bounds for the volume
288 double y2 = (nSmallTubes+1)*parameters.tubePitch ;
289 double y1 = 2*parameters.halfY - y2;
290 mdtTransform = mdtTransform*Amg::getTranslateY3D(parameters.halfY-y2);
291 mdtBounds = boundsFactory.makeBounds<Acts::DiamondVolumeBounds>(0.5*(*maxX), 0.5*(*maxX), 0.5*(*minX),
292 y1, y2, parameters.halfHeight);
293 }else{
294 //check for rectangular or trapezoidal shape bounds
295 if(std::abs(parameters.shortHalfX - parameters.longHalfX) < Acts::s_epsilon){
296 mdtBounds = boundsFactory.makeBounds<Acts::CuboidVolumeBounds>(parameters.shortHalfX, parameters.halfY, parameters.halfHeight);
297 } else {
298 mdtBounds = boundsFactory.makeBounds<Acts::TrapezoidVolumeBounds>(parameters.shortHalfX,
299 parameters.longHalfX, parameters.halfY, parameters.halfHeight);
300 }
301 }
302 mwCfg.bounds = mdtBounds;
303 mwCfg.transform = mdtTransform;
304 using BoundsV = Acts::TrapezoidVolumeBounds::BoundValues;
305 mwCfg.binning = {{{Acts::AxisDirection::AxisY, Acts::AxisBoundaryType::Bound,
306 -parameters.halfY,
307 parameters.halfY,
308 static_cast<std::size_t>(std::lround(2 * parameters.halfY / parameters.tubePitch))}, 2u},
309 {{Acts::AxisDirection::AxisZ, Acts::AxisBoundaryType::Bound,
310 -parameters.halfHeight,
311 parameters.halfHeight,
312 static_cast<std::size_t>(std::lround(2 * parameters.halfHeight / parameters.tubePitch))}, 1u}};
313 Acts::Experimental::MultiWireVolumeBuilder mdtBuilder{mwCfg};
314 std::unique_ptr<Acts::TrackingVolume> mdtVolume = mdtBuilder.buildVolume();
315
316 mdtVolume->assignGeometryId(chId.withExtra(mdtId++));
317 //create the blueprint node for the mdt multilayers
318 std::shared_ptr<Acts::Experimental::StaticBlueprintNode> mdtNode = std::make_shared<Acts::Experimental::StaticBlueprintNode>(std::move(mdtVolume));
319 mdtNode->setNavigationPolicyFactory(mdtBuilder.createNavigationPolicyFactory());
320 readoutVolumes.push_back(std::move(mdtNode));
321
322 break;
323
324 } case DetectorType::Rpc:
327 case DetectorType::Mm: {
328
329 readoutSurfaces.insert(readoutSurfaces.end(), std::make_move_iterator(detSurfaces.begin()),
330 std::make_move_iterator(detSurfaces.end()));
331
332 break;
333
334 } default:
335 THROW_EXCEPTION("Unknown detector type for readout element: " << ActsTrk::to_string(readoutEle->detectorType()));
336 break;
337
338 }
339 }
340
341 return std::make_pair(std::move(readoutVolumes), std::move(readoutSurfaces));
342}
343
344template<typename ElementSet_t>
345std::vector<std::shared_ptr<Acts::Surface>>
347 const Acts::GeometryContext& gctx,
348 const std::unordered_map<unsigned int, ElementSet_t>& elementsPerStation) const {
349
350 //this is a margin to put the surfaces along Z
351 //(a margin distance from the corresponding chamber's boundary surface)
352 constexpr double margin{4._mm};
353
354 std::vector<std::shared_ptr<Acts::Surface>> surfaces;
355 surfaces.reserve(elementsPerStation.size());
356 LayIdx layIdx = LayIdx::LayerIndexMax;
357 DetIdx detIdx = DetIdx::DetectorRegionIndexMax;
358
359 const ActsTrk::GeometryContext* context = gctx.get<const ActsTrk::GeometryContext* >();
360
361 //lamda function to reject BIS78 chambers from the extension of the passive surface
362 //otherwise they create overlap with the NSW sectors - stop a little bit before the cylinder of the passive surface
363 const auto rejectBIS78 = [&](const MuonGMR4::MuonReadoutElement* readoutEle) {
364 bool reject{false};
365 switch (readoutEle->detectorType()) {
366 case DetectorType::Mdt: {
367 const auto* techEle =
368 static_cast<const MuonGMR4::MdtReadoutElement*>(readoutEle);
369 if (techEle->multilayer() == 2) {
370 reject = true;
371 }
372 break;
373 }
374 case DetectorType::Rpc: {
375 const auto* techEle =
376 static_cast<const MuonGMR4::RpcReadoutElement*>(readoutEle);
377 if (techEle->doubletZ() == 2) {
378 reject = true;
379 }
380 break;
381 }
382 default:
383 break;
384 }
385 return isBIS78(readoutEle) && reject;
386 };
387
388 for(const auto& [hash, elements] : elementsPerStation){
389
390 //decompose the layer hash to the detector region idx and layer index
391 const auto& [detIdxVal, chIdx] = Muon::MuonStationIndex::decomposeRegionChamberHash(hash);
393 detIdx = detIdxVal;
394
395 double maxZ{std::numeric_limits<double>::lowest()};
396 double minZ{std::numeric_limits<double>::max()};
397 double rMin{std::numeric_limits<double>::max()};
398 double rMax{std::numeric_limits<double>::lowest()};
399 //loop through the elements of every station to construct the cylinder/disc surfaces
400 for(const auto& el : elements){
401
402 if(rejectBIS78(el->readoutEles().front())){
403 continue;
404 }
405 //for the rMin we use the center of the chamber insetad of the vertices - otherwise there is overlap with the chamber volume
406 const Amg::Transform3D& locToGlobal = el->localToGlobalTransform(*context);
407 const auto& bounds = el->bounds();
408 for(const auto& surface : bounds->orientedSurfaces(locToGlobal)){
409 const auto& surfaceRepr = (*surface.surface);
410 const Amg::Vector3D& center = surfaceRepr.center(gctx);
411 rMin = std::min(rMin, center.perp());
412 minZ = std::min(minZ, center.z());
413 maxZ = std::max(maxZ, center.z());
414 rMax = std::max(rMax, center.perp());
415 }
416
417 }
418 double halfZ = 0.5*std::abs(maxZ-minZ);
419 Amg::Transform3D trf = Amg::Transform3D::Identity();
420 double zShift{0.};
421 //the chambers are groupd per chamber index and detector region(side) - we can use the first one for the distinction
422 const auto& testCh = elements.front();
423 int8_t side = testCh->side();
424 switch (testCh->chamberIndex()) {
425 //small NSW sectors (disc passive surface in front of NSW and one in front of EMS)
426 case ChIdx::EIS :
427 case ChIdx::EMS :{
428 side > 0 ? zShift = minZ - margin : zShift = maxZ + margin;
429 trf = Amg::getTranslateZ3D(zShift);
430 auto surface = Acts::Surface::makeShared<Acts::DiscSurface>(trf, std::make_shared<Acts::RadialBounds>(0., rMax));
431 surfaces.push_back(surface);
432 break;
433 //large sectors (disc passive surface after NSW/EIL and after EML)
434 } case ChIdx::EIL :
435 case ChIdx::EML : {
436 // HARDCODED!! (maybe think a better solution in the future)
437 // But for the EIL that we put after the EIS/EIL chambers we extend the radius of the disc surface
438 // in order to have a better coverage for the projections from EE
439 if(testCh->chamberIndex() == ChIdx::EIL){
440 rMax += 60*margin;
441 }
442 side > 0 ? zShift = maxZ + margin : zShift = minZ - margin;
443 trf = Amg::getTranslateZ3D(zShift);
444 auto surface = Acts::Surface::makeShared<Acts::DiscSurface>(trf, std::make_shared<Acts::RadialBounds>(0., rMax));
445 surfaces.push_back(surface);
446 break;
447 } case ChIdx::BIS :
448 case ChIdx::BML :
449 case ChIdx::BOL : {
450 trf = Amg::getTranslateZ3D(halfZ + minZ);
451 auto surface = Acts::Surface::makeShared<Acts::CylinderSurface>(
452 trf, std::make_shared<Acts::CylinderBounds>(rMin - margin, halfZ));
453 surfaces.push_back(surface);
454 break;
455 } default :
456 throw std::runtime_error("No implementation of passive material surface for this station!!!! - sorry :) ");
457 }
458 ATH_MSG_VERBOSE("Putting passive material surface for station " << layerName(layIdx) << "/ "<< regionName(detIdx) << ": minZ = " << minZ << ", maxZ = " << maxZ<< "and radius "<< rMax);
459 }
460
461 if(msgLvl(MSG::VERBOSE)){
462 std::stringstream stream{};
463 for(const auto& surf : surfaces){
464 stream<< " at position : "<< Amg::toString(surf->center(gctx))<< "with bounds "<< surf->bounds()<<std::endl;
465 }
466 ATH_MSG_VERBOSE("Constructed "<< surfaces.size()<< " surfaces for passive material description : "<<std::endl<<stream.str());
467 }
468 return surfaces;
469}
470
471template<typename T>
473 const std::vector<StIdx>& stationIndex,
474 const EndcapSide side) const
475 requires(std::is_same_v<T, MuonGMR4::Chamber> ||
476 std::is_same_v<T, MuonGMR4::SpectrometerSector>) {
477 bool etaSignCorrect = (side == EndcapSide::Both) ||
478 (side == EndcapSide::A && element.side() > 0) ||
479 (side == EndcapSide::C && element.side() < 0);
480 return etaSignCorrect &&
481 Acts::rangeContainsValue(stationIndex, toStationIndex(element.chamberIndex()));
482}
483
484
485} //namespace ActsTrk
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
double length(const pvec &v)
double tubeLength
BluePrintSurfPairs_t getSensitiveElements(const ActsTrk::GeometryContext &gctx, const T &element, const Acts::GeometryIdentifier &chId, Acts::VolumeBoundFactory &boundsFactory) const
Get the chamber's sensitive elements.
std::shared_ptr< Acts::Experimental::BlueprintNode > buildBlueprintNode(const Acts::GeometryContext &gctx, std::shared_ptr< Acts::Experimental::BlueprintNode > &&childNode) override
Build the Muon Blueprint Node.
staticNodePtr buildMuonNode(const Acts::GeometryContext &gctx, const EnvelopeSet_t &elements, const std::string &name, const Acts::GeometryIdentifier &id, Acts::VolumeBoundFactory &boundsFactory, const std::vector< ChIdx > &passiveStationIds={}) const
Build subnodes for the muon system node.
bool isElementInTheStation(const T &element, const std::vector< StIdx > &stationNames, const EndcapSide side) const
Check if the chamber is in this node.
std::vector< surfacePtr > getPassiveMaterialSurfaces(const Acts::GeometryContext &gctx, const std::unordered_map< unsigned int, ElementSet_t > &elementsPerStation) const
Construct and return the surfaces for the passive material description (e.g cylinders for barrel/ dis...
Muon::MuonStationIndex::DetectorRegionIndex DetIdx
Abrivatin for the detector region index.
Gaudi::Property< bool > m_useSectors
Flag to control if we want to build the muon node from sectors or chambers.
std::variant< MuonChamberSet, MuonSectorSet > EnvelopeSet_t
Hide the flexibility to build the tracking geometry from sectors or chambers behind a variant.
const MuonGMR4::MuonDetectorManager * m_detMgr
the Detector manager
Muon::MuonStationIndex::LayerIndex LayIdx
Abrivation for the layer index.
std::pair< std::vector< staticNodePtr >, std::vector< surfacePtr > > BluePrintSurfPairs_t
Abrivate the vector pair of blue print nodes and associated active surfaces.
This is a "hash" representation of an Identifier.
Readout element to describe the Monitored Drift Tube (Mdt) chambers Mdt chambers usually comrpise out...
static IdentifierHash measurementHash(unsigned layerNumber, unsigned tubeNumber)
Constructs a Measurement hash from layer && tube number.
MuonReadoutElement is an abstract class representing the geometry of a muon detector.
int stationEta() const
Returns the stationEta (positive A site, negative C site)
Muon::MuonStationIndex::ChIndex chamberIndex() const
Returns the chamber index of the Identifier (MMS & STS) have the same chamber Index (EIS)
Definition node.h:24
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
std::string to_string(const DetectorType &type)
@ Mm
Maybe not needed in the migration.
@ Tgc
Resitive Plate Chambers.
@ sTgc
Micromegas (NSW)
@ Rpc
Monitored Drift Tubes.
@ Mdt
MuonSpectrometer.
Amg::Transform3D getTranslate3D(const double X, const double Y, const double Z)
: Returns a shift transformation along an arbitrary axis
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Amg::Transform3D getTranslateZ3D(const double Z)
: Returns a shift transformation along the z-axis
Amg::Transform3D getTranslateY3D(const double Y)
: Returns a shift transformation along the y-axis
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
std::pair< DetectorRegionIndex, ChIndex > decomposeRegionChamberHash(unsigned int hash)
decompose the hash into Region and Chamber
LayerIndex toLayerIndex(ChIndex index)
convert ChIndex into LayerIndex
DetectorRegionIndex toDetectorRegionIndex(ChIndex index, int8_t etaSign)
convert ChamberIndex + etaSign into DetectorRegionIndex
ChIndex
enum to classify the different chamber layers in the muon spectrometer
#define THROW_EXCEPTION(MESSAGE)
Definition throwExcept.h:10