ATLAS Offline Software
Loading...
Searching...
No Matches
ReadoutGeomCnvAlg.cxx
Go to the documentation of this file.
1
2/*
3 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
4*/
5#include "ReadoutGeomCnvAlg.h"
6
7#include <GeoModelKernel/GeoVPhysVol.h>
11#include <GeoModelKernel/GeoFullPhysVol.h>
12#include <GeoModelKernel/GeoShapeShift.h>
13#include <GeoModelHelpers/printVolume.h>
14
20
21
23
27
28
35
37
39#include <GaudiKernel/SystemOfUnits.h>
40
41#include <GeoModelHelpers/defineWorld.h>
42#include <GeoModelHelpers/cloneVolume.h>
43#include <GeoModelHelpers/getChildNodesWithTrf.h>
44#include <GeoModelHelpers/TransformToStringConverter.h>
45#include <GeoModelHelpers/GeoShapeUtils.h>
46#include <GeoModelIOHelpers/GMIO.h>
47#include <map>
48#include <format>
49
50
51#include "Acts/Definitions/Units.hpp"
52using namespace Acts::UnitLiterals;
53
54namespace {
55 using SubDetAlignment = ActsTrk::GeometryContext::AlignmentStorePtr;
56 bool hasStationVolume(const PVConstLink treeTop,
57 const std::set<PVConstLink>& translated) {
58 const unsigned int nCh = treeTop->getNChildVols();
59 for (unsigned int ch = 0 ; ch < nCh; ++ch) {
60 PVConstLink child = treeTop->getChildVol(ch);
61 if (translated.count(child) ||
62 hasStationVolume(child, translated)){
63 return true;
64 }
65 }
66 return false;
67 };
68 Amg::Transform3D amdbTransform(const ActsTrk::GeometryContext& gctx,
69 const MuonGMR4::MuonReadoutElement& reEle) {
70 return reEle.localToGlobalTransform(gctx) *
72 }
73}
74
75namespace MuonGMR4{
76
78 ATH_CHECK(m_idHelperSvc.retrieve());
79 ATH_CHECK(m_writeKey.initialize());
80 ATH_CHECK(m_alignStoreKeys.initialize());
81 ATH_CHECK(detStore()->retrieve(m_detMgr));
82 return StatusCode::SUCCESS;
83}
84
85
86StatusCode ReadoutGeomCnvAlg::execute(const EventContext& ctx) const {
87 SG::WriteCondHandle writeHandle{m_writeKey, ctx};
88 if (writeHandle.isValid()) {
89 ATH_MSG_DEBUG("The current readout geometry is still valid.");
90 return StatusCode::SUCCESS;
91 }
94 ActsTrk::GeometryContext geoContext{};
96 SG::ReadCondHandle readHandle{key, ctx};
97 if (!readHandle.isValid()) {
98 ATH_MSG_FATAL("Failed to retrieve alignment store "<<key.fullKey());
99 return StatusCode::FAILURE;
100 }
101 writeHandle.addDependency(readHandle);
102 if (m_splitTrfCache) {
103 geoContext.setStore(copyDeltas(**readHandle));
104 } else {
105 geoContext.setStore(std::make_unique<ActsTrk::DetectorAlignStore>(**readHandle));
106 }
107 }
110 std::vector<ActsTrk::DetectorType> presentTechs = m_detMgr->getDetectorTypes();
111 for (const ActsTrk::DetectorType detType : presentTechs) {
112 if (geoContext.getStore(detType)) {
113 continue;
114 }
115 ATH_MSG_WARNING("No external detector alignment has been defined for technology "<<ActsTrk::to_string(detType));
116 geoContext.setStore(std::make_unique<ActsTrk::DetectorAlignStore>(detType));
117 }
119 ConstructionCache cacheObj;
120 cacheObj.detMgr = std::make_unique<MuonGM::MuonDetectorManager>();
121 cacheObj.world = createGeoWorld();
122 cacheObj.detMgr->addTreeTop(cacheObj.world);
124 ATH_CHECK(buildMdt(geoContext, cacheObj));
125 ATH_CHECK(buildTgc(geoContext, cacheObj));
126 ATH_CHECK(buildRpc(geoContext, cacheObj));
127 ATH_CHECK(buildSTGC(geoContext, cacheObj));
128 ATH_CHECK(buildMM(geoContext, cacheObj));
130 std::vector<GeoChildNodeWithTrf> treeTops = getChildrenWithRef(m_detMgr->getTreeTop(0), false);
131
133 for (const GeoChildNodeWithTrf& treeTop : treeTops) {
134 if (hasStationVolume(treeTop.volume, cacheObj.translatedStations)) {
135 continue;
136 }
137 ATH_MSG_VERBOSE("Detected passive volume "<<treeTop.nodeName);
138
139 cacheObj.world->add(const_pointer_cast(treeTop.volume));
140 }
141
143 if (m_checkGeo) {
144 const std::vector<const MuonGMR4::MuonReadoutElement*> refEles{m_detMgr->getAllReadoutElements()};
145 for (const MuonGMR4::MuonReadoutElement* refEle : refEles) {
146 ATH_CHECK(checkIdCompability(*refEle, *cacheObj.detMgr->getReadoutElement(refEle->identify())));
147 }
148 }
149 if (m_dumpGeo) {
150 ATH_MSG_DEBUG("Save geometry to SqLite file "<<m_geoDumpName);
151 GeoModelIO::IO::saveToDB(cacheObj.world, m_geoDumpName, 0 , true);
152 }
153
154 ATH_CHECK(writeHandle.record(std::move(cacheObj.detMgr)));
155 return StatusCode::SUCCESS;
156}
158 const Identifier& stationId,
159 ConstructionCache& cacheObj) const {
160 const std::string stName{m_idHelperSvc->stationNameString(stationId)};
161 const int stEta{m_idHelperSvc->stationEta(stationId)};
162 const int stPhi{m_idHelperSvc->stationPhi(stationId)};
163 MuonGM::MuonStation* station = cacheObj.detMgr->getMuonStation(stName, stEta, stPhi);
164 if (station) {
165 ATH_MSG_DEBUG("Station "<<stName<<", stEta: "<<stEta<<", stPhi: "<<stPhi<<" already exists.");
166 return StatusCode::SUCCESS;
167 }
169 const MuonGMR4::MuonReadoutElement* copyMe = m_detMgr->getReadoutElement(stationId);
170
172 const GeoVFullPhysVol* readOutVol = copyMe->getMaterialGeom();
173 // This is the physical volume that contains the readOutVol as a child.
174 PVConstLink parentVolume = readOutVol->getParent();
175
176 const GeoAlignableTransform* alignTrf{copyMe->alignableTransform()};
177
179 GeoIntrusivePtr<const GeoGraphNode> alignNode{*(parentVolume->getParent()->findChildNode(alignTrf) + 1)};
181 GeoIntrusivePtr<const GeoTransform> stationShiftNode{alignNode != parentVolume ?
182 dynamic_pointer_cast<const GeoTransform>(alignNode) : nullptr};
183
184 cacheObj.translatedStations.insert(parentVolume);
186 PVLink copiedStationVol{};
187 if (!stationShiftNode) {
188 copiedStationVol = make_intrusive<GeoFullPhysVol>(parentVolume->getLogVol());
189 } else {
190 auto volToCopy = parentVolume->getLogVol();
191 auto newShape = cacheObj.cacheShape(make_intrusive<GeoShapeShift>(volToCopy->getShape(),
192 stationShiftNode->getDefTransform()));
193 auto newLogVol = make_intrusive<GeoLogVol>(volToCopy->getName(), newShape, volToCopy->getMaterial());
194 copiedStationVol = make_intrusive<GeoFullPhysVol>(cacheObj.cacheVolume(newLogVol));
195 }
196
199 const std::vector<GeoChildNodeWithTrf> children = getChildrenWithRef(parentVolume, false); // we get the list of child nodes attached to the parent volume
200 double minX{1.e9}, maxX{-1.e9}, minY1{1.e9}, maxY1{-1.e9}, minY2{1.e9}, maxY2{-1.e9}, minZ{1.e9}, maxZ{-1.e9};
201 for (const GeoChildNodeWithTrf& child : children) {
202 std::vector<Amg::Vector3D> edges = getPolyShapeEdges(child.volume->getLogVol()->getShape(), //we are getting corner points of the edges
203 readOutVol->getX().inverse() * child.transform); //getX() returns the transformation from readout physical volume ref to parent physical volume ref. We take the inverse and we chain it with child.transform, which is from child ref to parent ref
204 for (const Amg::Vector3D& edge : edges) {
205 minX = std::min(minX, edge.x());
206 maxX = std::max(maxX, edge.x());
207 minZ = std::min(minZ, edge.z());
208 maxZ = std::max(maxZ, edge.z());
209 if (edge.z() < 0) {
210 minY1 = std::min(minY1, edge.y());
211 maxY1 = std::max(maxY1, edge.y());
212 } else {
213 minY2 = std::min(minY2, edge.y());
214 maxY2 = std::max(maxY2, edge.y());
215 }
216 }
218 const GeoVPhysVol &childVolRef = *child.volume;
219 if (typeid(childVolRef) == typeid(GeoFullPhysVol)) {
220 continue;
221 }
222 // Add the beam lines / foams inside the station volume
223 PVLink childVol = const_pointer_cast<GeoVPhysVol>(child.volume);
224 copiedStationVol->add(cacheObj.newIdTag());
225 if (stationShiftNode) {
226 copiedStationVol->add(const_pointer_cast(stationShiftNode));
227 }
228 copiedStationVol->add(cacheObj.makeTransform(child.transform));
229 copiedStationVol->add(cloneVolume(childVol));
230 }
231
234 const double shortS = (maxY1 - minY1);
235 const double longS = (maxY2 - minY2);
236 const double lengthR = (maxX - minX);
237 const double lengthZ = (maxZ - minZ);
238
240 const Amg::Transform3D alignedTransform = amdbTransform(gctx, *copyMe) *
241 ( ( stationShiftNode ? stationShiftNode->getDefTransform() : Amg::Transform3D::Identity())
242 * readOutVol->getDefX()).inverse();
243
244
245 auto newStation = std::make_unique<MuonGM::MuonStation>(stName,
246 shortS, lengthR, lengthZ,
247 longS, lengthR, lengthZ,
248 stEta, stPhi, false);
249 newStation->setPhysVol(copiedStationVol);
251 cacheObj.world->add(cacheObj.newIdTag());
252 auto copyAlignNode = make_intrusive<GeoAlignableTransform>(alignedTransform);
253 newStation->setTransform(copyAlignNode);
254 newStation->setNominalAmdbLRSToGlobal(copyAlignNode->getTransform());
255
256 ATH_MSG_VERBOSE("stName: "<<stName<<", stEta: "<<stEta<<", stPhi: "<<stPhi
257 <<" -- shortS: "<<shortS<<", longS: "<<longS
258 <<", lengthR: "<<lengthR<<", lengthZ: "<<lengthZ
259 <<std::endl<<"AlignableNode: "<<GeoTrf::toString(alignedTransform, true)
260 <<std::endl<<"Station shift: "<<GeoTrf::toString(stationShiftNode ? stationShiftNode->getDefTransform()
261 : Amg::Transform3D::Identity(), true)
262 <<std::endl<<"AmdLRSToGlobal: "<<GeoTrf::toString(newStation->getNominalAmdbLRSToGlobal(), true)
263 <<std::endl<<"Readout transform: "<<GeoTrf::toString(readOutVol->getX(), true));
264 cacheObj.detMgr->addMuonStation(std::move(newStation));
265 cacheObj.world->add(copyAlignNode);
266 cacheObj.world->add(copiedStationVol);
267 return StatusCode::SUCCESS;
268}
269
270
272 const Identifier& reId,
273 ConstructionCache& cacheObj,
274 GeoIntrusivePtr<GeoVFullPhysVol>& physVol,
275 MuonGM::MuonStation* & station) const {
276
277 ATH_CHECK(buildStation(gctx, reId, cacheObj));
278 const std::string stName{m_idHelperSvc->stationNameString(reId)};
279 station = cacheObj.detMgr->getMuonStation(stName,
280 m_idHelperSvc->stationEta(reId),
281 m_idHelperSvc->stationPhi(reId));
282
283 PVLink copiedStationVol{station->getPhysVol()};
284 const MuonGMR4::MuonReadoutElement* copyMe = m_detMgr->getReadoutElement(reId);
285 GeoIntrusivePtr<const GeoVFullPhysVol> readOutVol{copyMe->getMaterialGeom()};
286 copiedStationVol->add(cacheObj.newIdTag());
297 const Amg::Transform3D alignNodeToRE{copyMe->alignableTransform()->getDefTransform().inverse() *
298 readOutVol->getParent()->getX() * readOutVol->getX()};
299 const Amg::Transform3D alignedNode{amdbTransform(gctx, *copyMe) * alignNodeToRE.inverse()};
300
301 const Amg::Transform3D stationTrf{copiedStationVol->getX().inverse() * alignedNode};
302
303 copiedStationVol->add(cacheObj.makeTransform(stationTrf*alignNodeToRE));
305 PVLink clonedVol{cloneVolume(const_pointer_cast<GeoVFullPhysVol>(readOutVol))};
306 physVol = dynamic_pointer_cast<GeoVFullPhysVol>(clonedVol);
307 copiedStationVol->add(physVol);
308 return StatusCode::SUCCESS;
309}
310
312
313 const std::vector<const MuonGMR4::RpcReadoutElement*> readoutEles = m_detMgr->getAllRpcReadoutElements();
314 ATH_MSG_INFO("Copy "<<readoutEles.size()<<" Rpc readout elements to the legacy system");
315 if (readoutEles.empty()) return StatusCode::SUCCESS;
316 const RpcIdHelper& idHelper{m_idHelperSvc->rpcIdHelper()};
317 for (const MuonGMR4::RpcReadoutElement* copyMe : readoutEles) {
318 const Identifier reId = copyMe->identify();
319 const MuonGMR4::RpcReadoutElement::parameterBook& pars{copyMe->getParameters()};
320 GeoIntrusivePtr<GeoVFullPhysVol> physVol{};
321 MuonGM::MuonStation* station{nullptr};
322 ATH_CHECK(cloneReadoutVolume(gctx, reId, cacheObj, physVol, station));
323 auto newElement = std::make_unique<MuonGM::RpcReadoutElement>(physVol,
324 m_idHelperSvc->stationNameString(reId),
325 1, 1, false, cacheObj.detMgr.get());
326 newElement->setDoubletPhi(copyMe->doubletPhi());
327 newElement->setDoubletR(copyMe->doubletR());
328 newElement->setDoubletZ(copyMe->doubletZ());
329 newElement->setIdentifier(reId);
330 newElement->setParentMuonStation(station);
331 station->addMuonReadoutElementWithAlTransf(newElement.get(), nullptr, station->nMuonReadoutElements());
332
334 newElement->setLongZsize(2.*pars.halfLength);
335 newElement->setLongSsize(2.*pars.halfWidth);
336 newElement->setLongRsize(2.*pars.halfThickness);
337 newElement->setZsize(2.*pars.halfLength);
338 newElement->setSsize(2.*pars.halfWidth);
339 newElement->setRsize(2.*pars.halfThickness);
340
341 newElement->m_nlayers = copyMe->nGasGaps();
342 newElement->m_phistripwidth = copyMe->stripPhiWidth();
343 newElement->m_etastripwidth = copyMe->stripEtaWidth();
344 newElement->m_phistrippitch = copyMe->stripPhiPitch();
345 newElement->m_etastrippitch = Acts::copySign(1., copyMe->stationEta() -
346 (copyMe->stationEta()==0))*copyMe->stripEtaPitch();
347 newElement->m_phistriplength = copyMe->stripPhiLength();
348 newElement->m_etastriplength = copyMe->stripEtaLength();
349
350 newElement->m_nphistripsperpanel = copyMe->nPhiStrips();
351 newElement->m_netastripsperpanel = copyMe->nEtaStrips();
352 newElement->m_nphistrippanels = copyMe->nPhiPanels();
353 newElement->m_hasDEDontop = true;
354 newElement->m_descratzneg = false;
355
356 std::vector<Identifier> gapIds{};
357 for (unsigned int gasGap = 1; gasGap <= copyMe->nGasGaps(); ++gasGap) {
358 for (int doubPhi = copyMe->doubletPhiMax(); doubPhi >= copyMe->doubletPhi(); --doubPhi) {
359 for (bool measPhi : {false, true}) {
360 if (measPhi && copyMe->nPhiStrips()==0) continue;
361 const int channel = 1;
362 const Identifier gapId = idHelper.channelID(copyMe->identify(),
363 copyMe->doubletZ(),
364 doubPhi, gasGap, measPhi,
365 channel);
366
367 gapIds.push_back(gapId);
368 const Amg::Vector3D locStripPos = amdbTransform(gctx, *copyMe).inverse() * copyMe->stripPosition(gctx, gapId);
369 ATH_MSG_VERBOSE("GasGap "<<m_idHelperSvc->toString(gapId)<<", local strip position: "<<Amg::toString(locStripPos));
370 newElement->m_gasGap_xPos[gasGap -1] = locStripPos.x();
373 const int dbPIdx = copyMe->doubletPhi() == 2 ? 1 : doubPhi;
374 if (measPhi) {
375 newElement->m_first_phistrip_s[dbPIdx -1] = locStripPos.y();
376 newElement->m_phistrip_z = locStripPos.z();
377 } else{
378 newElement->m_first_etastrip_z = locStripPos.z();
379 newElement->m_etastrip_s[dbPIdx-1] = locStripPos.y();
380 }
381 }
382 }
383 }
384 newElement->fillCache();
386 for (const Identifier& gapId : gapIds) {
387 const int surfaceHash = newElement->surfaceHash(gapId);
388 const int layerHash = newElement->layerHash(gapId);
389 const Amg::Transform3D refTrf{copyMe->localToGlobalTransform(gctx, gapId)*
390 (m_idHelperSvc->measuresPhi(gapId) ?
391 Amg::getRotateZ3D(90_degree) :
392 Amg::Transform3D::Identity())};
393 ATH_MSG_VERBOSE("Assign transform: "<<m_idHelperSvc->toString(gapId)<<", "<<Amg::toString(refTrf));
394 newElement->m_surfaceData->m_layerTransforms[surfaceHash] = refTrf;
395 newElement->m_surfaceData->m_layerCenters[layerHash] = refTrf.translation();
396 newElement->m_surfaceData->m_layerNormals[layerHash] = refTrf.linear() * Amg::Vector3D::UnitZ();
397 }
398 ATH_CHECK(dumpAndCompare(gctx, *copyMe, *newElement));
399 cacheObj.detMgr->addRpcReadoutElement(std::move(newElement));
400 }
401 return StatusCode::SUCCESS;
402}
403
404
406
407 std::vector<const MuonGMR4::TgcReadoutElement*> tgcReadouts{m_detMgr->getAllTgcReadoutElements()};
408 std::ranges::stable_sort(tgcReadouts,[](const MuonGMR4::TgcReadoutElement* a, const MuonGMR4::TgcReadoutElement* b){
409 return a->stationEta() > b->stationEta();
410 });
411 ATH_MSG_INFO("Copy "<<tgcReadouts.size()<<" Tgc readout elements to the legacy system");
412 if (tgcReadouts.empty()) return StatusCode::SUCCESS;
413 const TgcIdHelper& idHelper{m_idHelperSvc->tgcIdHelper()};
414
415 using TgcReadoutParams = MuonGM::TgcReadoutParams;
416 std::map<std::string, std::shared_ptr<TgcReadoutParams>> readoutParMap{};
417
418 for (const MuonGMR4::TgcReadoutElement* copyMe: tgcReadouts) {
419 const Identifier reId = copyMe->identify();
420 GeoIntrusivePtr<GeoVFullPhysVol> physVol{};
421 MuonGM::MuonStation* station{nullptr};
422 ATH_CHECK(cloneReadoutVolume(gctx,reId, cacheObj, physVol, station));
423
424 auto newRE = std::make_unique<MuonGM::TgcReadoutElement>(physVol, m_idHelperSvc->stationNameString(reId),
425 cacheObj.detMgr.get());
426 newRE->setIdentifier(reId);
427 newRE->setParentMuonStation(station);
428 ATH_MSG_DEBUG("Readout element "<<m_idHelperSvc->toString(reId)<<", design: "<<copyMe->chamberDesign());
429 std::shared_ptr<TgcReadoutParams>& readOutPars = readoutParMap[std::format("{:}_{:}", copyMe->chamberDesign(),
430 copyMe->stationEta()> 0? 'A' : 'C')];
431 if (!readOutPars) {
432 using WiregangArray = TgcReadoutParams::WiregangArray;
433 using StripArray = TgcReadoutParams::StripArray;
434 using GasGapIntArray = TgcReadoutParams::GasGapIntArray;
435
436 std::array<WiregangArray, 3> wires{};
437 GasGapIntArray nWireGangs{}, nStrips{};
438 std::vector<StripArray> botMountings(copyMe->nGasGaps()),
439 topMountings(copyMe->nGasGaps());
440
441 double wirePitch{0.};
442 for (unsigned int gasGap =1; gasGap <= copyMe->nGasGaps(); ++gasGap) {
443 const IdentifierHash gangHash = copyMe->constructHash(0, gasGap, false);
444 const IdentifierHash stripHash = copyMe->constructHash(0, gasGap, true);
445 nWireGangs[gasGap -1] = copyMe->numWireGangs(gangHash);
446 nStrips[gasGap -1] = copyMe->numStrips(stripHash);
447 ATH_MSG_VERBOSE("Assigned wire gangs: "<<nWireGangs[gasGap-1]<<", strips: "<<nStrips[gasGap -1]
448 <<" for gas gap "<<gasGap);
449
450 if (nWireGangs[gasGap -1]) {
451 const MuonGMR4::WireGroupDesign& design{copyMe->wireGangLayout(gangHash)};
452 wirePitch = design.stripPitch();
453 WiregangArray& fillMe{wires[gasGap-1]};
454 for (int gang = 1; gang <= design.numStrips(); ++gang) {
455 fillMe[gang -1] = design.numWiresInGroup(gang);
456 }
457 ATH_MSG_VERBOSE("Gang layout: "<<fillMe);
458 }
459 if (nStrips[gasGap -1]) {
460 const MuonGMR4::RadialStripDesign& design{copyMe->stripLayout(stripHash)};
461 const int nCh = nStrips[gasGap -1];
462 for (int strip = 1; strip <= nCh; ++strip) {
463 botMountings[gasGap-1][strip-1] = - design.stripLeftBottom(strip).x();
464 topMountings[gasGap-1][strip-1] = - design.stripLeftTop(strip).x();
465 }
466 botMountings[gasGap-1][nCh] = - design.stripRightBottom(nCh).x();
467 topMountings[gasGap-1][nCh] = - design.stripRightTop(nCh).x();
468 ATH_MSG_VERBOSE("Strip layout\n bottom: "<<botMountings<<"\n top: "<<topMountings);
469 }
470 }
471 readOutPars = std::make_unique<TgcReadoutParams>(copyMe->chamberDesign(),
472 0, wirePitch,
473 idHelper.stationPhiMax(reId),
474 std::move(nWireGangs),
475 std::move(wires[0]),
476 std::move(wires[1]),
477 std::move(wires[2]),
478 0,
479 std::move(botMountings),
480 std::move(topMountings),
481 std::move(nStrips));
482 }
483
485 for (unsigned int gasGap = 1; gasGap <= copyMe->nGasGaps(); ++gasGap) {
486 const IdentifierHash layHash{copyMe->constructHash(0, gasGap, false)};
488 const Amg::Vector3D translation{amdbTransform(gctx, *copyMe).inverse() * copyMe->center(gctx, layHash)};
489 newRE->setPlaneZ(translation.x(), gasGap);
490 }
491 newRE->setRsize(copyMe->moduleHeight());
492 newRE->setSsize(copyMe->moduleWidthS());
493 newRE->setZsize(copyMe->moduleThickness());
494
495 newRE->setLongRsize(copyMe->moduleHeight());
496 newRE->setLongSsize(copyMe->moduleWidthL());
497 newRE->setLongZsize(copyMe->moduleThickness());
498
499 newRE->setReadOutParams(readOutPars);
500 newRE->fillCache();
501 ATH_CHECK(dumpAndCompare(gctx, *copyMe, *newRE));
502 cacheObj.detMgr->addTgcReadoutElement(std::move(newRE));
503
504 }
505 return StatusCode::SUCCESS;
506}
507
508GeoIntrusivePtr<GeoVFullPhysVol>
510 const MuonGMR4::MuonReadoutElement& copyMe,
511 ConstructionCache& cacheObj) const {
512 GeoIntrusivePtr<const GeoVFullPhysVol> readOutVol{copyMe.getMaterialGeom()};
513 cacheObj.translatedStations.insert(readOutVol->getParent());
514
515 PVLink clonedVol{cloneVolume(const_pointer_cast<GeoVFullPhysVol>(readOutVol))};
516 GeoIntrusivePtr<GeoFullPhysVol> physVol{dynamic_pointer_cast<GeoFullPhysVol>(clonedVol)};
517 cacheObj.world->add(cacheObj.newIdTag());
518 cacheObj.world->add(cacheObj.makeTransform(amdbTransform(gctx, copyMe)));
519 cacheObj.world->add(physVol);
520 return physVol;
521}
523
524 SubDetAlignment alignItr = gctx.getStore(ActsTrk::DetectorType::Mm);
525 const auto alignStore = alignItr ?
526 static_cast<const MmAlignmentStore*>(alignItr->internalAlignment.get()) : nullptr;
527
528 if (alignStore) {
529 cacheObj.detMgr->setMMPassivation(alignStore->passivation);
530 }
531 const std::vector<const MuonGMR4::MmReadoutElement*> mmReadouts{m_detMgr->getAllMmReadoutElements()};
532 ATH_MSG_INFO("Copy "<<mmReadouts.size()<<" Mm readout elements to the legacy system");
533
534 if (mmReadouts.empty()) return StatusCode::SUCCESS;
535
536 for (const MuonGMR4::MmReadoutElement* copyMe : mmReadouts) {
537 const Identifier reId = copyMe->identify();
538 GeoIntrusivePtr<GeoVFullPhysVol> physVol{cloneNswWedge(gctx, *copyMe, cacheObj)};
539 auto newRE = std::make_unique<MuonGM::MMReadoutElement>(physVol,
540 m_idHelperSvc->stationNameString(reId),
541 copyMe->stationEta(),
542 copyMe->stationPhi(),
543 copyMe->multilayer(), cacheObj.detMgr.get());
545 for (unsigned int gasGap = 0; gasGap < copyMe->nGasGaps(); ++gasGap) {
546 const MuonGMR4::StripLayer& stripLayer{copyMe->stripLayer(MuonGMR4::MmReadoutElement::createHash(gasGap +1, 0))};
547 const MuonGMR4::StripDesign& designFrom{stripLayer.design()};
548
549 newRE->m_Xlg[gasGap] = stripLayer.toOrigin() *
550 Amg::getRotateZ3D(-designFrom.stereoAngle()) *
551 Amg::getRotateY3D(90. * Gaudi::Units::deg);
552 ATH_MSG_VERBOSE("Layer transform "<<gasGap<<" "<<GeoTrf::toString(newRE->m_Xlg[gasGap], true));
553
554 MuonGM::MuonChannelDesign& designTo{newRE->m_etaDesign[gasGap]};
555 designTo.defineTrapezoid(designFrom.shortHalfHeight(),
556 designFrom.longHalfHeight(),
557 designFrom.halfWidth(),
558 designFrom.stereoAngle());
561 designTo.inputPitch = designFrom.stripPitch();
562 designTo.inputWidth = designTo.inputPitch * std::cos(designTo.stereoAngle());
563 designTo.nMissedBottomEta = designTo.nMissedBottomStereo = designFrom.firstStripNumber() - 1;
564 designTo.totalStrips = designFrom.numStrips();
565 designTo.nch = designFrom.numStrips();
566
567 designTo.setFirstPos(designFrom.firstStripPos().x() + 0.5*designTo.inputPitch);
568 }
569
570 newRE->fillCache();
571 if (alignStore && alignStore->getBLine(reId)) {
572 newRE->setBLinePar(*alignStore->getBLine(reId));
573 }
574 ATH_CHECK(dumpAndCompare(gctx, *copyMe, *newRE));
575 cacheObj.detMgr->addMMReadoutElement(std::move(newRE));
576 }
577 return StatusCode::SUCCESS;
578}
579
581 SubDetAlignment alignItr = gctx.getStore(ActsTrk::DetectorType::sTgc);
582 auto alignStore = alignItr ? static_cast<const sTgcAlignmentStore*>(alignItr->internalAlignment.get()) : nullptr;
583
584 const std::vector<const MuonGMR4::sTgcReadoutElement*> sTgcReadOuts{m_detMgr->getAllsTgcReadoutElements()};
585 ATH_MSG_INFO("Copy "<<sTgcReadOuts.size()<<" sTgc readout elements to the legacy system");
586
587 if (sTgcReadOuts.empty()) return StatusCode::SUCCESS;
588
589 for (const MuonGMR4::sTgcReadoutElement* copyMe : sTgcReadOuts) {
590 const Identifier reId = copyMe->identify();
591 ATH_MSG_DEBUG("Translate readout element "<<m_idHelperSvc->toStringDetEl(reId)<<".");
592 GeoIntrusivePtr<GeoVFullPhysVol> physVol{cloneNswWedge(gctx, *copyMe, cacheObj)};
593
594 auto newRE = std::make_unique<MuonGM::sTgcReadoutElement>(physVol,
595 m_idHelperSvc->stationNameString(reId).substr(1),
596 copyMe->stationEta(),
597 copyMe->stationPhi(),
598 copyMe->multilayer(),
599 cacheObj.detMgr.get());
600
601 if (alignStore && alignStore->getBLine(reId)) {
602 newRE->setBLinePar(*alignStore->getBLine(reId));
603 }
604 for (unsigned int layer = 1; layer <= copyMe->numLayers(); ++layer) {
606 using ChannelDesign = MuonGM::MuonChannelDesign;
607 const IdentifierHash layerHash = MuonGMR4::sTgcReadoutElement::createHash(layer,channelType::Strip,0);
608
609 const MuonGMR4::StripLayer& stripLayer{copyMe->stripLayer(layerHash)};
610 newRE->m_Xlg[layer -1] = stripLayer.toOrigin() *
611 Amg::getRotateY3D(90._degree) *
612 Amg::getTranslateX3D( layer%2 ? - 0.01 : 0.01 );
613
614 const MuonGMR4::StripDesign& copyEtaDesign{stripLayer.design()};
615 ATH_MSG_VERBOSE("Layer: "<<layer<<" "<<copyEtaDesign);
617 ChannelDesign& etaDesign{newRE->m_etaDesign[layer-1]};
618 etaDesign.type = ChannelDesign::ChannelType::etaStrip;
619 etaDesign.detType = ChannelDesign::DetType::STGC;
620 if (copyEtaDesign.yCutout()) {
621 etaDesign.defineDiamond(copyEtaDesign.shortHalfHeight(),
622 copyEtaDesign.longHalfHeight(),
623 copyEtaDesign.halfWidth(),
624 copyEtaDesign.yCutout());
625 } else {
626 etaDesign.defineTrapezoid(copyEtaDesign.shortHalfHeight(),
627 copyEtaDesign.longHalfHeight(),
628 copyEtaDesign.halfWidth());
629
630 }
631 etaDesign.firstPitch = copyEtaDesign.firstStripPos().x() + 0.5*copyEtaDesign.stripPitch() + copyEtaDesign.halfWidth();
632 etaDesign.inputPitch = copyEtaDesign.stripPitch();
633 etaDesign.inputWidth = copyEtaDesign.stripWidth();
634 etaDesign.nch = copyEtaDesign.numStrips();
635 ATH_MSG_VERBOSE(m_idHelperSvc->toStringDetEl(copyMe->identify())<<", layer: "<<layer<<", eta-design: "<< copyEtaDesign);
636 etaDesign.setFirstPos(copyEtaDesign.firstStripPos().x() + 0.5*copyEtaDesign.stripPitch());
638
639 const MuonGMR4::WireGroupDesign& copyPhiDesign{copyMe->wireDesign(layerHash)};
640
641 ChannelDesign& phiDesign{newRE->m_phiDesign[layer-1]};
642 phiDesign.type = ChannelDesign::ChannelType::phiStrip;
643 phiDesign.detType = ChannelDesign::DetType::STGC;
644 if (copyPhiDesign.yCutout() == 0.) {
645 phiDesign.defineTrapezoid(copyPhiDesign.shortHalfHeight(),
646 copyPhiDesign.longHalfHeight(),
647 copyPhiDesign.halfWidth());
648 } else {
649 phiDesign.defineDiamond(copyPhiDesign.shortHalfHeight(),
650 copyPhiDesign.longHalfHeight(),
651 copyPhiDesign.halfWidth(),
652 copyPhiDesign.yCutout());
653 }
654 phiDesign.inputPitch = copyPhiDesign.stripPitch();
655 phiDesign.inputWidth = copyPhiDesign.stripWidth();
656 ATH_MSG_VERBOSE(m_idHelperSvc->toStringDetEl(copyMe->identify())<<", layer: "<<layer<<", phi-design: "<< copyPhiDesign);
657 phiDesign.setFirstPos(copyPhiDesign.firstStripPos().x()); // Position of 1st wire, accounts for staggering
658 phiDesign.firstPitch = copyPhiDesign.numWiresInGroup(1); // Number of Wires in 1st group, group staggering
659 phiDesign.groupWidth = copyPhiDesign.numWiresInGroup(2); // Number of Wires normal group
660 phiDesign.nGroups = copyPhiDesign.numStrips(); // Number of Wire Groups
661 phiDesign.wireCutout = copyPhiDesign.wireCutout(); // Size of "active" wire region for digits
662 phiDesign.nch = copyPhiDesign.nAllWires();
663 phiDesign.isConvertedFromPhaseII = true;
664
665 const MuonGMR4::PadDesign& copyPadDesign{copyMe->padDesign(layerHash)};
666 MuonGM::MuonPadDesign& padDesign{newRE->m_padDesign[layer-1]};
667 padDesign.Length = copyMe->chamberHeight();
668 padDesign.sWidth = copyMe->sChamberLength();
669 padDesign.lWidth = copyMe->lChamberLength();
670 padDesign.Size = 2.*copyPadDesign.halfWidth();
671 padDesign.ysFrame = copyMe->sFrameWidth();
672 padDesign.ylFrame = copyMe->lFrameWidth();
673 padDesign.thickness = copyMe->thickness();
675 if (copyPadDesign.yCutout()) {
676 padDesign.yCutout = copyPadDesign.halfWidth();
677 }
678 padDesign.setR(copyPadDesign.beamlineRadius());
679 padDesign.sPadWidth = 2.*copyPadDesign.shortHalfHeight();
680 padDesign.lPadWidth = 2.*copyPadDesign.longHalfHeight();
681 padDesign.nPadColumns = copyPadDesign.numPadPhi();
682 padDesign.firstPhiPos = copyPadDesign.firstPadPhiDiv();
683 padDesign.inputPhiPitch = copyPadDesign.anglePadPhi();
684 padDesign.PadPhiShift = copyPadDesign.padPhiShift();
685 padDesign.nPadH = copyPadDesign.numPadEta();
686 padDesign.padEtaMax = copyPadDesign.maxPadEta();
687 padDesign.firstRowPos = copyPadDesign.firstPadHeight();
688 padDesign.inputRowPitch = copyPadDesign.padHeight();
689 padDesign.sectorOpeningAngle = copyPadDesign.sectorAngle();
690 padDesign.isConvertedFromPhaseII = true;
691 }
692 newRE->fillCache();
693 ATH_CHECK(dumpAndCompare(gctx, *copyMe, *newRE));
694 cacheObj.detMgr->addsTgcReadoutElement(std::move(newRE));
695
696 }
697 return StatusCode::SUCCESS;
698}
701 SubDetAlignment alignItr = gctx.getStore(ActsTrk::DetectorType::Mdt);
702 const MdtAlignmentStore* alignStore = alignItr ?
703 static_cast<const MdtAlignmentStore*>(alignItr->internalAlignment.get()) : nullptr;
704
705 const std::vector<const MuonGMR4::MdtReadoutElement*> mdtReadOuts{m_detMgr->getAllMdtReadoutElements()};
706 ATH_MSG_INFO("Copy "<<mdtReadOuts.size()<<" Mdt readout elements to the legacy system");
707 if (mdtReadOuts.empty()) return StatusCode::SUCCESS;
708 for (const MuonGMR4::MdtReadoutElement* copyMe : mdtReadOuts) {
709 const Identifier reId = copyMe->identify();
710 ATH_MSG_DEBUG("Translate "<<m_idHelperSvc->toStringDetEl(reId));
712 GeoIntrusivePtr<GeoVFullPhysVol> physVol{};
713 MuonGM::MuonStation* station{nullptr};
714 ATH_CHECK(cloneReadoutVolume(gctx,reId, cacheObj, physVol, station));
715 if (copyMe->multilayer() == 1) {
716 const MuonGMR4::MdtReadoutElement* otherRE = copyMe->complementaryRE();
717 const double height = std::max(copyMe->moduleHeight(), otherRE->moduleHeight()) -
718 (copyMe->tubePitch() - 2. * copyMe->tubeRadius());
719
720 const double modHalTHickO{0.5*otherRE->moduleThickness()},
721 modHalfThick{-0.5*copyMe->moduleThickness()};
722
723 const double thickness = ( (otherRE->asBuiltRefFrame()*(modHalTHickO* Amg::Vector3D::UnitX())) -
724 (copyMe->asBuiltRefFrame()*(modHalfThick* Amg::Vector3D::UnitX()))).z();
725 if (copyMe->isBarrel()) {
726 station->setMdtZsize(height);
727 station->setMdtRsize(thickness);
728 } else {
729 station->setMdtRsize(height);
730 station->setMdtZsize(thickness);
731 }
732 }
733 const MuonGMR4::MdtReadoutElement::parameterBook& pars{copyMe->getParameters()};
734 auto newElement = std::make_unique<MuonGM::MdtReadoutElement>(physVol,
735 m_idHelperSvc->stationNameString(reId),
736 cacheObj.detMgr.get());
737 newElement->setIdentifier(reId);
738 newElement->setMultilayer(copyMe->multilayer());
739 newElement->setNMdtInStation(m_idHelperSvc->mdtIdHelper().multilayerMax(reId));
740 // cppcheck-suppress invalidLifetime; ok: mgr took ownership.
741 newElement->setParentMuonStation(station);
742
744 newElement->setLongSsize(2*pars.longHalfX - 1._cm);
745 newElement->setSsize(2*pars.shortHalfX - 1._cm);
746 newElement->setLongRsize(2*pars.halfY);
747 newElement->setRsize(2*pars.halfY);
748 newElement->setZsize(2*pars.halfHeight);
749 newElement->setLongZsize(2*pars.halfHeight);
750
751 newElement->m_nlayers = copyMe->numLayers();
752 newElement->m_ntubesperlayer = copyMe->numTubesInLay();
753 newElement->m_deadlength = pars.deadLength;
754 newElement->m_endpluglength = pars.endPlugLength;
755 newElement->m_innerRadius = pars.tubeInnerRad;
756 newElement->m_tubeWallThickness = pars.tubeWall;
757 newElement->m_tubepitch = pars.tubePitch;
760
762 const MuonGMR4::MdtTubeLayer& tubeLay{*pars.tubeLayers[0]};
763 unsigned int step{1};
764 double lastLength{2.*tubeLay.uncutHalfLength(1)};
765 for (unsigned tube = 0; tube < copyMe->numTubesInLay(); ++tube) {
766 const double currLength = 2.*tubeLay.uncutHalfLength(tube);
767 ATH_MSG_VERBOSE(m_idHelperSvc->toString(copyMe->identify())<< ", tube "<<tube<<", length: "<<currLength);
768 if (std::abs(lastLength - currLength) > std::numeric_limits<float>::epsilon() ||
769 tube == copyMe->numTubesInLay() -1) {
770 newElement->m_tubelength[step-1] = lastLength;
771 newElement->m_tubelength[step] = currLength;
772 if (step == 1) {
773 newElement->m_ntubesinastep = tube;
774 }
775 lastLength = currLength;
776 ++step;
777 }
778 }
779 newElement->m_nsteps = step;
780
782 double xOffSet{pars.halfY}, yOffSet{pars.halfHeight};
783 if (newElement->barrel()) std::swap(xOffSet, yOffSet);
784 for (unsigned lay = 1; lay <= copyMe->numLayers(); ++lay) {
785 const IdentifierHash tubeHash{copyMe->measurementHash(lay, 1)};
786 const Amg::Vector3D locTube = copyMe->localTubePos(tubeHash);
787 newElement->m_firstwire_x[lay-1] = locTube.z() + xOffSet;
788 newElement->m_firstwire_y[lay-1] = locTube.x() + yOffSet;
789 }
790 MdtAlignmentStore::chamberDistortions distort = alignStore ? alignStore->getDistortion(reId) :
792
793 if (!station->hasMdtAsBuiltParams()){
794 station->setMdtAsBuiltParams(distort.asBuilt);
795 }
796 if (!station->hasBLines()){
797 station->setBline(distort.bLine);
798 }
799 const Amg::Vector3D refPoint = copyMe->bLineReferencePoint();
800 station->setBlineFixedPointInAmdbLRS(refPoint.x(), refPoint.y(), refPoint.z());
801
802 newElement->geoInitDone();
803 newElement->setBLinePar(distort.bLine);
804 newElement->fillCache();
805 ATH_CHECK(dumpAndCompare(gctx, *copyMe, *newElement));
807 cacheObj.detMgr->addMdtReadoutElement(std::move(newElement));
808 }
809 return StatusCode::SUCCESS;
810}
811
813 const MuonGM::MuonReadoutElement& testEle) const{
814
815 if (refEle.identify() != testEle.identify()) {
816 ATH_MSG_FATAL("Two different elements are compared "
817 <<m_idHelperSvc->toString(refEle.identify())<<" vs. "
818 <<m_idHelperSvc->toString(testEle.identify()));
819 return StatusCode::FAILURE;
820 }
821 if (refEle.identHash() != testEle.detectorElementHash()) {
822 ATH_MSG_FATAL("The hashes of the two detector elements "<<m_idHelperSvc->toString(refEle.identify())
823 <<" are completely different "<<refEle.identHash()<<" vs. "<<testEle.detectorElementHash());
824 return StatusCode::FAILURE;
825 }
826 return StatusCode::SUCCESS;
827}
828
830 const MuonGMR4::MmReadoutElement& refEle,
831 const MuonGM::MMReadoutElement& testEle) const {
832
833 if (!m_checkGeo) {
834 return StatusCode::SUCCESS;
835 }
836 ATH_CHECK(checkIdCompability(refEle, testEle));
837
838 ATH_MSG_VERBOSE("Compare basic readout transforms"<<std::endl
839 <<GeoTrf::toString(testEle.absTransform(),true)<<std::endl
840 <<GeoTrf::toString(amdbTransform(gctx, refEle), true));
841 const MmIdHelper& idHelper{m_idHelperSvc->mmIdHelper()};
842 for (unsigned int gasGap = 1; gasGap <= refEle.nGasGaps(); ++ gasGap) {
843 const Identifier gapId = idHelper.channelID(refEle.identify(), refEle.multilayer(), gasGap, 1);
844
845 const Amg::Transform3D& refTrf{refEle.localToGlobalTransform(gctx, gapId)};
846 const Amg::Transform3D& testTrf{testEle.transform(gapId)};
847 if (!Amg::isIdentity(refTrf.inverse()*testTrf)) {
848 ATH_MSG_FATAL("The layer "<<m_idHelperSvc->toStringGasGap(gapId)<<" does not transform equally"
849 <<GeoTrf::toString(refTrf, true) <<" vs. "<<GeoTrf::toString(testTrf, true));
850 return StatusCode::FAILURE;
851 }
852 const MuonGMR4::StripDesign& stripDesign{refEle.stripLayer(gapId).design()};
853
854 for (int strip = stripDesign.firstStripNumber(); strip <= stripDesign.numStrips(); ++strip) {
855 const Identifier stripId = idHelper.channelID(refEle.identify(), refEle.multilayer(), gasGap, strip);
856 const Amg::Vector3D refStripPos{refEle.stripPosition(gctx, stripId)};
857 const Amg::Vector3D refStripDir{refEle.localToGlobalTransform(gctx, refEle.layerHash(stripId)).linear() * Amg::Vector3D::UnitX()};
858
859 Amg::Vector3D testStripPos{Amg::Vector3D::Zero()};
860 if (!testEle.stripGlobalPosition(stripId, testStripPos)) {
861 ATH_MSG_FATAL("Failed to retrieve strip position "<<m_idHelperSvc->toString(stripId));
862 return StatusCode::FAILURE;
863 }
864 const double dist = refStripDir.dot(refStripPos - testStripPos);
865 if (std::abs(dist) > 10. * Gaudi::Units::micrometer) {
866 ATH_MSG_FATAL("The strip "<<Amg::toString(testStripPos)<<" is not describing the same strip as "
867 <<Amg::toString(refStripPos)<<". Channel "<<m_idHelperSvc->toString(stripId)
868 <<" distance: "<<dist<<" "<<(dist / testEle.m_etaDesign[gasGap -1].inputWidth));
869 return StatusCode::FAILURE;
870 }
871 ATH_MSG_VERBOSE("Channel postion "<<m_idHelperSvc->toString(stripId)<<" match between legacy & new");
872 }
873 }
874 return StatusCode::SUCCESS;
875}
876
878 const MuonGMR4::MdtReadoutElement& refEle,
879 const MuonGM::MdtReadoutElement& testEle) const {
880
881 if (!m_checkGeo) {
882 return StatusCode::SUCCESS;
883 }
884 ATH_CHECK(checkIdCompability(refEle, testEle));
885
886 ATH_MSG_VERBOSE("Detector element "<<m_idHelperSvc->toString(refEle.identify())
887 <<std::endl<<GeoTrf::toString(amdbTransform(gctx, refEle))
888 <<std::endl<<GeoTrf::toString(testEle.getMaterialGeom()->getAbsoluteTransform())
889 <<std::endl<<"r-size: "<<testEle.getRsize()<<"/"<<testEle.getLongRsize()
890 <<" s-size: "<<testEle.getSsize()<<"/"<<testEle.getLongSsize()
891 <<" z-size: "<<testEle.getZsize()<<"/"<<testEle.getLongZsize());
892 for (unsigned int lay = 1; lay <= refEle.numLayers(); ++lay){
893 for (unsigned int tube = 1; tube <= refEle.numTubesInLay(); ++tube) {
894 const IdentifierHash tubeHash {refEle.measurementHash(lay,tube)};
895 if (!refEle.isValid(tubeHash)) {
896 ATH_MSG_VERBOSE("SKip layer / tube "<<lay <<","<<tube);
897 continue;
898 }
899 const Amg::Transform3D globToLocal = refEle.globalToLocalTransform(gctx, tubeHash);
900
901 const Amg::Vector3D refPos = refEle.globalTubePos(gctx, tubeHash);
902 const Amg::Vector3D tubePos = testEle.tubePos(lay, tube);
903
904
905 if ( (refPos - tubePos).mag() > Gaudi::Units::micrometer &&
906 (globToLocal*refPos - globToLocal * tubePos).perp() > Gaudi::Units::micrometer) {
907 ATH_MSG_ERROR("Tube positions differ for "<<m_idHelperSvc->toString(refEle.measurementId(tubeHash))
908 <<" reference: "<<GeoTrf::toString(globToLocal*refPos)<<" vs. test: "
909 <<GeoTrf::toString(globToLocal*tubePos) <<" delta: "<<(refPos - tubePos).mag()
910 <<" Transforms "<<std::endl
911 <<" **** "<< GeoTrf::toString(globToLocal.inverse())<<std::endl
912 <<" **** "<< GeoTrf::toString(testEle.transform(lay, tube)));
913 return StatusCode::FAILURE;
914 }
915 ATH_MSG_VERBOSE("Tube positions layer: "<<lay<<", tube: "<<tube
916 <<std::endl<<"reference: "<<GeoTrf::toString(refPos)
917 <<std::endl<<"test: "<<GeoTrf::toString(tubePos)
918 <<std::endl<<testEle.tubeLength(lay, tube)<<"/"<<testEle.getActiveTubeLength(lay, tube)<<"/"
919 <<testEle.getWireLength(lay,tube)<<" vs. "<<refEle.tubeLength(tubeHash)
920 <<"/"<<refEle.activeTubeLength(tubeHash)<<"/"<<refEle.wireLength(tubeHash)
921 <<"/"<<refEle.uncutTubeLength(tubeHash));
922 if (std::abs(testEle.getTubeLengthForCaching(lay,tube) - refEle.uncutTubeLength(tubeHash)) >
923 std::numeric_limits<float>::epsilon() ) {
924 ATH_MSG_FATAL("Different tube length's detected for "<<m_idHelperSvc->toStringDetEl(refEle.identify())
925 << " layer: "<<lay<<", tube: "<<tube<<" -- "<<testEle.getTubeLengthForCaching(lay,tube)<<" (new) vs. "
926 <<refEle.uncutTubeLength(tubeHash)<<" (ref)");
927 return StatusCode::FAILURE;
928 }
929 }
930 }
931
932 return StatusCode::SUCCESS;
933}
935 const MuonGMR4::RpcReadoutElement& refEle,
936 const MuonGM::RpcReadoutElement& testEle) const {
937
938 if (!m_checkGeo) {
939 return StatusCode::SUCCESS;
940 }
941 ATH_CHECK(checkIdCompability(refEle, testEle));
942
943 ATH_MSG_VERBOSE("Compare basic readout transforms"<<std::endl
944 <<" ref: "<<GeoTrf::toString(amdbTransform(gctx, refEle), true)<<std::endl
945 <<" test: "<<GeoTrf::toString(testEle.absTransform(),true)<<std::endl
946 <<"delta: "<<GeoTrf::toString(testEle.absTransform().inverse()*amdbTransform(gctx, refEle), true ));
947 const RpcIdHelper& idHelper{m_idHelperSvc->rpcIdHelper()};
948 for (unsigned int gasGap = 1; gasGap <= refEle.nGasGaps(); ++gasGap) {
949 for (int doubPhi = refEle.doubletPhi(); doubPhi <= refEle.doubletPhiMax(); ++doubPhi) {
950 for (bool measPhi : {false, true}) {
951 if (measPhi && !refEle.nPhiStrips()) continue;
952 for (int strip = 1; strip <= testEle.Nstrips(measPhi); ++strip) {
953 const Identifier stripId = idHelper.channelID(refEle.identify(),
954 refEle.doubletZ(),
955 doubPhi, gasGap, measPhi, strip);
956
957 const Amg::Transform3D refTrans{refEle.localToGlobalTransform(gctx, stripId) *
958 (measPhi ? Amg::getRotateZ3D(90_degree) :
959 Amg::Transform3D::Identity())};
960 const Amg::Transform3D& testTrans{testEle.transform(stripId)};
961 if (strip == 1 && !Amg::isIdentity(refTrans.inverse()*testTrans)) {
962 ATH_MSG_ERROR("Transformation for "<<m_idHelperSvc->toString(stripId)<<" - "<<refEle.identHash()<<std::endl
963 <<" *** ref: "<<GeoTrf::toString(refTrans)<<std::endl
964 <<" *** test: "<<GeoTrf::toString(testTrans)<<std::endl
965 <<" -> delta: "<<GeoTrf::toString(refTrans.inverse()*testTrans));
966 return StatusCode::FAILURE;
967 }
968
969 const Amg::Vector3D refStripPos = refEle.stripPosition(gctx, stripId);
970 const Amg::Vector3D testStripPos = testEle.stripPos(stripId);
971 // The threshold here used to be epsilon for a float.
972 // But this was then giving a failure in aarch64,
973 // with a difference of almost exactly 1e-4.
974 // It turned out that that was coming from GeoDeDuplicator,
975 // where to consider two transforms equivalent,
976 // the translations must match to 1e-4. But if the
977 // difference is almost exactly 1e-4, then small FP
978 // differences can be magnified to just about 1e-4.
979 if ((refStripPos - testStripPos).mag() > 2e-4){
980 ATH_MSG_ERROR("Mismatch in strip positions "<<m_idHelperSvc->toString(stripId)
981 <<" ref: "<<Amg::toString(refStripPos)<<" test: "<<Amg::toString(testStripPos)
982 <<" local coordinates -- ref: "<<Amg::toString(refTrans.inverse()*refStripPos)
983 <<" test: "<<Amg::toString(refTrans.inverse()*testStripPos));
984 return StatusCode::FAILURE;
985 }
986 ATH_MSG_VERBOSE("Agreement between new and old geometry for channel "<<m_idHelperSvc->toString(stripId)
987 <<" strip position "<<Amg::toString(refStripPos)
988 <<", local: "<<Amg::toString(refTrans.inverse()*refStripPos));
989 }
990 }
991 }
992 }
993 return StatusCode::SUCCESS;
994}
996 const MuonGMR4::TgcReadoutElement& refEle,
997 const MuonGM::TgcReadoutElement& testEle) const {
998
999 if (!m_checkGeo) {
1000 return StatusCode::SUCCESS;
1001 }
1002 ATH_CHECK(checkIdCompability(refEle, testEle));
1003
1004 const TgcIdHelper& idHelper{m_idHelperSvc->tgcIdHelper()};
1005
1006 ATH_MSG_VERBOSE("Detector element "<<m_idHelperSvc->toString(refEle.identify())
1007 <<std::endl<<GeoTrf::toString(amdbTransform(gctx, refEle), true)
1008 <<std::endl<<GeoTrf::toString(testEle.getMaterialGeom()->getAbsoluteTransform(), true)
1009 <<std::endl<<"r-size: "<<testEle.getRsize()<<"/"<<testEle.getLongRsize()
1010 <<" s-size: "<<testEle.getSsize()<<"/"<<testEle.getLongSsize()
1011 <<" z-size: "<<testEle.getZsize()<<"/"<<testEle.getLongZsize());
1012
1013 for (unsigned int gasGap = 1; gasGap <= refEle.nGasGaps(); ++gasGap) {
1014 for (bool isStrip : {false, true}) {
1015 const IdentifierHash layHash = refEle.constructHash(0, gasGap, isStrip);
1016
1017 const Identifier layId = idHelper.channelID(refEle.identify(), gasGap, isStrip, 1);
1018 ATH_MSG_VERBOSE("Test layer "<<m_idHelperSvc->toString(layId)<<", nCh: "<<refEle.numChannels(layHash)<<", layHash: "<<layHash);
1019 if (!refEle.numChannels(layHash)) continue;
1020 const Amg::Transform3D refLayerTrf = refEle.localToGlobalTransform(gctx, refEle.constructHash(0, gasGap, false)) *
1021 (!isStrip ? Amg::Transform3D::Identity()
1022 : Amg::getRotateZ3D(-90._degree));
1023 const Amg::Transform3D& testLayerTrf = testEle.transform(layId);
1024 if (!Amg::isIdentity(refLayerTrf.inverse()* testLayerTrf)) {
1025 ATH_MSG_FATAL("The transformations in "<<m_idHelperSvc->toString(layId)
1026 <<std::endl<<"ref : "<<GeoTrf::toString(refLayerTrf,true)
1027 <<std::endl<<"test: "<<GeoTrf::toString(testLayerTrf,true)
1028 <<" are not identical. ");
1029 return StatusCode::FAILURE;
1030 }
1031 ATH_MSG_VERBOSE("Transformations in "<<m_idHelperSvc->toString(layId)
1032 <<std::endl<<"ref : "<<GeoTrf::toString(refLayerTrf,true)
1033 <<std::endl<<"test: "<<GeoTrf::toString(testLayerTrf,true));
1034
1035 for (unsigned int ch = 1; ch <= refEle.numChannels(layHash); ++ch) {
1036 const IdentifierHash measHash = refEle.constructHash(ch, gasGap, isStrip);
1037 const Identifier measId = refEle.measurementId(measHash);
1038 const Amg::Vector3D refChannel = refEle.channelPosition(gctx, measHash);
1039 const Amg::Vector3D testChannel = testEle.channelPos(measId);
1040 if ((refChannel - testChannel).mag() < std::numeric_limits<float>::epsilon()){
1041 continue;
1042 }
1043 std::stringstream msg{};
1044 msg<<"The channel "<<m_idHelperSvc->toString(measId)
1045 << " is not at the same position "<<Amg::toString(refChannel)
1046 <<" vs. "<<Amg::toString(testChannel)<<". Difference: "
1047 <<(refChannel - testChannel).mag();
1048 if (!isStrip) {
1049 msg<<std::endl<<"*** Test *** - wirePitch: "<<testEle.wirePitch()
1050 <<", tot wires "<<testEle.nWires(gasGap)
1051 <<", wires to reach "<<testEle.nPitchesToGang(gasGap, ch)
1052 <<", wires in gang "<<testEle.nWires(gasGap, ch);
1053 const MuonGMR4::WireGroupDesign& design{refEle.wireGangLayout(gasGap)};
1054 msg<<std::endl<<"*** Ref *** - wirePitch: "<<design.stripPitch()
1055 <<", tot wires "<<testEle.nWires(gasGap)
1056 <<", wires to reach "<<design.numPitchesToGroup(ch)
1057 <<", wires in gang "<<design.numWiresInGroup(ch);
1058 } else {
1059 const Amg::Vector3D locRefPos{refLayerTrf.inverse() * refChannel};
1060 const Amg::Vector3D locTestPos{refLayerTrf.inverse()* testChannel};
1061 msg<<std::endl<<"*** Ref **** - "<<Amg::toString(locRefPos)<<std::endl;
1062 msg<<std::endl<<"*** Test **** - "<<Amg::toString(locTestPos)<<std::endl;
1063 }
1064 ATH_MSG_FATAL(msg.str());
1065 return StatusCode::FAILURE;
1066 }
1067
1068 }
1069 }
1070 return StatusCode::SUCCESS;
1071}
1073 const MuonGMR4::sTgcReadoutElement& refEle,
1074 const MuonGM::sTgcReadoutElement& testEle) const {
1075 if (!m_checkGeo) {
1076 return StatusCode::SUCCESS;
1077 }
1078 ATH_CHECK(checkIdCompability(refEle, testEle));
1079
1080 ATH_MSG_VERBOSE("Compare basic readout transforms"<<std::endl
1081 <<GeoTrf::toString(testEle.absTransform(),true)<<std::endl
1082 <<GeoTrf::toString(amdbTransform(gctx, refEle), true));
1083 const sTgcIdHelper& idHelper{m_idHelperSvc->stgcIdHelper()};
1084 for (unsigned int gasGap = 1; gasGap <= refEle.numLayers(); ++gasGap) {
1088 const IdentifierHash layHash = refEle.createHash(gasGap, chType, 1);
1089 const unsigned int numChannel = refEle.numChannels(layHash);
1090 constexpr unsigned firstCh = 1;
1091 for (unsigned int channel = firstCh; channel < numChannel ; ++channel) {
1092 Identifier chID{};
1093 bool isValid = false;
1095 const int etaIndex = refEle.padDesign(layHash).padNumber(channel).first;
1096 const int phiIndex = refEle.padDesign(layHash).padNumber(channel).second;
1097 chID = idHelper.padID(refEle.identify(),
1098 refEle.multilayer(),
1099 gasGap, chType, etaIndex, phiIndex, isValid);
1100 } else {
1101 chID = idHelper.channelID(refEle.identify(),
1102 refEle.multilayer(),
1103 gasGap, chType, channel, isValid);
1104 }
1105
1106 if(!isValid) {
1107 ATH_MSG_WARNING("Invalid Identifier detected: " << m_idHelperSvc->toString(chID));
1108 return StatusCode::FAILURE;
1109 }
1110 const IdentifierHash measHash = refEle.measurementHash(chID);
1111 Amg::Transform3D refTrans{refEle.localToGlobalTransform(gctx, refEle.layerHash(measHash))*
1113 const Amg::Transform3D& testTrans{testEle.transform(chID)};
1114 if (channel == firstCh && (!Amg::doesNotDeform(testTrans.inverse()*refTrans)
1115 || (testTrans.inverse()*refTrans).translation().perp() >
1116 std::numeric_limits<float>::epsilon() ) ) {
1117 ATH_MSG_ERROR(__func__<<"() "<<__LINE__<<" - Transformation for "
1118 <<m_idHelperSvc->toString(chID)<<std::endl
1119 <<" *** ref: "<<GeoTrf::toString(refTrans, true)<<std::endl
1120 <<" *** test: "<<GeoTrf::toString(testTrans, true));
1121 return StatusCode::FAILURE;
1122 }
1123 const Amg::Vector3D refChannelPos = refEle.globalChannelPosition(gctx, measHash);
1124
1126 const Amg::Transform3D& testPadTrans{testEle.transform(chID)};
1127 Amg::Vector3D testChannelPos(Amg::Vector3D::Zero());
1128 testEle.stripGlobalPosition(chID, testChannelPos);
1129
1130 const std::array<Amg::Vector3D,4> refPadCorners = refEle.globalPadCorners(gctx, measHash);
1131 std::array<Amg::Vector3D,4> testPadCorners{make_array<Amg::Vector3D, 4>(Amg::Vector3D::Zero())};
1132 testEle.padGlobalCorners(chID, testPadCorners);
1133 for (unsigned int cornerIdx = 0; cornerIdx < refPadCorners.size(); ++cornerIdx) {
1134 const double padCornerDiff = (refPadCorners[cornerIdx] - testPadCorners[cornerIdx]).mag();
1135 if (padCornerDiff - 25. > 1. * Gaudi::Units::micrometer){
1136 ATH_MSG_ERROR("Mismatch in pad Corner " << cornerIdx << ": " <<m_idHelperSvc->toString(chID)
1137 <<" ref: "<<Amg::toString(refPadCorners[cornerIdx])<<" test: "<<Amg::toString(testPadCorners[cornerIdx])
1138 <<" difference: " << padCornerDiff
1139 <<" local coordinates -- ref: "<<Amg::toString(refTrans.inverse()*refPadCorners[cornerIdx])
1140 <<" test: "<<Amg::toString(testPadTrans.inverse()*testPadCorners[cornerIdx]));
1141 return StatusCode::FAILURE;
1142 }
1143 }
1144 const double padChannelDiff = (refChannelPos - testChannelPos).mag();
1145 if (padChannelDiff - 25. > 1. * Gaudi::Units::micrometer){
1146 ATH_MSG_ERROR("Mismatch in pad positions "<<m_idHelperSvc->toString(chID)
1147 <<" ref: "<<Amg::toString(refChannelPos)<<" test: "<<Amg::toString(testChannelPos)
1148 <<" difference: " << padChannelDiff
1149 <<" local coordinates -- ref: "<<Amg::toString(refTrans.inverse()*refChannelPos)
1150 <<" test: "<<Amg::toString(testPadTrans.inverse()*testChannelPos));
1151 return StatusCode::FAILURE;
1152 }
1153 ATH_MSG_VERBOSE("Agreement between new and old geometry for channel "<<m_idHelperSvc->toString(chID)
1154 <<" channel position "<<Amg::toString(refChannelPos));
1155 }
1157 Amg::Vector3D testChannelPos{Amg::Vector3D::Zero()};
1158 testEle.stripGlobalPosition(chID, testChannelPos);
1159 if ((refChannelPos - testChannelPos).mag() > 1. * Gaudi::Units::micrometer){
1160 ATH_MSG_ERROR("Mismatch in strip positions "<<m_idHelperSvc->toString(chID)
1161 <<" ref: "<<Amg::toString(refChannelPos)<<" test: "<<Amg::toString(testChannelPos)
1162 <<" local coordinates -- ref: "<<Amg::toString(testTrans.inverse()*refChannelPos)
1163 <<" test: "<<Amg::toString(testTrans.inverse()*testChannelPos));
1164 return StatusCode::FAILURE;
1165 }
1166 ATH_MSG_VERBOSE("Agreement between new and old geometry for channel "<<m_idHelperSvc->toString(chID)
1167 <<" channel position "<<Amg::toString(refChannelPos));
1168 } else { // wire
1169 Amg::Vector3D testChannelPos{Amg::Vector3D::Zero()};
1170 testEle.stripGlobalPosition(chID, testChannelPos);
1171 Amg::Vector3D localRefPos {testTrans.inverse()*refChannelPos};
1172 Amg::Vector3D localTestPos{testTrans.inverse()*testChannelPos};
1174 if((std::abs(localRefPos.x() -localTestPos.x()) > 1.* Gaudi::Units::micrometer)
1175 || (std::abs(refChannelPos.z() -testChannelPos.z()) > 15.* Gaudi::Units::micrometer)){
1176 ATH_MSG_ERROR("Mismatch in wire positions "<<m_idHelperSvc->toString(chID)
1177 <<" ref: "<<Amg::toString(refChannelPos)<<" test: "<<Amg::toString(testChannelPos)
1178 <<" local coordinates -- ref: "<<Amg::toString(testTrans.inverse()*refChannelPos)
1179 <<" test: "<<Amg::toString(testTrans.inverse()*testChannelPos)
1180 <<"delta X: "<<std::abs(localRefPos.x() -localTestPos.x())
1181 <<", delta Z: "<<std::abs(localRefPos.z() -localTestPos.z()));
1182 return StatusCode::FAILURE;
1183 }
1184 }
1185 }
1186 }
1187 }
1188 return StatusCode::SUCCESS;
1189}
1190}
Scalar perp() const
perp method - perpendicular length
Scalar mag() const
mag method
constexpr std::array< T, N > make_array(const T &def_val)
Helper function to initialize in-place arrays with non-zero values.
Definition ArrayHelper.h:10
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
bool isValid(const T &p)
Av: we implement here an ATLAS-sepcific convention: all particles which are 99xxxxx are fine.
Definition AtlasPID.h:878
static Double_t a
GeoModel::TransientConstSharedPtr< AlignmentStore > AlignmentStorePtr
AlignmentStorePtr & getStore(const DetectorType type)
Returns the mutable alignable store for the ATLAS detector type (Pixel, Mdt, etc.)
void setStore(AlignmentStorePtr store)
Adds the store to the Geometry context.
virtual DetectorType detectorType() const =0
Returns the detector element type.
const ServiceHandle< StoreGateSvc > & detStore() const
static EventIDRange infiniteRunLB()
Produces an EventIDRange that is infinite in RunLumi and invalid in Time.
This is a "hash" representation of an Identifier.
Helper struct to cache simulatenously the As-built and the BLine corrections of the Mdts for fast acc...
chamberDistortions getDistortion(const Identifier &detElId) const
Returns a chamber distortion that's cached for the corresponding Mdt chamber element.
Identifier channelID(int stationName, int stationEta, int stationPhi, int multilayer, int gasGap, int channel) const
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].
bool isValid(const IdentifierHash &measHash) const
Checks whether the passed meaurement hash corresponds to a valid tube described by the readout elemen...
double moduleHeight() const
Returns the height of the chamber (Distance bottom - topWidth)
Amg::Transform3D asBuiltRefFrame() const
Returns the transformation to go into the reference frame of the as-buit & b-line model starting from...
Amg::Vector3D globalTubePos(const ActsTrk::GeometryContext &ctx, const Identifier &measId) const
Returns the position of the tube mid point in the ATLAS coordinate frame.
double moduleThickness() const
Returns the thickness of the chamber.
double uncutTubeLength(const IdentifierHash &tubeHash) const
Returns the uncut tube length.
unsigned numTubesInLay() const
Returns the number of tubes in a layer.
const MdtReadoutElement * complementaryRE() const
Returns the pointer to the other readout element inside the muon station.
static IdentifierHash measurementHash(unsigned layerNumber, unsigned tubeNumber)
Constructs a Measurement hash from layer && tube number.
Identifier measurementId(const IdentifierHash &measHash) const override final
Back conversion of the measurement hash towards a full identifier Tube & layer number are extracted f...
Helper struct to retrieve the tube lengths and the tube centers directly from the GeoModel tree.
double uncutHalfLength(const unsigned int tube) const
Returns the uncut-half length of the given tube.
const StripLayer & stripLayer(const Identifier &measId) const
unsigned int nGasGaps() const
Returns the number of gas gaps.
int multilayer() const
Returns the multi layer of the element [1-2].
IdentifierHash layerHash(const Identifier &measId) const override final
The layer hash removes the bits from the IdentifierHash corresponding to the measurement's channel nu...
Amg::Vector3D stripPosition(const ActsTrk::GeometryContext &ctx, const Identifier &measId) const
Returns the position of the strip center.
static IdentifierHash createHash(const int gasGap, const int strip)
MuonReadoutElement is an abstract class representing the geometry of a muon detector.
const Amg::Transform3D & localToGlobalTransform(const ActsTrk::GeometryContext &ctx) const
Returns the transformation from the local coordinate system of the readout element into the global AT...
Amg::Transform3D globalToLocalTransform(const ActsTrk::GeometryContext &ctx) const
Returns the transformation from the global ATLAS coordinate system into the local coordinate system o...
IdentifierHash identHash() const
Returns the hash of the readout element which is identical to the detector element hash provided by t...
Identifier identify() const override final
Return the ATLAS identifier.
const GeoAlignableTransform * alignableTransform() const
Return the alignable transform node of the readout element.
double beamlineRadius() const
Returns the distance between the gasGap center and the beamline.
int numPadPhi() const
Returns the number of pads in the Phi direction in the given gasGap layer.
std::pair< int, int > padNumber(const int SeqChannel) const
Returns the pad (eta,phi) for a given pad number in sequence (1,2,3,...18,19,20......
int numPadEta() const
Returns the number of pads in the eta direction in the given layer.
double sectorAngle() const
Function gives the angular width of the sector.
double padPhiShift() const
Returns the staggering shift of inner pad edges in the phi direction.
int maxPadEta() const
Returns the maximum number of pads that can be contained in a column of a pad. Used to match the pad ...
double firstPadHeight() const
Returns the height of the pads that are adjacent to the bottom edge of the trapezoid active area.
double anglePadPhi() const
Returns the angular pitch of the pads in the phi direction.
double padHeight() const
Returns the height of all the pads that are not adjacent to the bottom edge of the trapezoid active a...
double firstPadPhiDiv() const
Returns the angle of the first pad outer edge w.r.t. the gasGap center from the beamline.
Amg::Vector2D stripLeftTop(int stripNumber) const
: Returns the intersection of the left strip edge at the top panel's edge
Amg::Vector2D stripRightTop(int stripNumber) const
: Returns the intersecetion fo the right strip edge at the top panel's edge
Amg::Vector2D stripRightBottom(int stripNumber) const
: Returns the intersecton of the strip right edge at the bottom panel's edge
Amg::Vector2D stripLeftBottom(int stripNumber) const
: Returns the intersection of the left strip edge at the bottom panel's edge
StatusCode buildStation(const ActsTrk::GeometryContext &gctx, const Identifier &stationId, ConstructionCache &cacheObj) const
builds a station object from readout element.
Gaudi::Property< std::string > m_geoDumpName
StatusCode buildMdt(const ActsTrk::GeometryContext &gctx, ConstructionCache &cacheObj) const
Converts all Mdt readout elements from the R4 format into the legacy Trk format.
StatusCode initialize() override
StatusCode cloneReadoutVolume(const ActsTrk::GeometryContext &gctx, const Identifier &stationId, ConstructionCache &cacheObj, GeoIntrusivePtr< GeoVFullPhysVol > &clonedPhysVol, MuonGM::MuonStation *&station) const
Clones the fullPhysical volume of the readoutElement and embeds it into the associated station.
StatusCode execute(const EventContext &ctx) const override
SG::WriteCondHandleKey< MuonGM::MuonDetectorManager > m_writeKey
Gaudi::Property< bool > m_splitTrfCache
Instantiate a new transform cache to ensure lazy transform population in the event processing.
GeoIntrusivePtr< GeoVFullPhysVol > cloneNswWedge(const ActsTrk::GeometryContext &gctx, const MuonGMR4::MuonReadoutElement &nswRE, ConstructionCache &cacheObj) const
Clones the full phyical volume associated to the NSw readout element.
StatusCode buildRpc(const ActsTrk::GeometryContext &gctx, ConstructionCache &cacheObj) const
Converts all Rpc readout elements from the R4 format into the legacy Trk format.
StatusCode buildTgc(const ActsTrk::GeometryContext &gctx, ConstructionCache &cacheObj) const
Converts all Tgc readout elements from the R4 format into the legacy Trk format.
Gaudi::Property< bool > m_dumpGeo
StatusCode buildSTGC(const ActsTrk::GeometryContext &gctx, ConstructionCache &cacheObj) const
Converts all sTgc readout elements from the R4 format into the legacy Trk format.
StatusCode dumpAndCompare(const ActsTrk::GeometryContext &gctx, const MuonGMR4::RpcReadoutElement &refEle, const MuonGM::RpcReadoutElement &testEle) const
Compares the R4 readout element with the constructed Trk readout element.
StatusCode checkIdCompability(const MuonGMR4::MuonReadoutElement &refEle, const MuonGM::MuonReadoutElement &testEle) const
Checks whether the Identifier fields of both readout elements are identical.
StatusCode buildMM(const ActsTrk::GeometryContext &gctx, ConstructionCache &cacheObj) const
Converts all Mm readout elements from the R4 format into the legacy Trk format.
SG::ReadCondHandleKeyArray< ActsTrk::DetectorAlignStore > m_alignStoreKeys
const MuonGMR4::MuonDetectorManager * m_detMgr
Gaudi::Property< bool > m_checkGeo
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
unsigned nPhiStrips() const
Number of strips measuring the phi coordinate.
int doubletZ() const
Returns the doublet Z field of the MuonReadoutElement identifier.
int doubletPhi() const
Returns the doublet Phi field of the MuonReadoutElement identifier.
int doubletPhiMax() const
Returns the maximum phi panel.
Amg::Vector3D stripPosition(const ActsTrk::GeometryContext &ctx, const Identifier &measId) const
Returns the position of the strip center.
unsigned nGasGaps() const
Returns the number of gasgaps described by this ReadOutElement (usally 2 or 3)
double halfWidth() const
Returns the half height of the strip panel.
double stereoAngle() const
Returns the value of the stereo angle.
int firstStripNumber() const
Returns the number of the first strip.
const Amg::Vector2D & firstStripPos() const
Vector indicating the first strip position.
double yCutout() const
Returns the cutout of the diamond.
double stripPitch() const
Distance between two adjacent strips.
double stripWidth() const
Width of a strip.
double shortHalfHeight() const
Returns the shorter half height of the panel.
double longHalfHeight() const
Returns the longer half height of the panel.
virtual int numStrips() const
Number of strips on the panel.
The StripLayer interfaces the 2D description of the strip plane layout with the 3D description of the...
Definition StripLayer.h:19
const StripDesign & design(bool phiView=false) const
Returns the underlying strip design.
const Amg::Transform3D & toOrigin() const
Returns the transformation to go from the strip layer center to the origin of the Strip chamber.
Amg::Vector3D channelPosition(const ActsTrk::GeometryContext &ctx, const Identifier &measId) const
Returns the center of the measurement channel eta measurement: wire gang center phi measurement: stri...
Identifier measurementId(const IdentifierHash &measHash) const override final
Back conversion of the measurement hash to a full Athena Identifier The behaviour is undefined if a l...
static IdentifierHash constructHash(unsigned measCh, unsigned gasGap, const bool isStrip)
Constructs the Hash out of the Identifier fields (channel, gasGap, isStrip)
const WireGroupDesign & wireGangLayout(const IdentifierHash &layHash) const
Returns access to the wire group design of the given gasGap [1-3] If the gap does not have a wires an...
unsigned numChannels(const IdentifierHash &measHash) const
Returns the number of readout channels.
unsigned nGasGaps() const
Returns the number of gasgaps described by this ReadOutElement (usally 2 or 3)
unsigned int numWiresInGroup(unsigned int groupNum) const
Returns the number of wires in a given group.
unsigned int numPitchesToGroup(unsigned int groupNum) const
Returns the number of wire pitches to reach the given group.
double wireCutout() const
Extract the wireCutout for a wireGroup layer.
unsigned int nAllWires() const
Returns the number of all wires.
unsigned numChannels(const IdentifierHash &measHash) const
Returns the number of strips / wires / pads in a given gasGap.
IdentifierHash measurementHash(const Identifier &measId) const override final
Constructs the identifier hash from the full measurement Identifier.
const PadDesign & padDesign(const IdentifierHash &measHash) const
Retrieves the readoutElement Layer given the Identifier/Hash.
int multilayer() const
Returns the multilayer of the sTgcReadoutElement.
globalCornerArray globalPadCorners(const ActsTrk::GeometryContext &ctx, const IdentifierHash &measHash) const
unsigned numLayers() const
Returns the number of gas gap layers.
IdentifierHash layerHash(const Identifier &measId) const override final
Transforms the Identifier into a layer hash.
ReadoutChannelType
ReadoutChannelType to distinguish the available readout channels Pad - pad readout channel Strip - et...
Amg::Vector3D globalChannelPosition(const ActsTrk::GeometryContext &ctx, const IdentifierHash &measHash) const
Returns the global pad/strip/wireGroup position.
static IdentifierHash createHash(const unsigned gasGap, const unsigned channelType, const unsigned channel, const unsigned wireInGrp=0)
Create a measurement hash from the Identifier fields.
An MMReadoutElement corresponds to a single STGC module; therefore typicaly a barrel muon station con...
bool stripGlobalPosition(const Identifier &id, Amg::Vector3D &gpos) const
std::array< MuonChannelDesign, 4 > m_etaDesign
double getTubeLengthForCaching(const int tubeLayer, const int tube) const
double getActiveTubeLength(const int tubeLayer, const int tube) const
Amg::Vector3D tubePos(const Identifier &id) const
Returns the global position of the given tube.
virtual const Amg::Transform3D & transform(const Identifier &id) const override final
Return local to global transform associated with this identifier.
double tubeLength(const int tubeLayer, const int tube) const
double getWireLength(const int tubeLayer, const int tube) const
virtual const Amg::Transform3D & transform() const override
Return local to global transform.
const MuonReadoutElement * getReadoutElement(const Identifier &id) const
Get any read out element.
void addsTgcReadoutElement(std::unique_ptr< sTgcReadoutElement > &&reEle)
store the sTGCReadoutElement using as "key" the identifier
void addRpcReadoutElement(std::unique_ptr< RpcReadoutElement > &&reEle)
store the RpcReadoutElement using as "key" the identifier
const MuonStation * getMuonStation(const std::string &stName, int eta, int phi) const
void addMdtReadoutElement(std::unique_ptr< MdtReadoutElement > &&reEle)
store the MdtReadoutElement using as "key" the identifier
void addTgcReadoutElement(std::unique_ptr< TgcReadoutElement > &&reEle)
store the TgcReadoutElement using as "key" the identifier
void addMMReadoutElement(std::unique_ptr< MMReadoutElement > &&reEle)
store the MMReadoutElement using as "key" the identifier
Base class for the XxxReadoutElement, with Xxx = Mdt, Rpc, Tgc, Csc.
IdentifierHash detectorElementHash() const
Returns the IdentifierHash of the detector element.
Identifier identify() const override final
Returns the ATLAS Identifier of the MuonReadOutElement.
void setBlineFixedPointInAmdbLRS(double s0, double z0, double t0)
PVConstLink getPhysVol() const
bool hasBLines() const
void setMdtAsBuiltParams(const MdtAsBuiltPar *xtomo)
void setMdtRsize(const double rSize)
int nMuonReadoutElements() const
void addMuonReadoutElementWithAlTransf(MuonReadoutElement *a, GeoAlignableTransform *ptrsf, int jobIndex)
void setMdtZsize(const double zSize)
void setBline(const BLinePar *bline)
bool hasMdtAsBuiltParams() const
An RpcReadoutElement corresponds to a single RPC module; therefore typicaly a barrel muon station con...
int Nstrips(bool measphi) const
returns the number of strips for the phi or eta plane
A TgcReadoutElement corresponds to a single TGC chamber; therefore typically a TGC station contains s...
Amg::Vector3D channelPos(const Identifier &id) const
Returns the position of the active channel (wireGang or strip)
double nPitchesToGang(int gasGap, int gang) const
Returns the number of wire pitches that have to be travelled to reach gang i.
int nWires(int gasGap) const
Returns the total number of wires in a given gas gap.
double wirePitch() const
Returns the pitch of the wires.
An sTgcReadoutElement corresponds to a single STGC module; therefore typicaly a barrel muon station c...
bool stripGlobalPosition(const Identifier &id, Amg::Vector3D &gpos) const
bool padGlobalCorners(const Identifier &id, std::array< Amg::Vector3D, 4 > &gcorners) const
pad global corners
Identifier channelID(int stationName, int stationEta, int stationPhi, int doubletR, int doubletZ, int doubletPhi, int gasGap, int measuresPhi, int strip) const
void addDependency(const EventIDRange &range)
StatusCode record(const EventIDRange &range, T *t)
record handle, with explicit range DEPRECATED
static int stationPhiMax(bool endcap)
Identifier channelID(int stationName, int stationEta, int stationPhi, int gasGap, int isStrip, int channel) const
Identifier padID(int stationName, int stationEta, int stationPhi, int multilayer, int gasGap, int channelType, int padEta, int padPhi) const
Identifier channelID(int stationName, int stationEta, int stationPhi, int multilayer, int gasGap, int channelType, int channel) const
std::string to_string(const DetectorType &type)
DetectorType
Simple enum to Identify the Type of the ACTS sub detector.
@ Mm
Maybe not needed in the migration.
@ sTgc
Micromegas (NSW)
@ Mdt
MuonSpectrometer.
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
bool isIdentity(const Amg::Transform3D &trans)
Checks whether the transformation is the Identity transformation.
bool doesNotDeform(const Amg::Transform3D &trans)
Checks whether the linear part of the transformation rotates or stetches any of the basis vectors.
Amg::Transform3D getRotateZ3D(double angle)
get a rotation transformation around Z-axis
Eigen::Affine3d Transform3D
Amg::Transform3D getTranslateX3D(const double X)
: Returns a shift transformation along the x-axis
Eigen::Matrix< double, 3, 1 > Vector3D
Amg::Transform3D getRotateY3D(double angle)
get a rotation transformation around Y-axis
Amg::Transform3D rotationToAMDB(const ActsTrk::DetectorType type)
Returns the rotation matrix from the readout element coordinate system into the AMDB coordinate syste...
The ReadoutGeomCnvAlg converts the Run4 Readout geometry build from the GeoModelXML into the legacy M...
std::unique_ptr< ActsTrk::DetectorAlignStore > copyDeltas(const ActsTrk::DetectorAlignStore &inStore)
Copy the alignment deltas from the inStore to a new alignment store.
void swap(ElementLinkVector< DOBJ > &lhs, ElementLinkVector< DOBJ > &rhs)
Helper struct to store the pointer to the Mdt distrotion parameters, namely the As-built and the BLin...
Cache object holding the constructed detector manager, and the intermediate GeoModel objects needed t...
std::unique_ptr< MuonGM::MuonDetectorManager > detMgr
Pointer to the legacy MuonDetectorManager.
GeoIntrusivePtr< GeoIdentifierTag > newIdTag()
Returns an identifier tag.
std::set< PVConstLink > translatedStations
Set of all translated Physical volumes.
double stereoAngle() const
returns the stereo angle
void defineTrapezoid(double HalfShortY, double HalfLongY, double HalfHeight)
set the trapezoid dimensions
void setFirstPos(const double pos)
Set the position of the first strip along the x-axis.
Parameters defining the design of the readout sTGC pads.
void setR(double R)
access to cache