7 #include <GaudiKernel/SystemOfUnits.h>
13 #include <GeoModelKernel/GeoFullPhysVol.h>
14 #include <GeoModelKernel/GeoPhysVol.h>
15 #include <GeoModelKernel/GeoTrd.h>
16 #include <GeoModelKernel/GeoBox.h>
18 #include <GeoModelRead/ReadGeoModel.h>
23 #ifndef SIMULATIONBASE
24 # include "Acts/Surfaces/TrapezoidBounds.hpp"
41 GeoChildNodeWithTrf{std::move(physVol)},
45 unsigned int doubPhi{0};
55 <<std::endl<<std::endl<<m_geoUtilTool->dumpVolume(define.
physVol));
57 const GeoShape* shape = m_geoUtilTool->extractShape(define.
physVol);
60 return StatusCode::FAILURE;
62 ATH_MSG_DEBUG(
"Extracted shape "<<m_geoUtilTool->dumpShape(shape));
64 if (shape->typeID() != GeoBox::getClassTypeID()) {
65 ATH_MSG_FATAL(__FILE__<<
":"<<__LINE__<<
" expect shape to be a box but it's "<<m_geoUtilTool->dumpShape(shape));
66 return StatusCode::FAILURE;
69 const GeoBox* box =
static_cast<const GeoBox*
>(shape);
83 std::vector<GeoChildNodeWithTrf> rpcLayers = getChildrenWithRef(define.
physVol,
false);
85 rpcLayers.erase(std::remove_if(rpcLayers.begin(), rpcLayers.end(),
86 [](
const GeoChildNodeWithTrf& subVol){ return !subVol.volumeId; }), rpcLayers.end());
88 std::ranges::sort(rpcLayers, [](
const GeoChildNodeWithTrf&
a,
const GeoChildNodeWithTrf&
b){
89 return a.volumeId.value_or(0) <
b.volumeId.value_or(0);});
91 if (rpcLayers.empty()) {
92 ATH_MSG_FATAL(
"The volume "<<m_idHelperSvc->toStringDetEl(define.
detElId)<<
" does not have any childern with Identifiers "
93 <<std::endl<<m_geoUtilTool->dumpVolume(define.
physVol));
94 return StatusCode::FAILURE;
98 const unsigned int modulePhi = m_idHelperSvc->rpcIdHelper().doubletPhi(define.
detElId);
100 std::vector<gapVolume> allGapsWithIdx{};
101 for (
const GeoChildNodeWithTrf& rpcSinglet : rpcLayers) {
102 auto fetchNodes = [
this, &rpcSinglet] (
const std::string& leafName) {
103 std::vector<GeoChildNodeWithTrf> nodes = m_geoUtilTool->findAllLeafNodesByName(rpcSinglet.volume, leafName);
104 std::ranges::for_each(nodes,[&rpcSinglet](GeoChildNodeWithTrf&
node){
node.transform = rpcSinglet.transform *
node.transform; });
107 std::vector<GeoChildNodeWithTrf> gasGaps = fetchNodes(
"RpcGasGap");
108 if (gasGaps.empty()) {
109 ATH_MSG_FATAL(
"The child "<<m_geoUtilTool->dumpVolume(rpcSinglet.volume)<<
" has "<<gasGaps.size()<<
" gasGaps. ");
110 return StatusCode::FAILURE;
112 std::vector<GeoChildNodeWithTrf> stripLayers = fetchNodes(
"bottomStripLayer");
113 if (stripLayers.empty()) {
114 ATH_MSG_FATAL(
"The child "<<m_geoUtilTool->dumpVolume(rpcSinglet.volume)<<
" does not have a strip layer ");
115 return StatusCode::FAILURE;
118 for (GeoChildNodeWithTrf& stripPanel : stripLayers) {
120 stripPanel.transform.translation().x() = gasGaps.front().transform.translation().x();
121 const int doubPhi =
std::max(modulePhi, 1
u*stripPanel.volumeId.value_or(999));
122 allGapsWithIdx.emplace_back(std::move(stripPanel),
gasGap, doubPhi);
126 const bool isAside{m_idHelperSvc->stationEta(define.
detElId) > 0};
135 return StatusCode::FAILURE;
137 const wRPCTable& paramBook{parBookItr->second};
139 for (
gapVolume& gapVol : allGapsWithIdx) {
140 const GeoShape* gapShape = m_geoUtilTool->extractShape(gapVol.volume);
141 if (gapShape->typeID() != GeoBox::getClassTypeID()) {
143 return StatusCode::FAILURE;
145 const GeoBox* gapBox =
static_cast<const GeoBox*
>(gapShape);
146 ATH_MSG_DEBUG(
"Gas gap dimensions "<<m_geoUtilTool->dumpShape(gapBox));
149 const double firstStripPosEta = -gapBox->getZHalfLength() + paramBook.firstOffSetEta;
150 etaDesign->defineStripLayout(firstStripPosEta * Amg::Vector2D::UnitX(),
151 paramBook.stripPitchEta,
152 paramBook.stripWidthEta,
153 paramBook.numEtaStrips);
155 etaDesign->defineTrapezoid(gapBox->getYHalfLength(), gapBox->getYHalfLength(), gapBox->getZHalfLength());
158 etaDesign = (*factoryCache.
stripDesigns.emplace(etaDesign).first);
159 const IdentifierHash etaHash {RpcReadoutElement::createHash(0, gapVol.gasGap, gapVol.doubPhi,
false)};
160 const unsigned int etaIdx =
static_cast<unsigned int>(etaHash);
161 if (etaIdx >= define.
layers.size()) {
162 define.
layers.resize(etaIdx + 1);
165 auto etaLayer = std::make_unique<StripLayer>(gapVol.transform, etaDesign, etaHash);
166 define.
layers[etaIdx] = (*factoryCache.
stripLayers.emplace(std::move(etaLayer)).first);
171 if (!paramBook.numPhiStrips) {
176 const double firstStripPosPhi = -gapBox->getYHalfLength() + paramBook.firstOffSetPhi;
177 phiDesign->defineStripLayout(firstStripPosPhi * Amg::Vector2D::UnitX(),
178 paramBook.stripPitchPhi,
179 paramBook.stripWidthPhi,
180 paramBook.numPhiStrips);
181 phiDesign->defineTrapezoid(gapBox->getZHalfLength(), gapBox->getZHalfLength(), gapBox->getYHalfLength());
183 phiDesign = (*factoryCache.
stripDesigns.emplace(phiDesign).first);
185 const IdentifierHash phiHash {RpcReadoutElement::createHash(0, gapVol.gasGap, gapVol.doubPhi,
true)};
186 const unsigned int phiIdx =
static_cast<unsigned int>(phiHash);
187 if (phiIdx >= define.
layers.size()) {
188 define.
layers.resize(phiIdx + 1);
192 define.
layers[phiIdx] = (*factoryCache.
stripLayers.emplace(std::move(phiLayer)).first);
196 return StatusCode::SUCCESS;
199 GeoModelIO::ReadGeoModel* sqliteReader = m_geoDbTagSvc->getSqliteReader();
201 ATH_MSG_FATAL(
"Error, the tool works exclusively from sqlite geometry inputs");
202 return StatusCode::FAILURE;
208 const RpcIdHelper& idHelper{m_idHelperSvc->rpcIdHelper()};
212 physNodeMap mapFPV = sqliteReader->getPublishedNodes<std::string, GeoFullPhysVol*>(
"Muon");
213 #ifndef SIMULATIONBASE
216 for (
auto& [
key,
pv] : mapFPV) {
223 std::vector<std::string> key_tokens =
tokenize(
key,
"_");
224 if (key_tokens.size() < 7 ||
225 key_tokens[1].find(
"RPC") == std::string::npos) {
230 const Identifier elementID = idHelper.padID(idHelper.stationNameIndex(key_tokens[0].substr(0, 3)),
239 return StatusCode::FAILURE;
243 define.chambDesign = key_tokens[1];
244 define.alignTransform = m_geoUtilTool->findAlignableTransform(define.physVol);
245 define.detElId = elementID;
246 ATH_MSG_VERBOSE(
"Key "<<
key<<
" lead to Identifier "<<m_idHelperSvc->toStringDetEl(elementID));
247 ATH_CHECK(loadDimensions(define, facCache));
248 #ifndef SIMULATIONBASE
249 define.layerBounds = layerBounds;
251 std::unique_ptr<RpcReadoutElement> readoutEle = std::make_unique<RpcReadoutElement>(std::move(define));
252 ATH_CHECK(
mgr.addRpcReadoutElement(std::move(readoutEle)));
254 return StatusCode::SUCCESS;
260 if (paramTable->size() == 0) {
262 return StatusCode::FAILURE;
265 << paramTable->tagName() <<
"] table with "
266 << paramTable->size() <<
" records");
269 const std::string chambType = record->getString(
"WRPC_TYPE");
273 const double stripDeadWidth = record->getDouble(
"stripDeadWidth") *
Gaudi::Units::cm;
289 <<
", etaStripOffSet: "<<(record->getDouble(
"etaStripOffSet") *
Gaudi::Units::cm)
290 <<
", phiStripOffSet: "<<(record->getDouble(
"phiStripOffSet") *
Gaudi::Units::cm)
293 return StatusCode::SUCCESS;