ATLAS Offline Software
Loading...
Searching...
No Matches
ReadoutGeomCnvAlg.cxx
Go to the documentation of this file.
1
2/*
3 Copyright (C) 2002-2025 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#include <GaudiKernel/SystemOfUnits.h>
51
52
53namespace {
54 using SubDetAlignment = ActsTrk::GeometryContext::AlignmentStorePtr;
55 bool hasStationVolume(const PVConstLink treeTop,
56 const std::set<PVConstLink>& translated) {
57 const unsigned int nCh = treeTop->getNChildVols();
58 for (unsigned int ch = 0 ; ch < nCh; ++ch) {
59 PVConstLink child = treeTop->getChildVol(ch);
60 if (translated.count(child) ||
61 hasStationVolume(child, translated)){
62 return true;
63 }
64 }
65 return false;
66 };
67}
68
69namespace MuonGMR4{
70
72 ATH_CHECK(m_idHelperSvc.retrieve());
73 ATH_CHECK(m_writeKey.initialize());
74 ATH_CHECK(m_alignStoreKeys.initialize());
75 ATH_CHECK(detStore()->retrieve(m_detMgr));
76 return StatusCode::SUCCESS;
77}
78
79
80StatusCode ReadoutGeomCnvAlg::execute(const EventContext& ctx) const {
81 SG::WriteCondHandle writeHandle{m_writeKey, ctx};
82 if (writeHandle.isValid()) {
83 ATH_MSG_DEBUG("The current readout geometry is still valid.");
84 return StatusCode::SUCCESS;
85 }
88 ActsTrk::GeometryContext geoContext{};
92 if (!readHandle.isValid()) {
93 ATH_MSG_FATAL("Failed to retrieve alignment store "<<key.fullKey());
94 return StatusCode::FAILURE;
95 }
96 writeHandle.addDependency(readHandle);
97 auto alignStore = std::make_unique<ActsTrk::DetectorAlignStore>(**readHandle);
99 if (alignStore->geoModelAlignment) {
100 alignStore->geoModelAlignment->clearPosCache();
101 }
102 alignStore->trackingAlignment = std::make_unique<TrackingAlignment>(alignStore->detType);
103 geoContext.setStore(std::move(alignStore));
104 }
107 std::vector<ActsTrk::DetectorType> presentTechs = m_detMgr->getDetectorTypes();
108 for (const ActsTrk::DetectorType detType : presentTechs) {
109 if (geoContext.getStore(detType)) {
110 continue;
111 }
112 ATH_MSG_WARNING("No external detector alignment has been defined for technology "<<ActsTrk::to_string(detType));
113 geoContext.setStore(std::make_unique<ActsTrk::DetectorAlignStore>(detType));
114 }
116 ConstructionCache cacheObj;
117 cacheObj.detMgr = std::make_unique<MuonGM::MuonDetectorManager>();
118 cacheObj.world = createGeoWorld();
119 cacheObj.detMgr->addTreeTop(cacheObj.world);
121 ATH_CHECK(buildMdt(geoContext, cacheObj));
122 ATH_CHECK(buildTgc(geoContext, cacheObj));
123 ATH_CHECK(buildRpc(geoContext, cacheObj));
124 ATH_CHECK(buildSTGC(geoContext, cacheObj));
125 ATH_CHECK(buildMM(geoContext, cacheObj));
127 std::vector<GeoChildNodeWithTrf> treeTops = getChildrenWithRef(m_detMgr->getTreeTop(0), false);
128
130 for (const GeoChildNodeWithTrf& treeTop : treeTops) {
131 if (hasStationVolume(treeTop.volume, cacheObj.translatedStations)) continue;
132 ATH_MSG_VERBOSE("Detected passive volume "<<treeTop.nodeName);
133
134 cacheObj.world->add(const_pointer_cast(treeTop.volume));
135 }
136
138 if (m_checkGeo) {
139 const std::vector<const MuonGMR4::MuonReadoutElement*> refEles{m_detMgr->getAllReadoutElements()};
140 for (const MuonGMR4::MuonReadoutElement* refEle : refEles) {
141 ATH_CHECK(checkIdCompability(*refEle, *cacheObj.detMgr->getReadoutElement(refEle->identify())));
142 }
143 }
144 if (m_dumpGeo) {
145 ATH_MSG_DEBUG("Save geometry to SqLite file "<<m_geoDumpName);
146 GeoModelIO::IO::saveToDB(cacheObj.world, m_geoDumpName, 0 , true);
147 }
148
149 ATH_CHECK(writeHandle.record(std::move(cacheObj.detMgr)));
150 return StatusCode::SUCCESS;
151}
153 const Identifier& stationId,
154 ConstructionCache& cacheObj) const {
155 const std::string stName{m_idHelperSvc->stationNameString(stationId)};
156 const int stEta{m_idHelperSvc->stationEta(stationId)};
157 const int stPhi{m_idHelperSvc->stationPhi(stationId)};
158 MuonGM::MuonStation* station = cacheObj.detMgr->getMuonStation(stName, stEta, stPhi);
159 if (station) {
160 ATH_MSG_DEBUG("Station "<<stName<<", stEta: "<<stEta<<", stPhi: "<<stPhi<<" already exists.");
161 return StatusCode::SUCCESS;
162 }
164 const MuonGMR4::MuonReadoutElement* copyMe = m_detMgr->getReadoutElement(stationId);
165
167 const GeoVFullPhysVol* readOutVol = copyMe->getMaterialGeom();
168 // This is the physical volume that contains the readOutVol as a child.
169 PVConstLink parentVolume = readOutVol->getParent();
170
171 const GeoAlignableTransform* alignTrf{copyMe->alignableTransform()};
172
174 GeoIntrusivePtr<const GeoGraphNode> alignNode{*(parentVolume->getParent()->findChildNode(alignTrf) + 1)};
176 GeoIntrusivePtr<const GeoTransform> stationShiftNode{alignNode != parentVolume ?
177 dynamic_pointer_cast<const GeoTransform>(alignNode) : nullptr};
178
179 cacheObj.translatedStations.insert(parentVolume);
181 PVLink copiedStationVol{};
182 if (!stationShiftNode) {
183 copiedStationVol = make_intrusive<GeoFullPhysVol>(parentVolume->getLogVol());
184 } else {
185 auto volToCopy = parentVolume->getLogVol();
186 auto newShape = cacheObj.cacheShape(make_intrusive<GeoShapeShift>(volToCopy->getShape(),
187 stationShiftNode->getDefTransform()));
188 auto newLogVol = make_intrusive<GeoLogVol>(volToCopy->getName(), newShape, volToCopy->getMaterial());
189 copiedStationVol = make_intrusive<GeoFullPhysVol>(cacheObj.cacheVolume(newLogVol));
190 }
191
194 const std::vector<GeoChildNodeWithTrf> children = getChildrenWithRef(parentVolume, false); // we get the list of child nodes attached to the parent volume
195 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};
196 for (const GeoChildNodeWithTrf& child : children) {
197 std::vector<Amg::Vector3D> edges = getPolyShapeEdges(child.volume->getLogVol()->getShape(), //we are getting corner points of the edges
198 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
199 for (const Amg::Vector3D& edge : edges) {
200 minX = std::min(minX, edge.x());
201 maxX = std::max(maxX, edge.x());
202 minZ = std::min(minZ, edge.z());
203 maxZ = std::max(maxZ, edge.z());
204 if (edge.z() < 0) {
205 minY1 = std::min(minY1, edge.y());
206 maxY1 = std::max(maxY1, edge.y());
207 } else {
208 minY2 = std::min(minY2, edge.y());
209 maxY2 = std::max(maxY2, edge.y());
210 }
211 }
213 const GeoVPhysVol &childVolRef = *child.volume;
214 if (typeid(childVolRef) == typeid(GeoFullPhysVol)) {
215 continue;
216 }
217 // Add the beam lines / foams inside the station volume
218 PVLink childVol = const_pointer_cast<GeoVPhysVol>(child.volume);
219 copiedStationVol->add(cacheObj.newIdTag());
220 if (stationShiftNode) {
221 copiedStationVol->add(const_pointer_cast(stationShiftNode));
222 }
223 copiedStationVol->add(cacheObj.makeTransform(child.transform));
224 copiedStationVol->add(cloneVolume(childVol));
225 }
226
229 const double shortS = (maxY1 - minY1);
230 const double longS = (maxY2 - minY2);
231 const double lengthR = (maxX - minX);
232 const double lengthZ = (maxZ - minZ);
233
235 const Amg::Transform3D alignedTransform = copyMe->localToGlobalTrans(gctx) *
236 ( ( stationShiftNode ? stationShiftNode->getDefTransform() : Amg::Transform3D::Identity())
237 * readOutVol->getDefX()).inverse();
238
239
240 auto newStation = std::make_unique<MuonGM::MuonStation>(stName,
241 shortS, lengthR, lengthZ,
242 longS, lengthR, lengthZ,
243 stEta, stPhi, false);
244 newStation->setPhysVol(copiedStationVol);
246 cacheObj.world->add(cacheObj.newIdTag());
247 auto copyAlignNode = make_intrusive<GeoAlignableTransform>(alignedTransform);
248 newStation->setTransform(copyAlignNode);
249 newStation->setNominalAmdbLRSToGlobal(copyAlignNode->getTransform());
250
251 ATH_MSG_VERBOSE("stName: "<<stName<<", stEta: "<<stEta<<", stPhi: "<<stPhi
252 <<" -- shortS: "<<shortS<<", longS: "<<longS
253 <<", lengthR: "<<lengthR<<", lengthZ: "<<lengthZ
254 <<std::endl<<"AlignableNode: "<<GeoTrf::toString(alignedTransform, true)
255 <<std::endl<<"Station shift: "<<GeoTrf::toString(stationShiftNode ? stationShiftNode->getDefTransform()
256 : Amg::Transform3D::Identity(), true)
257 <<std::endl<<"AmdLRSToGlobal: "<<GeoTrf::toString(newStation->getNominalAmdbLRSToGlobal(), true)
258 <<std::endl<<"Readout transform: "<<GeoTrf::toString(readOutVol->getX(), true));
259 cacheObj.detMgr->addMuonStation(std::move(newStation));
260 cacheObj.world->add(copyAlignNode);
261 cacheObj.world->add(copiedStationVol);
262 return StatusCode::SUCCESS;
263}
264
265
267 const Identifier& reId,
268 ConstructionCache& cacheObj,
269 GeoIntrusivePtr<GeoVFullPhysVol>& physVol,
270 MuonGM::MuonStation* & station) const {
271
272 ATH_CHECK(buildStation(gctx, reId, cacheObj));
273 const std::string stName{m_idHelperSvc->stationNameString(reId)};
274 station = cacheObj.detMgr->getMuonStation(stName,
275 m_idHelperSvc->stationEta(reId),
276 m_idHelperSvc->stationPhi(reId));
277
278 PVLink copiedStationVol{station->getPhysVol()};
279 const MuonGMR4::MuonReadoutElement* copyMe = m_detMgr->getReadoutElement(reId);
280 GeoIntrusivePtr<const GeoVFullPhysVol> readOutVol{copyMe->getMaterialGeom()};
281 copiedStationVol->add(cacheObj.newIdTag());
292 const Amg::Transform3D alignNodeToRE{copyMe->alignableTransform()->getDefTransform().inverse() *
293 readOutVol->getParent()->getX() * readOutVol->getX()};
294 const Amg::Transform3D alignedNode{copyMe->localToGlobalTrans(gctx) * alignNodeToRE.inverse()};
295
296 const Amg::Transform3D stationTrf{copiedStationVol->getX().inverse() * alignedNode};
297
298 copiedStationVol->add(cacheObj.makeTransform(stationTrf*alignNodeToRE));
300 PVLink clonedVol{cloneVolume(const_pointer_cast<GeoVFullPhysVol>(readOutVol))};
301 physVol = dynamic_pointer_cast<GeoVFullPhysVol>(clonedVol);
302 copiedStationVol->add(physVol);
303 return StatusCode::SUCCESS;
304}
305
307
308 const std::vector<const MuonGMR4::RpcReadoutElement*> readoutEles = m_detMgr->getAllRpcReadoutElements();
309 ATH_MSG_INFO("Copy "<<readoutEles.size()<<" Rpc readout elements to the legacy system");
310 const RpcIdHelper& idHelper{m_idHelperSvc->rpcIdHelper()};
311 for (const MuonGMR4::RpcReadoutElement* copyMe : readoutEles) {
312 const Identifier reId = copyMe->identify();
313 const MuonGMR4::RpcReadoutElement::parameterBook& pars{copyMe->getParameters()};
314 GeoIntrusivePtr<GeoVFullPhysVol> physVol{};
315 MuonGM::MuonStation* station{nullptr};
316 ATH_CHECK(cloneReadoutVolume(gctx, reId, cacheObj, physVol, station));
317 auto newElement = std::make_unique<MuonGM::RpcReadoutElement>(physVol,
318 m_idHelperSvc->stationNameString(reId),
319 1, 1, false, cacheObj.detMgr.get());
320 newElement->setDoubletPhi(copyMe->doubletPhi());
321 newElement->setDoubletR(copyMe->doubletR());
322 newElement->setDoubletZ(copyMe->doubletZ());
323 newElement->setIdentifier(reId);
324 newElement->setParentMuonStation(station);
325 station->addMuonReadoutElementWithAlTransf(newElement.get(), nullptr, station->nMuonReadoutElements());
326
328 newElement->setLongZsize(2.*pars.halfLength);
329 newElement->setLongSsize(2.*pars.halfWidth);
330 newElement->setLongRsize(2.*pars.halfThickness);
331 newElement->setZsize(2.*pars.halfLength);
332 newElement->setSsize(2.*pars.halfWidth);
333 newElement->setRsize(2.*pars.halfThickness);
334
335 newElement->m_nlayers = copyMe->nGasGaps();
336 newElement->m_phistripwidth = copyMe->stripPhiWidth();
337 newElement->m_etastripwidth = copyMe->stripEtaWidth();
338 newElement->m_phistrippitch = copyMe->stripPhiPitch();
339 newElement->m_etastrippitch = Acts::copySign(1., copyMe->stationEta() -
340 (copyMe->stationEta()==0))*copyMe->stripEtaPitch();
341 newElement->m_phistriplength = copyMe->stripPhiLength();
342 newElement->m_etastriplength = copyMe->stripEtaLength();
343
344 newElement->m_nphistripsperpanel = copyMe->nPhiStrips();
345 newElement->m_netastripsperpanel = copyMe->nEtaStrips();
346 newElement->m_nphistrippanels = copyMe->nPhiPanels();
347 newElement->m_hasDEDontop = true;
348 newElement->m_descratzneg = false;
349
350 std::vector<Identifier> gapIds{};
351 for (unsigned int gasGap = 1; gasGap <= copyMe->nGasGaps(); ++gasGap) {
352 for (int doubPhi = copyMe->doubletPhiMax(); doubPhi >= copyMe->doubletPhi(); --doubPhi) {
353 for (bool measPhi : {false, true}) {
354 if (measPhi && copyMe->nPhiStrips()==0) continue;
355 const int channel = 1;
356 const Identifier gapId = idHelper.channelID(copyMe->identify(),
357 copyMe->doubletZ(),
358 doubPhi, gasGap, measPhi,
359 channel);
360
361 gapIds.push_back(gapId);
362 const Amg::Vector3D locStripPos = copyMe->globalToLocalTrans(gctx) * copyMe->stripPosition(gctx, gapId);
363 ATH_MSG_VERBOSE("GasGap "<<m_idHelperSvc->toString(gapId)<<", local strip position: "<<Amg::toString(locStripPos));
364 newElement->m_gasGap_xPos[gasGap -1] = locStripPos.x();
367 const int dbPIdx = copyMe->doubletPhi() == 2 ? 1 : doubPhi;
368 if (measPhi) {
369 newElement->m_first_phistrip_s[dbPIdx -1] = locStripPos.y();
370 newElement->m_phistrip_z = locStripPos.z();
371 } else{
372 newElement->m_first_etastrip_z = locStripPos.z();
373 newElement->m_etastrip_s[dbPIdx-1] = locStripPos.y();
374 }
375 }
376 }
377 }
378 newElement->fillCache();
380 for (const Identifier& gapId : gapIds) {
381 const int surfaceHash = newElement->surfaceHash(gapId);
382 const int layerHash = newElement->layerHash(gapId);
383 const Amg::Transform3D refTrf{copyMe->localToGlobalTrans(gctx, gapId)*
384 (m_idHelperSvc->measuresPhi(gapId) ?
385 Amg::getRotateZ3D(90*Gaudi::Units::deg) :
386 Amg::Transform3D::Identity())};
387 ATH_MSG_VERBOSE("Assign transform: "<<m_idHelperSvc->toString(gapId)<<", "<<Amg::toString(refTrf));
388 newElement->m_surfaceData->m_layerTransforms[surfaceHash] = refTrf;
389 newElement->m_surfaceData->m_layerCenters[layerHash] = refTrf.translation();
390 newElement->m_surfaceData->m_layerNormals[layerHash] = refTrf.linear() * Amg::Vector3D::UnitZ();
391 }
392 ATH_CHECK(dumpAndCompare(gctx, *copyMe, *newElement));
393 cacheObj.detMgr->addRpcReadoutElement(std::move(newElement));
394 }
395 return StatusCode::SUCCESS;
396}
397
398
400
401 std::vector<const MuonGMR4::TgcReadoutElement*> tgcReadouts{m_detMgr->getAllTgcReadoutElements()};
402 std::ranges::stable_sort(tgcReadouts,[](const MuonGMR4::TgcReadoutElement* a, const MuonGMR4::TgcReadoutElement* b){
403 return a->stationEta() > b->stationEta();
404 });
405 ATH_MSG_INFO("Copy "<<tgcReadouts.size()<<" Tgc readout elements to the legacy system");
406 const TgcIdHelper& idHelper{m_idHelperSvc->tgcIdHelper()};
407
408 using TgcReadoutParams = MuonGM::TgcReadoutParams;
409 std::map<std::string, std::shared_ptr<TgcReadoutParams>> readoutParMap{};
410
411 for (const MuonGMR4::TgcReadoutElement* copyMe: tgcReadouts) {
412 const Identifier reId = copyMe->identify();
413 GeoIntrusivePtr<GeoVFullPhysVol> physVol{};
414 MuonGM::MuonStation* station{nullptr};
415 ATH_CHECK(cloneReadoutVolume(gctx,reId, cacheObj, physVol, station));
416
417 auto newRE = std::make_unique<MuonGM::TgcReadoutElement>(physVol, m_idHelperSvc->stationNameString(reId),
418 cacheObj.detMgr.get());
419 newRE->setIdentifier(reId);
420 newRE->setParentMuonStation(station);
421 ATH_MSG_DEBUG("Readout element "<<m_idHelperSvc->toString(reId)<<", design: "<<copyMe->chamberDesign());
422 std::shared_ptr<TgcReadoutParams>& readOutPars = readoutParMap[std::format("{:}_{:}", copyMe->chamberDesign(),
423 copyMe->stationEta()> 0? 'A' : 'C')];
424 if (!readOutPars) {
425 using WiregangArray = TgcReadoutParams::WiregangArray;
426 using StripArray = TgcReadoutParams::StripArray;
427 using GasGapIntArray = TgcReadoutParams::GasGapIntArray;
428
429 std::array<WiregangArray, 3> wires{};
430 GasGapIntArray nWireGangs{}, nStrips{};
431 std::vector<StripArray> botMountings(copyMe->nGasGaps()),
432 topMountings(copyMe->nGasGaps());
433
434 double wirePitch{0.};
435 for (unsigned int gasGap =1; gasGap <= copyMe->nGasGaps(); ++gasGap) {
436 const IdentifierHash gangHash = copyMe->constructHash(0, gasGap, false);
437 const IdentifierHash stripHash = copyMe->constructHash(0, gasGap, true);
438 nWireGangs[gasGap -1] = copyMe->numWireGangs(gangHash);
439 nStrips[gasGap -1] = copyMe->numStrips(stripHash);
440 ATH_MSG_VERBOSE("Assigned wire gangs: "<<nWireGangs[gasGap-1]<<", strips: "<<nStrips[gasGap -1]
441 <<" for gas gap "<<gasGap);
442
443 if (nWireGangs[gasGap -1]) {
444 const MuonGMR4::WireGroupDesign& design{copyMe->wireGangLayout(gangHash)};
445 wirePitch = design.stripPitch();
446 WiregangArray& fillMe{wires[gasGap-1]};
447 for (int gang = 1; gang <= design.numStrips(); ++gang) {
448 fillMe[gang -1] = design.numWiresInGroup(gang);
449 }
450 ATH_MSG_VERBOSE("Gang layout: "<<fillMe);
451 }
452 if (nStrips[gasGap -1]) {
453 const MuonGMR4::RadialStripDesign& design{copyMe->stripLayout(stripHash)};
454 const int nCh = nStrips[gasGap -1];
455 for (int strip = 1; strip <= nCh; ++strip) {
456 botMountings[gasGap-1][strip-1] = - design.stripLeftBottom(strip).x();
457 topMountings[gasGap-1][strip-1] = - design.stripLeftTop(strip).x();
458 }
459 botMountings[gasGap-1][nCh] = - design.stripRightBottom(nCh).x();
460 topMountings[gasGap-1][nCh] = - design.stripRightTop(nCh).x();
461 ATH_MSG_VERBOSE("Strip layout\n bottom: "<<botMountings<<"\n top: "<<topMountings);
462 }
463 }
464 readOutPars = std::make_unique<TgcReadoutParams>(copyMe->chamberDesign(),
465 0, wirePitch,
466 idHelper.stationPhiMax(reId),
467 std::move(nWireGangs),
468 std::move(wires[0]),
469 std::move(wires[1]),
470 std::move(wires[2]),
471 0,
472 std::move(botMountings),
473 std::move(topMountings),
474 std::move(nStrips));
475 }
476
478 for (unsigned int gasGap = 1; gasGap <= copyMe->nGasGaps(); ++gasGap) {
479 const IdentifierHash layHash{copyMe->constructHash(0, gasGap, false)};
481 const Amg::Vector3D translation{copyMe->globalToLocalTrans(gctx) * copyMe->center(gctx, layHash)};
482 newRE->setPlaneZ(translation.x(), gasGap);
483 }
484 newRE->setRsize(copyMe->moduleHeight());
485 newRE->setSsize(copyMe->moduleWidthS());
486 newRE->setZsize(copyMe->moduleThickness());
487
488 newRE->setLongRsize(copyMe->moduleHeight());
489 newRE->setLongSsize(copyMe->moduleWidthL());
490 newRE->setLongZsize(copyMe->moduleThickness());
491
492 newRE->setReadOutParams(readOutPars);
493 newRE->fillCache();
494 ATH_CHECK(dumpAndCompare(gctx, *copyMe, *newRE));
495 cacheObj.detMgr->addTgcReadoutElement(std::move(newRE));
496
497 }
498 return StatusCode::SUCCESS;
499}
500
501GeoIntrusivePtr<GeoVFullPhysVol>
503 const MuonGMR4::MuonReadoutElement* copyMe,
504 ConstructionCache& cacheObj) const {
505 GeoIntrusivePtr<const GeoVFullPhysVol> readOutVol{copyMe->getMaterialGeom()};
506 cacheObj.translatedStations.insert(readOutVol->getParent());
507
508 PVLink clonedVol{cloneVolume(const_pointer_cast<GeoVFullPhysVol>(readOutVol))};
509 GeoIntrusivePtr<GeoFullPhysVol> physVol{dynamic_pointer_cast<GeoFullPhysVol>(clonedVol)};
510 cacheObj.world->add(cacheObj.newIdTag());
511 cacheObj.world->add(cacheObj.makeTransform(copyMe->localToGlobalTrans(gctx)));
512 cacheObj.world->add(physVol);
513 return physVol;
514}
516
517 SubDetAlignment alignItr = gctx.getStore(ActsTrk::DetectorType::Mm);
518 const auto alignStore = alignItr ?
519 static_cast<const MmAlignmentStore*>(alignItr->internalAlignment.get()) : nullptr;
520
521 if (alignStore) {
522 cacheObj.detMgr->setMMPassivation(alignStore->passivation);
523 }
524 const std::vector<const MuonGMR4::MmReadoutElement*> mmReadouts{m_detMgr->getAllMmReadoutElements()};
525 ATH_MSG_INFO("Copy "<<mmReadouts.size()<<" Mm readout elements to the legacy system");
526
527 for (const MuonGMR4::MmReadoutElement* copyMe : mmReadouts) {
528 const Identifier reId = copyMe->identify();
529 GeoIntrusivePtr<GeoVFullPhysVol> physVol{cloneNswWedge(gctx, copyMe, cacheObj)};
530 auto newRE = std::make_unique<MuonGM::MMReadoutElement>(physVol,
531 m_idHelperSvc->stationNameString(reId),
532 copyMe->stationEta(),
533 copyMe->stationPhi(),
534 copyMe->multilayer(), cacheObj.detMgr.get());
536 for (unsigned int gasGap = 0; gasGap < copyMe->nGasGaps(); ++gasGap) {
537 const MuonGMR4::StripLayer& stripLayer{copyMe->stripLayer(MuonGMR4::MmReadoutElement::createHash(gasGap +1, 0))};
538 const MuonGMR4::StripDesign& designFrom{stripLayer.design()};
539
540 newRE->m_Xlg[gasGap] = stripLayer.toOrigin() *
541 Amg::getRotateZ3D(-designFrom.stereoAngle()) *
542 Amg::getRotateY3D(90. * Gaudi::Units::deg);
543 ATH_MSG_VERBOSE("Layer transform "<<gasGap<<" "<<GeoTrf::toString(newRE->m_Xlg[gasGap], true));
544
545 MuonGM::MuonChannelDesign& designTo{newRE->m_etaDesign[gasGap]};
546 designTo.defineTrapezoid(designFrom.shortHalfHeight(),
547 designFrom.longHalfHeight(),
548 designFrom.halfWidth(),
549 designFrom.stereoAngle());
552 designTo.inputPitch = designFrom.stripPitch();
553 designTo.inputWidth = designTo.inputPitch * std::cos(designTo.stereoAngle());
554 designTo.nMissedBottomEta = designTo.nMissedBottomStereo = designFrom.firstStripNumber() - 1;
555 designTo.totalStrips = designFrom.numStrips();
556 designTo.nch = designFrom.numStrips();
557
558 designTo.setFirstPos(designFrom.firstStripPos().x() + 0.5*designTo.inputPitch);
559 }
560
561 newRE->fillCache();
562 if (alignStore && alignStore->getBLine(reId)) {
563 newRE->setBLinePar(*alignStore->getBLine(reId));
564 }
565 ATH_CHECK(dumpAndCompare(gctx, *copyMe, *newRE));
566 cacheObj.detMgr->addMMReadoutElement(std::move(newRE));
567 }
568 return StatusCode::SUCCESS;
569}
570
572 SubDetAlignment alignItr = gctx.getStore(ActsTrk::DetectorType::sTgc);
573 auto alignStore = alignItr ? static_cast<const sTgcAlignmentStore*>(alignItr->internalAlignment.get()) : nullptr;
574
575 const std::vector<const MuonGMR4::sTgcReadoutElement*> sTgcReadOuts{m_detMgr->getAllsTgcReadoutElements()};
576 ATH_MSG_INFO("Copy "<<sTgcReadOuts.size()<<" sTgc readout elements to the legacy system");
577
578 for (const MuonGMR4::sTgcReadoutElement* copyMe : sTgcReadOuts) {
579 const Identifier reId = copyMe->identify();
580 ATH_MSG_DEBUG("Translate readout element "<<m_idHelperSvc->toStringDetEl(reId)<<".");
581 GeoIntrusivePtr<GeoVFullPhysVol> physVol{cloneNswWedge(gctx, copyMe, cacheObj)};
582
583 auto newRE = std::make_unique<MuonGM::sTgcReadoutElement>(physVol,
584 m_idHelperSvc->stationNameString(reId).substr(1),
585 copyMe->stationEta(),
586 copyMe->stationPhi(),
587 copyMe->multilayer(),
588 cacheObj.detMgr.get());
589
590 if (alignStore && alignStore->getBLine(reId)) {
591 newRE->setBLinePar(*alignStore->getBLine(reId));
592 }
593 for (unsigned int layer = 1; layer <= copyMe->numLayers(); ++layer) {
595 using ChannelDesign = MuonGM::MuonChannelDesign;
596 const IdentifierHash layerHash = MuonGMR4::sTgcReadoutElement::createHash(layer,channelType::Strip,0);
597
598 const MuonGMR4::StripLayer& stripLayer{copyMe->stripLayer(layerHash)};
599 newRE->m_Xlg[layer -1] = stripLayer.toOrigin() * Amg::getRotateY3D(90. * Gaudi::Units::deg) * Amg::getTranslateX3D( layer%2 ? - 0.01 : 0.01 );
600
601 const MuonGMR4::StripDesign& copyEtaDesign{stripLayer.design()};
602 ATH_MSG_VERBOSE("Layer: "<<layer<<" "<<copyEtaDesign);
604 ChannelDesign& etaDesign{newRE->m_etaDesign[layer-1]};
605 etaDesign.type = ChannelDesign::ChannelType::etaStrip;
606 etaDesign.detType = ChannelDesign::DetType::STGC;
607 if (copyEtaDesign.yCutout()) {
608 etaDesign.defineDiamond(copyEtaDesign.shortHalfHeight(),
609 copyEtaDesign.longHalfHeight(),
610 copyEtaDesign.halfWidth(),
611 copyEtaDesign.yCutout());
612 } else {
613 etaDesign.defineTrapezoid(copyEtaDesign.shortHalfHeight(),
614 copyEtaDesign.longHalfHeight(),
615 copyEtaDesign.halfWidth());
616
617 }
618 etaDesign.firstPitch = copyEtaDesign.firstStripPos().x() + 0.5*copyEtaDesign.stripPitch() + copyEtaDesign.halfWidth();
619 etaDesign.inputPitch = copyEtaDesign.stripPitch();
620 etaDesign.inputWidth = copyEtaDesign.stripWidth();
621 etaDesign.nch = copyEtaDesign.numStrips();
622 ATH_MSG_VERBOSE(m_idHelperSvc->toStringDetEl(copyMe->identify())<<", layer: "<<layer<<", eta-design: "<< copyEtaDesign);
623 etaDesign.setFirstPos(copyEtaDesign.firstStripPos().x() + 0.5*copyEtaDesign.stripPitch());
625
626 const MuonGMR4::WireGroupDesign& copyPhiDesign{copyMe->wireDesign(layerHash)};
627
628 ChannelDesign& phiDesign{newRE->m_phiDesign[layer-1]};
629 phiDesign.type = ChannelDesign::ChannelType::phiStrip;
630 phiDesign.detType = ChannelDesign::DetType::STGC;
631 if (copyPhiDesign.yCutout() == 0.) {
632 phiDesign.defineTrapezoid(copyPhiDesign.shortHalfHeight(),
633 copyPhiDesign.longHalfHeight(),
634 copyPhiDesign.halfWidth());
635 } else {
636 phiDesign.defineDiamond(copyPhiDesign.shortHalfHeight(),
637 copyPhiDesign.longHalfHeight(),
638 copyPhiDesign.halfWidth(),
639 copyPhiDesign.yCutout());
640 }
641 phiDesign.inputPitch = copyPhiDesign.stripPitch();
642 phiDesign.inputWidth = copyPhiDesign.stripWidth();
643 ATH_MSG_VERBOSE(m_idHelperSvc->toStringDetEl(copyMe->identify())<<", layer: "<<layer<<", phi-design: "<< copyPhiDesign);
644 phiDesign.setFirstPos(copyPhiDesign.firstStripPos().x()); // Position of 1st wire, accounts for staggering
645 phiDesign.firstPitch = copyPhiDesign.numWiresInGroup(1); // Number of Wires in 1st group, group staggering
646 phiDesign.groupWidth = copyPhiDesign.numWiresInGroup(2); // Number of Wires normal group
647 phiDesign.nGroups = copyPhiDesign.numStrips(); // Number of Wire Groups
648 phiDesign.wireCutout = copyPhiDesign.wireCutout(); // Size of "active" wire region for digits
649 phiDesign.nch = copyPhiDesign.nAllWires();
650 phiDesign.isConvertedFromPhaseII = true;
651
652 const MuonGMR4::PadDesign& copyPadDesign{copyMe->padDesign(layerHash)};
653 MuonGM::MuonPadDesign& padDesign{newRE->m_padDesign[layer-1]};
654 padDesign.Length = copyMe->chamberHeight();
655 padDesign.sWidth = copyMe->sChamberLength();
656 padDesign.lWidth = copyMe->lChamberLength();
657 padDesign.Size = 2.*copyPadDesign.halfWidth();
658 padDesign.ysFrame = copyMe->sFrameWidth();
659 padDesign.ylFrame = copyMe->lFrameWidth();
660 padDesign.thickness = copyMe->thickness();
662 if (copyPadDesign.yCutout()) {
663 padDesign.yCutout = copyPadDesign.halfWidth();
664 }
665 padDesign.setR(copyPadDesign.beamlineRadius());
666 padDesign.sPadWidth = 2.*copyPadDesign.shortHalfHeight();
667 padDesign.lPadWidth = 2.*copyPadDesign.longHalfHeight();
668 padDesign.nPadColumns = copyPadDesign.numPadPhi();
669 padDesign.firstPhiPos = copyPadDesign.firstPadPhiDiv();
670 padDesign.inputPhiPitch = copyPadDesign.anglePadPhi();
671 padDesign.PadPhiShift = copyPadDesign.padPhiShift();
672 padDesign.nPadH = copyPadDesign.numPadEta();
673 padDesign.padEtaMax = copyPadDesign.maxPadEta();
674 padDesign.firstRowPos = copyPadDesign.firstPadHeight();
675 padDesign.inputRowPitch = copyPadDesign.padHeight();
676 padDesign.sectorOpeningAngle = copyPadDesign.sectorAngle();
677 padDesign.isConvertedFromPhaseII = true;
678 }
679 newRE->fillCache();
680 ATH_CHECK(dumpAndCompare(gctx, *copyMe, *newRE));
681 cacheObj.detMgr->addsTgcReadoutElement(std::move(newRE));
682
683 }
684 return StatusCode::SUCCESS;
685}
688 SubDetAlignment alignItr = gctx.getStore(ActsTrk::DetectorType::Mdt);
689 const MdtAlignmentStore* alignStore = alignItr ?
690 static_cast<const MdtAlignmentStore*>(alignItr->internalAlignment.get()) : nullptr;
691
692 const std::vector<const MuonGMR4::MdtReadoutElement*> mdtReadOuts{m_detMgr->getAllMdtReadoutElements()};
693 ATH_MSG_INFO("Copy "<<mdtReadOuts.size()<<" Mdt readout elements to the legacy system");
694 for (const MuonGMR4::MdtReadoutElement* copyMe : mdtReadOuts) {
695 const Identifier reId = copyMe->identify();
696 ATH_MSG_DEBUG("Translate "<<m_idHelperSvc->toStringDetEl(reId));
698 GeoIntrusivePtr<GeoVFullPhysVol> physVol{};
699 MuonGM::MuonStation* station{nullptr};
700 ATH_CHECK(cloneReadoutVolume(gctx,reId, cacheObj, physVol, station));
701 if (copyMe->multilayer() == 1) {
702 const MuonGMR4::MdtReadoutElement* otherRE = copyMe->complementaryRE();
703 const double height = std::max(copyMe->moduleHeight(), otherRE->moduleHeight()) -
704 (copyMe->tubePitch() - 2. * copyMe->tubeRadius());
705
706 const double modHalTHickO{0.5*otherRE->moduleThickness()},
707 modHalfThick{-0.5*copyMe->moduleThickness()};
708
709 const double thickness = ( (otherRE->asBuiltRefFrame()*(modHalTHickO* Amg::Vector3D::UnitX())) -
710 (copyMe->asBuiltRefFrame()*(modHalfThick* Amg::Vector3D::UnitX()))).z();
711 if (copyMe->isBarrel()) {
712 station->setMdtZsize(height);
713 station->setMdtRsize(thickness);
714 } else {
715 station->setMdtRsize(height);
716 station->setMdtZsize(thickness);
717 }
718 }
719 const MuonGMR4::MdtReadoutElement::parameterBook& pars{copyMe->getParameters()};
720 auto newElement = std::make_unique<MuonGM::MdtReadoutElement>(physVol,
721 m_idHelperSvc->stationNameString(reId),
722 cacheObj.detMgr.get());
723 newElement->setIdentifier(reId);
724 newElement->setMultilayer(copyMe->multilayer());
725 newElement->setNMdtInStation(m_idHelperSvc->mdtIdHelper().multilayerMax(reId));
726 // cppcheck-suppress invalidLifetime; ok: mgr took ownership.
727 newElement->setParentMuonStation(station);
728
730 newElement->setLongSsize(2*pars.longHalfX - 1.*Gaudi::Units::cm);
731 newElement->setSsize(2*pars.shortHalfX - 1.*Gaudi::Units::cm);
732 newElement->setLongRsize(2*pars.halfY);
733 newElement->setRsize(2*pars.halfY);
734 newElement->setZsize(2*pars.halfHeight);
735 newElement->setLongZsize(2*pars.halfHeight);
736
737 newElement->m_nlayers = copyMe->numLayers();
738 newElement->m_ntubesperlayer = copyMe->numTubesInLay();
739 newElement->m_deadlength = pars.deadLength;
740 newElement->m_endpluglength = pars.endPlugLength;
741 newElement->m_innerRadius = pars.tubeInnerRad;
742 newElement->m_tubeWallThickness = pars.tubeWall;
743 newElement->m_tubepitch = pars.tubePitch;
746
748 const MuonGMR4::MdtTubeLayer& tubeLay{*pars.tubeLayers[0]};
749 unsigned int step{1};
750 double lastLength{2.*tubeLay.uncutHalfLength(1)};
751 for (unsigned tube = 0; tube < copyMe->numTubesInLay(); ++tube) {
752 const double currLength = 2.*tubeLay.uncutHalfLength(tube);
753 ATH_MSG_VERBOSE(m_idHelperSvc->toString(copyMe->identify())<< ", tube "<<tube<<", length: "<<currLength);
754 if (std::abs(lastLength - currLength) > std::numeric_limits<float>::epsilon() ||
755 tube == copyMe->numTubesInLay() -1) {
756 newElement->m_tubelength[step-1] = lastLength;
757 newElement->m_tubelength[step] = currLength;
758 if (step == 1) {
759 newElement->m_ntubesinastep = tube;
760 }
761 lastLength = currLength;
762 ++step;
763 }
764 }
765 newElement->m_nsteps = step;
766
768 double xOffSet{pars.halfY}, yOffSet{pars.halfHeight};
769 if (newElement->barrel()) std::swap(xOffSet, yOffSet);
770 for (unsigned lay = 1; lay <= copyMe->numLayers(); ++lay) {
771 const IdentifierHash tubeHash{copyMe->measurementHash(lay, 1)};
772 const Amg::Vector3D locTube = copyMe->localTubePos(tubeHash);
773 newElement->m_firstwire_x[lay-1] = locTube.z() + xOffSet;
774 newElement->m_firstwire_y[lay-1] = locTube.x() + yOffSet;
775 }
776 MdtAlignmentStore::chamberDistortions distort = alignStore ? alignStore->getDistortion(reId) :
778
779 if (!station->hasMdtAsBuiltParams()){
780 station->setMdtAsBuiltParams(distort.asBuilt);
781 }
782 if (!station->hasBLines()){
783 station->setBline(distort.bLine);
784 }
785 const Amg::Vector3D refPoint = copyMe->bLineReferencePoint();
786 station->setBlineFixedPointInAmdbLRS(refPoint.x(), refPoint.y(), refPoint.z());
787
788 newElement->geoInitDone();
789 newElement->setBLinePar(distort.bLine);
790 newElement->fillCache();
791 ATH_CHECK(dumpAndCompare(gctx, *copyMe, *newElement));
793 cacheObj.detMgr->addMdtReadoutElement(std::move(newElement));
794 }
795 return StatusCode::SUCCESS;
796}
797
799 const MuonGM::MuonReadoutElement& testEle) const{
800
801 if (refEle.identify() != testEle.identify()) {
802 ATH_MSG_FATAL("Two different elements are compared "
803 <<m_idHelperSvc->toString(refEle.identify())<<" vs. "
804 <<m_idHelperSvc->toString(testEle.identify()));
805 return StatusCode::FAILURE;
806 }
807 if (refEle.identHash() != testEle.detectorElementHash()) {
808 ATH_MSG_FATAL("The hashes of the two detector elements "<<m_idHelperSvc->toString(refEle.identify())
809 <<" are completely different "<<refEle.identHash()<<" vs. "<<testEle.detectorElementHash());
810 return StatusCode::FAILURE;
811 }
812 return StatusCode::SUCCESS;
813}
814
816 const MuonGMR4::MmReadoutElement& refEle,
817 const MuonGM::MMReadoutElement& testEle) const {
818
819 if (!m_checkGeo) {
820 return StatusCode::SUCCESS;
821 }
822 ATH_CHECK(checkIdCompability(refEle, testEle));
823
824 ATH_MSG_VERBOSE("Compare basic readout transforms"<<std::endl
825 <<GeoTrf::toString(testEle.absTransform(),true)<<std::endl
826 <<GeoTrf::toString(refEle.localToGlobalTrans(gctx), true));
827 const MmIdHelper& idHelper{m_idHelperSvc->mmIdHelper()};
828 for (unsigned int gasGap = 1; gasGap <= refEle.nGasGaps(); ++ gasGap) {
829 const Identifier gapId = idHelper.channelID(refEle.identify(), refEle.multilayer(), gasGap, 1);
830
831 const Amg::Transform3D& refTrf{refEle.localToGlobalTrans(gctx, gapId)};
832 const Amg::Transform3D& testTrf{testEle.transform(gapId)};
833 if (!Amg::isIdentity(refTrf.inverse()*testTrf)) {
834 ATH_MSG_FATAL("The layer "<<m_idHelperSvc->toStringGasGap(gapId)<<" does not transform equally"
835 <<GeoTrf::toString(refTrf, true) <<" vs. "<<GeoTrf::toString(testTrf, true));
836 return StatusCode::FAILURE;
837 }
838 const MuonGMR4::StripDesign& stripDesign{refEle.stripLayer(gapId).design()};
839
840 for (int strip = stripDesign.firstStripNumber(); strip <= stripDesign.numStrips(); ++strip) {
841 const Identifier stripId = idHelper.channelID(refEle.identify(), refEle.multilayer(), gasGap, strip);
842 const Amg::Vector3D refStripPos{refEle.stripPosition(gctx, stripId)};
843 const Amg::Vector3D refStripDir{refEle.localToGlobalTrans(gctx, refEle.layerHash(stripId)).linear() * Amg::Vector3D::UnitX()};
844
845 Amg::Vector3D testStripPos{Amg::Vector3D::Zero()};
846 if (!testEle.stripGlobalPosition(stripId, testStripPos)) {
847 ATH_MSG_FATAL("Failed to retrieve strip position "<<m_idHelperSvc->toString(stripId));
848 return StatusCode::FAILURE;
849 }
850 const double dist = refStripDir.dot(refStripPos - testStripPos);
851 if (std::abs(dist) > 10. * Gaudi::Units::micrometer) {
852 ATH_MSG_FATAL("The strip "<<Amg::toString(testStripPos)<<" is not describing the same strip as "
853 <<Amg::toString(refStripPos)<<". Channel "<<m_idHelperSvc->toString(stripId)
854 <<" distance: "<<dist<<" "<<(dist / testEle.m_etaDesign[gasGap -1].inputWidth));
855 return StatusCode::FAILURE;
856 }
857 ATH_MSG_VERBOSE("Channel postion "<<m_idHelperSvc->toString(stripId)<<" match between legacy & new");
858 }
859 }
860 return StatusCode::SUCCESS;
861}
862
864 const MuonGMR4::MdtReadoutElement& refEle,
865 const MuonGM::MdtReadoutElement& testEle) const {
866
867 if (!m_checkGeo) {
868 return StatusCode::SUCCESS;
869 }
870 ATH_CHECK(checkIdCompability(refEle, testEle));
871
872 ATH_MSG_VERBOSE("Detector element "<<m_idHelperSvc->toString(refEle.identify())
873 <<std::endl<<GeoTrf::toString(refEle.localToGlobalTrans(gctx))
874 <<std::endl<<GeoTrf::toString(testEle.getMaterialGeom()->getAbsoluteTransform())
875 <<std::endl<<"r-size: "<<testEle.getRsize()<<"/"<<testEle.getLongRsize()
876 <<" s-size: "<<testEle.getSsize()<<"/"<<testEle.getLongSsize()
877 <<" z-size: "<<testEle.getZsize()<<"/"<<testEle.getLongZsize());
878 for (unsigned int lay = 1; lay <= refEle.numLayers(); ++lay){
879 for (unsigned int tube = 1; tube <= refEle.numTubesInLay(); ++tube) {
880 const IdentifierHash tubeHash {refEle.measurementHash(lay,tube)};
881 if (!refEle.isValid(tubeHash)) {
882 ATH_MSG_VERBOSE("SKip layer / tube "<<lay <<","<<tube);
883 continue;
884 }
885 const Amg::Transform3D globToLocal = refEle.globalToLocalTrans(gctx, tubeHash);
886
887 const Amg::Vector3D refPos = refEle.globalTubePos(gctx, tubeHash);
888 const Amg::Vector3D tubePos = testEle.tubePos(lay, tube);
889
890
891 if ( (refPos - tubePos).mag() > Gaudi::Units::micrometer &&
892 (globToLocal*refPos - globToLocal * tubePos).perp() > Gaudi::Units::micrometer) {
893 ATH_MSG_ERROR("Tube positions differ for "<<m_idHelperSvc->toString(refEle.measurementId(tubeHash))
894 <<" reference: "<<GeoTrf::toString(globToLocal*refPos)<<" vs. test: "
895 <<GeoTrf::toString(globToLocal*tubePos) <<" delta: "<<(refPos - tubePos).mag()
896 <<" Transforms "<<std::endl
897 <<" **** "<< GeoTrf::toString(globToLocal.inverse())<<std::endl
898 <<" **** "<< GeoTrf::toString(testEle.transform(lay, tube)));
899 return StatusCode::FAILURE;
900 }
901 ATH_MSG_VERBOSE("Tube positions layer: "<<lay<<", tube: "<<tube
902 <<std::endl<<"reference: "<<GeoTrf::toString(refPos)
903 <<std::endl<<"test: "<<GeoTrf::toString(tubePos)
904 <<std::endl<<testEle.tubeLength(lay, tube)<<"/"<<testEle.getActiveTubeLength(lay, tube)<<"/"
905 <<testEle.getWireLength(lay,tube)<<" vs. "<<refEle.tubeLength(tubeHash)
906 <<"/"<<refEle.activeTubeLength(tubeHash)<<"/"<<refEle.wireLength(tubeHash)
907 <<"/"<<refEle.uncutTubeLength(tubeHash));
908 if (std::abs(testEle.getTubeLengthForCaching(lay,tube) - refEle.uncutTubeLength(tubeHash)) >
909 std::numeric_limits<float>::epsilon() ) {
910 ATH_MSG_FATAL("Different tube length's detected for "<<m_idHelperSvc->toStringDetEl(refEle.identify())
911 << " layer: "<<lay<<", tube: "<<tube<<" -- "<<testEle.getTubeLengthForCaching(lay,tube)<<" (new) vs. "
912 <<refEle.uncutTubeLength(tubeHash)<<" (ref)");
913 return StatusCode::FAILURE;
914 }
915 }
916 }
917
918 return StatusCode::SUCCESS;
919}
921 const MuonGMR4::RpcReadoutElement& refEle,
922 const MuonGM::RpcReadoutElement& testEle) const {
923
924 if (!m_checkGeo) {
925 return StatusCode::SUCCESS;
926 }
927 ATH_CHECK(checkIdCompability(refEle, testEle));
928
929 ATH_MSG_VERBOSE("Compare basic readout transforms"<<std::endl
930 <<" ref: "<<GeoTrf::toString(refEle.localToGlobalTrans(gctx), true)<<std::endl
931 <<" test: "<<GeoTrf::toString(testEle.absTransform(),true)<<std::endl
932 <<"delta: "<<GeoTrf::toString(testEle.absTransform().inverse()*refEle.localToGlobalTrans(gctx), true ));
933 const RpcIdHelper& idHelper{m_idHelperSvc->rpcIdHelper()};
934 for (unsigned int gasGap = 1; gasGap <= refEle.nGasGaps(); ++gasGap) {
935 for (int doubPhi = refEle.doubletPhi(); doubPhi <= refEle.doubletPhiMax(); ++doubPhi) {
936 for (bool measPhi : {false, true}) {
937 if (measPhi && !refEle.nPhiStrips()) continue;
938 for (int strip = 1; strip <= testEle.Nstrips(measPhi); ++strip) {
939 const Identifier stripId = idHelper.channelID(refEle.identify(),
940 refEle.doubletZ(),
941 doubPhi, gasGap, measPhi, strip);
942
943 const Amg::Transform3D refTrans{refEle.localToGlobalTrans(gctx, stripId) *
944 (measPhi ? Amg::getRotateZ3D(90*Gaudi::Units::deg) :
945 Amg::Transform3D::Identity())};
946 const Amg::Transform3D& testTrans{testEle.transform(stripId)};
947 if (strip == 1 && !Amg::isIdentity(refTrans.inverse()*testTrans)) {
948 ATH_MSG_ERROR("Transformation for "<<m_idHelperSvc->toString(stripId)<<" - "<<refEle.identHash()<<std::endl
949 <<" *** ref: "<<GeoTrf::toString(refTrans)<<std::endl
950 <<" *** test: "<<GeoTrf::toString(testTrans)<<std::endl
951 <<" -> delta: "<<GeoTrf::toString(refTrans.inverse()*testTrans));
952 return StatusCode::FAILURE;
953 }
954
955 const Amg::Vector3D refStripPos = refEle.stripPosition(gctx, stripId);
956 const Amg::Vector3D testStripPos = testEle.stripPos(stripId);
957 // The threshold here used to be epsilon for a float.
958 // But this was then giving a failure in aarch64,
959 // with a difference of almost exactly 1e-4.
960 // It turned out that that was coming from GeoDeDuplicator,
961 // where to consider two transforms equivalent,
962 // the translations must match to 1e-4. But if the
963 // difference is almost exactly 1e-4, then small FP
964 // differences can be magnified to just about 1e-4.
965 if ((refStripPos - testStripPos).mag() > 2e-4){
966 ATH_MSG_ERROR("Mismatch in strip positions "<<m_idHelperSvc->toString(stripId)
967 <<" ref: "<<Amg::toString(refStripPos)<<" test: "<<Amg::toString(testStripPos)
968 <<" local coordinates -- ref: "<<Amg::toString(refTrans.inverse()*refStripPos)
969 <<" test: "<<Amg::toString(refTrans.inverse()*testStripPos));
970 return StatusCode::FAILURE;
971 }
972 ATH_MSG_VERBOSE("Agreement between new and old geometry for channel "<<m_idHelperSvc->toString(stripId)
973 <<" strip position "<<Amg::toString(refStripPos)
974 <<", local: "<<Amg::toString(refTrans.inverse()*refStripPos));
975 }
976 }
977 }
978 }
979 return StatusCode::SUCCESS;
980}
982 const MuonGMR4::TgcReadoutElement& refEle,
983 const MuonGM::TgcReadoutElement& testEle) const {
984
985 if (!m_checkGeo) {
986 return StatusCode::SUCCESS;
987 }
988 ATH_CHECK(checkIdCompability(refEle, testEle));
989
990 const TgcIdHelper& idHelper{m_idHelperSvc->tgcIdHelper()};
991
992 ATH_MSG_VERBOSE("Detector element "<<m_idHelperSvc->toString(refEle.identify())
993 <<std::endl<<GeoTrf::toString(refEle.localToGlobalTrans(gctx), true)
994 <<std::endl<<GeoTrf::toString(testEle.getMaterialGeom()->getAbsoluteTransform(), true)
995 <<std::endl<<"r-size: "<<testEle.getRsize()<<"/"<<testEle.getLongRsize()
996 <<" s-size: "<<testEle.getSsize()<<"/"<<testEle.getLongSsize()
997 <<" z-size: "<<testEle.getZsize()<<"/"<<testEle.getLongZsize());
998
999 for (unsigned int gasGap = 1; gasGap <= refEle.nGasGaps(); ++gasGap) {
1000 for (bool isStrip : {false, true}) {
1001 const IdentifierHash layHash = refEle.constructHash(0, gasGap, isStrip);
1002
1003 const Identifier layId = idHelper.channelID(refEle.identify(), gasGap, isStrip, 1);
1004 ATH_MSG_VERBOSE("Test layer "<<m_idHelperSvc->toString(layId)<<", nCh: "<<refEle.numChannels(layHash)<<", layHash: "<<layHash);
1005 if (!refEle.numChannels(layHash)) continue;
1006 const Amg::Transform3D refLayerTrf = refEle.localToGlobalTrans(gctx, refEle.constructHash(0, gasGap, false)) *
1007 (!isStrip ? Amg::Transform3D::Identity()
1008 : Amg::getRotateZ3D(-90.*Gaudi::Units::deg));
1009 const Amg::Transform3D& testLayerTrf = testEle.transform(layId);
1010 if (!Amg::isIdentity(refLayerTrf.inverse()* testLayerTrf)) {
1011 ATH_MSG_FATAL("The transformations in "<<m_idHelperSvc->toString(layId)
1012 <<std::endl<<"ref : "<<GeoTrf::toString(refLayerTrf,true)
1013 <<std::endl<<"test: "<<GeoTrf::toString(testLayerTrf,true)
1014 <<" are not identical. ");
1015 return StatusCode::FAILURE;
1016 }
1017 ATH_MSG_VERBOSE("Transformations in "<<m_idHelperSvc->toString(layId)
1018 <<std::endl<<"ref : "<<GeoTrf::toString(refLayerTrf,true)
1019 <<std::endl<<"test: "<<GeoTrf::toString(testLayerTrf,true));
1020
1021 for (unsigned int ch = 1; ch <= refEle.numChannels(layHash); ++ch) {
1022 const IdentifierHash measHash = refEle.constructHash(ch, gasGap, isStrip);
1023 const Identifier measId = refEle.measurementId(measHash);
1024 const Amg::Vector3D refChannel = refEle.channelPosition(gctx, measHash);
1025 const Amg::Vector3D testChannel = testEle.channelPos(measId);
1026 if ((refChannel - testChannel).mag() < std::numeric_limits<float>::epsilon()){
1027 continue;
1028 }
1029 std::stringstream msg{};
1030 msg<<"The channel "<<m_idHelperSvc->toString(measId)
1031 << " is not at the same position "<<Amg::toString(refChannel)
1032 <<" vs. "<<Amg::toString(testChannel)<<". Difference: "
1033 <<(refChannel - testChannel).mag();
1034 if (!isStrip) {
1035 msg<<std::endl<<"*** Test *** - wirePitch: "<<testEle.wirePitch()
1036 <<", tot wires "<<testEle.nWires(gasGap)
1037 <<", wires to reach "<<testEle.nPitchesToGang(gasGap, ch)
1038 <<", wires in gang "<<testEle.nWires(gasGap, ch);
1039 const MuonGMR4::WireGroupDesign& design{refEle.wireGangLayout(gasGap)};
1040 msg<<std::endl<<"*** Ref *** - wirePitch: "<<design.stripPitch()
1041 <<", tot wires "<<testEle.nWires(gasGap)
1042 <<", wires to reach "<<design.numPitchesToGroup(ch)
1043 <<", wires in gang "<<design.numWiresInGroup(ch);
1044 } else {
1045 const Amg::Vector3D locRefPos{refLayerTrf.inverse() * refChannel};
1046 const Amg::Vector3D locTestPos{refLayerTrf.inverse()* testChannel};
1047 msg<<std::endl<<"*** Ref **** - "<<Amg::toString(locRefPos)<<std::endl;
1048 msg<<std::endl<<"*** Test **** - "<<Amg::toString(locTestPos)<<std::endl;
1049 }
1050 ATH_MSG_FATAL(msg.str());
1051 return StatusCode::FAILURE;
1052 }
1053
1054 }
1055 }
1056 return StatusCode::SUCCESS;
1057}
1059 const MuonGMR4::sTgcReadoutElement& refEle,
1060 const MuonGM::sTgcReadoutElement& testEle) const {
1061 if (!m_checkGeo) {
1062 return StatusCode::SUCCESS;
1063 }
1064 ATH_CHECK(checkIdCompability(refEle, testEle));
1065
1066 ATH_MSG_VERBOSE("Compare basic readout transforms"<<std::endl
1067 <<GeoTrf::toString(testEle.absTransform(),true)<<std::endl
1068 <<GeoTrf::toString(refEle.localToGlobalTrans(gctx), true));
1069 const sTgcIdHelper& idHelper{m_idHelperSvc->stgcIdHelper()};
1070 for (unsigned int gasGap = 1; gasGap <= refEle.numLayers(); ++gasGap) {
1072 const Identifier layID = idHelper.channelID(refEle.identify(),
1073 refEle.multilayer(),
1074 gasGap, chType, 1);
1075 const unsigned int numChannel = refEle.numChannels(layID);
1076 constexpr unsigned firstCh = 1;
1077 for (unsigned int channel = firstCh; channel < numChannel ; ++channel) {
1078 Identifier chID;
1079 bool isValid = false;
1081 const int etaIndex = refEle.padDesign(layID).padNumber(channel).first;
1082 const int phiIndex = refEle.padDesign(layID).padNumber(channel).second;
1083 chID = idHelper.padID(refEle.identify(),
1084 refEle.multilayer(),
1085 gasGap, chType, etaIndex, phiIndex, isValid);
1086 } else {
1087 chID = idHelper.channelID(refEle.identify(),
1088 refEle.multilayer(),
1089 gasGap, chType, channel, isValid);
1090 }
1091
1092 if(!isValid) {
1093 ATH_MSG_WARNING("Invalid Identifier detected: " << m_idHelperSvc->toString(chID));
1094 }
1095
1096 const Amg::Transform3D& refTrans{refEle.localToGlobalTrans(gctx, chID)};
1097 const Amg::Transform3D& testTrans{testEle.transform(chID)};
1098 if (channel == firstCh && (!Amg::doesNotDeform(testTrans.inverse()*refTrans)
1099 || (testTrans.inverse()*refTrans).translation().perp() > std::numeric_limits<float>::epsilon() ) ) {
1100 ATH_MSG_ERROR(__func__<<"() "<<__LINE__<<" - Transformation for "<<m_idHelperSvc->toString(chID)<<std::endl
1101 <<" *** ref: "<<GeoTrf::toString(refTrans, true)<<std::endl
1102 <<" *** test: "<<GeoTrf::toString(testTrans, true));
1103 return StatusCode::FAILURE;
1104 }
1106 const Amg::Transform3D& testPadTrans{testEle.transform(chID)};
1107 const Amg::Vector3D refChannelPos = refEle.globalChannelPosition(gctx, chID);
1108 Amg::Vector3D testChannelPos(Amg::Vector3D::Zero());
1109 testEle.stripGlobalPosition(chID, testChannelPos);
1110
1111 const std::array<Amg::Vector3D,4> refPadCorners = refEle.globalPadCorners(gctx, chID);
1112 std::array<Amg::Vector3D,4> testPadCorners{make_array<Amg::Vector3D, 4>(Amg::Vector3D::Zero())};
1113 testEle.padGlobalCorners(chID, testPadCorners);
1114 for (unsigned int cornerIdx = 0; cornerIdx < refPadCorners.size(); ++cornerIdx) {
1115 const double padCornerDiff = (refPadCorners[cornerIdx] - testPadCorners[cornerIdx]).mag();
1116 if (padCornerDiff - 25. > 1. * Gaudi::Units::micrometer){
1117 ATH_MSG_ERROR("Mismatch in pad Corner " << cornerIdx << ": " <<m_idHelperSvc->toString(chID)
1118 <<" ref: "<<Amg::toString(refPadCorners[cornerIdx])<<" test: "<<Amg::toString(testPadCorners[cornerIdx])
1119 <<" difference: " << padCornerDiff
1120 <<" local coordinates -- ref: "<<Amg::toString(refTrans.inverse()*refPadCorners[cornerIdx])
1121 <<" test: "<<Amg::toString(testPadTrans.inverse()*testPadCorners[cornerIdx]));
1122 return StatusCode::FAILURE;
1123 }
1124 }
1125 const double padChannelDiff = (refChannelPos - testChannelPos).mag();
1126 if (padChannelDiff - 25. > 1. * Gaudi::Units::micrometer){
1127 ATH_MSG_ERROR("Mismatch in pad positions "<<m_idHelperSvc->toString(chID)
1128 <<" ref: "<<Amg::toString(refChannelPos)<<" test: "<<Amg::toString(testChannelPos)
1129 <<" difference: " << padChannelDiff
1130 <<" local coordinates -- ref: "<<Amg::toString(refTrans.inverse()*refChannelPos)
1131 <<" test: "<<Amg::toString(testPadTrans.inverse()*testChannelPos));
1132 return StatusCode::FAILURE;
1133 }
1134 ATH_MSG_VERBOSE("Agreement between new and old geometry for channel "<<m_idHelperSvc->toString(chID)
1135 <<" channel position "<<Amg::toString(refChannelPos));
1136 }
1138 const Amg::Vector3D refChannelPos = refEle.globalChannelPosition(gctx, chID);
1139 Amg::Vector3D testChannelPos{Amg::Vector3D::Zero()};
1140 testEle.stripGlobalPosition(chID, testChannelPos);
1141 if ((refChannelPos - testChannelPos).mag() > 1. * Gaudi::Units::micrometer){
1142 ATH_MSG_ERROR("Mismatch in strip positions "<<m_idHelperSvc->toString(chID)
1143 <<" ref: "<<Amg::toString(refChannelPos)<<" test: "<<Amg::toString(testChannelPos)
1144 <<" local coordinates -- ref: "<<Amg::toString(testTrans.inverse()*refChannelPos)
1145 <<" test: "<<Amg::toString(testTrans.inverse()*testChannelPos));
1146 return StatusCode::FAILURE;
1147 }
1148 ATH_MSG_VERBOSE("Agreement between new and old geometry for channel "<<m_idHelperSvc->toString(chID)
1149 <<" channel position "<<Amg::toString(refChannelPos));
1150 } else { // wire
1151 const Amg::Vector3D refChannelPos = refEle.globalChannelPosition(gctx, chID);
1152 Amg::Vector3D testChannelPos{Amg::Vector3D::Zero()};
1153 testEle.stripGlobalPosition(chID, testChannelPos);
1154 Amg::Vector3D localRefPos {testTrans.inverse()*refChannelPos};
1155 Amg::Vector3D localTestPos{testTrans.inverse()*testChannelPos};
1157 if((std::abs(localRefPos.x() -localTestPos.x()) > 1.* Gaudi::Units::micrometer)
1158 || (std::abs(refChannelPos.z() -testChannelPos.z()) > 15.* Gaudi::Units::micrometer)){
1159 ATH_MSG_ERROR("Mismatch in wire positions "<<m_idHelperSvc->toString(chID)
1160 <<" ref: "<<Amg::toString(refChannelPos)<<" test: "<<Amg::toString(testChannelPos)
1161 <<" local coordinates -- ref: "<<Amg::toString(testTrans.inverse()*refChannelPos)
1162 <<" test: "<<Amg::toString(testTrans.inverse()*testChannelPos)
1163 <<"delta X: "<<std::abs(localRefPos.x() -localTestPos.x())
1164 <<", delta Z: "<<std::abs(localRefPos.z() -localTestPos.z()));
1165 return StatusCode::FAILURE;
1166 }
1167 }
1168 }
1169 }
1170 }
1171 return StatusCode::SUCCESS;
1172}
1173}
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
Store holding the transfomations used by the Acts algorithms.
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.
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
static IdentifierHash measurementHash(unsigned int layerNumber, unsigned int tubeNumber)
Transform the layer and tube number to the measurementHash.
bool isValid(const IdentifierHash &measHash) const
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 global position of the tube center.
unsigned int numTubesInLay() const
Returns the number of tubes per layer.
double moduleThickness() const
Returns the thickness of the chamber.
double uncutTubeLength(const IdentifierHash &tubeHash) const
Returns the uncut tube length.
const MdtReadoutElement * complementaryRE() const
Returns the pointer to the other readout element inside the muon station.
Identifier measurementId(const IdentifierHash &measHash) const override final
Converts the measurement hash back to the full Identifier.
unsigned int numLayers() const
Returns the number of tube layer.
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
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)
The MuonReadoutElement is an abstract class representing the geometry representing the muon detector.
const Amg::Transform3D & localToGlobalTrans(const ActsTrk::GeometryContext &ctx) const
Returns the local to global transformation into the ATLAS coordinate system.
IdentifierHash identHash() const
Returns the Identifier has of the Element that is Identical to the detElHash from the id_helper class...
Identifier identify() const override final
Return the athena identifier.
const GeoAlignableTransform * alignableTransform() const
Returnsthe alignable transform of the readout element.
Amg::Transform3D globalToLocalTrans(const ActsTrk::GeometryContext &ctx) const
Transformations to translate between local <-> global coordinates.
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
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
StatusCode buildRpc(const ActsTrk::GeometryContext &gctx, ConstructionCache &cacheObj) const
GeoIntrusivePtr< GeoVFullPhysVol > cloneNswWedge(const ActsTrk::GeometryContext &gctx, const MuonGMR4::MuonReadoutElement *nswRE, ConstructionCache &cacheObj) const
Clones the fullPhysicalVolume of the.
StatusCode buildTgc(const ActsTrk::GeometryContext &gctx, ConstructionCache &cacheObj) const
Gaudi::Property< bool > m_dumpGeo
StatusCode buildSTGC(const ActsTrk::GeometryContext &gctx, ConstructionCache &cacheObj) const
StatusCode dumpAndCompare(const ActsTrk::GeometryContext &gctx, const MuonGMR4::RpcReadoutElement &refEle, const MuonGM::RpcReadoutElement &testEle) const
StatusCode checkIdCompability(const MuonGMR4::MuonReadoutElement &refEle, const MuonGM::MuonReadoutElement &testEle) const
StatusCode buildMM(const ActsTrk::GeometryContext &gctx, ConstructionCache &cacheObj) const
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
Converts the measurement hash back to the full Identifier.
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.
Amg::Vector3D globalChannelPosition(const ActsTrk::GeometryContext &ctx, const Identifier &measId) const
Returns the global pad/strip/wireGroup position.
static IdentifierHash createHash(const unsigned int gasGap, const unsigned int channelType, const unsigned int channel, const unsigned int wireInGrp=0)
Create a measurement hash from the Identifier fields.
const PadDesign & padDesign(const Identifier &measId) const
Retrieves the readoutElement Layer given the Identifier/Hash.
globalCornerArray globalPadCorners(const ActsTrk::GeometryContext &ctx, const Identifier &measId) const
int multilayer() const
Returns the multilayer of the sTgcReadoutElement.
unsigned int numLayers() const
Returns the number of gas gap layers.
ReadoutChannelType
ReadoutChannelType to distinguish the available readout channels Pad - pad readout channel Strip - et...
unsigned int numChannels(const Identifier &measId) const
Returns the number of strips / wires / pads in a given gasGap.
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
The ReadoutGeomCnvAlg converts the Run4 Readout geometry build from the GeoModelXML into the legacy M...
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...
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