54std::variant<MuonChamberSet, MuonSectorSet> elements;
55std::variant<MuonChamberSet, MuonSectorSet> barrelStations, endcapAStations, endcapCStations, endcapMiddleAStations, endcapMiddleCStations;
58 elements =
m_detMgr->getAllSectors();
60 elements =
m_detMgr->getAllChambers();
63std::visit([&](
auto& elems) {
64 using SetType = std::decay_t<
decltype(elems)>;
67 SetType
barrel, endcapA, endcapC, endcapMiddleA, endcapMiddleC;
69 for (
const auto& element : elems) {
71 {StIdx::BI, StIdx::BM, StIdx::BO, StIdx::BE, StIdx::EE, StIdx::EI},
75 endcapA.push_back(element);
77 endcapC.push_back(element);
79 endcapMiddleA.push_back(element);
81 endcapMiddleC.push_back(element);
84 <<
" not assigned to any station!");
89 barrelStations = std::move(
barrel);
90 endcapAStations = std::move(endcapA);
91 endcapCStations = std::move(endcapC);
92 endcapMiddleAStations= std::move(endcapMiddleA);
93 endcapMiddleCStations= std::move(endcapMiddleC);
98auto muonNode = std::make_shared<Acts::Experimental::CylinderContainerBlueprintNode>(
"MuonNode", Acts::AxisDirection::AxisZ);
100Acts::VolumeBoundFactory boundsFactory{};
101auto barrelNode =
buildMuonNode(gctx, barrelStations,
"BI_BM_BO_EE_EI",Acts::GeometryIdentifier().withVolume(s_muonBarrelId), boundsFactory);
102auto endcapANode =
buildMuonNode(gctx, endcapAStations,
"EO_A", Acts::GeometryIdentifier().withVolume(s_muonEndcapAId), boundsFactory);
103auto endcapCNode =
buildMuonNode(gctx, endcapCStations,
"EO_C", Acts::GeometryIdentifier().withVolume(s_muonEndcapCId), boundsFactory);
104auto endcapMiddleANode =
buildMuonNode(gctx, endcapMiddleAStations,
"EM_A", Acts::GeometryIdentifier().withVolume(s_muonEndcapMiddleAId), boundsFactory);
105auto endcapMiddleCNode =
buildMuonNode(gctx, endcapMiddleCStations,
"EM_C", Acts::GeometryIdentifier().withVolume(s_muonEndcapMiddleCId), boundsFactory);
109 barrelNode->addChild(std::move(childNode));
111muonNode->addChild(std::move(barrelNode));
112muonNode->addChild(std::move(endcapANode));
113muonNode->addChild(std::move(endcapCNode));
114muonNode->addChild(std::move(endcapMiddleANode));
115muonNode->addChild(std::move(endcapMiddleCNode));
124 const Acts::GeometryContext& gctx,
125 const MuonElementsSet& elements,
126 const std::string& name,
127 const Acts::GeometryIdentifier&
id,
128 Acts::VolumeBoundFactory& boundsFactory)
const {
131 std::vector<std::string> stationNames;
133 std::vector<std::shared_ptr<Acts::Experimental::StaticBlueprintNode>> nodes;
135 double innerRadius = 0.0;
136 double outerRadius = std::numeric_limits<double>::lowest();
137 double maxZ = std::numeric_limits<double>::lowest();
138 double minZ = std::numeric_limits<double>::max();
140 std::visit([&](
const auto& elems){
142 for(
const auto& element : elems){
143 const Amg::Transform3D& transform = element->localToGlobalTransform(*context);
144 std::string volName = element->identString();
146 auto vol = std::make_unique<Acts::TrackingVolume>(
153 vol->addSurface(std::move(material));
155 Acts::GeometryIdentifier chId =
id.withLayer(chamberId++);
156 vol->assignGeometryId(chId);
157 std::pair<std::vector<staticNodePtr>,std::vector<surfacePtr>> innerStructure =
getSensitiveElements(*context, *element, chId, boundsFactory);
158 for(
auto& surface: innerStructure.second){
159 vol->addSurface(surface);
162 for(
const auto& surface: vol->boundarySurfaces()){
163 const auto& surfaceRepr = surface->surfaceRepresentation();
164 const Acts::Polyhedron& polyhedron = surfaceRepr.polyhedronRepresentation(gctx);
167 maxZ = std::max(maxZ, center.z());
168 minZ = std::min(minZ, center.z());
172 outerRadius = std::max(outerRadius, vertex.perp());
176 std::shared_ptr<Acts::Experimental::StaticBlueprintNode>
node;
177 const bool isSingleMdt =
178 (element->readoutEles().size() == 1 &&
183 node = std::move(innerStructure.first.front());
185 node = std::make_shared<Acts::Experimental::StaticBlueprintNode>(std::move(vol));
186 for (
auto& childNode : innerStructure.first) {
187 node->addChild(std::move(childNode));
189 innerStructure.first.clear();
194 nodes.emplace_back(std::move(
node));
199 double halfLengthZ = 0.5 * std::abs(maxZ - minZ);
208 auto bounds = boundsFactory.makeBounds<Acts::CylinderVolumeBounds>(innerRadius, outerRadius, halfLengthZ);
209 auto volume = std::make_unique<Acts::TrackingVolume>(trf, bounds, name);
210 volume->assignGeometryId(
id);
211 auto muonNode = std::make_shared<Acts::Experimental::StaticBlueprintNode>(std::move(volume));
214 std::ranges::for_each(nodes, [&muonNode](
auto&
node) {
215 muonNode->addChild(std::move(
node));
225 const Acts::GeometryIdentifier& chId,
226 Acts::VolumeBoundFactory& boundsFactory)
const {
228 std::vector<staticNodePtr> readoutVolumes;
229 std::vector<surfacePtr> readoutSurfaces;
230 Acts::GeometryIdentifier::Value mdtId{1};
239 auto& mdtIdHelper =
m_detMgr->idHelperSvc()->mdtIdHelper();
240 const int BIS = mdtIdHelper.stationNameIndex(
"BIS");
241 int stEta = rElem->stationEta();
243 return rElem->stationName() ==
BIS && std::abs(stEta) >= 7;
249 std::vector<surfacePtr> detSurfaces = readoutEle->getSurfaces();
250 switch(readoutEle->detectorType()){
256 const Amg::Vector3D toChamber = element.globalToLocalTransform(gctx)*mdtReadoutEle->center(gctx);
257 Acts::Transform3 mdtTransform = element.localToGlobalTransform(gctx) *
Amg::getTranslate3D(toChamber);
260 Acts::Experimental::MultiWireVolumeBuilder::Config mwCfg;
261 mwCfg.name =
m_detMgr->idHelperSvc()->toStringDetEl(mdtReadoutEle->identify());
262 mwCfg.mlSurfaces = detSurfaces;
263 mwCfg.transform = mdtTransform;
267 std::shared_ptr<Acts::VolumeBounds> mdtBounds{
nullptr};
268 if(isBIS78(readoutEle) && mdtReadoutEle->multilayer() == 2){
271 std::vector<double> tubeLengths;
272 tubeLengths.reserve(mdtReadoutEle->numTubesInLay());
273 for(std::size_t tube = 1; tube < mdtReadoutEle->numTubesInLay(); ++tube){
275 double tubeLength = mdtReadoutEle->tubeLength(tubeHash);
278 auto [minX,maxX] = std::ranges::minmax_element(tubeLengths);
279 int nSmallTubes = std::count_if(tubeLengths.begin(), tubeLengths.end(), [minX](
double length){
280 return std::abs(*minX-length) < Acts::s_epsilon;
284 double y2 = (nSmallTubes+1)*parameters.tubePitch ;
285 double y1 = 2*parameters.halfY - y2;
287 mdtBounds = boundsFactory.makeBounds<Acts::DiamondVolumeBounds>(0.5*(*maxX), 0.5*(*maxX), 0.5*(*minX),
288 y1, y2, parameters.halfHeight);
291 if(std::abs(parameters.shortHalfX - parameters.longHalfX) < Acts::s_epsilon){
292 mdtBounds = boundsFactory.makeBounds<Acts::CuboidVolumeBounds>(parameters.shortHalfX, parameters.halfY, parameters.halfHeight);
294 mdtBounds = boundsFactory.makeBounds<Acts::TrapezoidVolumeBounds>(parameters.shortHalfX,
295 parameters.longHalfX, parameters.halfY, parameters.halfHeight);
298 mwCfg.bounds = mdtBounds;
299 mwCfg.transform = mdtTransform;
300 using BoundsV = Acts::TrapezoidVolumeBounds::BoundValues;
301 mwCfg.binning = {{{Acts::AxisDirection::AxisY, Acts::AxisBoundaryType::Bound,
304 static_cast<std::size_t
>(std::lround(2 * parameters.halfY / parameters.tubePitch))}, 2u},
305 {{Acts::AxisDirection::AxisZ, Acts::AxisBoundaryType::Bound,
306 -parameters.halfHeight,
307 parameters.halfHeight,
308 static_cast<std::size_t
>(std::lround(2 * parameters.halfHeight / parameters.tubePitch))}, 1u}};
309 Acts::Experimental::MultiWireVolumeBuilder mdtBuilder{mwCfg};
310 std::unique_ptr<Acts::TrackingVolume> mdtVolume = mdtBuilder.buildVolume();
312 mdtVolume->assignGeometryId(chId.withExtra(mdtId++));
314 std::shared_ptr<Acts::Experimental::StaticBlueprintNode> mdtNode = std::make_shared<Acts::Experimental::StaticBlueprintNode>(std::move(mdtVolume));
315 mdtNode->setNavigationPolicyFactory(mdtBuilder.createNavigationPolicyFactory());
316 readoutVolumes.push_back(std::move(mdtNode));
325 readoutSurfaces.insert(readoutSurfaces.end(), std::make_move_iterator(detSurfaces.begin()),
326 std::make_move_iterator(detSurfaces.end()));
337 return std::make_pair(std::move(readoutVolumes), std::move(readoutSurfaces));
344 const T& element)
const {
346 const float thickness = element.halfZ() * 2;
347 PVConstLink parentVolume = element.readoutEles().front()->getMaterialGeom()->getParent();
348 GeoModelTools::GeoMaterialHelper geoMaterialHelper;
349 std::pair<GeoModelTools::GeoMaterialPtr, double> geoMaterials = geoMaterialHelper.collectMaterial(parentVolume);
351 const Acts::Material aMat = ActsPlugins::GeoModel::geoMaterialConverter(*geoMaterials.first);
353 auto constPtr = element.surface().getSharedPtr();
355 auto ptr = std::const_pointer_cast<Acts::Surface>(constPtr);
357 Acts::MaterialSlab slab{aMat, thickness};
358 std::shared_ptr<Acts::HomogeneousSurfaceMaterial> material = std::make_shared<Acts::HomogeneousSurfaceMaterial>(slab);
359 ptr->assignSurfaceMaterial(material);