ATLAS Offline Software
Loading...
Searching...
No Matches
MdtReadoutGeomTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7#include <GaudiKernel/SystemOfUnits.h>
10
13#include <GeoModelKernel/GeoFullPhysVol.h>
14#include <GeoModelKernel/GeoPhysVol.h>
15#include <GeoModelKernel/GeoTrd.h>
16#include <GeoModelKernel/GeoTube.h>
17
18#include <GeoModelRead/ReadGeoModel.h>
21
22#ifndef SIMULATIONBASE
23# include "Acts/Surfaces/TrapezoidBounds.hpp"
24# include "Acts/Surfaces/LineBounds.hpp"
25#endif
26
27using namespace CxxUtils;
28using namespace ActsTrk;
29
30namespace MuonGMR4 {
32
33
35 MdtReadoutElement::defineArgs& define) const {
36
37 ATH_MSG_VERBOSE("Load dimensions of "<<m_idHelperSvc->toString(define.detElId)
38 <<std::endl<<std::endl<<m_geoUtilTool->dumpVolume(define.physVol));
39 const GeoShape* shape = m_geoUtilTool->extractShape(define.physVol);
40 if (!shape) {
41 ATH_MSG_FATAL("Failed to deduce a valid shape for "<<m_idHelperSvc->toString(define.detElId));
42 return StatusCode::FAILURE;
43 }
46 if (shape->typeID() == GeoTrd::getClassTypeID()) {
47 ATH_MSG_VERBOSE("Extracted shape "<<m_geoUtilTool->dumpShape(shape));
48 const GeoTrd* trd = static_cast<const GeoTrd*>(shape);
49 define.longHalfX = std::max(trd->getYHalfLength1(), trd->getYHalfLength2()) * Gaudi::Units::mm;
50 define.shortHalfX = std::min(trd->getYHalfLength1(), trd->getYHalfLength2())* Gaudi::Units::mm;
51 define.halfY = trd->getZHalfLength()* Gaudi::Units::mm;
52 define.halfHeight = std::max(trd->getXHalfLength1(), trd->getXHalfLength2()) * Gaudi::Units::mm;
53 } else {
54 ATH_MSG_FATAL("Unknown shape type "<<shape->type());
55 return StatusCode::FAILURE;
56 }
60 const MdtIdHelper& idHelper{m_idHelperSvc->mdtIdHelper()};
61 for (unsigned int ch = 1; ch < define.physVol->getNChildNodes(); ++ch) {
62 const GeoGraphNode* childNode = (*define.physVol->getChildNode(ch));
63 const GeoVPhysVol* childVol = dynamic_cast<const GeoVPhysVol*>(childNode);
64 if (!childVol || childVol->getLogVol()->getName() != "TubeLayerLog") {
65 continue;
66 }
67 const GeoTransform* trfNode = dynamic_cast<const GeoTransform*>(*define.physVol->getChildNode(ch-1));
68 if (!trfNode) {
69 ATH_MSG_FATAL("Expect a GeoTransform node right before the tubelayer node");
70 return StatusCode::FAILURE;
71 }
72 ATH_MSG_VERBOSE("Add new tube layer "<<m_idHelperSvc->toStringDetEl(define.detElId)<<
73 std::endl<<std::endl<<m_geoUtilTool->dumpVolume(childVol));
74 const Identifier tubeLayId = idHelper.channelID(define.detElId,
75 idHelper.multilayer(define.detElId),
76 define.tubeLayers.size() +1, 1);
77 MdtTubeLayerPtr newLay = std::make_unique<MdtTubeLayer>(childVol, trfNode, facCache.cutTubes[tubeLayId]);
78 define.tubeLayers.emplace_back(*facCache.tubeLayers.insert(newLay).first);
79
80 const MdtTubeLayer& lay{*define.tubeLayers.back()};
83 bool chEndPlug{false};
84 for (unsigned int tube = 0 ; tube < lay.nTubes(); ++tube) {
85 constexpr std::string_view airTubeName{"airTube"};
86 PVConstLink tubeVol{lay.getTubeNode(tube)};
87 if (tubeVol->getLogVol()->getName() == airTubeName) {
88 define.removedTubes.insert(MdtReadoutElement::measurementHash(define.tubeLayers.size(), tube+1));
89 } else if (!chEndPlug) {
91 chEndPlug = true;
92 std::vector<physVolWithTrans> endPlugs = m_geoUtilTool->findAllLeafNodesByName(tubeVol, "Endplug");
93 if (endPlugs.empty()) {
95 continue;
96 }
97 const GeoShape* plugShape = m_geoUtilTool->extractShape(endPlugs[0].volume);
98 if (plugShape->typeID() != GeoTube::getClassTypeID()){
99 ATH_MSG_FATAL("The shape "<<m_geoUtilTool->dumpShape(plugShape)<<" is not a tube");
100 return StatusCode::FAILURE;
101 }
102 const GeoTube* plugTube = static_cast<const GeoTube*>(plugShape);
103 define.endPlugLength = plugTube->getZHalfLength();
104 }
105 }
106 }
107 define.readoutSide = facCache.readoutOnLeftSide.count(m_idHelperSvc->chamberId(define.detElId)) ? -1. : 1.;
108 return StatusCode::SUCCESS;
109}
111 ATH_CHECK(m_geoDbTagSvc.retrieve());
112 ATH_CHECK(m_idHelperSvc.retrieve());
113 ATH_CHECK(m_geoUtilTool.retrieve());
114 GeoModelIO::ReadGeoModel* sqliteReader = m_geoDbTagSvc->getSqliteReader();
115 if (!sqliteReader) {
116 ATH_MSG_FATAL("Error, the tool works exclusively from sqlite geometry inputs");
117 return StatusCode::FAILURE;
118 }
119 FactoryCache facCache{};
120 ATH_CHECK(readParameterBook(facCache));
121 const MdtIdHelper& idHelper{m_idHelperSvc->mdtIdHelper()};
122 // Get the list of full phys volumes from SQLite, and create detector elements
123 physNodeMap mapFPV = sqliteReader->getPublishedNodes<std::string, GeoFullPhysVol*>("Muon");
124#ifndef SIMULATIONBASE
125 auto boundFactory = std::make_shared<Acts::SurfaceBoundFactory>();
126#endif
127 for (auto& [key, pv] : mapFPV) {
134 std::vector<std::string> key_tokens = tokenize(key, "_");
135 if (key_tokens.size() != 5 ||
136 key_tokens[1].find("MDT") == std::string::npos)
137 continue;
138
140 bool isValid{false};
141 define.detElId = idHelper.channelID(key_tokens[0].substr(0, 3),
142 atoi(key_tokens[2]),
143 atoi(key_tokens[3]),
144 atoi(key_tokens[4]), 1, 1, isValid);
145 if (!isValid) {
146 ATH_MSG_FATAL("Failed to build a good identifier out of " << key);
147 return StatusCode::FAILURE;
148 }
149 ATH_MSG_DEBUG("Key "<<key<<" brought us "<<m_idHelperSvc->toStringDetEl(define.detElId));
151 define.physVol = pv;
152 define.chambDesign = key_tokens[1];
153 define.alignTransform = m_geoUtilTool->findAlignableTransform(define.physVol);
154
156 ParamBookTable::const_iterator book_itr = facCache.parBook.find(define.chambDesign);
157 if (book_itr == facCache.parBook.end()) {
158 ATH_MSG_FATAL("There is no chamber called "<<define.chambDesign);
159 return StatusCode::FAILURE;
160 }
161 static_cast<parameterBook&>(define) = book_itr->second;
162#ifndef SIMULATIONBASE
163 define.boundFactory = boundFactory;
164 #endif
166 ATH_CHECK(loadDimensions(facCache, define));
167 std::unique_ptr<MdtReadoutElement> mdtDetectorElement = std::make_unique<MdtReadoutElement>(std::move(define));
168 ATH_CHECK(mgr.addMdtReadoutElement(std::move(mdtDetectorElement)));
169 }
170 return StatusCode::SUCCESS;
171}
173 ServiceHandle<IRDBAccessSvc> accessSvc(m_geoDbTagSvc->getParamSvcName(),
174 name());
175 ATH_CHECK(accessSvc.retrieve());
176 IRDBRecordset_ptr paramTable = accessSvc->getRecordsetPtr("WMDT", "");
177 if (paramTable->size() == 0) {
178 ATH_MSG_FATAL("Empty parameter book table found");
179 return StatusCode::FAILURE;
180 }
181 ATH_MSG_VERBOSE("Found the " << paramTable->nodeName() << " ["
182 << paramTable->tagName() << "] table with "
183 << paramTable->size() << " records");
184 for (const IRDBRecord_ptr& record : *paramTable) {
185 parameterBook pars{};
186 pars.tubeWall = record->getDouble("TUBWAL") * Gaudi::Units::cm;
187 pars.tubePitch = record->getDouble("TUBPIT") * Gaudi::Units::cm;
188 pars.tubeInnerRad = record->getDouble("TUBRAD") * Gaudi::Units::cm;
189 pars.endPlugLength = record->getDouble("TUBDEA") * Gaudi::Units::cm;
190 pars.radLengthX0 = record->getDouble("X0");
191 unsigned int nLay = record->getInt("LAYMDT");
192 const std::string key {record->getString("WMDT_TYPE")};
193 ATH_MSG_DEBUG("Extracted parameters " <<pars<<" number of layers: "<<nLay<<" will be safed under key "<<key);
194 cache.parBook[key] = std::move(pars);
195 }
197 const MdtIdHelper& idHelper{m_idHelperSvc->mdtIdHelper()};
198 paramTable = accessSvc->getRecordsetPtr("MdtTubeROSides" ,"");
199 if (paramTable->size() == 0) {
200 ATH_MSG_FATAL("Empty parameter book table found");
201 return StatusCode::FAILURE;
202 }
203 ATH_MSG_VERBOSE("Found the " << paramTable->nodeName() << " ["
204 << paramTable->tagName() << "] table with "
205 << paramTable->size() << " records");
206 for (const IRDBRecord_ptr& record : *paramTable) {
207 const std::string stName = record->getString("stationName");
208 const int stEta = record->getInt("stationEta");
209 const int stPhi = record->getInt("stationPhi");
210 const int side = record->getInt("side");
211 if (side == -1) {
212 bool isValid{false};
213 cache.readoutOnLeftSide.insert(idHelper.elementID(stName,stEta,stPhi, isValid));
214 if (!isValid) {
215 ATH_MSG_FATAL("station "<<stName<<" eta: "<<stEta<<" phi: "<<stPhi<<" is unknown.");
216 return StatusCode::FAILURE;
217 }
218 }
219 }
221 paramTable = accessSvc->getRecordsetPtr("MdtCutTubes" ,"");
222 if (paramTable->size() == 0) {
223 ATH_MSG_INFO("No information about cut mdt tubes has been found. Skipping.");
224 return StatusCode::SUCCESS;
225 }
226 for (const IRDBRecord_ptr& record : *paramTable) {
227 const std::string stName = record->getString("stationName");
228 const int stEta = record->getInt("stationEta");
229 const int stPhi = record->getInt("stationPhi");
230 const int multiLay = record->getInt("multiLayer");
231 const int tubeLay = record->getInt("tubeLayer");
232 bool isValid{false};
233 const Identifier tubeId = idHelper.channelID(stName, stEta, stPhi, multiLay, tubeLay, 1 , isValid);
234 if (!isValid) {
235 ATH_MSG_FATAL("Failed to deduce valid Idnetifier "<<stName<<", "<<stEta<<", "<<stPhi<<","<<multiLay<<", "<<tubeLay);
236 return StatusCode::FAILURE;
237 }
238 FactoryCache::CutTubes cutTubes{};
239
240 cutTubes.firstTube = record->getInt("firstTube");
241 cutTubes.lastTube = record->getInt("lastTube");
242 cutTubes.unCutHalfLength = record->getDouble("uncutHalfLength");
243 ATH_MSG_VERBOSE("Found new uncut tube set in "<<m_idHelperSvc->toString(tubeId)<<" tubes: ["
244 <<cutTubes.firstTube<<"-"<<cutTubes.lastTube<<"], length: "<< 2.*cutTubes.unCutHalfLength );
245 cache.cutTubes[tubeId].insert(std::move(cutTubes));
246
247 }
248 return StatusCode::SUCCESS;
249}
250
251} // namespace MuonGMR4
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(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
Definition of the abstract IRDBAccessSvc interface.
std::shared_ptr< IRDBRecordset > IRDBRecordset_ptr
Definition of the abstract IRDBRecord interface.
Definition of the abstract IRDBRecordset interface.
std::unique_ptr< IRDBRecord > IRDBRecord_ptr
virtual std::string tagName() const =0
virtual std::string nodeName() const =0
virtual unsigned int size() const =0
int multilayer(const Identifier &id) const
Access to components of the ID.
Identifier elementID(int stationName, int stationEta, int stationPhi) const
Identifier channelID(int stationName, int stationEta, int stationPhi, int multilayer, int tubeLayer, int tube) const
GeoChildNodeWithTrf physVolWithTrans
Helper struct to cache a PhysVolume pointer together with the transformation to go from the volume to...
static IdentifierHash measurementHash(unsigned int layerNumber, unsigned int tubeNumber)
Transform the layer and tube number to the measurementHash.
ServiceHandle< IGeoDbTagSvc > m_geoDbTagSvc
PublicToolHandle< IMuonGeoUtilityTool > m_geoUtilTool
StatusCode loadDimensions(FactoryCache &facCache, MdtReadoutElement::defineArgs &args) const
Loads the chamber dimensions from GeoModel.
StatusCode readParameterBook(FactoryCache &facCache) const
Retrieves the auxillary tables from the database.
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
StatusCode buildReadOutElements(MuonDetectorManager &mgr) override final
MdtReadoutElement::parameterBook parameterBook
Helper struct to retrieve the tube lengths and the tube centers directly from the GeoModel tree.
PVConstLink getTubeNode(unsigned int tube) const
returns the PVConst link to the n-th tube [0 - nTubes() -1]
unsigned int nTubes() const
Returns the number of tubes in the layer.
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
std::vector< std::string > tokenize(const std::string &the_str, std::string_view delimiters)
Splits the string into smaller substrings.
int atoi(std::string_view str)
Helper functions to unpack numbers decoded in string into integers and doubles The strings are requir...
The ReadoutGeomCnvAlg converts the Run4 Readout geometry build from the GeoModelXML into the legacy M...
GeoModel::TransientConstSharedPtr< MdtTubeLayer > MdtTubeLayerPtr
IMuonGeoUtilityTool::physVolWithTrans physVolWithTrans
double shortHalfX
The chambers have either a rectangular or a trapezoidal shape to first approximation.
std::shared_ptr< Acts::SurfaceBoundFactory > boundFactory
Sets of surface bounds which is shared amongst all readout elements used to assign the same bound obj...
std::vector< MdtTubeLayerPtr > tubeLayers
Vector defining the position of all tubes in each tube layer.
std::unordered_map< Identifier, CutTubeSet > cutTubes
std::unordered_set< Identifier > readoutOnLeftSide
List of chambers that have the readout chip at negative Z.
unsigned int firstTube
First tube of the cut.
double unCutHalfLength
Tube length before cut.
unsigned int lastTube
Last tube of the cut.
GeoIntrusivePtr< GeoVFullPhysVol > physVol
Pointer to the underlying physical volume in GeoModel.
std::string chambDesign
chamber design name as it's occuring in the parameter book tables E.g. BMS5, RPC10,...