ATLAS Offline Software
Loading...
Searching...
No Matches
MuonStation.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/***************************************************************************
6 Holds the info related to a full station
7 -----------------------------------------
8 ***************************************************************************/
9
11
12#include <iomanip>
13#include <utility>
14#include <ranges>
15
16
22namespace MuonGM {
23
24 MuonStation::MuonStation(std::string_view stName,
25 double Ssize, double Rsize, double Zsize,
26 double LongSsize, double LongRsize, double LongZsize,
27 int zi, int fi, bool descratzneg) :
28 AthMessaging{"MuonStation"},
29 m_statname(stName) {
30 m_Ssize = Ssize;
31 m_Rsize = Rsize;
32 m_Zsize = Zsize;
36 m_descratzneg = descratzneg;
37 m_statEtaIndex = zi;
38 m_statPhiIndex = fi;
39 }
40
41 MuonStation::~MuonStation() = default;
42
47
48 void MuonStation::setTransform(GeoAlignableTransform* xf) { m_transform = xf; }
49
50 void MuonStation::setxAmdbCRO(double xpos) { m_xAmdbCRO = xpos; }
51
53 m_native_to_amdbl = std::move(xf);
54 ATH_MSG_VERBOSE("stationName/Jff/Jzz " << getStationType() << " " << getPhiIndex() << " "<< getEtaIndex()
55 <<"setNativeToAmdbLRS: "<<Amg::toString(m_native_to_amdbl));
56 }
57
59 m_amdbl_to_global = std::move(xf);
60 ATH_MSG_DEBUG("setNominalAmdbLRSToGlobal: stationName/Jff/Jzz " << getStationType() << " " << getPhiIndex() << " "<< getEtaIndex()
61 << " Origin of AmdbLocalFrame= " << Amg::toString(m_amdbl_to_global.translation()));
62 }
63 void MuonStation::setBlineFixedPointInAmdbLRS(double s0, double z0, double t0) {
64
65 ATH_MSG_DEBUG("Station " << getStationType() << " at zi/fi " << getEtaIndex() << "/" << getPhiIndex()
66 << " setting fixed point for B-lines at s0,z0,t0 = " << s0 << " " << z0 << " " << t0 );
67
68
72
73 ATH_MSG_DEBUG("setBlineFixedPointInAmdbLRS: stationName/Jff/Jzz " << getStationType() << " " << getPhiIndex() << " "
74 << getEtaIndex() << " nominal(i.e. from-station-envelop-only) B-line fixed point "
76
77 }
78
80 // needed to update the station-level BlineFixedPoint with data from second multilayer
82 }
83
85 if (!m_firstRequestBlineFixedP) return;
86 // Before correction m_BlineFixedPointInAmdbLRS has a z set at the edge of
87 // lowest-z tube of the first layer of one of the two multilayers.
88 // For endcap A, endcap C, and barrel A, this is correct, given the tube staggering
89 // For barrel side C, given the tube staggering, the z should be at the
90 // edge at the second layer, i.e. the z should be corrected by a half tube
91 // pitch. Correction is thus computed only for barrel side C.
92 if (barrel() && (getEtaIndex() < 0)) {
93 for (auto&[jobId, alignPair] : m_REwithAlTransfInStation) {
94 const MuonReadoutElement* muonRE = alignPair.first;
95
97 continue;
98 }
99 const MdtReadoutElement* mdtRE = dynamic_cast<const MdtReadoutElement*>(muonRE);
100 // Correct for tube staggering on barrel side C
101 double shiftInZ = -0.5 * mdtRE->tubePitch();
102 // in addition, correct for 35microm glue width incorrectly applied
103 double multilayerRealSize{0};
104 for (int ilayer = 1; ilayer <= 2; ++ilayer) {
105 double val{0.};
106 bool wellDefined = mdtRE->getWireFirstLocalCoordAlongZ(ilayer, val);
107 if (!wellDefined) {
108 ATH_MSG_WARNING("getUpdatedBlineFixedPointInAmdbLRS: stationName/Jff/Jzz " << getStationType()
109 << " " << getPhiIndex() << " " << getEtaIndex()
110 << " cannot get wire coordinates for second tube layer");
111 val = 0.;
112 }
113 if ((ilayer == 1) || (val > multilayerRealSize)) multilayerRealSize = val;
114 }
115 multilayerRealSize += (mdtRE->getNtubesperlayer() - 1) * mdtRE->tubePitch();
116 multilayerRealSize += mdtRE->outerTubeRadius(); // last tube: no glue width
117 shiftInZ += mdtRE->getZsize() - multilayerRealSize;
118
120 ATH_MSG_DEBUG("getUpdatedBlineFixedPointInAmdbLRS: stationName/Jff/Jzz " << getStationType() << " "
121 << getPhiIndex() << " " << getEtaIndex() << " shiftInZ = " << shiftInZ << " re-set B-line fixed point "
123 break;
124 }
125 }
127 }
128
130 m_delta_amdb_frame = std::move(xf);
131 ATH_MSG_DEBUG("Station " << getStationType() << " at zi/fi " << getEtaIndex() << "/" << getPhiIndex()
132 << " adding Aline " << std::endl
133 << " native_to_amdbl computed from A-line " << Amg::toString(m_native_to_amdbl) << std::endl
134 << "Station amdbl_to_global " << endmsg << Amg::toString(m_amdbl_to_global));
136 }
137
138 void MuonStation::setDelta_fromAline(double tras, double traz, double trat, double rots, double rotz, double rott) {
139 // store here the angles of A-line
140 m_rots = rots;
141 m_rotz = rotz;
142 m_rott = rott;
143
144 Amg::Transform3D delta_amdb{Amg::Transform3D::Identity()};
145 if (std::abs(tras) + std::abs(traz) + std::abs(trat) + (std::abs(rots) + std::abs(rotz) + std::abs(rott)) * 1000. > 0.01) {
146 // compute the delta transform in the local AMDB frame
147 delta_amdb = Amg::Translation3D{tras, traz, trat} *
149 m_hasALines = true;
150 }
151
152 // store the delta transform in the local AMDB frame
153 setDeltaAmdbLRS(delta_amdb);
154
155 ATH_MSG_DEBUG("Station " << getStationType() << " at zi/fi " << getEtaIndex() << "/" << getPhiIndex()
156 << " adding Aline " << setiosflags(std::ios::fixed) << std::setprecision(6) << std::setw(12)
157 << tras << " " << traz << " " << trat << " " << rots << " " << rotz << " " << rott << std::endl
158 << " delta_amdb computed from A-line " << Amg::toString(delta_amdb));
159 }
160
162 std::map<int, pairRE_AlignTransf>::const_iterator itr = m_REwithAlTransfInStation.find(jobIndex);
163 return itr !=m_REwithAlTransfInStation.end() ? itr->second.first : nullptr;
164 }
166 std::map<int, pairRE_AlignTransf>::const_iterator itr = m_REwithAlTransfInStation.find(jobIndex);
167 return itr !=m_REwithAlTransfInStation.end() ? itr->second.first : nullptr;
168 }
169
170 GeoAlignableTransform* MuonStation::getComponentAlTransf(int jobIndex) const {
171 std::map<int, pairRE_AlignTransf>::const_iterator itr = m_REwithAlTransfInStation.find(jobIndex);
172 return itr != m_REwithAlTransfInStation.end() ? itr->second.second : nullptr;
173 }
174
175 void MuonStation::addMuonReadoutElementWithAlTransf(MuonReadoutElement* a, GeoAlignableTransform* ptrsf, int jobIndex) {
176 ATH_MSG_DEBUG("addMuonReadoutElementWithAlTransf for station " << getStationName() << " at zi/fi = " << getEtaIndex()
177 << "/" << getPhiIndex() << " adding new component with Alignable transf... " << a->getStationName()
178 << " job ondex = " << jobIndex );
179 m_REwithAlTransfInStation[jobIndex] = std::make_pair(a, ptrsf);
180
181 ATH_MSG_DEBUG("addMuonReadoutElementWithAlTransf for station " << getStationName() << " at zi/fi = " << getEtaIndex()
182 << "/" << getPhiIndex() << " added new component - now size of map is " << m_REwithAlTransfInStation.size());
183 }
184
185 void MuonStation::setDelta_fromAline_forComp(int jobindex, double tras, double traz, double trat, double rots, double rotz,
186 double rott) {
187 GeoAlignableTransform* parentToChild = getComponentAlTransf(jobindex);
188 if (!parentToChild) {
189 ATH_MSG_WARNING( "setDelta_fromAline_forComp: WARNING: component for index " << jobindex
190 << " not found in MuonStation named " << getStationName() << " at zi/fi = " << getEtaIndex() << "/" << getPhiIndex());
191 return;
192 }
193 if (std::abs(tras) + std::abs(traz) + std::abs(trat) + (std::abs(rots) + std::abs(rotz) + std::abs(rott)) * 1000. < 0.01) {
194 ATH_MSG_DEBUG("setDelta_fromAline_forComp: A-line ignored --- too small (translations < 10microns & rotations <10microrad)");
195 return;
196 }
197
200
201 Amg::Transform3D parentToChildT = parentToChild->getTransform();
202 Amg::Transform3D delta_amdb = Amg::Translation3D{tras, traz, trat} *
204 // The station to component transform is static and must be computed in terms of "nominal geometry parameters"; fixing here bug
205 const MuonReadoutElement* reElement = getMuonReadoutElement(jobindex);
206
207 const Amg::Vector3D thisREnominalCenter{reElement->defTransform().translation()};
208 double Rcomp = thisREnominalCenter.perp() - (reElement->getRsize()) / 2.;
209 double DZcomp = std::abs(thisREnominalCenter.z()) - std::abs((m_amdbl_to_global.translation()).z()) -
210 std::abs((reElement->getZsize()) / 2.);
211
212 Amg::Transform3D childToLocAmdbStation = m_native_to_amdbl * parentToChildT;
213 Amg::Transform3D locAmdbStatToLocAmdbComp{Amg::Transform3D::Identity()};
214 // the following line is needed to go for scenario B in last slide of
215 // http://www.fisica.unisalento.it/~spagnolo/allow_listing/TGC_Alines/TGC-ALines_2011_03_01.pdf COMMENT next line to go
216 // for scenario A in last slide of http://www.fisica.unisalento.it/~spagnolo/allow_listing/TGC_Alines/TGC-ALines_2011_03_01.pdf
217 if (getStationType()[0] == 'T') locAmdbStatToLocAmdbComp = Amg::Translation3D{0,-Rcomp, -DZcomp};
218 Amg::Transform3D childToLocAmdbComponent = locAmdbStatToLocAmdbComp * childToLocAmdbStation;
219
220 ATH_MSG_DEBUG("setDelta_fromAline_forComp: stationName/Jff/Jzz " << getStationType() << " " << getPhiIndex() << " "
221 << getEtaIndex() << " Job " << jobindex << " Origin of component/station AmdbLocalFrame= "
222 <<Amg::toString(m_amdbl_to_global * locAmdbStatToLocAmdbComp.inverse().translation()) << " / "
223 << Amg::toString(m_amdbl_to_global.translation()));
224
225 parentToChild->setDelta(childToLocAmdbComponent.inverse() * delta_amdb * childToLocAmdbComponent);
226 ATH_MSG_DEBUG("setDelta_fromAline_forComp2:stationName/Jff/Jzz " << getStationType() << " " << getPhiIndex() << " "
227 << getEtaIndex() << " Job " << jobindex << " Origin of component/station AmdbLocalFrame= "
228 << Amg::toString(m_amdbl_to_global * locAmdbStatToLocAmdbComp.inverse().translation()) << " / "
229 << Amg::toString(m_amdbl_to_global.translation()));
230
231 ATH_MSG_DEBUG("Station " << getStationType() << " at zi/fi " << getEtaIndex() << "/" << getPhiIndex()
232 << " adding Aline " << tras << " " << traz << " " << trat << " " << rots << " " << rotz << " " << rott
233 << " for component with index =" << jobindex << std::endl
234 << " delta_amdb computed from A-line " <<Amg::toString(delta_amdb));
235 }
236
238 ATH_MSG_DEBUG("n. of RE in this station is " << m_REwithAlTransfInStation.size());
239 for (auto& [jobId, readAlignPair] : m_REwithAlTransfInStation) {
240 ATH_MSG_DEBUG("Clearing cache .... for RE ... iteration n. " << jobId);
241 MuonReadoutElement* re = readAlignPair.first;
242 if (!re) {
243 ATH_MSG_WARNING(" in MuonStation:clearCache " << getStationType() << " at zi/fi " << getEtaIndex() << "/"
244 << getPhiIndex() << " trying to get a not existing RE (iteration n. ) " << jobId << " RE is null, skipping" );
245 continue;
246 }
247 re->clearCache();
248 ATH_MSG_DEBUG("cache cleared ");
249 }
250 }
251
253 for (auto& [jobId, readAlignPair] : m_REwithAlTransfInStation) {
254 ATH_MSG_DEBUG("fillCache cache .... for RE ... iteration n. " << jobId);
255 MuonReadoutElement* re = readAlignPair.first;
256 if (!re) {
257 ATH_MSG_WARNING(" in MuonStation:fillCache " << getStationType() << " at zi/fi " << getEtaIndex() << "/"
258 << getPhiIndex() << " trying to get a not existing RE (iteration n. ) " << jobId << " RE is null, skipping" );
259 continue;
260 }
261 re->fillCache();
262 }
263 }
264
266 clearCache();
267 fillCache();
268 }
269
270 void MuonStation::setBline(const BLinePar* bline) {
271 if (!bline) return;
272 m_hasBLines = true;
273 for (auto& [jobId, readAlignPair] : m_REwithAlTransfInStation) {
274 ATH_MSG_DEBUG("fillCache cache .... for RE ... iteration n. " << jobId);
275 MuonReadoutElement* re = readAlignPair.first;
276 if (re->detectorType() !=Trk::DetectorElemType::Mdt) {
277 continue;
278 }
279 MdtReadoutElement* mdt = dynamic_cast<MdtReadoutElement*>(re);
280 mdt->setBLinePar(bline);
281 }
282 }
283
284
285#if defined(FLATTEN)
286 // We compile this package with optimization, even in debug builds; otherwise,
287 // the heavy use of Eigen makes it too slow. However, from here we may call
288 // to out-of-line Eigen code that is linked from other DSOs; in that case,
289 // it would not be optimized. Avoid this by forcing all Eigen code
290 // to be inlined here if possible.
292#endif
293 double
295 if (getStationName()[0] == 'T' || getStationName()[0] == 'C') return 0.; // TGC and CSC stations
296 if (m_mdtRsize.isValid()) {
297 return *m_mdtRsize.ptr();
298 }
299 double Rsize = 0.;
300
301 Amg::Vector3D RposFirst{Amg::Vector3D::Zero()}, Rpos{Amg::Vector3D::Zero()};
302 bool first = true;
303 int nmdt = 0;
304 ATH_MSG_VERBOSE("RsizeMdtStation for " << getStationType() << " at zi/fi " << getEtaIndex() << "/" << getPhiIndex()
305 << " nRE = " << nMuonReadoutElements());
306
307 for (const auto& [jIdx, reWithTrf ] : m_REwithAlTransfInStation) {
308 const MuonReadoutElement* activeComponent = reWithTrf.first;
309 if (activeComponent->detectorType() !=Trk::DetectorElemType::Mdt) {
310 continue;
311 }
312 ++nmdt;
313 Rsize += activeComponent->getRsize() / 2.;
314 Rpos = activeComponent->toParentStation().translation();
315 ATH_MSG_VERBOSE("Readout element "<<activeComponent->idHelperSvc()->toStringDetEl(activeComponent->identify())
316 <<" r position: "<<Amg::toString(Rpos));
317 if (first) {
318 RposFirst = Rpos;
319 first = false;
320 } else {
321 if (barrel())
322 Rsize += std::abs(Rpos.x() - RposFirst.x());
323 else
324 Rsize += std::abs(Rpos.y() - RposFirst.y());
325 }
326 }
327 if (nmdt == 1) Rsize = 2. * Rsize;
328 m_mdtRsize.set(Rsize);
329 return Rsize;
330 }
332 if (getStationName()[0] == 'T' || getStationName()[0] == 'C') return 0.; // TGC and CSC stations
333 if (m_mdtZsize.isValid()) {
334 return *m_mdtZsize.ptr();
335 }
336 double Zsize = 0.;
337
338 Amg::Vector3D ZposFirst{Amg::Vector3D::Zero()}, Zpos{Amg::Vector3D::Zero()};
339 bool first = true;
340 int nmdt = 0;
341
342
343 ATH_MSG_VERBOSE("ZsizeMdtStation for " << getStationType() << " at zi/fi " << getEtaIndex() << "/" << getPhiIndex()
344 << " nRE = " << nMuonReadoutElements());
345
346 for (const auto& [jobIdx, compWithTrf] : m_REwithAlTransfInStation) {
347 const MuonReadoutElement* activeComponent = compWithTrf.first;
348 if (activeComponent->detectorType() !=Trk::DetectorElemType::Mdt) {
349 continue;
350 }
351 ++nmdt;
352
353 Zsize += activeComponent->getZsize() / 2.;
354 Zpos = activeComponent->toParentStation() * Amg::Vector3D(0., 0., 0.);
355 ATH_MSG_VERBOSE("Readout element "<<activeComponent->idHelperSvc()->toStringDetEl(activeComponent->identify())
356 <<" z position: "<<Amg::toString(Zpos));
357 if (first) {
358 ZposFirst = Zpos;
359 first = false;
360 } else {
361 if (barrel())
362 Zsize += std::abs(Zpos.z() - ZposFirst.z());
363 else
364 Zsize += std::abs(Zpos.x() - ZposFirst.x());
365 }
366 }
367 if (nmdt == 1) Zsize = 2. * Zsize;
368 m_mdtZsize.set(Zsize);
369 return Zsize;
370 }
371 void MuonStation::setMdtRsize(const double rSize){
372 m_mdtRsize.reset();
373 m_mdtRsize.set(rSize);
374 }
375 void MuonStation::setMdtZsize(const double zSize){
376 m_mdtZsize.reset();
377 m_mdtZsize.set(zSize);
378 }
379 bool MuonStation::barrel() const {
380 return getStationName()[0] == 'B';
381 }
382 bool MuonStation::endcap() const { return !barrel(); }
383
385 if (!m_XTomoData) {
386 ATH_MSG_WARNING("No Mdt AsBuilt parameters for chamber " << getStationName());
387 }
388 return m_XTomoData;
389 }
390
392 m_XTomoData = xtomo;
393 refreshCache();
394 }
395 void MuonStation::setPhysVol(const PVLink& vol) { m_physVol = vol; }
396 PVConstLink MuonStation::getPhysVol() const {return m_physVol; }
398
399 std::vector<const MuonReadoutElement*> MuonStation::getReadoutElements() const {
400 std::vector<const MuonReadoutElement*> result{};
401 std::ranges::transform(m_REwithAlTransfInStation, std::back_inserter(result),
402 [](const auto& idReAlign){
403 const MuonReadoutElement* re = idReAlign.second.first;
404 return re;
405 });
406 return result;
407 }
408} // namespace MuonGM
const boost::regex re(r_e)
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#define endmsg
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
static Double_t s0
static Double_t a
static Double_t t0
AthMessaging(IMessageSvc *msgSvc, const std::string &name)
Constructor.
Container classifier the MDT as-built parameters See parameter description in http://atlas-muon-align...
double outerTubeRadius() const
Returns the tube radius taking the thickness of the tubes into account.
int getNtubesperlayer() const
Returns the number of tubes in each tube layer.
double tubePitch() const
Returns the distance between 2 tubes in a tube layer.
bool getWireFirstLocalCoordAlongZ(int tubeLayer, double &coord) const
Base class for the XxxReadoutElement, with Xxx = Mdt, Rpc, Tgc, Csc.
Trk::DetectorElemType detectorType() const override final
Return the Detector element type.
Identifier identify() const override final
Returns the ATLAS Identifier of the MuonReadOutElement.
double Zsize() const
void setBlineFixedPointInAmdbLRS(double s0, double z0, double t0)
GeoAlignableTransform * m_transform
PVConstLink getPhysVol() const
Amg::Transform3D m_delta_amdb_frame
int getEtaIndex() const
a la AMDB
void setEtaPhiIndices(int eta, int phi)
a la AMDB
void updateBlineFixedPointInAmdbLRS()
double LongSsize() const
double ZsizeMdtStation() const
void setDeltaAmdbLRS(Amg::Transform3D xf)
set the delta transform in the amdb frame and update the geoModel Delta
int getPhiIndex() const
a la AMDB
double LongZsize() const
const std::string & getStationName() const
like BMS5, T1F1, CSL1
MuonStation(std::string_view stName, double Ssize, double Rsize, double Zsize, double LongSsize, double LongRsize, double LongZsize, int zi, int fi, bool m_descratzneg)
std::string getStationType() const
like BMS, T1F, CSL
void setNominalAmdbLRSToGlobal(Amg::Transform3D xf)
void setxAmdbCRO(double xpos)
std::string m_statname
void setMdtAsBuiltParams(const MdtAsBuiltPar *xtomo)
void setDelta_fromAline(double, double, double, double, double, double)
set the delta transform in the amdb frame and update the geoModel Delta
void setMdtRsize(const double rSize)
double Ssize() const
int nMuonReadoutElements() const
Amg::Transform3D m_native_to_amdbl
const Amg::Vector3D & getBlineFixedPointInAmdbLRS() const
Amg::Vector3D m_BlineFixedPointInAmdbLRS
void setTransform(GeoAlignableTransform *xf)
CxxUtils::CachedValue< double > m_mdtRsize
const MdtAsBuiltPar * getMdtAsBuiltParams() const
std::vector< const MuonReadoutElement * > getReadoutElements() const
std::map< int, pairRE_AlignTransf > m_REwithAlTransfInStation
keep track of the REs in this station
void addMuonReadoutElementWithAlTransf(MuonReadoutElement *a, GeoAlignableTransform *ptrsf, int jobIndex)
GeoAlignableTransform * getComponentAlTransf(int jobIndex) const
void setPhysVol(const PVLink &vol)
PVLink m_physVol
Link the full physical volume associated with the station.
void setNativeToAmdbLRS(Amg::Transform3D xf)
double RsizeMdtStation() const
void setMdtZsize(const double zSize)
double LongRsize() const
void setBline(const BLinePar *bline)
const MuonReadoutElement * getMuonReadoutElement(int jobIndex) const
CxxUtils::CachedValue< double > m_mdtZsize
void setDelta_fromAline_forComp(int, double, double, double, double, double, double)
Amg::Transform3D m_amdbl_to_global
double Rsize() const
const MdtAsBuiltPar * m_XTomoData
virtual std::string toStringDetEl(const Identifier &id) const =0
print all fields up to detector element to string
#define ATH_FLATTEN
Amg::Transform3D getRotateX3D(double angle)
get a rotation transformation around X-axis
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Amg::Transform3D getRotateZ3D(double angle)
get a rotation transformation around Z-axis
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
Amg::Transform3D getRotateY3D(double angle)
get a rotation transformation around Y-axis
Eigen::Translation< double, 3 > Translation3D
Ensure that the Athena extensions are properly loaded.
Definition GeoMuonHits.h:27
static std::atomic< int > nmdt
Definition DBReader.h:140