7#include <GaudiKernel/SystemOfUnits.h>
14#include <GeoModelKernel/GeoFullPhysVol.h>
15#include <GeoModelKernel/GeoPhysVol.h>
16#include <GeoModelKernel/GeoBox.h>
18#include <GeoModelRead/ReadGeoModel.h>
23# include "Acts/Utilities/BoundFactory.hpp"
40 GeoChildNodeWithTrf{
std::move(physVol)},
51 bool phiPlane)
const {
54 ATH_MSG_VERBOSE(
"Parameter book does not for see a readout in "<<(phiPlane?
"phi" :
"eta")<<
" direction");
58 const double halfX = phiPlane ? planeBox->getYHalfLength() : planeBox->getZHalfLength();
59 const double halfY = phiPlane ? planeBox->getZHalfLength() : planeBox->getYHalfLength();
64 auto newDesign = std::make_unique<StripDesign>();
65 newDesign->defineTrapezoid(
halfY,
halfY, halfX);
66 newDesign->defineStripLayout(firstPos * Amg::Vector2D::UnitX(), pitch,
width, nStrips);
79 return StatusCode::FAILURE;
83 if (shape->typeID() != GeoBox::getClassTypeID()) {
85 return StatusCode::FAILURE;
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;
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);});
110 if (rpcLayers.empty()) {
113 return StatusCode::FAILURE;
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; });
126 std::vector<GeoChildNodeWithTrf> gasGaps = fetchNodes(
"RpcGasGap");
127 if (gasGaps.empty()) {
129 return StatusCode::FAILURE;
131 std::vector<GeoChildNodeWithTrf> stripLayers = fetchNodes(
"bottomStripLayer");
132 if (stripLayers.empty()) {
134 return StatusCode::FAILURE;
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);
150 define.
nPanelsInPhi = modulePhi == 2 ? 1 : allGapsWithIdx.size () / gasGap;
154 return StatusCode::FAILURE;
156 const wRPCTable& paramBook{parBookItr->second};
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);
163 define.
layers[layIdx] = (*factoryCache.
stripLayers.emplace(std::move(stripLay)).first);
166 for (
gapVolume& gapVol : allGapsWithIdx) {
167 const GeoShape* gapShape =
m_geoUtilTool->extractShape(gapVol.volume);
168 if (gapShape->typeID() != GeoBox::getClassTypeID()) {
170 return StatusCode::FAILURE;
172 const GeoBox* gapBox =
static_cast<const GeoBox*
>(gapShape);
177 etaDesign = (*factoryCache.
stripDesigns.emplace(etaDesign).first);
180 phiDesign = (*factoryCache.
stripDesigns.emplace(phiDesign).first);
188 gapVol.transform = gapVol.transform *
Amg::getRotateY3D( (isAside ? -90. : 90.)* Gaudi::Units::degree);
190 if (etaDesign && phiDesign) {
191 insertStripLayer(std::make_unique<StripLayer>(factoryCache.
trfNodeMaker.makeTransform(gapVol.transform),
192 etaDesign, phiDesign,
194 }
else if (etaDesign) {
195 insertStripLayer(std::make_unique<StripLayer>(factoryCache.
trfNodeMaker.makeTransform(gapVol.transform),
198 ATH_MSG_ERROR(
"It's not forseen to have a chamber without eta design");
199 return StatusCode::FAILURE;
202 return StatusCode::SUCCESS;
205 GeoModelIO::ReadGeoModel* sqliteReader =
m_geoDbTagSvc->getSqliteReader();
207 ATH_MSG_FATAL(
"Error, the tool works exclusively from sqlite geometry inputs");
208 return StatusCode::FAILURE;
218 physNodeMap mapFPV = sqliteReader->getPublishedNodes<std::string, GeoFullPhysVol*>(
"Muon");
219#ifndef SIMULATIONBASE
220 auto layerBounds = std::make_shared<Acts::SurfaceBoundFactory>();
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) {
244 ATH_MSG_FATAL(
"Failed to construct the station Identifier from "<<key);
245 return StatusCode::FAILURE;
254#ifndef SIMULATIONBASE
257 std::unique_ptr<RpcReadoutElement> readoutEle = std::make_unique<RpcReadoutElement>(std::move(define));
258 ATH_CHECK(mgr.addRpcReadoutElement(std::move(readoutEle)));
260 return StatusCode::SUCCESS;
266 if (paramTable->
size() == 0) {
268 return StatusCode::FAILURE;
271 << paramTable->
tagName() <<
"] table with "
272 << paramTable->
size() <<
" records");
275 const std::string chambType = 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;
284 parBook.
firstOffSetPhi = record->getDouble(
"phiStripOffSet") * Gaudi::Units::cm +
286 parBook.
firstOffSetEta = record->getDouble(
"etaStripOffSet") * Gaudi::Units::cm +
287 record->getDouble(
"TCKSSU") * Gaudi::Units::cm +
295 <<
", etaStripOffSet: "<<(record->getDouble(
"etaStripOffSet") * Gaudi::Units::cm)
296 <<
", phiStripOffSet: "<<(record->getDouble(
"phiStripOffSet") * Gaudi::Units::cm)
297 <<
", TCKSSU: "<<(record->getDouble(
"TCKSSU")* Gaudi::Units::cm));
299 return StatusCode::SUCCESS;
Scalar phi() const
phi method
#define ATH_CHECK
Evaluate an expression and check for errors.
#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 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
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.
int stationNameIndex(const std::string &name) const
Identifier padID(const Identifier &elementID, int doubletZ, int doubletPhi) const
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
Amg::Transform3D getRotateY3D(double angle)
get a rotation transformation around Y-axis
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...
double halfY(const Acts::VolumeBounds &bounds)
Returns the half-Y length for the parsed volume bounds (Trapezoid/ Cuboid)
RpcReadoutElement::defineArgs defineArgs
IMuonGeoUtilityTool::physVolWithTrans physVolWithTrans
GeoModel::TransientConstSharedPtr< StripDesign > StripDesignPtr
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.
Identifier detElId
ATLAS identifier.
GeoIntrusivePtr< GeoVFullPhysVol > physVol
Pointer to the underlying physical volume in GeoModel.
const GeoAlignableTransform * alignTransform
Pointer to the alignable transformation.
std::string chambDesign
chamber design name as it's occuring in the parameter book tables E.g. BMS5, RPC10,...
double halfLength
RPC panel dimensions.
int nPanelsInPhi
Each gas gap is usually subdivided into 2 phi panels which is actually the sector granularity of the ...
unsigned nGasGaps
The number of gas gaps (along the radial direction) in the RPC chamber (2 or 3)
double halfThickness
Half thickness of the Rpc module.
std::vector< StripLayerPtr > layers
double halfWidth
Elongation within the sector.
std::shared_ptr< Acts::SurfaceBoundFactory > layerBounds
Helper struct to attribute the Identifier fields with the gas gap volumes.
gapVolume(GeoChildNodeWithTrf &&physVol, unsigned gap, unsigned phi)