ATLAS Offline Software
Loading...
Searching...
No Matches
MuonGMR4::RpcReadoutGeomTool Class Reference

Implementation to construct Rpc readout element from the list of published full physical volumes and the WRPC meta data table. More...

#include <RpcReadoutGeomTool.h>

Inheritance diagram for MuonGMR4::RpcReadoutGeomTool:
Collaboration diagram for MuonGMR4::RpcReadoutGeomTool:

Classes

struct  FactoryCache
 Cache object to the wRPCTable & store stripDesigns & layers to make the information available throughout the geometry building and to allow for sharing of Identical StripLayers. More...
struct  wRPCTable
 Struct to cache the relevant parameters of from the WRPC tables. More...

Public Member Functions

StatusCode buildReadOutElements (MuonDetectorManager &mgr) override final

Private Member Functions

StatusCode readParameterBook (FactoryCache &cache)
 Retrieves the auxillary tables from the database.
StatusCode loadDimensions (RpcReadoutElement::defineArgs &args, FactoryCache &factory)
 Loads the chamber dimensions from GeoModel.
std::unique_ptr< StripDesignconstructDesign (const GeoBox *planeBox, const wRPCTable &paramBook, bool phiPlane) const
 Constructs a new Strip design from the parameter book to describe either the phi plane or the eta strip-plane.

Private Attributes

ServiceHandle< Muon::IMuonIdHelperSvcm_idHelperSvc
ServiceHandle< IGeoDbTagSvcm_geoDbTagSvc {this, "GeoDbTagSvc", "GeoDbTagSvc"}
PublicToolHandle< IMuonGeoUtilityToolm_geoUtilTool {this,"GeoUtilTool", "" }

Detailed Description

Implementation to construct Rpc readout element from the list of published full physical volumes and the WRPC meta data table.

Definition at line 23 of file RpcReadoutGeomTool.h.

Member Function Documentation

◆ buildReadOutElements()

StatusCode MuonGMR4::RpcReadoutGeomTool::buildReadOutElements ( MuonDetectorManager & mgr)
finaloverride

Retrieve the list of full physical volumes & alignable nodes and connect them together afterwards

The keys should be formatted like <STATION_NAME>_<MUON_CHAMBERTYPE>etc. The <MUON_CHAMBERTYPE> also indicates whether we're dealing with a MDT / TGC / CSC / RPC chamber If we are dealing with a MDT chamber, then there are 3 additional properties encoded into the chamber <STATIONETA><STATIONPHI>_<DOUBLETR>_<DOUBLETPHI>_<DOUBLETZ>

Retrieve first the station Identifier

stationEta

stationPhi

DoubletR

DoubletZ

DoubletPhi

Definition at line 204 of file RpcReadoutGeomTool.cxx.

204 {
205 GeoModelIO::ReadGeoModel* sqliteReader = m_geoDbTagSvc->getSqliteReader();
206 if (!sqliteReader) {
207 ATH_MSG_FATAL("Error, the tool works exclusively from sqlite geometry inputs");
208 return StatusCode::FAILURE;
209 }
210
211 FactoryCache facCache{};
212 ATH_CHECK(readParameterBook(facCache));
213
214 const RpcIdHelper& idHelper{m_idHelperSvc->rpcIdHelper()};
215 // Get the list of full phys volumes from SQLite, and create detector elements
216
218 physNodeMap mapFPV = sqliteReader->getPublishedNodes<std::string, GeoFullPhysVol*>("Muon");
219#ifndef SIMULATIONBASE
220 auto layerBounds = std::make_shared<Acts::SurfaceBoundFactory>();
221#endif
222 for (auto& [key, pv] : mapFPV) {
229 std::vector<std::string> key_tokens = tokenize(key, "_");
230 if (key_tokens.size() < 7 ||
231 key_tokens[1].find("RPC") == std::string::npos) {
232 continue;
233 }
234 bool isValid{false};
236 const Identifier elementID = idHelper.padID(idHelper.stationNameIndex(key_tokens[0].substr(0, 3)),
237 atoi(key_tokens[2]),
238 atoi(key_tokens[3]),
239 atoi(key_tokens[4]),
240 atoi(key_tokens[6]),
241 atoi(key_tokens[5]),
242 isValid);
243 if (!isValid) {
244 ATH_MSG_FATAL("Failed to construct the station Identifier from "<<key);
245 return StatusCode::FAILURE;
246 }
247 defineArgs define{};
248 define.physVol = pv;
249 define.chambDesign = key_tokens[1];
250 define.alignTransform = m_geoUtilTool->findAlignableTransform(define.physVol);
251 define.detElId = elementID;
252 ATH_MSG_VERBOSE("Key "<<key<<" lead to Identifier "<<m_idHelperSvc->toStringDetEl(elementID));
253 ATH_CHECK(loadDimensions(define, facCache));
254#ifndef SIMULATIONBASE
255 define.layerBounds = layerBounds;
256#endif
257 std::unique_ptr<RpcReadoutElement> readoutEle = std::make_unique<RpcReadoutElement>(std::move(define));
258 ATH_CHECK(mgr.addRpcReadoutElement(std::move(readoutEle)));
259 }
260 return StatusCode::SUCCESS;
261}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_FATAL(x)
#define ATH_MSG_VERBOSE(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
PublicToolHandle< IMuonGeoUtilityTool > m_geoUtilTool
StatusCode readParameterBook(FactoryCache &cache)
Retrieves the auxillary tables from the database.
ServiceHandle< IGeoDbTagSvc > m_geoDbTagSvc
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
StatusCode loadDimensions(RpcReadoutElement::defineArgs &args, FactoryCache &factory)
Loads the chamber dimensions from GeoModel.
int stationNameIndex(const std::string &name) const
Identifier padID(const Identifier &elementID, int doubletZ, int doubletPhi) const
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...
RpcReadoutElement::defineArgs defineArgs
GeoIntrusivePtr< GeoVFullPhysVol > physVol
Pointer to the underlying physical volume in GeoModel.
Cache object to the wRPCTable & store stripDesigns & layers to make the information available through...

