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}
65
66
67const Amg::Transform3D& SpectrometerSector::localToGlobalTransform(const Acts::GeometryContext& tgContext) const{
68 return surface().localToGlobalTransform(tgContext);
69}
70Amg::Transform3D SpectrometerSector::globalToLocalTransform(const Acts::GeometryContext& tgContext) const{
71 return localToGlobalTransform(tgContext).inverse();
72}
74 return surface().localToGlobalTransform(gctx.context());
75}
81double SpectrometerSector::halfY() const { return MuonGMR4::halfY(* m_args.bounds); }
82double SpectrometerSector::halfZ() const { return MuonGMR4::halfZ(*m_args.bounds);}
83
84
85std::shared_ptr<Acts::Volume> SpectrometerSector::boundingVolume(const ActsTrk::GeometryContext& gctx) const {
86 return std::make_shared<Acts::Volume>(localToGlobalTransform(gctx), bounds());
87}
88std::shared_ptr<Acts::VolumeBounds> SpectrometerSector::bounds() const { return m_args.bounds; }
90 Chamber::ReadoutSet toReturn{};
91 for (const ChamberPtr& ch : chambers()) {
92 toReturn.insert(toReturn.end(), ch->readoutEles().begin(), ch->readoutEles().end());
93 }
94 return toReturn;
95}
96const std::vector<SpectrometerSector::chamberLocation> & SpectrometerSector::chamberLocations() const{
97 return m_args.detectorLocs;
98
99}
100std::ostream& operator<<(std::ostream& ostr,
101 const SpectrometerSector::defineArgs& args) {
102 ostr<<std::endl;
103 ostr<<"halfX (S/L): "<<halfXlowY(*args.bounds)<<"/"<<halfXhighY(*args.bounds)<<" [mm], ";
104 ostr<<"halfY: "<<halfY(*args.bounds)<<" [mm], ";
105 ostr<<"halfZ: "<<halfZ(*args.bounds)<<" [mm], ";
106 ostr<<"************************************************************************"<<std::endl;
107 for (const SpectrometerSector::ChamberPtr& ch : args.chambers) {
108 ostr<<" --- "<<(*ch)<<std::endl;
109 }
110 return ostr;
111}
112std::ostream& operator<<(std::ostream& ostr, const SpectrometerSector& chamber) {
113 ostr<<"MS sector "<<chamber.identString()<<" "<<chamber.parameters();
114 return ostr;
115}
116
117const std::vector<unsigned int>& SpectrometerSector::logicalLayerIdx(const MuonReadoutElement* reEle) const{
118 return m_detLayIdCache.at(reEle);
119};
120
121std::unordered_map<const MuonReadoutElement*, std::vector<unsigned int>>
123
124 std::unordered_map<const MuonReadoutElement*, std::vector<unsigned int>> cache{};
125 const ActsTrk::GeometryContext gctx{};
126 const Amg::Transform3D sectorTrans = globalToLocalTransform(gctx);
127
128 // sort the Readout elements by z in the sector fram
129 Chamber::ReadoutSet reEleSorted {readoutEles()};
130 std::ranges::sort(reEleSorted, [&sectorTrans, &gctx](const MuonReadoutElement* reEle1, const MuonReadoutElement* reEle2)-> bool {
131 return (sectorTrans * reEle1->center(gctx, reEle1->identify())).z() < (sectorTrans * reEle2->center(gctx, reEle2->identify())).z();
132 });
133
134 // this is a function to find the next logical layer, returning the corresponding reEle and Id
135 auto nextLayer = [this, &cache, &reEleSorted](const Identifier& lastId) ->
136 std::pair<const MuonReadoutElement*, const Identifier> {
137
138 const MuonReadoutElement* nextReEle {nullptr};
139 Identifier nextId {};
140
141 for (const MuonReadoutElement* reEle : reEleSorted){
142
143 // Check if this reEle has already been filled up
144 if (cache.count(reEle)) continue;
145
146 // compute the logical layer Id of the first layer of the reEle (first layer/gasgap, first channel, projecting to
147 // stationEta=1, doubletZ=1, doubletPhi=1, according to the technology)
148 const Identifier logicalId {computeDetLayerId(reEle)};
149
150 //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)
151 if (logicalId == lastId){
152 return std::make_pair(reEle, logicalId);
153 }
154
155 // Save the next (subsequent) logic layer in z
156 if (!nextReEle) {
157 nextReEle = reEle;
158 nextId = logicalId;
159 }
160
161 }
162 return std::make_pair(nextReEle, nextId);
163 };
164
165 unsigned int layCounter {0}, nIter {0};
166 Identifier lastId {};
167 unsigned int deltaN {0};
168 while(++nIter <= reEleSorted.size()){
169
170 auto [nextReEle, nextId] = nextLayer(lastId);
171 if (!nextReEle){
172 THROW_EXCEPTION("Failed to retrieve next reEle in fillDetLayIdCache()");
173 }
174
175 unsigned int nLayers = nLayerPerReadout(nextReEle);
176
177 if (nextId != lastId) {
178 layCounter += deltaN;
179 deltaN = nLayers;
180 lastId = nextId;
181 }
182 else{
183 deltaN = std::max(deltaN, nLayers);
184 }
185
186 cache[nextReEle] = range(layCounter, layCounter + nLayers);
187
188 ATH_MSG_DEBUG( identString() << " ReEle: " << idHelperSvc()->toStringDetEl(nextReEle->identify()) <<
189 " Add logicLay: " << idHelperSvc()->toStringGasGap(nextId) << " nInserted, layCounter " << cache.at(nextReEle).size() << " ," << layCounter);
190 }
191 return cache;
192};
193
195
196 switch (rele->detectorType()) {
198 auto mdtRele = dynamic_cast<const MdtReadoutElement*>(rele);
199 return idHelperSvc()->mdtIdHelper().channelID(mdtRele->stationName(), 1,
200 mdtRele->stationPhi(),
201 mdtRele->multilayer(),
202 1,1);
203 }
205 auto rpcRele = dynamic_cast<const RpcReadoutElement*>(rele);
206 return idHelperSvc()->rpcIdHelper().channelID(rpcRele->stationName(), 1,
207 rpcRele->stationPhi(),
208 rpcRele->doubletR(), 1, 1,
209 1, 0, 1);
210 }
212 auto tgcRele = dynamic_cast<const TgcReadoutElement*>(rele);
213 return idHelperSvc()->tgcIdHelper().channelID(tgcRele->stationName(), 1,
214 tgcRele->stationPhi(),
215 1, 0, 1);
216 }
218 auto stgcRele = dynamic_cast<const sTgcReadoutElement*>(rele);
219 return idHelperSvc()->stgcIdHelper().channelID(stgcRele->stationName(), 1,
220 stgcRele->stationPhi(),
221 stgcRele->multilayer(),
222 1, 0, 1);
223 }
225 auto mmRele = dynamic_cast<const MmReadoutElement*>(rele);
226 return idHelperSvc()->mmIdHelper().channelID(mmRele->stationName(), 1,
227 mmRele->stationPhi(),
228 mmRele->multilayer(),
229 1, 1);
230 }
231 default:
232 THROW_EXCEPTION("Unexpected Readout Element Type in computeDetLayerId()");
233 }
234}
235
237
238 switch (rele->detectorType()) {
240 auto mdtRele = dynamic_cast<const MdtReadoutElement*>(rele);
241 return mdtRele->numLayers();
242 }
244 auto rpcRele = dynamic_cast<const RpcReadoutElement*>(rele);
245 return rpcRele->nGasGaps();
246 }
248 auto tgcRele = dynamic_cast<const TgcReadoutElement*>(rele);
249 return tgcRele->nGasGaps();
250 }
252 auto stgcRele = dynamic_cast<const sTgcReadoutElement*>(rele);
253 return stgcRele->numLayers();
254 }
256 auto mmRele = dynamic_cast<const MmReadoutElement*>(rele);
257 return mmRele->nGasGaps();
258 }
259 default:
260 THROW_EXCEPTION("Unexpected Readout Element Type in nLayerPerReadout()");
261 }
262}
263void SpectrometerSector::addPlacement(std::unique_ptr<ActsTrk::VolumePlacement>&& placement) const {
264 m_args.chambers.front()->addPlacement(std::move(placement));
265}
266
267}
268
269#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:32
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
void addPlacement(std::unique_ptr< ActsTrk::VolumePlacement > &&placement) const
Adds a volume placement to the Chamber's memory management.
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:18
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