ATLAS Offline Software
Loading...
Searching...
No Matches
SpectrometerSector.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 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>
14
21
22#include <format>
23
24namespace {
25 std::vector<unsigned int> range (unsigned min, unsigned max) {
26 assert(max > min);
27 std::vector<unsigned int> v(max - min);
28 std::iota(v.begin(), v.end(), min);
29 return v;
30 };
31}
32
33namespace MuonGMR4 {
34
36using BoundEnums = Acts::TrapezoidVolumeBounds::BoundValues;
37
39 AthMessaging("MuonSpectrometerSector"), m_args{std::move(args)} {
40 for (auto & chamber : m_args.chambers) {
41 chamber->setParent(this);
42 }
43 }
44
46 return m_args.id < other.m_args.id;
47}
49 return m_args.chambers.front()->stationEta() > 0 ? 1 : -1;
50}
52const Muon::IMuonIdHelperSvc* SpectrometerSector::idHelperSvc() const { return m_args.chambers.front()->idHelperSvc();}
53Muon::MuonStationIndex::ChIndex SpectrometerSector::chamberIndex() const { return m_args.chambers.front()->chamberIndex(); }
54int SpectrometerSector::stationPhi() const { return m_args.chambers.front()->stationPhi(); }
55int SpectrometerSector::sector() const {return m_args.chambers.front()->sector(); }
56bool SpectrometerSector::barrel() const { return m_args.chambers.front()->barrel(); }
58 return std::format("id: {:3d}, {:} {:}-side sector: {:2},", m_args.id,
60 side() == 1 ? 'A' : 'C' , sector());
61}
62const ChamberSet& SpectrometerSector::chambers() const{ return m_args.chambers; }
63const Acts::PlaneSurface& SpectrometerSector::surface() const {
64 return *m_args.surface;
65}
67 return surface().transform(gctx.context());
68}
74double SpectrometerSector::halfY() const { return MuonGMR4::halfY(* m_args.bounds); }
75double SpectrometerSector::halfZ() const { return MuonGMR4::halfZ(*m_args.bounds);}
76
77
78std::shared_ptr<Acts::Volume> SpectrometerSector::boundingVolume(const ActsTrk::GeometryContext& gctx) const {
79 return std::make_shared<Acts::Volume>(localToGlobalTrans(gctx), bounds());
80}
81std::shared_ptr<Acts::VolumeBounds> SpectrometerSector::bounds() const { return m_args.bounds; }
83 Chamber::ReadoutSet toReturn{};
84 for (const ChamberPtr& ch : chambers()) {
85 toReturn.insert(toReturn.end(), ch->readoutEles().begin(), ch->readoutEles().end());
86 }
87 return toReturn;
88}
89const std::vector<SpectrometerSector::chamberLocation> & SpectrometerSector::chamberLocations() const{
90 return m_args.detectorLocs;
91
92}
93std::ostream& operator<<(std::ostream& ostr,
95 ostr<<std::endl;
96 ostr<<"halfX (S/L): "<<halfXlowY(*args.bounds)<<"/"<<halfXhighY(*args.bounds)<<" [mm], ";
97 ostr<<"halfY: "<<halfY(*args.bounds)<<" [mm], ";
98 ostr<<"halfZ: "<<halfZ(*args.bounds)<<" [mm], ";
99 ostr<<"************************************************************************"<<std::endl;
100 for (const SpectrometerSector::ChamberPtr& ch : args.chambers) {
101 ostr<<" --- "<<(*ch)<<std::endl;
102 }
103 return ostr;
104}
105std::ostream& operator<<(std::ostream& ostr, const SpectrometerSector& chamber) {
106 ostr<<"MS sector "<<chamber.identString()<<" "<<chamber.parameters();
107 return ostr;
108}
109
110const std::vector<unsigned int>& SpectrometerSector::logicalLayerIdx(const MuonReadoutElement* reEle) const{
111 return m_detLayIdCache.at(reEle);
112};
113
114std::unordered_map<const MuonReadoutElement*, std::vector<unsigned int>>
116
117 std::unordered_map<const MuonReadoutElement*, std::vector<unsigned int>> cache{};
118 const ActsTrk::GeometryContext gctx{};
119 const Amg::Transform3D sectorTrans = globalToLocalTrans(gctx);
120
121 // sort the Readout elements by z in the sector fram
122 Chamber::ReadoutSet reEleSorted {readoutEles()};
123 std::ranges::sort(reEleSorted, [&sectorTrans, &gctx](const MuonReadoutElement* reEle1, const MuonReadoutElement* reEle2)-> bool {
124 return (sectorTrans * reEle1->center(gctx, reEle1->identify())).z() < (sectorTrans * reEle2->center(gctx, reEle2->identify())).z();
125 });
126
127 // this is a function to find the next logical layer, returning the corresponding reEle and Id
128 auto nextLayer = [this, &cache, &reEleSorted](const Identifier& lastId) ->
129 std::pair<const MuonReadoutElement*, const Identifier> {
130
131 const MuonReadoutElement* nextReEle {nullptr};
132 Identifier nextId {};
133
134 for (const MuonReadoutElement* reEle : reEleSorted){
135
136 // Check if this reEle has already been filled up
137 if (cache.count(reEle)) continue;
138
139 // compute the logical layer Id of the first layer of the reEle (first layer/gasgap, first channel, projecting to
140 // stationEta=1, doubletZ=1, doubletPhi=1, according to the technology)
141 const Identifier logicalId {computeDetLayerId(reEle)};
142
143 //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)
144 if (logicalId == lastId){
145 return std::make_pair(reEle, logicalId);
146 }
147
148 // Save the next (subsequent) logic layer in z
149 if (!nextReEle) {
150 nextReEle = reEle;
151 nextId = logicalId;
152 }
153
154 }
155 return std::make_pair(nextReEle, nextId);
156 };
157
158 unsigned int layCounter {0}, nIter {0};
159 Identifier lastId {};
160 unsigned int deltaN {0};
161 while(++nIter <= reEleSorted.size()){
162
163 auto [nextReEle, nextId] = nextLayer(lastId);
164 if (!nextReEle){
165 THROW_EXCEPTION("Failed to retrieve next reEle in fillDetLayIdCache()");
166 }
167
168 unsigned int nLayers = nLayerPerReadout(nextReEle);
169
170 if (nextId != lastId) {
171 layCounter += deltaN;
172 deltaN = nLayers;
173 lastId = nextId;
174 }
175 else{
176 deltaN = std::max(deltaN, nLayers);
177 }
178
179 cache[nextReEle] = range(layCounter, layCounter + nLayers);
180
181 ATH_MSG_DEBUG( identString() << " ReEle: " << idHelperSvc()->toStringDetEl(nextReEle->identify()) <<
182 " Add logicLay: " << idHelperSvc()->toStringGasGap(nextId) << " nInserted, layCounter " << cache.at(nextReEle).size() << " ," << layCounter);
183 }
184 return cache;
185};
186
188
189 switch (rele->detectorType()) {
191 auto mdtRele = dynamic_cast<const MdtReadoutElement*>(rele);
192 return idHelperSvc()->mdtIdHelper().channelID(mdtRele->stationName(), 1,
193 mdtRele->stationPhi(),
194 mdtRele->multilayer(),
195 1,1);
196 }
198 auto rpcRele = dynamic_cast<const RpcReadoutElement*>(rele);
199 return idHelperSvc()->rpcIdHelper().channelID(rpcRele->stationName(), 1,
200 rpcRele->stationPhi(),
201 rpcRele->doubletR(), 1, 1,
202 1, 0, 1);
203 }
205 auto tgcRele = dynamic_cast<const TgcReadoutElement*>(rele);
206 return idHelperSvc()->tgcIdHelper().channelID(tgcRele->stationName(), 1,
207 tgcRele->stationPhi(),
208 1, 0, 1);
209 }
211 auto stgcRele = dynamic_cast<const sTgcReadoutElement*>(rele);
212 return idHelperSvc()->stgcIdHelper().channelID(stgcRele->stationName(), 1,
213 stgcRele->stationPhi(),
214 stgcRele->multilayer(),
215 1, 0, 1);
216 }
218 auto mmRele = dynamic_cast<const MmReadoutElement*>(rele);
219 return idHelperSvc()->mmIdHelper().channelID(mmRele->stationName(), 1,
220 mmRele->stationPhi(),
221 mmRele->multilayer(),
222 1, 1);
223 }
224 default:
225 THROW_EXCEPTION("Unexpected Readout Element Type in computeDetLayerId()");
226 }
227}
228
230
231 switch (rele->detectorType()) {
233 auto mdtRele = dynamic_cast<const MdtReadoutElement*>(rele);
234 return mdtRele->numLayers();
235 }
237 auto rpcRele = dynamic_cast<const RpcReadoutElement*>(rele);
238 return rpcRele->nGasGaps();
239 }
241 auto tgcRele = dynamic_cast<const TgcReadoutElement*>(rele);
242 return tgcRele->nGasGaps();
243 }
245 auto stgcRele = dynamic_cast<const sTgcReadoutElement*>(rele);
246 return stgcRele->numLayers();
247 }
249 auto mmRele = dynamic_cast<const MmReadoutElement*>(rele);
250 return mmRele->nGasGaps();
251 }
252 default:
253 THROW_EXCEPTION("Unexpected Readout Element Type in nLayerPerReadout()");
254 }
255}
256
257}
258
259#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:26
unsigned int numLayers() const
Returns the number of tube layer.
unsigned int nGasGaps() const
Returns the number of gas gaps.
The MuonReadoutElement is an abstract class representing the geometry representing the muon detector.
Amg::Vector3D center(const ActsTrk::GeometryContext &ctx) const
Returns the detector center (Which is the same as the detector center of the first measurement layer)
Identifier identify() const override final
Return the athena 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.
Amg::Transform3D globalToLocalTrans(const ActsTrk::GeometryContext &gctx) const
Returns the global -> local transformation from the ATLAS global.
const Amg::Transform3D & localToGlobalTrans(const ActsTrk::GeometryContext &gctx) const
Returns the local -> global tarnsformation from the sector.
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.
std::string identString() const
Returns a string encoding the chamber index & the sector of the MS sector.
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 int 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