ATLAS Offline Software
Loading...
Searching...
No Matches
MMReadoutElement.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 The MM detector = an assembly module = STGC in amdb
7 ----------------------------------------------------
8***************************************************************************/
9
11
13#include <GaudiKernel/IMessageSvc.h>
14#include <GeoModelKernel/GeoLogVol.h>
15#include <GeoModelKernel/GeoShape.h>
16#include <GeoModelKernel/GeoVFullPhysVol.h>
17#include <GeoModelKernel/GeoDefinitions.h>
18#include <cstdlib>
19
20#include <cmath>
21#include <memory>
22#include <utility>
23
24#include "GaudiKernel/SystemOfUnits.h"
25#include "GeoModelHelpers/getChildNodesWithTrf.h"
26#include "GeoModelHelpers/StringUtils.h"
27#include "GeoModelHelpers/GeoShapeUtils.h"
28#include "GeoModelHelpers/TransformToStringConverter.h"
29
30#include "GeoModelKernel/GeoFullPhysVol.h"
31#include "GeoModelKernel/GeoShapeSubtraction.h"
32#include "GeoModelKernel/GeoTrd.h"
40
41#include "GaudiKernel/ISvcLocator.h"
47
48
49#define THROW_EXCEPTION_MM(MSG) \
50 { \
51 std::stringstream sstr{}; \
52 sstr<<"MMReadoutElement - "<<idHelperSvc()->toStringDetEl(identify())<<" "<<__LINE__<<": "; \
53 sstr<<MSG; \
54 throw std::runtime_error(sstr.str()); \
55 } \
56
57namespace {
58 template <class ObjType, size_t N> void assign(const std::vector<ObjType>& in,
59 std::array<ObjType, N>& out) {
60 for (size_t k =0 ; k < std::min(in.size(), N) ; ++k){
61 out[k] = in[k];
62 }
63 }
64}
65
66using namespace GeoStrUtils;
67namespace MuonGM {
68
69 //============================================================================
70 MMReadoutElement::MMReadoutElement(GeoVFullPhysVol* pv, const std::string& stName, int zi, int fi, int mL, MuonDetectorManager* mgr)
71 : MuonClusterReadoutElement{pv,mgr, Trk::DetectorElemType::MM},
72 m_ml(mL) {
73
74 std::string fixName = (stName[2] == 'L') ? "MML" : "MMS";
75 setStationName(fixName);
77 Identifier id = mgr->mmIdHelper()->channelID(fixName, zi, fi, mL, 1, 1);
78 setIdentifier(id);
79
80
81 if (mgr->MinimalGeoFlag()) {
82 return;
83 }
84 bool foundShape = false;
85 const PVConstLink pvc {getMaterialGeom()};
86 const GeoTrd* trd=dynamic_cast<const GeoTrd *> (pvc->getLogVol()->getShape());
87 if (trd) {
88 setSsize(2*trd->getYHalfLength1());
89 setLongSsize( 2*trd->getYHalfLength2());
90 setRsize(2*trd->getZHalfLength());
91 setZsize(trd->getXHalfLength1());
92
93 } else {
94 ATH_MSG_DEBUG("Expected a GeoTrd but got "<<printGeoShape(pvc->getLogVol()->getShape()));
95 }
96
97 std::vector<GeoChildNodeWithTrf> children{getAllSubVolumes(pvc)};
98 for (const GeoChildNodeWithTrf& child : children) {
99 ATH_MSG_VERBOSE("Child node "<<child.nodeName<<" "<<child.volume->getLogVol()->getName());
100 if (child.volume->getLogVol()->getName().find("Sensitive") == std::string::npos &&
102 child.volume->getLogVol()->getName() != "actMicroMegaGas") {
103 continue;
104 }
105 ++m_nlayers;
106 if (m_nlayers > 4) {
107 THROW_EXCEPTION_MM("number of MM layers > 4: increase transform array size" );
108 }
109 m_Xlg[m_nlayers - 1] = child.transform;
110 // save layer dimensions
111 if (foundShape) {
112 continue;
113 }
114 const GeoShape* childShape = child.volume->getLogVol()->getShape();
115 while (childShape->typeID() != GeoTrd::getClassTypeID()){
116 auto [opA, opB] = getOps(childShape);
117 ATH_MSG_VERBOSE("Operands are "<<printGeoShape(opA)<<", "<<printGeoShape(opB));
118 childShape = opA;
119 }
120 const GeoTrd* trd = dynamic_cast<const GeoTrd*>(childShape);
121 m_halfX = trd->getZHalfLength();
122 // adjust phi dimensions according to the active area
123 m_minHalfY = trd->getYHalfLength1();
124 m_maxHalfY = trd->getYHalfLength2();
125 foundShape = true;
126 }
127
128 if (!foundShape) {
129 THROW_EXCEPTION_MM(" failed to initialize dimensions of this chamber " );
130 }
131 }
132
133
134 //============================================================================
136
137 //============================================================================
139
140 SmartIF<IGeoDbTagSvc> geoDbTag{Gaudi::svcLocator()->service("GeoDbTagSvc")};
141 if (!geoDbTag) {
142 THROW_EXCEPTION_MM("Could not locate GeoDbTagSvc");
143 }
144 SmartIF<IRDBAccessSvc> accessSvc{Gaudi::svcLocator()->service(geoDbTag->getParamSvcName())};
145 if (!accessSvc) {
146 THROW_EXCEPTION_MM("Could not locate " << geoDbTag->getParamSvcName() );
147 }
148 const char sector_l = getStationName()[2];
149 IRDBRecordset_ptr wmmRec = accessSvc->getRecordsetPtr("WMM","","");
150 for (unsigned int ind = 0; ind < wmmRec->size(); ind++) {
151 std::string WMM_TYPE = (*wmmRec)[ind]->getString("WMM_TYPE");
152 if (sector_l != WMM_TYPE[4]){
153 continue;
154 }
155 if (std::abs(getStationEta())!=(int) (WMM_TYPE[6]-'0')) {
156 continue;
157 }
158 if (m_ml != (int) (WMM_TYPE[12]-'0')){
159 continue;
160 }
161 const double Tck = (*wmmRec)[ind]->getDouble("Tck");
162 const double activeBottomLength = (*wmmRec)[ind]->getDouble("activeBottomLength");
163 const double activeH = (*wmmRec)[ind]->getDouble("activeH");
164 const double activeTopLength = (*wmmRec)[ind]->getDouble("activeTopLength");
165 const double gasTck = (*wmmRec)[ind]->getDouble("gasTck");
166 const int nMissedBottomEta = (*wmmRec)[ind]->getInt("nMissedBottomEta");
167 const int nMissedBottomStereo = (*wmmRec)[ind]->getInt("nMissedBottomStereo");
168 const int nMissedTopEta = (*wmmRec)[ind]->getInt("nMissedTopEta");
169 const int nMissedTopStereo = (*wmmRec)[ind]->getInt("nMissedTopStereo");
170
171 assign(tokenizeInt((*wmmRec)[ind]->getString("readoutSide"), ";"), m_readoutSide);
172 const std::vector<double> stereoAngle{tokenizeDouble((*wmmRec)[ind]->getString("stereoAngle"), ";")};
173 const double stripPitch = (*wmmRec)[ind]->getDouble("stripPitch");
174 const int totalStrips = (*wmmRec)[ind]->getInt ("totalStrips");
175 const double ylFrame = (*wmmRec)[ind]->getDouble("ylFrame");
176 const double ysFrame = (*wmmRec)[ind]->getDouble("ysFrame");
177
178 setZsize(Tck); // thickness (full chamber)
179 m_halfX = activeH / 2; // 0.5*radial_size (active area)
180 m_minHalfY = activeBottomLength / 2; // 0.5*bottom length (active area)
181 m_maxHalfY = activeTopLength / 2; // 0.5*top length (active area)
182 m_offset = -0.5*(ylFrame - ysFrame); // radial dist. of active area center w.r.t. chamber center
183 ATH_MSG_DEBUG(idHelperSvc()->toStringDetEl(identify())<<", ylFrame: "<<ylFrame<<", ysFrame: "<<ysFrame<<", offset: "<<m_offset);
184 for (int il = 0; il < m_nlayers; il++) {
185 // identifier of the first channel to retrieve max number of strips
186 Identifier id = m_idHelper.channelID(identify(), m_ml, il + 1, 1);
187 int chMax = m_idHelper.channelMax(id);
188 if (chMax < 0) {
189 THROW_EXCEPTION_MM("MMReadoutElement -- Max number of strips not a valid value" );
190 }
191 MuonChannelDesign& design = m_etaDesign[il];
192
195 design.inputPitch = stripPitch;
196 design.thickness = gasTck;
197 design.nMissedTopEta = nMissedTopEta; // #of eta strips that are not connected to any FE board
198 design.nMissedBottomEta = nMissedBottomEta;
199 design.nMissedTopStereo = nMissedTopStereo; // #of stereo strips that are not connected to any FE board
200 design.nMissedBottomStereo = nMissedBottomStereo;
201 design.totalStrips = totalStrips;
205 design.inputWidth = stripPitch * std::cos(design.stereoAngle());
206
207 if (!design.hasStereoAngle()) { // eta layers
208 design.nch = design.totalStrips - design.nMissedBottomEta - design.nMissedTopEta;
209 design.setFirstPos(-0.5 * design.xSize() + stripPitch);
210 } else { // stereo layers
211 design.nch = design.totalStrips - design.nMissedBottomStereo - design.nMissedTopStereo;
212 design.setFirstPos( -0.5 * design.xSize() + (1 + design.nMissedBottomStereo - design.nMissedBottomEta) * stripPitch);
213 }
214 ATH_MSG_DEBUG("initDesign:" <<idHelperSvc()->toStringDetEl(identify())<< " layer " << il
215 << ", strip pitch " << design.inputPitch << ", nstrips " << design.nch
216 << " stereo " << design.stereoAngle() / Gaudi::Units::degree
217 <<", "<<design.xSize()<<", "<<design.maxYSize()<<" "<<design.minYSize()
218 <<", firstPos: "<<design.firstPos()<<", first pitch: "<<design.firstPitch);
219 }
220 }
221 }
222
223
225 if (m_ml < 1 || m_ml > 2) {
226 THROW_EXCEPTION_MM("MMReadoutElement -- Unexpected Multilayer: m_ml= " << m_ml );
227 return;
228 }
229 // Get the detector configuration.
230 SmartIF<IGeoDbTagSvc> geoDbTag{Gaudi::svcLocator()->service("GeoDbTagSvc")};
231 if (!geoDbTag) {
232 THROW_EXCEPTION_MM("Could not locate GeoDbTagSvc");
233 }
234 if (geoDbTag->getSqliteReader()) {
236 return;
237 }
238 char side = getStationEta() < 0 ? 'C' : 'A';
239 char sector_l = getStationName().substr(2, 1) == "L" ? 'L' : 'S';
240 // Initialize from database:
241
242 MMDetectorHelper aHelper;
243 MMDetectorDescription* mm = aHelper.Get_MMDetector(sector_l, std::abs(getStationEta()), getStationPhi(), m_ml, side);
244 MMReadoutParameters roParam = mm->GetReadoutParameters();
245
246 double ylFrame = mm->ylFrame();
247 double ysFrame = mm->ysFrame();
248 double pitch = roParam.stripPitch;
249
250
251
252
253 setSsize(mm->sWidth()); // bottom base length (full chamber)
254 setLongSsize(mm->lWidth()); // top base length (full chamber)
255 setRsize(mm->Length()); // height of the trapezoid (full chamber)
256 setZsize(mm->Tck()); // thickness (full chamber)
257 m_halfX = roParam.activeH / 2; // 0.5*radial_size (active area)
258 m_minHalfY = roParam.activeBottomLength / 2; // 0.5*bottom length (active area)
259 m_maxHalfY = roParam.activeTopLength / 2; // 0.5*top length (active area)
260 m_offset = -0.5*(ylFrame - ysFrame); // radial dist. of active area center w.r.t. chamber center
261 ATH_MSG_DEBUG(idHelperSvc()->toStringDetEl(identify())<<", ylFrame: "<<ylFrame<<", ysFrame: "<<ysFrame<<", offset: "<<m_offset);
262 assign(roParam.readoutSide, m_readoutSide);
263
264 for (int il = 0; il < m_nlayers; il++) {
265 // identifier of the first channel to retrieve max number of strips
266 Identifier id = m_idHelper.channelID(identify(), m_ml, il + 1, 1);
267 int chMax = m_idHelper.channelMax(id);
268 if (chMax < 0) {
269 THROW_EXCEPTION_MM("MMReadoutElement -- Max number of strips not a valid value" );
270 }
271 MuonChannelDesign& design = m_etaDesign[il];
272
275 design.inputPitch = pitch;
276 design.thickness = roParam.gasThickness;
277 design.nMissedTopEta = roParam.nMissedTopEta; // #of eta strips that are not connected to any FE board
278 design.nMissedBottomEta = roParam.nMissedBottomEta;
279 design.nMissedTopStereo = roParam.nMissedTopStereo; // #of stereo strips that are not connected to any FE board
281 design.totalStrips = roParam.tStrips;
283 design.defineTrapezoid(m_minHalfY, m_maxHalfY,m_halfX, - roParam.stereoAngle.at(il));
285 design.inputWidth = pitch * std::cos(design.stereoAngle());
286
287 if (!design.hasStereoAngle()) { // eta layers
288 design.nch = design.totalStrips - design.nMissedBottomEta - design.nMissedTopEta;
289 design.setFirstPos(-0.5 * design.xSize() + pitch);
290 } else { // stereo layers
291 design.nch = design.totalStrips - design.nMissedBottomStereo - design.nMissedTopStereo;
292 design.setFirstPos( -0.5 * design.xSize() +
293 (1 + design.nMissedBottomStereo - design.nMissedBottomEta) * pitch);
294 }
295 ATH_MSG_DEBUG("initDesign:" <<idHelperSvc()->toStringDetEl(identify())<< " layer " << il
296 << ", strip pitch " << design.inputPitch << ", nstrips " << design.nch
297 << " stereo " << design.stereoAngle() / Gaudi::Units::degree
298 <<", "<<design.xSize()<<", "<<design.maxYSize()<<" "<<design.minYSize()
299 <<", firstPos: "<<design.firstPos()<<", first pitch: "<<design.firstPitch);
300 }
301 }
302
303
304 //============================================================================
306
307 if (m_surfaceData) {
308 ATH_MSG_WARNING("calling fillCache on an already filled cache" );
309 return;
310 }
311 m_surfaceData = std::make_unique<SurfaceData>();
312
313
314 for (int layer = 0; layer < m_nlayers; ++layer) {
315 // identifier of the first channel
316 Identifier id = m_idHelper.channelID(identify(), m_ml, layer + 1, 1);
317 const double sAngle = m_etaDesign[layer].stereoAngle();
318 m_surfaceData->m_layerSurfaces.emplace_back(std::make_unique<Trk::PlaneSurface>(*this,id));
319 m_surfaceData->m_surfBounds.emplace_back(std::make_unique<Trk::RotatedTrapezoidBounds>(m_halfX, m_minHalfY, m_maxHalfY, sAngle));
320
321 m_surfaceData->m_layerTransforms.push_back(
322 absTransform() // transformation from chamber to ATLAS frame
323 * m_delta // rotations (a-lines) from the alignment group
324 * m_Xlg[layer] // x-shift of the gas-gap center w.r.t. quadruplet center
325 * Amg::getTranslateZ3D(m_offset) // z-shift to volume center
326 * Amg::getRotateY3D(-90. * CLHEP::deg) // x<->z because of GeoTrd definition
327 * Amg::getRotateZ3D(sAngle));
328
329 // surface info (center, normal)
330 m_surfaceData->m_layerCenters.emplace_back(m_surfaceData->m_layerTransforms.back().translation());
331 m_surfaceData->m_layerNormals.emplace_back(m_surfaceData->m_layerTransforms.back().linear() * (-Amg::Vector3D::UnitZ()));
332
333 ATH_MSG_DEBUG("MMReadoutElement layer " << layer << " sAngle " << sAngle << " phi direction MM eta strip "
334 << (m_surfaceData->m_layerTransforms.back().linear() * Amg::Vector3D::UnitY()).phi() );
335 }
336 }
337
338
339 //============================================================================
341 if (m_idHelper.stationEta(id) != getStationEta()) return false;
342 if (m_idHelper.stationPhi(id) != getStationPhi()) return false;
343
344 if (m_idHelper.multilayer(id) != m_ml) return false;
345
346 int gasgap = m_idHelper.gasGap(id);
347 if (gasgap < 1 || gasgap > m_nlayers) return false;
348
349 int strip = m_idHelper.channel(id);
350 return strip >= 1 && strip <= m_etaDesign[gasgap - 1].totalStrips;
351 }
352
353
354 //============================================================================
356 int gg = m_idHelper.gasGap(id);
357 //const MuonChannelDesign* design = getDesign(id);
358 Amg::Vector3D locPos_ML = (m_Xlg[gg - 1]) * Amg::getTranslateZ3D(m_offset) *
359 // (design->hasStereoAngle() ?
360 // Amg::AngleAxis3D(90. * CLHEP::deg, Amg::Vector3D::UnitY()) * Amg::AngleAxis3D(design->stereoAngle(), Amg::Vector3D::UnitZ()) *
361 // Amg::AngleAxis3D(-90. * CLHEP::deg, Amg::Vector3D::UnitY()) : AmgSymMatrix(3)::Identity())*
362 locPos;
363
364 ATH_MSG_DEBUG("position coordinates in the gas-gap r.f.: " << Amg::toString(locPos) );
365 ATH_MSG_DEBUG("position coordinates in the multilayer r.f.: " << Amg::toString(locPos_ML) );
366 return absTransform() * m_delta * locPos_ML;
367 }
368
369
370 //============================================================================
372 // amdb frame (s, z, t) = chamber frame (y, z, x)
373 if (aline) {
374 const Amg::Transform3D permute{GeoTrf::GeoRotation{90.*Gaudi::Units::deg,90.*Gaudi::Units::deg, 0.}};
375 // The origin of the rotation axes is at the center of the active area
376 // in the z (radial) direction. Account for this shift in the definition
377 // of m_delta so that it can be applied on chamber frame coordinates.
378 m_ALinePar = &aline;
379 m_delta = Amg::getTranslateZ3D(m_offset)* permute*aline.delta()*
380 permute.inverse()*Amg::getTranslateZ3D(-m_offset);
381 ATH_MSG_DEBUG(idHelperSvc()->toStringDetEl(identify())<<" setup new alignment: "<<GeoTrf::toString(m_delta,true));
382 refreshCache();
383 } else {
385 }
386 }
387 //============================================================================
389 if (has_ALines()) {
390 m_ALinePar = nullptr;
391 m_delta = Amg::Transform3D::Identity();
392 refreshCache();
393 }
394 }
395
396 //============================================================================
398 ATH_MSG_VERBOSE("Setting B-line for " << idHelperSvc()->toStringDetEl(identify())<<" "<<bLine);
399 m_BLinePar = &bLine;
400 }
401 //============================================================================
403
404 // note: amdb frame (s, z, t) = chamber frame (y, z, x)
405 if (!has_BLines()) return;
406
407 double t0 = locPosML.x();
408 double s0 = locPosML.y();
409 double z0 = locPosML.z();
410 double width = getSsize() + (getLongSsize() - getSsize())*(z0/getRsize() + 0.5); // because z0 is in [-length/2, length/2]
411
412 double s_rel = s0/(width/2.); // in [-1, 1]
413 double z_rel = z0/(getRsize()/2.); // in [-1, 1]
414 double t_rel = t0/(getZsize()/2.); // in [-1, 1]
415
416 // b-line parameters
417 using Parameter = BLinePar::Parameter;
418 double bp = m_BLinePar->getParameter(Parameter::bp);
419 double bn = m_BLinePar->getParameter(Parameter::bn);
420 double sp = m_BLinePar->getParameter(Parameter::sp);
421 double sn = m_BLinePar->getParameter(Parameter::sn);
422 double tw = m_BLinePar->getParameter(Parameter::tw);
423 double eg = m_BLinePar->getParameter(Parameter::eg)*1.e-3;
424 double ep = m_BLinePar->getParameter(Parameter::ep)*1.e-3;
425 double en = m_BLinePar->getParameter(Parameter::en)*1.e-3;
426
427 double ds{0.}, dz{0.}, dt{0.};
428
429 if (bp != 0 || bn != 0)
430 dt += 0.5*(s_rel*s_rel - 1)*((bp + bn) + (bp - bn)*z_rel);
431
432 if (sp != 0 || sn != 0)
433 dt += 0.5*(z_rel*z_rel - 1)*((sp + sn) + (sp - sn)*s_rel);
434
435 if (tw != 0) {
436 dt -= tw*s_rel*z_rel;
437 dz += tw*s_rel*t_rel*getZsize()/getRsize();
438 }
439
440 if (eg != 0) {
441 dt += t0*eg;
442 ds += s0*eg;
443 dz += z0*eg;
444 }
445
446 if (ep != 0 || en != 0) {
447 // the formulas below differ from those in Christoph's talk
448 // because are origin for NSW is at the center of the chamber,
449 // whereas in the talk (i.e. MDTs), it is at the bottom!
450 double delta = s_rel*s_rel * ((ep + en)*s_rel/6 + (ep - en)/4);
451 double phi = s_rel * ((ep + en)*s_rel + (ep - en)) / 2;
452 dt += phi*t0;
453 ds += delta*width/2;
454 dz += phi*z0;
455 }
456
457 locPosML[0] += dt;
458 locPosML[1] += ds;
459 locPosML[2] += dz;
460 }
461
462
463 //============================================================================
464 bool MMReadoutElement::spacePointPosition(const Identifier& layerId, const Amg::Vector2D& lpos, Amg::Vector3D& pos) const {
465
466 pos = Amg::Vector3D(lpos.x(), lpos.y(), 0.);
467
468 const MuonChannelDesign* design = getDesign(layerId);
469 if (!design) {
470 ATH_MSG_WARNING("Unable to get MuonChannelDesign, therefore cannot provide position corrections. Returning." );
471 return false;
472 }
473
474 bool conditionsApplied{false};
475 Amg::Transform3D trfToML{Amg::Transform3D::Identity()};
476
477#ifndef SIMULATIONBASE
478 //*********************
479 // As-Built (MuonNswAsBuilt is not included in AthSimulation)
480 //*********************
482 if (sc) {
483
484 // express the local position w.r.t. the nearest active strip
485 Amg::Vector2D rel_pos;
486 int istrip = design->positionRelativeToStrip(lpos, rel_pos);
487 if (istrip < 0) {
488 ATH_MSG_WARNING("As-built corrections are provided only within the active area. Returning." );
489 return false;
490 }
491
492 // setup strip calculator
495 strip_id.ilayer = m_idHelper.gasGap(layerId);
496 strip_id.istrip = istrip;
497
498 // get the position coordinates, in the chamber frame, from NswAsBuilt.
499 // Applying a 2.75mm correction along the layer normal, since NswAsBuilt considers the layer
500 // on the readout strips, whereas Athena wants it at the middle of the drift gap.
501 NswAsBuilt::StripCalculator::position_t calcPos = sc->getPositionAlongStrip(NswAsBuilt::Element::ParameterClass::CORRECTION, strip_id, rel_pos.y(), rel_pos.x());
502
504 pos = calcPos.pos;
505 pos[0] += strip_id.ilayer%2 ? -2.75 : 2.75;
506
507 // signal that pos is now in the chamber reference frame
508 // (don't go back to the layer frame yet, since we may apply b-lines later on)
509 trfToML = m_delta.inverse()*absTransform().inverse()*transform(layerId);
510 conditionsApplied = true;
511 } else {
512 ATH_MSG_DEBUG( "No as-built corrections provided for "<<idHelperSvc()->toStringDetEl(identify())<<" layer: "<<strip_id.ilayer);
513 }
514 }
515#endif
516
517 //*********************
518 // B-Lines
519 //*********************
520 if (has_BLines()) {
521 // go to the multilayer reference frame if we are not already there
522 if (!conditionsApplied) {
523 trfToML = m_delta.inverse()*absTransform().inverse()*transform(layerId);
524 pos = trfToML*pos;
525
526 // signal that pos is now in the multilayer reference frame
527 conditionsApplied = true;
528 }
529 posOnDefChamber(pos);
530 }
531
532 // back to the layer reference frame from where we started
533 if (conditionsApplied) pos = trfToML.inverse()*pos;
534
535 return true;
536 }
537
538} // namespace MuonGM
Scalar phi() const
phi method
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Definition of the abstract IRDBAccessSvc interface.
std::shared_ptr< IRDBRecordset > IRDBRecordset_ptr
Definition of the abstract IRDBRecord interface.
Definition of the abstract IRDBRecordset interface.
static Double_t sp
static Double_t s0
static Double_t sc
static Double_t t0
#define THROW_EXCEPTION_MM(MSG)
@ MM
Definition RegSelEnums.h:38
const double width
Amg::Transform3D delta() const
Returns the final transformations of the A lines.
Definition ALinePar.cxx:35
virtual unsigned int size() const =0
MMDetectorDescription * Get_MMDetector(char type, int ieta, int iphi, int layer=1, char side='A')
void posOnDefChamber(Amg::Vector3D &locPosML) const
transform a position (in chamber-frame coordinates) to the deformed-chamber geometry
double stereoAngle(const Identifier &id) const
Wrapper to MuonChannelDesign::stereoAngle()
virtual bool containsId(const Identifier &id) const override final
function to be used to check whether a given Identifier is contained in the readout element
~MMReadoutElement()
destructor
std::array< Amg::Transform3D, 4 > m_Xlg
void initDesign()
initialize the design classes for this readout element
MMReadoutElement(GeoVFullPhysVol *pv, const std::string &stName, int zi, int fi, int mL, MuonDetectorManager *mgr)
constructor
void setDelta(const ALinePar &aline)
Amg::Vector3D localToGlobalCoords(const Amg::Vector3D &locPos, const Identifier &id) const
simHit local (SD) To Global position - to be used by MuonGeoAdaprors only
virtual void fillCache() override final
function to fill tracking cache
void setBLinePar(const BLinePar &bLine)
read B-line (chamber-deformation) parameters
virtual bool spacePointPosition(const Identifier &phiId, const Identifier &etaId, Amg::Vector2D &pos) const override final
space point position for a given pair of phi and eta identifiers The LocalPosition is expressed in th...
std::array< int, 4 > m_readoutSide
void setChamberLayer(int ml)
set methods only to be used by MuonGeoModel
const MuonChannelDesign * getDesign(const Identifier &id) const
returns the MuonChannelDesign class for the given identifier
const MmIdHelper & m_idHelper
std::array< MuonChannelDesign, 4 > m_etaDesign
std::unique_ptr< SurfaceData > m_surfaceData
MuonClusterReadoutElement(GeoVFullPhysVol *pv, MuonDetectorManager *mgr, Trk::DetectorElemType detType)
virtual const Amg::Transform3D & transform() const override
Return local to global transform.
The MuonDetectorManager stores the transient representation of the Muon Spectrometer geometry and pro...
void setIdentifier(const Identifier &id)
Sets the Identifier, hashes & station names.
Identifier identify() const override final
Returns the ATLAS Identifier of the MuonReadOutElement.
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Amg::Transform3D getTranslateZ3D(const double Z)
: Returns a shift transformation along the z-axis
Amg::Transform3D getRotateZ3D(double angle)
get a rotation transformation around Z-axis
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
Amg::Transform3D getRotateY3D(double angle)
get a rotation transformation around Y-axis
Ensure that the Athena extensions are properly loaded.
Definition GeoMuonHits.h:27
Ensure that the ATLAS eigen extensions are properly loaded.
std::vector< double > stereoAngle
std::vector< int > readoutSide
double stereoAngle() const
returns the stereo angle
double hasStereoAngle() const
returns whether the stereo angle is non-zero
double firstPos() const
Returns the position of the first strip along the x-axis.
void defineTrapezoid(double HalfShortY, double HalfLongY, double HalfHeight)
set the trapezoid dimensions
int positionRelativeToStrip(const Amg::Vector2D &lpos, Amg::Vector2D &rel_pos) const
STRIPS ONLY.
void setFirstPos(const double pos)
Set the position of the first strip along the x-axis.