diff --git a/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonGeoModelR4/src/MuonGeoUtilitiyTool.cxx b/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonGeoModelR4/src/MuonGeoUtilitiyTool.cxx index 73a4cc5ccdd1f1e1b3b9cc325dfaca2f5032d041..794623caa937563414a6d0224b2d0f01151c3f16 100644 --- a/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonGeoModelR4/src/MuonGeoUtilitiyTool.cxx +++ b/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonGeoModelR4/src/MuonGeoUtilitiyTool.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration */ #include "MuonGeoUtilityTool.h" @@ -20,8 +20,10 @@ #include <GeoModelKernel/GeoVolumeCursor.h> #include <GeoModelHelpers/GeoShapeUtils.h> +#include <GeoModelHelpers/printVolume.h> #include <GeoModelHelpers/TransformToStringConverter.h> + #include <set> #include <sstream> #include <string> @@ -31,9 +33,6 @@ using namespace ActsTrk; namespace MuonGMR4{ MuonGeoUtilityTool::~MuonGeoUtilityTool() = default; -MuonGeoUtilityTool::MuonGeoUtilityTool(const std::string &type, const std::string &name, - const IInterface *parent): - base_class(type,name,parent) {} const GeoShape* MuonGeoUtilityTool::extractShape(const PVConstLink& physVol) const { const GeoLogVol* logVol = physVol->getLogVol(); @@ -88,48 +87,7 @@ Amg::Transform3D MuonGeoUtilityTool::extractShifts(const GeoShape* inShape) cons return sumTrans; } std::string MuonGeoUtilityTool::dumpShape(const GeoShape* shape) const { return printGeoShape(shape); } -std::string MuonGeoUtilityTool::dumpVolume(const PVConstLink& physVol) const { - return dumpVolume(physVol, ""); -} -std::string MuonGeoUtilityTool::dumpVolume(const PVConstLink& physVol, const std::string& childDelim) const { - std::stringstream sstr{}; - if (!physVol || !physVol->getLogVol()){ - ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" "<<__func__<<" No logical volume attached "); - return sstr.str(); - } - const GeoShape* shape = extractShape(physVol); - if (!shape) { - ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" "<<__func__ - <<" Failed to extract shape from phys volume " - << physVol->getLogVol()->getName()); - return sstr.str(); - } - sstr<<"logical volume "<<physVol->getLogVol()->getName()<<", "; - if (physVol->isShared() || !physVol->getParent()){ - sstr<<"shared volume, "; - } else { - const GeoVPhysVol* pv = physVol; - if (typeid(*pv) == typeid(GeoFullPhysVol)){ - const Amg::Transform3D absTrans = static_cast<const GeoFullPhysVol&>(*physVol).getAbsoluteTransform(); - sstr<<"absolute pos: "<<GeoTrf::toString(absTrans,true) << ", "; - } else{ - sstr<<"relative pos: "<<GeoTrf::toString(physVol->getX(), true)<<", "; - } - } - sstr<<dumpShape(shape)<<", "; - const Amg::Transform3D shift = extractShifts(physVol); - if (!Amg::isIdentity(shift)) { - sstr<<" shape shifted by "<<GeoTrf::toString(shift, true); - } - sstr<<"number of children "<<physVol->getNChildVols()<<", "<<std::endl; - std::vector<GeoChildNodeWithTrf> children = getChildrenWithRef(physVol, false); - for (unsigned int child = 0; child < children.size(); ++child) { - sstr<<childDelim<<(child+1)<<": "<<GeoTrf::toString(children[child].transform, true) - <<", "<< dumpVolume(children[child].volume, childDelim + " "); - } - return sstr.str(); -} - +std::string MuonGeoUtilityTool::dumpVolume(const PVConstLink& physVol) const { return printVolume(physVol); } const GeoAlignableTransform* MuonGeoUtilityTool::findAlignableTransform(const PVConstLink& physVol) const { PVConstLink parent{physVol->getParent()}, child{physVol}; while (parent) { @@ -148,26 +106,9 @@ const GeoAlignableTransform* MuonGeoUtilityTool::findAlignableTransform(const PV } std::vector<MuonGeoUtilityTool::physVolWithTrans> MuonGeoUtilityTool::findAllLeafNodesByName(const PVConstLink& physVol, const std::string& volumeName) const { - const std::vector<physVolWithTrans> children = getChildrenWithRef(physVol, false); - std::vector<physVolWithTrans> foundVols{}; - for (const physVolWithTrans& child : children) { - /// The logical volume has precisely the name for what we're searching for - if (child.volume->getLogVol()->getName() == volumeName || child.nodeName == volumeName) { - foundVols.push_back(child); - } - /// There are no grand children of this volume. We're at a leaf node - if (!child.volume->getNChildVols()) { - continue; - } - std::vector<physVolWithTrans> grandChildren = findAllLeafNodesByName(child.volume, volumeName); - std::transform(std::make_move_iterator(grandChildren.begin()), - std::make_move_iterator(grandChildren.end()), std::back_inserter(foundVols), - [&child](physVolWithTrans&& vol){ - vol.transform = child.transform * vol.transform; - return vol; - }); - } - return foundVols; + return getAllSubVolumes(physVol,[&volumeName](const physVolWithTrans& child){ + return child.volume->getLogVol()->getName() == volumeName || child.nodeName == volumeName; + }); } std::vector<const GeoShape*> MuonGeoUtilityTool::getComponents(const GeoShape* booleanShape) const { return getBooleanComponents(booleanShape); diff --git a/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonGeoModelR4/src/MuonGeoUtilityTool.h b/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonGeoModelR4/src/MuonGeoUtilityTool.h index 786e0b81f0406f6ab63669899521d991057c9c4b..44f987e306af060bd463995a054c9041bb851a93 100644 --- a/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonGeoModelR4/src/MuonGeoUtilityTool.h +++ b/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonGeoModelR4/src/MuonGeoUtilityTool.h @@ -19,8 +19,7 @@ class MuonGeoUtilityTool final : public extends<AthAlgTool, IMuonGeoUtilityTool public: // Constructor - MuonGeoUtilityTool(const std::string &type, const std::string &name, - const IInterface *parent); + using base_class::base_class; // Destructor virtual ~MuonGeoUtilityTool() override final; @@ -51,7 +50,6 @@ class MuonGeoUtilityTool final : public extends<AthAlgTool, IMuonGeoUtilityTool const Amg::Transform3D& refTrf) const override; private: - std::string dumpVolume(const PVConstLink& physVol, const std::string& childDelim) const; }; } // namespace MuonGMR4 diff --git a/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonGeoModelR4/src/RpcReadoutGeomTool.cxx b/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonGeoModelR4/src/RpcReadoutGeomTool.cxx index bfd1f5e24eba5e9526dbf35b545a36d775927af1..edee52ea903ab0f59829f724df71e4c7d2faa6cb 100644 --- a/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonGeoModelR4/src/RpcReadoutGeomTool.cxx +++ b/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonGeoModelR4/src/RpcReadoutGeomTool.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration */ #include "RpcReadoutGeomTool.h" @@ -38,11 +38,11 @@ using defineArgs = RpcReadoutElement::defineArgs; /// Helper struct to attribute the Identifier fields with the /// gas gap volumes -struct gapVolume: public physVolWithTrans { - gapVolume(physVolWithTrans&& physVol, +struct gapVolume: public GeoChildNodeWithTrf { + gapVolume(GeoChildNodeWithTrf&& physVol, unsigned int gap, unsigned int phi): - physVolWithTrans{std::move(physVol)}, + GeoChildNodeWithTrf{std::move(physVol)}, gasGap{gap}, doubPhi{phi} {} unsigned int gasGap{0}; @@ -50,18 +50,7 @@ struct gapVolume: public physVolWithTrans { }; -inline bool layerSorter(const physVolWithTrans&a, const physVolWithTrans & b){ - const Amg::Vector3D cA = a.transform.translation(); - const Amg::Vector3D cB = b.transform.translation(); - if (std::abs(cA.x() - cB.x()) > tolerance) return (cA.x() < cB.x()); - return (cA.y() < cB.y()); -} - -RpcReadoutGeomTool::RpcReadoutGeomTool(const std::string& type, - const std::string& name, - const IInterface* parent) - : base_class{type, name, parent} {} StatusCode RpcReadoutGeomTool::loadDimensions(RpcReadoutElement::defineArgs& define, FactoryCache& factoryCache) { @@ -95,62 +84,55 @@ StatusCode RpcReadoutGeomTool::loadDimensions(RpcReadoutElement::defineArgs& def * | Strip layer | Strip layer | | Strip layer | Strip layer | * */ - std::vector<physVolWithTrans> stripLayers = m_geoUtilTool->findAllLeafNodesByName(define.physVol, "bottomStripLayer"); - if (stripLayers.empty()) { - ATH_MSG_FATAL("The volume "<<m_idHelperSvc->toStringDetEl(define.detElId)<<" does not have any childern 'bottomStripLayer'" - <<std::endl<<m_geoUtilTool->dumpVolume(define.physVol)); - return StatusCode::FAILURE; - } - std::vector<physVolWithTrans> allGasGaps = m_geoUtilTool->findAllLeafNodesByName(define.physVol, "RpcGasGap"); - if (allGasGaps.empty()) { - ATH_MSG_FATAL("The volume "<<m_idHelperSvc->toStringDetEl(define.detElId)<<" does not have any childern 'RpcGasGap'" + std::vector<GeoChildNodeWithTrf> rpcLayers = getChildrenWithRef(define.physVol, false); + /// Fetch all volumes with Identifiers from the tree + rpcLayers.erase(std::remove_if(rpcLayers.begin(), rpcLayers.end(), + [](const GeoChildNodeWithTrf& subVol){ return !subVol.volumeId; }), rpcLayers.end()); + /// Next sort them by Identifier + std::ranges::sort(rpcLayers, [](const GeoChildNodeWithTrf& a, const GeoChildNodeWithTrf& b){ + return a.volumeId.value_or(0) < b.volumeId.value_or(0);}); + + if (rpcLayers.empty()) { + ATH_MSG_FATAL("The volume "<<m_idHelperSvc->toStringDetEl(define.detElId)<<" does not have any childern with Identifiers " <<std::endl<<m_geoUtilTool->dumpVolume(define.physVol)); return StatusCode::FAILURE; } - /// In the GeoModel world, the x-axis points in radial direction & y axis along the phi direction - std::stable_sort(allGasGaps.begin(), allGasGaps.end(), layerSorter); - std::stable_sort(stripLayers.begin(),stripLayers.end(), layerSorter); - /// The strip layers are used to express the dimensions of the strip layer. However, that's projected into the - /// Center of the gasgap which may or maybe not be split into two --> Find the closest gas gap in x for each - /// strip layer and overwrite the x coordinate of the strip layerof that one. - for (physVolWithTrans& stripLayer : stripLayers){ - /// Find the closest gas Gap - const Amg::Vector3D stripTrans = stripLayer.transform.translation(); - std::vector<physVolWithTrans>::iterator closestGap = std::min_element(allGasGaps.begin(), allGasGaps.end(), - [&stripTrans](const physVolWithTrans& a, const physVolWithTrans& b){ - return std::abs(stripTrans.x() - a.transform.translation().x()) < - std::abs(stripTrans.x() - b.transform.translation().x()); - }); - stripLayer.transform.translation().x() = closestGap->transform.translation().x(); - } + /// Fetch for each rpc layer the gasGaps + unsigned int gasGap{0}; + const unsigned int modulePhi = m_idHelperSvc->rpcIdHelper().doubletPhi(define.detElId); - /// Now we need to associate the gasGap volumes with the gas gap number & - /// the doublet Phi - Amg::Vector3D prevGap{stripLayers[0].transform.translation()}; - unsigned int gasGap{1}, doubletPhi{0}; - - unsigned int modulePhi = m_idHelperSvc->rpcIdHelper().doubletPhi(define.detElId); std::vector<gapVolume> allGapsWithIdx{}; - const bool isAside{m_idHelperSvc->stationEta(define.detElId) > 0}; - for (physVolWithTrans& gapVol : stripLayers) { - Amg::Vector3D gCen = gapVol.transform.translation(); - /// The volume points to a new gasgap - if (std::abs(gCen.x() - prevGap.x()) > tolerance) { - ++gasGap; - doubletPhi = 1; - } else ++doubletPhi; - ATH_MSG_DEBUG("Gas gap at "<<Amg::toString(gCen, 2)<<" is associated with gasGap: "<<gasGap<<", doubletPhi: "<<doubletPhi); - prevGap = std::move(gCen); - /// Rpc volumes with doubletZ = 3 have two gas gaps along phi but they're split into two - /// distnict modules with doublePhi = 1, 2. - doubletPhi = std::max (doubletPhi, modulePhi); - allGapsWithIdx.emplace_back(std::move(gapVol), gasGap, doubletPhi); + for (const GeoChildNodeWithTrf& rpcSinglet : rpcLayers) { + auto fetchNodes = [this, &rpcSinglet] (const std::string& leafName) { + std::vector<GeoChildNodeWithTrf> nodes = m_geoUtilTool->findAllLeafNodesByName(rpcSinglet.volume, leafName); + std::ranges::for_each(nodes,[&rpcSinglet](GeoChildNodeWithTrf& node){ node.transform = rpcSinglet.transform * node.transform; }); + return nodes; + }; + std::vector<GeoChildNodeWithTrf> gasGaps = fetchNodes("RpcGasGap"); + if (gasGaps.empty()) { + ATH_MSG_FATAL("The child "<<m_geoUtilTool->dumpVolume(rpcSinglet.volume)<<" has "<<gasGaps.size()<<" gasGaps. "); + return StatusCode::FAILURE; + } + std::vector<GeoChildNodeWithTrf> stripLayers = fetchNodes("bottomStripLayer"); + if (stripLayers.empty()) { + ATH_MSG_FATAL("The child "<<m_geoUtilTool->dumpVolume(rpcSinglet.volume)<<" does not have a strip layer "); + return StatusCode::FAILURE; + } + ++gasGap; + for (GeoChildNodeWithTrf& stripPanel : stripLayers) { + /// Adjust the height of the strip panel to be in the centre of the gasGap + stripPanel.transform.translation().x() = gasGaps.front().transform.translation().x(); + const int doubPhi = std::max(modulePhi, 1u*stripPanel.volumeId.value_or(999)); + allGapsWithIdx.emplace_back(std::move(stripPanel), gasGap, doubPhi); + } } + + const bool isAside{m_idHelperSvc->stationEta(define.detElId) > 0}; /// We know now whether we had 2 or 3 gasgaps and also whether there 2 or 1 panels in phi define.nGasGaps = gasGap; /// Special case for the BML4 DBZ = 3 chambers. The doubletPhi is incorporated /// into the detector element but there's only one strip panel - define.nPanelsInPhi = modulePhi == 2 ? 1 : doubletPhi; + define.nPanelsInPhi = modulePhi == 2 ? 1 : allGapsWithIdx.size () / gasGap; FactoryCache::ParamBookTable::const_iterator parBookItr = factoryCache.parameterBook.find(define.chambDesign); if (parBookItr == factoryCache.parameterBook.end()) { ATH_MSG_FATAL("The chamber "<<define.chambDesign<<" is not part of the WRPC table"); diff --git a/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonGeoModelR4/src/RpcReadoutGeomTool.h b/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonGeoModelR4/src/RpcReadoutGeomTool.h index a3a110131c0c5c21d6211a7d95c81a7dd5438942..1e54c0f4b1d581e517a0c53b9490aa4fbbc2524d 100644 --- a/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonGeoModelR4/src/RpcReadoutGeomTool.h +++ b/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonGeoModelR4/src/RpcReadoutGeomTool.h @@ -19,8 +19,7 @@ namespace MuonGMR4 { class RpcReadoutGeomTool : public extends<AthAlgTool,IMuonReadoutGeomTool> { public: // Constructor - RpcReadoutGeomTool(const std::string &type, const std::string &name, - const IInterface *parent); + using base_class::base_class; StatusCode buildReadOutElements(MuonDetectorManager &mgr) override final; diff --git a/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonGeoModelTestR4/python/testGeoModel.py b/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonGeoModelTestR4/python/testGeoModel.py index cb6b6aba13ef77076dd8e40390366af94e02122a..e3e4e024b4834ccbf2e7e4f151c4b27372c40533 100644 --- a/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonGeoModelTestR4/python/testGeoModel.py +++ b/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonGeoModelTestR4/python/testGeoModel.py @@ -6,7 +6,7 @@ def geoModelFileDefault(useR4Layout = False): # If this is changed, remember to also test with other dependent tests # e.g. run ctest with ActsEventCnv if useR4Layout: - return "/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/MuonRecRTT/ATLAS-R4-MUONTEST.db" + return "/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/MuonGeomRTT/GeoDB/ATLAS-P2-RUN4-01-00-00.db" return "/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/MuonGeomRTT/GeoDB/ATLAS-R3S-2021-03-02-00.db" def SetupArgParser(): diff --git a/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonGeoModelTestR4/util/runRpcGeoComparison.cxx b/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonGeoModelTestR4/util/runRpcGeoComparison.cxx index 483bfd69fab8c1c4f31f522f542eb33cf3ffe36c..99d77f351f1e1e2c41e4eaefdf8526f40c2c24e1 100644 --- a/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonGeoModelTestR4/util/runRpcGeoComparison.cxx +++ b/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonGeoModelTestR4/util/runRpcGeoComparison.cxx @@ -434,8 +434,8 @@ int main( int argc, char** argv ) { const Amg::Vector3D diffStrip{testStrip.position - refStrip.position}; if (diffStrip.mag() > tolerance) { constexpr unsigned int maxFail = 3; - if ( (!refStrip.measPhi && (++failedEta) <= maxFail) || - (refStrip.measPhi && (++failedPhi) <= maxFail) ) { + if ( (!refStrip.measPhi && ( (++failedEta) <= maxFail || refStrip.strip <= 3)) || + (refStrip.measPhi && ( (++failedPhi) <= maxFail || refStrip.strip <= 3)) ) { std::cerr<<"runRpcGeoComparison() "<<__LINE__<<": "<<test<<" " <<testStrip<<" should be located at "<<Amg::toString(refStrip.position, 2) <<" displacement: "<<Amg::toString(diffStrip,2)<<", perp: "