◆ constructDesign()

std::unique_ptr< StripDesign > MuonGMR4::RpcReadoutGeomTool::constructDesign ( const GeoBox * planeBox,
const wRPCTable & paramBook,
bool phiPlane ) const
private

Constructs a new Strip design from the parameter book to describe either the phi plane or the eta strip-plane.

Parameters
planeBoxPointer to the shape describing the strip-readout volume, needed to fetch the design's dimensions
paramBookParameter book to read off the strip design paramters in terms of pitch, n-strips etc
phiPlaneSwitch toggling whether the eta / phi design should be created

Definition at line 49 of file RpcReadoutGeomTool.cxx.

51 {
52 const unsigned nStrips = phiPlane ? paramBook.numPhiStrips : paramBook.numEtaStrips;
53 if (!nStrips) {
54 ATH_MSG_VERBOSE("Parameter book does not for see a readout in "<<(phiPlane? "phi" : "eta")<<" direction");
55 return nullptr;
56 }
57
58 const double halfX = phiPlane ? planeBox->getYHalfLength() : planeBox->getZHalfLength();
59 const double halfY = phiPlane ? planeBox->getZHalfLength() : planeBox->getYHalfLength();
60
61 const double pitch = phiPlane ? paramBook.stripPitchPhi : paramBook.stripPitchEta;
62 const double width = phiPlane ? paramBook.stripWidthPhi : paramBook.stripWidthEta;
63 const double firstPos = -halfX + (phiPlane ? paramBook.firstOffSetPhi : paramBook.firstOffSetEta);
64 auto newDesign = std::make_unique<StripDesign>();
65 newDesign->defineTrapezoid(halfY, halfY, halfX);
66 newDesign->defineStripLayout(firstPos * Amg::Vector2D::UnitX(), pitch,width, nStrips);
67 return newDesign;
68}
const double width
double halfY(const Acts::VolumeBounds &bounds)
Returns the half-Y length for the parsed volume bounds (Trapezoid/ Cuboid)
int nStrips(const MuonGM::TgcReadoutElement &readoutEle, int layer)

◆ loadDimensions()

StatusCode MuonGMR4::RpcReadoutGeomTool::loadDimensions ( RpcReadoutElement::defineArgs & args,
FactoryCache & factory )
private

Loads the chamber dimensions from GeoModel.

The half sizes of the

Rpc are made up out of 2 or 3 gasGap singlet. A singlet module is a RPC gas gap sandwiched by two strip layers. In large sectors, the gas gap may be split into two gasGaps.

    | Strip layer  |  Strip layer |    |  Strip layer  |  Strip layer |
    |           gas gap           |    |    Gas gap    |    Gas gap   | 
    | Strip layer  |  Strip layer |    |  Strip layer  |  Strip layer |

Fetch all volumes with Identifiers from the tree

Next sort them by Identifier

Fetch for each rpc layer the gasGaps

