ATLAS Offline Software
Loading...
Searching...
No Matches
SpectrometerSector.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "Identifier/Identifier.h"
6#include <GeoModelKernel/throwExcept.h>
7#include <cstddef>
8#ifndef SIMULATIONBASE
10#include <Acts/Surfaces/PlaneSurface.hpp>
11#include <Acts/Geometry/TrapezoidVolumeBounds.hpp>
12#include <Acts/Geometry/Volume.hpp>
13
20
21#include <format>
22
23namespace {
24 std::vector<unsigned int> range (unsigned min, unsigned max) {
25 assert(max > min);
26 std::vector<unsigned int> v(max - min);
27 std::iota(v.begin(), v.end(), min);
28 return v;
29 };
30}
31
32namespace MuonGMR4 {
33
35using BoundEnums = Acts::TrapezoidVolumeBounds::BoundValues;
36
38 AthMessaging("MuonSpectrometerSector"), m_args{std::move(args)} {
39 for (auto & chamber : m_args.chambers) {
40 chamber->setParent(this);
41 }
42 }
43
45 return m_args.id < other.m_args.id;
46}
48 return Acts::copySign(1, chambers().front()->stationEta());
49}
51const Muon::IMuonIdHelperSvc* SpectrometerSector::idHelperSvc() const { return m_args.chambers.front()->idHelperSvc();}
52Muon::MuonStationIndex::ChIndex SpectrometerSector::chamberIndex() const { return m_args.chambers.front()->chamberIndex(); }
53int SpectrometerSector::stationPhi() const { return m_args.chambers.front()->stationPhi(); }
54int SpectrometerSector::sector() const {return m_args.chambers.front()->sector(); }
55bool SpectrometerSector::barrel() const { return m_args.chambers.front()->barrel(); }
57 return std::format("id: {:3d}, {:} {:}-side sector: {:2},", m_args.id,
59 side() == 1 ? 'A' : 'C' , sector());
60}
61const ChamberSet& SpectrometerSector::chambers() const{ return m_args.chambers; }
62const Acts::PlaneSurface& SpectrometerSector::surface() const {
63 return *m_args.surface;
64}
66 return surface().localToGlobalTransform(gctx.context());
67}
73double SpectrometerSector::halfY() const { return MuonGMR4::halfY(* m_args.bounds); }
74double SpectrometerSector::halfZ() const { return MuonGMR4::halfZ(*m_args.bounds);}
75
76
77std::shared_ptr<Acts::Volume> SpectrometerSector::boundingVolume(const ActsTrk::GeometryContext& gctx) const {
78 return std::make_shared<Acts::Volume>(localToGlobalTransform(gctx), bounds());
79}
80std::shared_ptr<Acts::VolumeBounds> SpectrometerSector::bounds() const { return m_args.bounds; }
82 Chamber::ReadoutSet toReturn{};
83 for (const ChamberPtr& ch : chambers()) {
84 toReturn.insert(toReturn.end(), ch->readoutEles().begin(), ch->readoutEles().end());
85 }
86 return toReturn;
87}
88const std::vector<SpectrometerSector::chamberLocation> & SpectrometerSector::chamberLocations() const{
89 return m_args.detectorLocs;
90
91}
92std::ostream& operator<<(std::ostream& ostr,
94 ostr<<std::endl;
95 ostr<<"halfX (S/L): "<<halfXlowY(*args.bounds)<<"/"<<halfXhighY(*args.bounds)<<" [mm], ";
96 ostr<<"halfY: "<<halfY(*args.bounds)<<" [mm], ";
97 ostr<<"halfZ: "<<halfZ(*args.bounds)<<" [mm], ";
98 ostr<<"************************************************************************"<<std::endl;
99 for (const SpectrometerSector::ChamberPtr& ch : args.chambers) {
100 ostr<<" --- "<<(*ch)<<std::endl;
101 }
102 return ostr;
103}
104std::ostream& operator<<(std::ostream& ostr, const SpectrometerSector& chamber) {
105 ostr<<"MS sector "<<chamber.identString()<<" "<<chamber.parameters();
106 return ostr;
107}
108
109const std::vector<unsigned int>& SpectrometerSector::logicalLayerIdx(const MuonReadoutElement* reEle) const{
110 return m_detLayIdCache.at(reEle);
111};
112
113std::unordered_map<const MuonReadoutElement*, std::vector<unsigned int>>
115
116 std::unordered_map<const MuonReadoutElement*, std::vector<unsigned int>> cache{};
117 const ActsTrk::GeometryContext gctx{};
118 const Amg::Transform3D sectorTrans = globalToLocalTransform(gctx);
119
120 // sort the Readout elements by z in the sector fram
121 Chamber::ReadoutSet reEleSorted {readoutEles()};
122 std::ranges::sort(reEleSorted, [&sectorTrans, &gctx](const MuonReadoutElement* reEle1, const MuonReadoutElement* reEle2)-> bool {
123 return (sectorTrans * reEle1->center(gctx, reEle1->identify())).z() < (sectorTrans * reEle2->center(gctx, reEle2->identify())).z();
124 });
125
126 // this is a function to find the next logical layer, returning the corresponding reEle and Id
127 auto nextLayer = [this, &cache, &reEleSorted](const Identifier& lastId) ->
128 std::pair<const MuonReadoutElement*, const Identifier> {
129
130 const MuonReadoutElement* nextReEle {nullptr};
131 Identifier nextId {};
132
133 for (const MuonReadoutElement* reEle : reEleSorted){
134
135 // Check if this reEle has already been filled up
136 if (cache.count(reEle)) continue;
137
138 // compute the logical layer Id of the first layer of the reEle (first layer/gasgap, first channel, projecting to
139 // stationEta=1, doubletZ=1, doubletPhi=1, according to the technology)
140 const Identifier logicalId {computeDetLayerId(reEle)};
141
142 //if we find another measurement layer with the same detLayerId as the last we added (e.g. the same gasgap of two RPC z doublets)
143 if (logicalId == lastId){
144 return std::make_pair(reEle, logicalId);
145 }
146
147 // Save the next (subsequent) logic layer in z
148 if (!nextReEle) {
149 nextReEle = reEle;
150 nextId = logicalId;
151 }
152
153 }
154 return std::make_pair(nextReEle, nextId);
155 };
156
157 unsigned int layCounter {0}, nIter {0};
158 Identifier lastId {};
159 unsigned int deltaN {0};
160 while(++nIter <= reEleSorted.size()){
161
162 auto [nextReEle, nextId] = nextLayer(lastId);
163 if (!nextReEle){
164 THROW_EXCEPTION("Failed to retrieve next reEle in fillDetLayIdCache()");
165 }
166
167 unsigned int nLayers = nLayerPerReadout(nextReEle);
168
169 if (nextId != lastId) {
170 layCounter += deltaN;
171 deltaN = nLayers;
172 lastId = nextId;
173 }
174 else{
175 deltaN = std::max(deltaN, nLayers);
176 }
177
178 cache[nextReEle] = range(layCounter, layCounter + nLayers);
179
180 ATH_MSG_DEBUG( identString() << " ReEle: " << idHelperSvc()->toStringDetEl(nextReEle->identify()) <<
181 " Add logicLay: " << idHelperSvc()->toStringGasGap(nextId) << " nInserted, layCounter " << cache.at(nextReEle).size() << " ," << layCounter);
182 }
183 return cache;
184};
185
187
188 switch (rele->detectorType()) {
190 auto mdtRele = dynamic_cast<const MdtReadoutElement*>(rele);
191 return idHelperSvc()->mdtIdHelper().channelID(mdtRele->stationName(), 1,
192 mdtRele->stationPhi(),
193 mdtRele->multilayer(),
194 1,1);
195 }
197 auto rpcRele = dynamic_cast<const RpcReadoutElement*>(rele);
198 return idHelperSvc()->rpcIdHelper().channelID(rpcRele->stationName(), 1,
199 rpcRele->stationPhi(),
200 rpcRele->doubletR(), 1, 1,
201 1, 0, 1);
202 }
204 auto tgcRele = dynamic_cast<const TgcReadoutElement*>(rele);
205 return idHelperSvc()->tgcIdHelper().channelID(tgcRele->stationName(), 1,
206 tgcRele->stationPhi(),
207 1, 0, 1);
208 }
210 auto stgcRele = dynamic_cast<const sTgcReadoutElement*>(rele);
211 return idHelperSvc()->stgcIdHelper().channelID(stgcRele->stationName(), 1,
212 stgcRele->stationPhi(),
213 stgcRele->multilayer(),
214 1, 0, 1);
215 }
217 auto mmRele = dynamic_cast<const MmReadoutElement*>(rele);
218 return idHelperSvc()->mmIdHelper().channelID(mmRele->stationName(), 1,
219 mmRele->stationPhi(),
220 mmRele->multilayer(),
221 1, 1);
222 }
223 default:
224 THROW_EXCEPTION("Unexpected Readout Element Type in computeDetLayerId()");
225 }
226}
227
229
230 switch (rele->detectorType()) {
232 auto mdtRele = dynamic_cast<const MdtReadoutElement*>(rele);
233 return mdtRele->numLayers();
234 }
236 auto rpcRele = dynamic_cast<const RpcReadoutElement*>(rele);
237 return rpcRele->nGasGaps();
238 }
240 auto tgcRele = dynamic_cast<const TgcReadoutElement*>(rele);
241 return tgcRele->nGasGaps();
242 }
244 auto stgcRele = dynamic_cast<const sTgcReadoutElement*>(rele);
245 return stgcRele->numLayers();
246 }
248 auto mmRele = dynamic_cast<const MmReadoutElement*>(rele);
249 return mmRele->nGasGaps();
250 }
251 default:
252 THROW_EXCEPTION("Unexpected Readout Element Type in nLayerPerReadout()");
253 }
254}
255
256}
257
258#endif
#define ATH_MSG_DEBUG(x)
#define min(a, b)
Definition cfImp.cxx:40
#define max(a, b)
Definition cfImp.cxx:41
Acts::GeometryContext context() const
virtual DetectorType detectorType() const =0
Returns the detector element type.
AthMessaging(IMessageSvc *msgSvc, const std::string &name)
Constructor.
Identifier channelID(int stationName, int stationEta, int stationPhi, int multilayer, int tubeLayer, int tube) const
Identifier channelID(int stationName, int stationEta, int stationPhi, int multilayer, int gasGap, int channel) const
std::vector< const MuonReadoutElement * > ReadoutSet
Define the list of read out elements of the chamber.
Definition Chamber.h:31
Readout element to describe the Monitored Drift Tube (Mdt) chambers Mdt chambers usually comrpise out...
unsigned numLayers() const
Returns how many tube layers are inside the multi layer [1;4].
unsigned int nGasGaps() const
Returns the number of gas gaps.
MuonReadoutElement is an abstract class representing the geometry of a muon detector.
Amg::Vector3D center(const ActsTrk::GeometryContext &ctx) const
Returns the geometrical center point of the readout element.
Identifier identify() const override final
Return the ATLAS identifier.
unsigned nGasGaps() const
Returns the number of gasgaps described by this ReadOutElement (usally 2 or 3)
A spectrometer sector forms the envelope of all chambers that are placed in the same MS sector & laye...
bool operator<(const SpectrometerSector &other) const
int8_t side() const
Returns the side of the MS-sector 1 -> A side ; -1 -> C side.
const std::vector< unsigned int > & logicalLayerIdx(const MuonReadoutElement *reEle) const
Returns the logic layer numbering of a given Readout Element.
double halfZ() const
Thickness of the chamber in the z-direction.
unsigned int nLayerPerReadout(const MuonReadoutElement *rele) const
Helper function giving the number of measurement layers in a given readout ele.
const Muon::IMuonIdHelperSvc * idHelperSvc() const
Returns the IdHelpeSvc.
bool barrel() const
Returns whether the sector is placed in the barrel.
Chamber::ReadoutSet readoutEles() const
Returns the list of all associated readout elements.
std::unordered_map< const MuonReadoutElement *, std::vector< unsigned int > > fillDetLayIdCache() const
Function filling the map mapping the readout elements to layer numbers.
SpectrometerSector(defineArgs &&args)
Standard constructor taking the defining parameters.
Identifier computeDetLayerId(const MuonReadoutElement *rele) const
Helper function calculating the logic layer Id and the physical layer id.
const Amg::Transform3D & localToGlobalTransform(const ActsTrk::GeometryContext &gctx) const
Returns the local -> global tarnsformation from the sector.
std::string identString() const
Returns a string encoding the chamber index & the sector of the MS sector.
Amg::Transform3D globalToLocalTransform(const ActsTrk::GeometryContext &gctx) const
Returns the global -> local transformation from the ATLAS global.
double halfY() const
Extend of the chamber in the y-direction.
const Acts::PlaneSurface & surface() const
Returns the associated surface.
const ChamberSet & chambers() const
Returns the associated chambers with this sector.
GeoModel::TransientConstSharedPtr< Chamber > ChamberPtr
double halfXLong() const
Long-extend of the chamber in the x-direction at positive Y.
int sector() const
Returns the sector of the MS-sector.
std::shared_ptr< Acts::VolumeBounds > bounds() const
Returns the volume bounds.
std::shared_ptr< Acts::Volume > boundingVolume(const ActsTrk::GeometryContext &gctx) const
Returns the Acts::Volume representation of the sector.
const std::unordered_map< const MuonReadoutElement *, std::vector< unsigned int > > m_detLayIdCache
Map mapping each Readout Element to the layer numbering in the sector frame.
const std::vector< chamberLocation > & chamberLocations() const
returns the list of all MDT chambers in the sector for fast navigation
double halfXShort() const
Short extend of the chamber in the x-direction at negative Y.
int stationPhi() const
: Returns the station phi of the sector
const defineArgs & parameters() const
Returns the reference to the defining parameters of the sector.
Muon::MuonStationIndex::ChIndex chamberIndex() const
Returns the chamber index scheme.
std::vector< ChamberPtr > ChamberSet
unsigned nGasGaps() const
Returns the number of gasgaps described by this ReadOutElement (usally 2 or 3)
unsigned numLayers() const
Returns the number of gas gap layers.
Interface for Helper service that creates muon Identifiers and can be used to print Identifiers.
virtual const MmIdHelper & mmIdHelper() const =0
access to CscIdHelper
virtual const RpcIdHelper & rpcIdHelper() const =0
access to RpcIdHelper
virtual const sTgcIdHelper & stgcIdHelper() const =0
access to TgcIdHelper
virtual const TgcIdHelper & tgcIdHelper() const =0
access to TgcIdHelper
virtual const MdtIdHelper & mdtIdHelper() const =0
access to MdtIdHelper
Identifier channelID(int stationName, int stationEta, int stationPhi, int doubletR, int doubletZ, int doubletPhi, int gasGap, int measuresPhi, int strip) const
Identifier channelID(int stationName, int stationEta, int stationPhi, int gasGap, int isStrip, int channel) const
Identifier channelID(int stationName, int stationEta, int stationPhi, int multilayer, int gasGap, int channelType, int channel) const
@ Mm
Maybe not needed in the migration.
@ Tgc
Resitive Plate Chambers.
@ sTgc
Micromegas (NSW)
@ Rpc
Monitored Drift Tubes.
@ Mdt
MuonSpectrometer.
Eigen::Affine3d Transform3D
The ReadoutGeomCnvAlg converts the Run4 Readout geometry build from the GeoModelXML into the legacy M...
Acts::TrapezoidVolumeBounds::BoundValues BoundEnums
double halfY(const Acts::VolumeBounds &bounds)
Returns the half-Y length for the parsed volume bounds (Trapezoid/ Cuboid)
std::ostream & operator<<(std::ostream &ostr, const Chamber::defineArgs &args)
Definition Chamber.cxx:14
SpectrometerSector::ChamberSet ChamberSet
double halfZ(const Acts::VolumeBounds &bounds)
Returns the half-Z length for the parsed volume bounds (Trapezoid/ Cuboid)
double halfXhighY(const Acts::VolumeBounds &bounds)
Returns the half-Y length @ posiive Y for the parsed volume bounds (Trapezoid/ Cuboid)
double halfXlowY(const Acts::VolumeBounds &bounds)
Returns the half-X length @ negative Y for the parsed volume bounds (Trapezoid/ Cuboid)
const std::string & chName(ChIndex index)
convert ChIndex into a string
ChIndex
enum to classify the different chamber layers in the muon spectrometer
STL namespace.
#define THROW_EXCEPTION(MESSAGE)
Definition throwExcept.h:10