ATLAS Offline Software
Loading...
Searching...
No Matches
MuonStation.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/***************************************************************************
6 Holds the info related to a full station
7 -----------------------------------------
8 ***************************************************************************/
9
11
12#include <iomanip>
13#include <utility>
14
15
21namespace MuonGM {
22
23 MuonStation::MuonStation(std::string_view stName,
24 double Ssize, double Rsize, double Zsize,
25 double LongSsize, double LongRsize, double LongZsize,
26 int zi, int fi, bool descratzneg) :
27 AthMessaging{"MuonStation"},
28 m_statname(stName) {
29 m_Ssize = Ssize;
30 m_Rsize = Rsize;
31 m_Zsize = Zsize;
35 m_descratzneg = descratzneg;
36 m_statEtaIndex = zi;
37 m_statPhiIndex = fi;
38 }
39
40 MuonStation::~MuonStation() = default;
41
46
47 void MuonStation::setTransform(GeoAlignableTransform* xf) { m_transform = xf; }
48
49 void MuonStation::setxAmdbCRO(double xpos) { m_xAmdbCRO = xpos; }
50
52 m_native_to_amdbl = std::move(xf);
53 ATH_MSG_VERBOSE("stationName/Jff/Jzz " << getStationType() << " " << getPhiIndex() << " "<< getEtaIndex()
54 <<"setNativeToAmdbLRS: "<<Amg::toString(m_native_to_amdbl));
55 }
56
58 m_amdbl_to_global = std::move(xf);
59 ATH_MSG_DEBUG("setNominalAmdbLRSToGlobal: stationName/Jff/Jzz " << getStationType() << " " << getPhiIndex() << " "<< getEtaIndex()
60 << " Origin of AmdbLocalFrame= " << Amg::toString(m_amdbl_to_global.translation()));
61 }
62 void MuonStation::setBlineFixedPointInAmdbLRS(double s0, double z0, double t0) {
63
64 ATH_MSG_DEBUG("Station " << getStationType() << " at zi/fi " << getEtaIndex() << "/" << getPhiIndex()
65 << " setting fixed point for B-lines at s0,z0,t0 = " << s0 << " " << z0 << " " << t0 );
66
67
71
72 ATH_MSG_DEBUG("setBlineFixedPointInAmdbLRS: stationName/Jff/Jzz " << getStationType() << " " << getPhiIndex() << " "
73 << getEtaIndex() << " nominal(i.e. from-station-envelop-only) B-line fixed point "
75
76 }
77
79 // needed to update the station-level BlineFixedPoint with data from second multilayer
81 }
82
84 if (!m_firstRequestBlineFixedP) return;
85 // Before correction m_BlineFixedPointInAmdbLRS has a z set at the edge of
86 // lowest-z tube of the first layer of one of the two multilayers.
87 // For endcap A, endcap C, and barrel A, this is correct, given the tube staggering
88 // For barrel side C, given the tube staggering, the z should be at the
89 // edge at the second layer, i.e. the z should be corrected by a half tube
90 // pitch. Correction is thus computed only for barrel side C.
91 if (barrel() && (getEtaIndex() < 0)) {
92 for (auto&[jobId, alignPair] : m_REwithAlTransfInStation) {
93 const MuonReadoutElement* muonRE = alignPair.first;
94
96 continue;
97 }
98 const MdtReadoutElement* mdtRE = dynamic_cast<const MdtReadoutElement*>(muonRE);
99 // Correct for tube staggering on barrel side C
100 double shiftInZ = -0.5 * mdtRE->tubePitch();
101 // in addition, correct for 35microm glue width incorrectly applied
102 double multilayerRealSize{0};
103 for (int ilayer = 1; ilayer <= 2; ++ilayer) {
104 double val{0.};
105 bool wellDefined = mdtRE->getWireFirstLocalCoordAlongZ(ilayer, val);
106 if (!wellDefined) {
107 ATH_MSG_WARNING("getUpdatedBlineFixedPointInAmdbLRS: stationName/Jff/Jzz " << getStationType()
108 << " " << getPhiIndex() << " " << getEtaIndex()
109 << " cannot get wire coordinates for second tube layer");
110 val = 0.;
111 }
112 if ((ilayer == 1) || (val > multilayerRealSize)) multilayerRealSize = val;
113 }
114 multilayerRealSize += (mdtRE->getNtubesperlayer() - 1) * mdtRE->tubePitch();
115 multilayerRealSize += mdtRE->outerTubeRadius(); // last tube: no glue width
116 shiftInZ += mdtRE->getZsize() - multilayerRealSize;
117
119 ATH_MSG_DEBUG("getUpdatedBlineFixedPointInAmdbLRS: stationName/Jff/Jzz " << getStationType() << " "
120 << getPhiIndex() << " " << getEtaIndex() << " shiftInZ = " << shiftInZ << " re-set B-line fixed point "
122 break;
123 }
124 }
126 }
127
129 m_delta_amdb_frame = std::move(xf);
130 ATH_MSG_DEBUG("Station " << getStationType() << " at zi/fi " << getEtaIndex() << "/" << getPhiIndex()
131 << " adding Aline " << std::endl
132 << " native_to_amdbl computed from A-line " << Amg::toString(m_native_to_amdbl) << std::endl
133 << "Station amdbl_to_global " << endmsg << Amg::toString(m_amdbl_to_global));
135 }
136
137 void MuonStation::setDelta_fromAline(double tras, double traz, double trat, double rots, double rotz, double rott) {
138 // store here the angles of A-line
139 m_rots = rots;
140 m_rotz = rotz;
141 m_rott = rott;
142
143 Amg::Transform3D delta_amdb{Amg::Transform3D::Identity()};
144 if (std::abs(tras) + std::abs(traz) + std::abs(trat) + (std::abs(rots) + std::abs(rotz) + std::abs(rott)) * 1000. > 0.01) {
145 // compute the delta transform in the local AMDB frame
146 delta_amdb = Amg::Translation3D{tras, traz, trat} *
148 m_hasALines = true;
149 }
150
151 // store the delta transform in the local AMDB frame
152 setDeltaAmdbLRS(delta_amdb);
153
154 ATH_MSG_DEBUG("Station " << getStationType() << " at zi/fi " << getEtaIndex() << "/" << getPhiIndex()
155 << " adding Aline " << setiosflags(std::ios::fixed) << std::setprecision(6) << std::setw(12)
156 << tras << " " << traz << " " << trat << " " << rots << " " << rotz << " " << rott << std::endl
157 << " delta_amdb computed from A-line " << Amg::toString(delta_amdb));
158 }
159
161 std::map<int, pairRE_AlignTransf>::const_iterator itr = m_REwithAlTransfInStation.find(jobIndex);
162 return itr !=m_REwithAlTransfInStation.end() ? itr->second.first : nullptr;
163 }
165 std::map<int, pairRE_AlignTransf>::const_iterator itr = m_REwithAlTransfInStation.find(jobIndex);
166 return itr !=m_REwithAlTransfInStation.end() ? itr->second.first : nullptr;
167 }
168
169 GeoAlignableTransform* MuonStation::getComponentAlTransf(int jobIndex) const {
170 std::map<int, pairRE_AlignTransf>::const_iterator itr = m_REwithAlTransfInStation.find(jobIndex);
171 return itr != m_REwithAlTransfInStation.end() ? itr->second.second : nullptr;
172 }
173
174 void MuonStation::addMuonReadoutElementWithAlTransf(MuonReadoutElement* a, GeoAlignableTransform* ptrsf, int jobIndex) {
175 ATH_MSG_DEBUG("addMuonReadoutElementWithAlTransf for station " << getStationName() << " at zi/fi = " << getEtaIndex()
176 << "/" << getPhiIndex() << " adding new component with Alignable transf... " << a->getStationName()
177 << " job ondex = " << jobIndex );
178 m_REwithAlTransfInStation[jobIndex] = std::make_pair(a, ptrsf);
179
180 ATH_MSG_DEBUG("addMuonReadoutElementWithAlTransf for station " << getStationName() << " at zi/fi = " << getEtaIndex()
181 << "/" << getPhiIndex() << " added new component - now size of map is " << m_REwithAlTransfInStation.size());
182 }
183
184 void MuonStation::setDelta_fromAline_forComp(int jobindex, double tras, double traz, double trat, double rots, double rotz,
185 double rott) {
186 GeoAlignableTransform* parentToChild = getComponentAlTransf(jobindex);
187 if (!parentToChild) {
188 ATH_MSG_WARNING( "setDelta_fromAline_forComp: WARNING: component for index " << jobindex
189 << " not found in MuonStation named " << getStationName() << " at zi/fi = " << getEtaIndex() << "/" << getPhiIndex());
190 return;
191 }
192 if (std::abs(tras) + std::abs(traz) + std::abs(trat) + (std::abs(rots) + std::abs(rotz) + std::abs(rott)) * 1000. < 0.01) {
193 ATH_MSG_DEBUG("setDelta_fromAline_forComp: A-line ignored --- too small (translations < 10microns & rotations <10microrad)");
194 return;
195 }
196
199
200 Amg::Transform3D parentToChildT = parentToChild->getTransform();
201 Amg::Transform3D delta_amdb = Amg::Translation3D{tras, traz, trat} *
203 // The station to component transform is static and must be computed in terms of "nominal geometry parameters"; fixing here bug
204 const MuonReadoutElement* reElement = getMuonReadoutElement(jobindex);
205
206 const Amg::Vector3D thisREnominalCenter{reElement->defTransform().translation()};
207 double Rcomp = thisREnominalCenter.perp() - (reElement->getRsize()) / 2.;
208 double DZcomp = std::abs(thisREnominalCenter.z()) - std::abs((m_amdbl_to_global.translation()).z()) -
209 std::abs((reElement->getZsize()) / 2.);
210
211 Amg::Transform3D childToLocAmdbStation = m_native_to_amdbl * parentToChildT;
212 Amg::Transform3D locAmdbStatToLocAmdbComp{Amg::Transform3D::Identity()};
213 // the following line is needed to go for scenario B in last slide of
214 // http://www.fisica.unisalento.it/~spagnolo/allow_listing/TGC_Alines/TGC-ALines_2011_03_01.pdf COMMENT next line to go
215 // for scenario A in last slide of http://www.fisica.unisalento.it/~spagnolo/allow_listing/TGC_Alines/TGC-ALines_2011_03_01.pdf
216 if (getStationType()[0] == 'T') locAmdbStatToLocAmdbComp = Amg::Translation3D{0,-Rcomp, -DZcomp};
217 Amg::Transform3D childToLocAmdbComponent = locAmdbStatToLocAmdbComp * childToLocAmdbStation;
218
219 ATH_MSG_DEBUG("setDelta_fromAline_forComp: stationName/Jff/Jzz " << getStationType() << " " << getPhiIndex() << " "
220 << getEtaIndex() << " Job " << jobindex << " Origin of component/station AmdbLocalFrame= "
221 <<Amg::toString(m_amdbl_to_global * locAmdbStatToLocAmdbComp.inverse().translation()) << " / "
222 << Amg::toString(m_amdbl_to_global.translation()));
223
224 parentToChild->setDelta(childToLocAmdbComponent.inverse() * delta_amdb * childToLocAmdbComponent);
225 ATH_MSG_DEBUG("setDelta_fromAline_forComp2:stationName/Jff/Jzz " << getStationType() << " " << getPhiIndex() << " "
226 << getEtaIndex() << " Job " << jobindex << " Origin of component/station AmdbLocalFrame= "
227 << Amg::toString(m_amdbl_to_global * locAmdbStatToLocAmdbComp.inverse().translation()) << " / "
228 << Amg::toString(m_amdbl_to_global.translation()));
229
230 ATH_MSG_DEBUG("Station " << getStationType() << " at zi/fi " << getEtaIndex() << "/" << getPhiIndex()
231 << " adding Aline " << tras << " " << traz << " " << trat << " " << rots << " " << rotz << " " << rott
232 << " for component with index =" << jobindex << std::endl
233 << " delta_amdb computed from A-line " <<Amg::toString(delta_amdb));
234 }
235
237 ATH_MSG_DEBUG("n. of RE in this station is " << m_REwithAlTransfInStation.size());
238 for (auto& [jobId, readAlignPair] : m_REwithAlTransfInStation) {
239 ATH_MSG_DEBUG("Clearing cache .... for RE ... iteration n. " << jobId);
240 MuonReadoutElement* re = readAlignPair.first;
241 if (!re) {
242 ATH_MSG_WARNING(" in MuonStation:clearCache " << getStationType() << " at zi/fi " << getEtaIndex() << "/"
243 << getPhiIndex() << " trying to get a not existing RE (iteration n. ) " << jobId << " RE is null, skipping" );
244 continue;
245 }
246 re->clearCache();
247 ATH_MSG_DEBUG("cache cleared ");
248 }
249 }
250
252 for (auto& [jobId, readAlignPair] : m_REwithAlTransfInStation) {
253 ATH_MSG_DEBUG("fillCache cache .... for RE ... iteration n. " << jobId);
254 MuonReadoutElement* re = readAlignPair.first;
255 if (!re) {
256 ATH_MSG_WARNING(" in MuonStation:fillCache " << getStationType() << " at zi/fi " << getEtaIndex() << "/"
257 << getPhiIndex() << " trying to get a not existing RE (iteration n. ) " << jobId << " RE is null, skipping" );
258 continue;
259 }
260 re->fillCache();
261 }
262 }
263
265 clearCache();
266 fillCache();
267 }
268
269 void MuonStation::setBline(const BLinePar* bline) {
270 if (!bline) return;
271 m_hasBLines = true;
272 for (auto& [jobId, readAlignPair] : m_REwithAlTransfInStation) {
273 ATH_MSG_DEBUG("fillCache cache .... for RE ... iteration n. " << jobId);
274 MuonReadoutElement* re = readAlignPair.first;
275 if (re->detectorType() !=Trk::DetectorElemType::Mdt) {
276 continue;
277 }
278 MdtReadoutElement* mdt = dynamic_cast<MdtReadoutElement*>(re);
279 mdt->setBLinePar(bline);
280 }
281 }
282
283
284#if defined(FLATTEN)
285 // We compile this package with optimization, even in debug builds; otherwise,
286 // the heavy use of Eigen makes it too slow. However, from here we may call
287 // to out-of-line Eigen code that is linked from other DSOs; in that case,
288 // it would not be optimized. Avoid this by forcing all Eigen code
289 // to be inlined here if possible.
291#endif
292 double
294 if (getStationName()[0] == 'T' || getStationName()[0] == 'C') return 0.; // TGC and CSC stations
295 if (m_mdtRsize.isValid()) {
296 return *m_mdtRsize.ptr();
297 }
298 double Rsize = 0.;
299
300 Amg::Vector3D RposFirst{Amg::Vector3D::Zero()}, Rpos{Amg::Vector3D::Zero()};
301 bool first = true;
302 int nmdt = 0;
303 ATH_MSG_VERBOSE("RsizeMdtStation for " << getStationType() << " at zi/fi " << getEtaIndex() << "/" << getPhiIndex()
304 << " nRE = " << nMuonReadoutElements());
305
306 for (const auto& [jIdx, reWithTrf ] : m_REwithAlTransfInStation) {
307 const MuonReadoutElement* activeComponent = reWithTrf.first;
308 if (activeComponent->detectorType() !=Trk::DetectorElemType::Mdt) {
309 continue;
310 }
311 ++nmdt;
312 Rsize += activeComponent->getRsize() / 2.;
313 Rpos = activeComponent->toParentStation().translation();
314 ATH_MSG_VERBOSE("Readout element "<<activeComponent->idHelperSvc()->toStringDetEl(activeComponent->identify())
315 <<" r position: "<<Amg::toString(Rpos));
316 if (first) {
317 RposFirst = Rpos;
318 first = false;
319 } else {
320 if (barrel())
321 Rsize += std::abs(Rpos.x() - RposFirst.x());
322 else
323 Rsize += std::abs(Rpos.y() - RposFirst.y());
324 }
325 }
326 if (nmdt == 1) Rsize = 2. * Rsize;
327 m_mdtRsize.set(Rsize);
328 return Rsize;
329 }
331 if (getStationName()[0] == 'T' || getStationName()[0] == 'C') return 0.; // TGC and CSC stations
332 if (m_mdtZsize.isValid()) {
333 return *m_mdtZsize.ptr();
334 }
335 double Zsize = 0.;
336
337 Amg::Vector3D ZposFirst{Amg::Vector3D::Zero()}, Zpos{Amg::Vector3D::Zero()};
338 bool first = true;
339 int nmdt = 0;
340
341
342 ATH_MSG_VERBOSE("ZsizeMdtStation for " << getStationType() << " at zi/fi " << getEtaIndex() << "/" << getPhiIndex()
343 << " nRE = " << nMuonReadoutElements());
344
345 for (const auto& [jobIdx, compWithTrf] : m_REwithAlTransfInStation) {
346 const MuonReadoutElement* activeComponent = compWithTrf.first;
347 if (activeComponent->detectorType() !=Trk::DetectorElemType::Mdt) {
348 continue;
349 }
350 ++nmdt;
351
352 Zsize += activeComponent->getZsize() / 2.;
353 Zpos = activeComponent->toParentStation() * Amg::Vector3D(0., 0., 0.);
354 ATH_MSG_VERBOSE("Readout element "<<activeComponent->idHelperSvc()->toStringDetEl(activeComponent->identify())
355 <<" z position: "<<Amg::toString(Zpos));
356 if (first) {
357 ZposFirst = Zpos;
358 first = false;
359 } else {
360 if (barrel())
361 Zsize += std::abs(Zpos.z() - ZposFirst.z());
362 else
363 Zsize += std::abs(Zpos.x() - ZposFirst.x());
364 }
365 }
366 if (nmdt == 1) Zsize = 2. * Zsize;
367 m_mdtZsize.set(Zsize);
368 return Zsize;
369 }
370 void MuonStation::setMdtRsize(const double rSize){
371 m_mdtRsize.reset();
372 m_mdtRsize.set(rSize);
373 }
374 void MuonStation::setMdtZsize(const double zSize){
375 m_mdtZsize.reset();
376 m_mdtZsize.set(zSize);
377 }
378 bool MuonStation::barrel() const {
379 return getStationName()[0] == 'B';
380 }
381 bool MuonStation::endcap() const { return !barrel(); }
382
384 if (!m_XTomoData) {
385 ATH_MSG_WARNING("No Mdt AsBuilt parameters for chamber " << getStationName());
386 }
387 return m_XTomoData;
388 }
389
391 m_XTomoData = xtomo;
392 refreshCache();
393 }
394 void MuonStation::setPhysVol(const PVLink& vol) { m_physVol = vol; }
395 PVConstLink MuonStation::getPhysVol() const {return m_physVol; }
397} // 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::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