Adjust the height of the strip panel to be in the centre of the gasGap

We know now whether we had 2 or 3 gasgaps and also whether there 2 or 1 panels in phi

Special case for the BML4 DBZ = 3 chambers. The doubletPhi is incorporated into the detector element but there's only one strip panel

Definition at line 70 of file RpcReadoutGeomTool.cxx.

71 {
72
73 ATH_MSG_VERBOSE("Load dimensions of "<<m_idHelperSvc->toString(define.detElId)
74 <<std::endl<<std::endl<<m_geoUtilTool->dumpVolume(define.physVol));
75
76 const GeoShape* shape = m_geoUtilTool->extractShape(define.physVol);
77 if (!shape) {
78 ATH_MSG_FATAL("Failed to deduce a valid shape for "<<m_idHelperSvc->toString(define.detElId));
79 return StatusCode::FAILURE;
80 }
81 ATH_MSG_DEBUG("Extracted shape "<<m_geoUtilTool->dumpShape(shape));
83 if (shape->typeID() != GeoBox::getClassTypeID()) {
84 ATH_MSG_FATAL(__FILE__<<":"<<__LINE__<<" expect shape to be a box but it's "<<m_geoUtilTool->dumpShape(shape));
85 return StatusCode::FAILURE;
86 }
87
88 const GeoBox* box = static_cast<const GeoBox*>(shape);
89 define.halfThickness = box->getXHalfLength() * Gaudi::Units::mm;
90 define.halfLength = box->getZHalfLength() * Gaudi::Units::mm;
91 define.halfWidth = box->getYHalfLength() * Gaudi::Units::mm;
92
102 std::vector<GeoChildNodeWithTrf> rpcLayers = getChildrenWithRef(define.physVol, false);
104 rpcLayers.erase(std::remove_if(rpcLayers.begin(), rpcLayers.end(),
105 [](const GeoChildNodeWithTrf& subVol){ return !subVol.volumeId; }), rpcLayers.end());
107 std::ranges::sort(rpcLayers, [](const GeoChildNodeWithTrf& a, const GeoChildNodeWithTrf& b){
108 return a.volumeId.value_or(0) < b.volumeId.value_or(0);});
109
110 if (rpcLayers.empty()) {
111 ATH_MSG_FATAL("The volume "<<m_idHelperSvc->toStringDetEl(define.detElId)<<" does not have any childern with Identifiers "
112 <<std::endl<<m_geoUtilTool->dumpVolume(define.physVol));
113 return StatusCode::FAILURE;
114 }
116 unsigned gasGap{0};
117 const unsigned modulePhi = m_idHelperSvc->rpcIdHelper().doubletPhi(define.detElId);
118
119 std::vector<gapVolume> allGapsWithIdx{};
120 for (const GeoChildNodeWithTrf& rpcSinglet : rpcLayers) {
121 auto fetchNodes = [this, &rpcSinglet] (const std::string& leafName) {
122 std::vector<GeoChildNodeWithTrf> nodes = m_geoUtilTool->findAllLeafNodesByName(rpcSinglet.volume, leafName);
123 std::ranges::for_each(nodes,[&rpcSinglet](GeoChildNodeWithTrf& node){ node.transform = rpcSinglet.transform * node.transform; });
124 return nodes;
125 };
126 std::vector<GeoChildNodeWithTrf> gasGaps = fetchNodes("RpcGasGap");
127 if (gasGaps.empty()) {
128 ATH_MSG_FATAL("The child "<<m_geoUtilTool->dumpVolume(rpcSinglet.volume)<<" has "<<gasGaps.size()<<" gasGaps. ");
129 return StatusCode::FAILURE;
130 }
131 std::vector<GeoChildNodeWithTrf> stripLayers = fetchNodes("bottomStripLayer");
132 if (stripLayers.empty()) {
133 ATH_MSG_FATAL("The child "<<m_geoUtilTool->dumpVolume(rpcSinglet.volume)<<" does not have a strip layer ");
134 return StatusCode::FAILURE;
135 }
136 ++gasGap;
137 for (GeoChildNodeWithTrf& stripPanel : stripLayers) {
139 stripPanel.transform.translation().x() = gasGaps.front().transform.translation().x();
140 const int doubPhi = std::max(modulePhi, 1u*stripPanel.volumeId.value_or(999));
141 allGapsWithIdx.emplace_back(std::move(stripPanel), gasGap, doubPhi);
142 }
143 }
144
145 const bool isAside{m_idHelperSvc->stationEta(define.detElId) > 0};
147 define.nGasGaps = gasGap;
150 define.nPanelsInPhi = modulePhi == 2 ? 1 : allGapsWithIdx.size () / gasGap;
151 FactoryCache::ParamBookTable::const_iterator parBookItr = factoryCache.parameterBook.find(define.chambDesign);
152 if (parBookItr == factoryCache.parameterBook.end()) {
153 ATH_MSG_FATAL("The chamber "<<define.chambDesign<<" is not part of the WRPC table");
154 return StatusCode::FAILURE;
155 }
156 const wRPCTable& paramBook{parBookItr->second};
157
158 auto insertStripLayer = [this, &define, &factoryCache](std::unique_ptr<StripLayer> stripLay) {
159 const unsigned layIdx = static_cast<unsigned>(stripLay->hash());
160 if (layIdx >= define.layers.size()) {
161 define.layers.resize(layIdx + 1);
162 }
163 define.layers[layIdx] = (*factoryCache.stripLayers.emplace(std::move(stripLay)).first);
164 ATH_MSG_VERBOSE("Added new eta gap at "<<(*define.layers[layIdx]));
165 };
166 for (gapVolume& gapVol : allGapsWithIdx) {
167 const GeoShape* gapShape = m_geoUtilTool->extractShape(gapVol.volume);
168 if (gapShape->typeID() != GeoBox::getClassTypeID()) {
169 ATH_MSG_FATAL("Failed to extract a geo shape");
170 return StatusCode::FAILURE;
171 }
172 const GeoBox* gapBox = static_cast<const GeoBox*>(gapShape);
173 ATH_MSG_DEBUG("Gas gap dimensions "<<m_geoUtilTool->dumpShape(gapBox));
174 StripDesignPtr etaDesign = constructDesign(gapBox, paramBook, false);
175 StripDesignPtr phiDesign = constructDesign(gapBox, paramBook, true);
176 if (etaDesign) {
177 etaDesign = (*factoryCache.stripDesigns.emplace(etaDesign).first);
178 }
179 if (phiDesign) {
180 phiDesign = (*factoryCache.stripDesigns.emplace(phiDesign).first);
181 }
182 if (!define.etaDesign) {
183 define.etaDesign = etaDesign;
184 }
185 if (!define.phiDesign) {
186 define.phiDesign = phiDesign;
187 }
188 gapVol.transform = gapVol.transform * Amg::getRotateY3D( (isAside ? -90. : 90.)* Gaudi::Units::degree);
189
190 if (etaDesign && phiDesign) {
191 insertStripLayer(std::make_unique<StripLayer>(factoryCache.trfNodeMaker.makeTransform(gapVol.transform),
192 etaDesign, phiDesign,
193 RpcReadoutElement::createHash(0, gapVol.gasGap, gapVol.doubPhi, false)));
194 } else if (etaDesign) {
195 insertStripLayer(std::make_unique<StripLayer>(factoryCache.trfNodeMaker.makeTransform(gapVol.transform),
196 etaDesign, RpcReadoutElement::createHash(0, gapVol.gasGap, gapVol.doubPhi, false)));
197 } else {
198 ATH_MSG_ERROR("It's not forseen to have a chamber without eta design");
199 return StatusCode::FAILURE;
200 }
201 }
202 return StatusCode::SUCCESS;
203}
#define ATH_MSG_ERROR(x)
#define ATH_MSG_DEBUG(x)
static Double_t a
static IdentifierHash createHash(const unsigned strip, const unsigned gasGap, const unsigned doubPhi, const bool measPhi)
Constructs an Identifier hash from the Identifier fields controlled by this readout element.
std::unique_ptr< StripDesign > constructDesign(const GeoBox *planeBox, const wRPCTable &paramBook, bool phiPlane) const
Constructs a new Strip design from the parameter book to describe either the phi plane or the eta str...
Amg::Transform3D getRotateY3D(double angle)
get a rotation transformation around Y-axis
GeoModel::TransientConstSharedPtr< StripDesign > StripDesignPtr
Definition StripDesign.h:29
DataModel_detail::iterator< DVL > remove_if(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end, Predicate pred)
Specialization of remove_if for DataVector/List.
Struct to cache the relevant parameters of from the WRPC tables.

◆ readParameterBook()

StatusCode MuonGMR4::RpcReadoutGeomTool::readParameterBook ( FactoryCache & cache)
private

Retrieves the auxillary tables from the database.

Definition at line 262 of file RpcReadoutGeomTool.cxx.

262 {
263 ServiceHandle<IRDBAccessSvc> accessSvc(m_geoDbTagSvc->getParamSvcName(), name());
264 ATH_CHECK(accessSvc.retrieve());
265 IRDBRecordset_ptr paramTable = accessSvc->getRecordsetPtr("WRPC", "");
266 if (paramTable->size() == 0) {
267 ATH_MSG_FATAL("Empty parameter book table found");
268 return StatusCode::FAILURE;
269 }
270 ATH_MSG_VERBOSE("Found the " << paramTable->nodeName() << " ["
271 << paramTable->tagName() << "] table with "
272 << paramTable->size() << " records");
273
274 for (const IRDBRecord_ptr& record : *paramTable) {
275 const std::string chambType = record->getString("WRPC_TYPE");
276 wRPCTable& parBook = cache.parameterBook[record->getString("WRPC_TYPE")];
277 parBook.stripPitchEta = record->getDouble("etaStripPitch") * Gaudi::Units::cm;
278 parBook.stripPitchPhi = record->getDouble("phiStripPitch") * Gaudi::Units::cm;
279 const double stripDeadWidth = record->getDouble("stripDeadWidth") * Gaudi::Units::cm;
280 parBook.stripWidthEta = parBook.stripPitchEta - stripDeadWidth;
281 parBook.stripWidthPhi = parBook.stripPitchPhi - stripDeadWidth;
282 parBook.numEtaStrips = record->getInt("nEtaStrips");
283 parBook.numPhiStrips = record->getInt("nPhiStrips");
284 parBook.firstOffSetPhi = record->getDouble("phiStripOffSet") * Gaudi::Units::cm +
285 0.5 * parBook.stripPitchPhi;
286 parBook.firstOffSetEta = record->getDouble("etaStripOffSet") * Gaudi::Units::cm +
287 record->getDouble("TCKSSU") * Gaudi::Units::cm +
288 0.5 * parBook.stripPitchEta;
289
290 ATH_MSG_VERBOSE("Extracted parameters for chamber "<<chambType
291 <<", num strips (eta/phi): "<<parBook.numEtaStrips<<"/"<<parBook.numPhiStrips
292 <<", strip pitch (eta/phi) "<<parBook.stripPitchEta<<"/"<<parBook.stripPitchPhi
293 <<", strip width (eta/phi): "<<parBook.stripWidthEta<<"/"<<parBook.stripWidthPhi
294 <<", strip offset (eta/phi): "<<parBook.firstOffSetEta<<"/"<<parBook.firstOffSetPhi
295 <<", etaStripOffSet: "<<(record->getDouble("etaStripOffSet") * Gaudi::Units::cm)
296 <<", phiStripOffSet: "<<(record->getDouble("phiStripOffSet") * Gaudi::Units::cm)
297 <<", TCKSSU: "<<(record->getDouble("TCKSSU")* Gaudi::Units::cm));
298 }
299 return StatusCode::SUCCESS;
300}
std::shared_ptr< IRDBRecordset > IRDBRecordset_ptr
std::unique_ptr< IRDBRecord > IRDBRecord_ptr
virtual std::string tagName() const =0
virtual std::string nodeName() const =0
virtual unsigned int size() const =0

Member Data Documentation

◆ m_geoDbTagSvc

ServiceHandle<IGeoDbTagSvc> MuonGMR4::RpcReadoutGeomTool::m_geoDbTagSvc {this, "GeoDbTagSvc", "GeoDbTagSvc"}
private

Definition at line 34 of file RpcReadoutGeomTool.h.

34{this, "GeoDbTagSvc", "GeoDbTagSvc"};

◆ m_geoUtilTool

PublicToolHandle<IMuonGeoUtilityTool> MuonGMR4::RpcReadoutGeomTool::m_geoUtilTool {this,"GeoUtilTool", "" }
private

Definition at line 36 of file RpcReadoutGeomTool.h.

36{this,"GeoUtilTool", "" };

◆ m_idHelperSvc

ServiceHandle<Muon::IMuonIdHelperSvc> MuonGMR4::RpcReadoutGeomTool::m_idHelperSvc
private
Initial value:
{this, "IdHelperSvc",
"Muon::MuonIdHelperSvc/MuonIdHelperSvc"}

Definition at line 31 of file RpcReadoutGeomTool.h.

31 {this, "IdHelperSvc",
32 "Muon::MuonIdHelperSvc/MuonIdHelperSvc"};

The documentation for this class was generated from the following files: