From 4b40ebeb4182bb10e9d966632eafbfdd270425e2 Mon Sep 17 00:00:00 2001 From: Johannes Junggeburth <johannes.josef.junggeburth@cern.ch> Date: Wed, 8 May 2024 09:36:56 +0200 Subject: [PATCH] Muon R4 - Add infrastructure to digitize BI-RPC hits Muon R4 - Add infrastructure to digitize BI-RPC hits --- .../src/xAODSimHitToRpcMeasCnvAlg.cxx | 248 ++++++++++++------ .../src/xAODSimHitToRpcMeasCnvAlg.h | 32 +++ 2 files changed, 206 insertions(+), 74 deletions(-) diff --git a/MuonSpectrometer/MuonPhaseII/MuonCnv/xAODMuonSimHitCnv/src/xAODSimHitToRpcMeasCnvAlg.cxx b/MuonSpectrometer/MuonPhaseII/MuonCnv/xAODMuonSimHitCnv/src/xAODSimHitToRpcMeasCnvAlg.cxx index 32611e78c423..ffd7ee8eebea 100644 --- a/MuonSpectrometer/MuonPhaseII/MuonCnv/xAODMuonSimHitCnv/src/xAODSimHitToRpcMeasCnvAlg.cxx +++ b/MuonSpectrometer/MuonPhaseII/MuonCnv/xAODMuonSimHitCnv/src/xAODSimHitToRpcMeasCnvAlg.cxx @@ -1,10 +1,12 @@ /* - Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration */ #include "xAODSimHitToRpcMeasCnvAlg.h" #include <xAODMuonPrepData/RpcStripAuxContainer.h> +#include <xAODMuonPrepData/RpcStrip2DAuxContainer.h> + #include <MuonReadoutGeometryR4/RpcReadoutElement.h> #include <MuonReadoutGeometryR4/MuonChamber.h> @@ -21,6 +23,9 @@ namespace { constexpr double percentage( unsigned int numerator, unsigned int denom) { return 100. * numerator / std::max(denom, 1u); } + + using CheckVector2D = MuonGMR4::CheckVector2D; + } xAODSimHitToRpcMeasCnvAlg::xAODSimHitToRpcMeasCnvAlg(const std::string& name, @@ -31,7 +36,10 @@ StatusCode xAODSimHitToRpcMeasCnvAlg::initialize(){ ATH_CHECK(m_geoCtxKey.initialize()); ATH_CHECK(m_readKey.initialize()); ATH_CHECK(m_writeKey.initialize()); + ATH_CHECK(m_writeKeyBI.initialize(!m_writeKeyBI.empty())); + ATH_CHECK(m_idHelperSvc.retrieve()); + m_stIdxBIL = m_idHelperSvc->rpcIdHelper().stationNameIndex("BIL"); ATH_CHECK(detStore()->retrieve(m_DetMgr)); return StatusCode::SUCCESS; } @@ -41,6 +49,156 @@ StatusCode xAODSimHitToRpcMeasCnvAlg::finalize() { <<percentage(m_acceptedHits[1], m_allHits[1]) <<" cases, the conversion was successful"); return StatusCode::SUCCESS; } +void xAODSimHitToRpcMeasCnvAlg::digitizeHit(const double hitTime, + const double locPosOnStrip, + const MuonGMR4::StripDesignPtr& designPtr, + const Identifier& gasGapId, + const bool measuresPhi, + xAOD::RpcStripContainer& prdContainer, + CLHEP::HepRandomEngine* rndEngine) const { + + /// There're Rpc chambers without phi strips (BI) + if (!designPtr){ + return; + } + const MuonGMR4::StripDesign& design{*designPtr}; + + const double uncert = design.stripPitch() / std::sqrt(12.); + const double smearedX = CLHEP::RandGaussZiggurat::shoot(rndEngine, locPosOnStrip, uncert); + const Amg::Vector2D locHitPos{smearedX * Amg::Vector2D::UnitX()}; + ++(m_allHits[measuresPhi]); + if (!design.insideTrapezoid(locHitPos)) { + ATH_MSG_VERBOSE("The hit "<<Amg::toString(locHitPos)<<" is outside of the trapezoid bounds for " + <<m_idHelperSvc->toStringGasGap(gasGapId)<<", measuresPhi: "<<(measuresPhi ? "yay" : "nay")); + return; + } + const int strip = stripNumber(design, locHitPos); + if (strip < 0) { + ATH_MSG_VERBOSE("Hit " << Amg::toString(locHitPos) << " cannot trigger any signal in a strip for " + << m_idHelperSvc->toStringGasGap(gasGapId) <<", measuresPhi: "<<(measuresPhi ? "yay" : "nay")); + return; + } + + const RpcIdHelper& id_helper{m_idHelperSvc->rpcIdHelper()}; + + bool isValid{false}; + const Identifier prdId{id_helper.channelID(gasGapId, + id_helper.doubletZ(gasGapId), + id_helper.doubletPhi(gasGapId), + id_helper.gasGap(gasGapId), + measuresPhi, strip, isValid)}; + + if (!isValid) { + ATH_MSG_WARNING("Invalid hit identifier obtained for "<<m_idHelperSvc->toStringGasGap(gasGapId) + <<", eta strip "<<strip<<" & hit "<<Amg::toString(locHitPos,2 ) + <<" /// "<<design); + return; + } + ++(m_acceptedHits[measuresPhi]); + + xAOD::RpcStrip* prd = new xAOD::RpcStrip(); + prdContainer.push_back(prd); + + prd->setIdentifier(prdId.get_compact()); + xAOD::MeasVector<1> lPos{smearedX}; + xAOD::MeasMatrix<1> cov{uncert * uncert}; + prd->setMeasurement<1>(m_idHelperSvc->detElementHash(prdId), + std::move(lPos), std::move(cov)); + const MuonGMR4::RpcReadoutElement* readOutEle = m_DetMgr->getRpcReadoutElement(prdId); + prd->setReadoutElement(readOutEle); + prd->setStripNumber(strip); + prd->setGasGap(id_helper.gasGap(prdId)); + prd->setDoubletPhi(id_helper.doubletPhi(prdId)); + prd->setMeasuresPhi(id_helper.measuresPhi(prdId)); + prd->setTime(hitTime); + prd->setAmbiguityFlag(0); +} + +void xAODSimHitToRpcMeasCnvAlg::digitizeHit(const double hitTime, + const Amg::Vector2D& locPosOnStrip, + const MuonGMR4::StripDesignPtr& designPtr, + const Identifier& gasGapId, + xAOD::RpcStrip2DContainer& prdContainer, + CLHEP::HepRandomEngine* rndEngine) const{ + + /// There're Rpc chambers without phi strips (BI) + if (!designPtr){ + return; + } + const MuonGMR4::StripDesign& design{*designPtr}; + + const double uncert = design.stripPitch() / std::sqrt(12.); + const double smearedX = CLHEP::RandGaussZiggurat::shoot(rndEngine, locPosOnStrip.x(), uncert); + const Amg::Vector2D locHitPos{smearedX, locPosOnStrip.y()}; + ++(m_allHits[false]); + if (!design.insideTrapezoid(locHitPos)) { + ATH_MSG_VERBOSE("The 2D hit "<<Amg::toString(locHitPos)<<" is outside of the trapezoid bounds for " + <<m_idHelperSvc->toStringGasGap(gasGapId)); + return; + } + const int strip = stripNumber(design, locHitPos); + if (strip < 0) { + ATH_MSG_VERBOSE("Hit " << Amg::toString(locHitPos) << " cannot trigger any signal in a strip for " + << m_idHelperSvc->toStringGasGap(gasGapId)); + return; + } + + const RpcIdHelper& id_helper{m_idHelperSvc->rpcIdHelper()}; + + bool isValid{false}; + const Identifier prdId{id_helper.channelID(gasGapId, + id_helper.doubletZ(gasGapId), + id_helper.doubletPhi(gasGapId), + id_helper.gasGap(gasGapId), + false, strip, isValid)}; + + if (!isValid) { + ATH_MSG_WARNING("Invalid hit identifier obtained for "<<m_idHelperSvc->toStringGasGap(gasGapId) + <<", eta strip "<<strip<<" & hit "<<Amg::toString(locHitPos,2 ) + <<" /// "<<design); + return; + } + ++(m_acceptedHits[false]); + + xAOD::RpcStrip2D* prd = new xAOD::RpcStrip2D(); + prdContainer.push_back(prd); + + prd->setIdentifier(prdId.get_compact()); + xAOD::MeasVector<2> lPos{}; + xAOD::MeasMatrix<2> cov{xAOD::MeasMatrix<2>::Identity()}; + cov(0,0) = uncert * uncert; + /// Dummy value for the moment + cov(1,1) = 1.; + prd->setMeasurement<2>(m_idHelperSvc->detElementHash(prdId), + xAOD::toStorage(locHitPos), std::move(cov)); + const MuonGMR4::RpcReadoutElement* readOutEle = m_DetMgr->getRpcReadoutElement(prdId); + prd->setReadoutElement(readOutEle); + prd->setStripNumber(strip); + prd->setGasGap(id_helper.gasGap(prdId)); + prd->setDoubletPhi(id_helper.doubletPhi(prdId)); + prd->setTime(hitTime); + prd->setAmbiguityFlag(0); +} + +int xAODSimHitToRpcMeasCnvAlg::stripNumber(const MuonGMR4::StripDesign& design, + const Amg::Vector2D& locHitPos) const { + + int strip = design.stripNumber(locHitPos); + if (strip > 0) return strip; + + const CheckVector2D firstStrip = design.center(1); + const CheckVector2D lastStrip = design.center(design.numStrips()); + if (!firstStrip || !lastStrip) { + return -1; + } + if ( (*firstStrip).x() - 0.5 *design.stripPitch() < locHitPos.x()) { + return 1; + } else if ( (*lastStrip).x() + 0.5 * design.stripPitch() > locHitPos.x()) { + return design.numStrips(); + } + return -1; +} + StatusCode xAODSimHitToRpcMeasCnvAlg::execute(const EventContext& ctx) const { SG::ReadHandle<xAOD::MuonSimHitContainer> simHitContainer{m_readKey, ctx}; if (!simHitContainer.isPresent()){ @@ -56,77 +214,15 @@ StatusCode xAODSimHitToRpcMeasCnvAlg::execute(const EventContext& ctx) const { ATH_CHECK(prdContainer.record(std::make_unique<xAOD::RpcStripContainer>(), std::make_unique<xAOD::RpcStripAuxContainer>())); - const RpcIdHelper& id_helper{m_idHelperSvc->rpcIdHelper()}; - CLHEP::HepRandomEngine* rndEngine = getRandomEngine(ctx); + SG::WriteHandle<xAOD::RpcStrip2DContainer> prd2DContainer{}; + if (!m_writeKeyBI.empty()) { + prd2DContainer = SG::WriteHandle<xAOD::RpcStrip2DContainer>{m_writeKeyBI, ctx}; + ATH_CHECK(prd2DContainer.record(std::make_unique<xAOD::RpcStrip2DContainer>(), + std::make_unique<xAOD::RpcStrip2DAuxContainer>())); - using CheckVector2D = MuonGMR4::CheckVector2D; - auto digitizeHit = [&] (const double hitTime, - const double locX, - const MuonGMR4::StripDesignPtr& designPtr, - const Identifier& hitId, - bool measPhi) { - /// There're Rpc chambers without phi strips (BI) - if (!designPtr){ - return; - } - const MuonGMR4::StripDesign& design{*designPtr}; - const double uncert = design.stripPitch() / std::sqrt(12.); - const double smearedX = CLHEP::RandGaussZiggurat::shoot(rndEngine, locX, uncert); - const Amg::Vector2D locHitPos{locX * Amg::Vector2D::UnitX()}; - ++(m_allHits[measPhi]); - if (!design.insideTrapezoid(locHitPos)) { - ATH_MSG_VERBOSE("The hit "<<Amg::toString(locHitPos)<<" is outside of the trapezoid bounds for " - <<m_idHelperSvc->toStringGasGap(hitId)<<", measuresPhi: "<<(measPhi ? "yay" : "nay")); - return; - } - int stripNumber = design.stripNumber(locHitPos); - /// There're subtle cases where the hit is smeared outside the boundaries - if (stripNumber < 0) { - const CheckVector2D firstStrip = design.center(1); - const CheckVector2D lastStrip = design.center(design.numStrips()); - if (!firstStrip || !lastStrip) { - return; - } - if ( (*firstStrip).x() - 0.5 *design.stripPitch() < locHitPos.x()) { - stripNumber = 1; - } else if ( (*lastStrip).x() + 0.5 * design.stripPitch() > locHitPos.x()) { - stripNumber = design.numStrips(); - } else { - ATH_MSG_VERBOSE("Hit " << Amg::toString(locHitPos) << " cannot trigger any signal in a strip for " - << m_idHelperSvc->toStringGasGap(hitId) <<", measuresPhi: "<<(measPhi ? "yay" : "nay")); - return; - } - } - bool isValid{false}; - const Identifier prdId{id_helper.channelID(hitId, - id_helper.doubletZ(hitId), - id_helper.doubletPhi(hitId), - id_helper.gasGap(hitId), - measPhi, stripNumber, isValid)}; - - if (!isValid) { - ATH_MSG_WARNING("Invalid hit identifier obtained for "<<m_idHelperSvc->toStringGasGap(hitId) - <<", eta strip "<<stripNumber<<" & hit "<<Amg::toString(locHitPos,2 ) - <<" /// "<<design); - return; - } - ++(m_acceptedHits[measPhi]); - xAOD::RpcStrip* prd = new xAOD::RpcStrip(); - prdContainer->push_back(prd); - prd->setIdentifier(prdId.get_compact()); - xAOD::MeasVector<1> lPos{smearedX}; - xAOD::MeasMatrix<1> cov{uncert * uncert}; - prd->setMeasurement<1>(m_idHelperSvc->detElementHash(prdId), - std::move(lPos), std::move(cov)); - const MuonGMR4::RpcReadoutElement* readOutEle = m_DetMgr->getRpcReadoutElement(prdId); - prd->setReadoutElement(readOutEle); - prd->setStripNumber(stripNumber); - prd->setGasGap(id_helper.gasGap(prdId)); - prd->setDoubletPhi(id_helper.doubletPhi(prdId)); - prd->setMeasuresPhi(id_helper.measuresPhi(prdId)); - prd->setTime(hitTime); - prd->setAmbiguityFlag(0); - }; + } + + CLHEP::HepRandomEngine* rndEngine = getRandomEngine(ctx); for (const xAOD::MuonSimHit* simHit : *simHitContainer) { const Identifier hitId = simHit->identify(); @@ -136,9 +232,13 @@ StatusCode xAODSimHitToRpcMeasCnvAlg::execute(const EventContext& ctx) const { const Amg::Vector3D locSimHitPos{xAOD::toEigen(simHit->localPosition())}; const double hitTime = simHit->globalTime() - invC *(readOutEle->localToGlobalTrans(gctx, hitId) * locSimHitPos).mag(); - digitizeHit(hitTime, locSimHitPos.x(), readOutEle->getParameters().etaDesign, hitId, false); - digitizeHit(hitTime, locSimHitPos.y(), readOutEle->getParameters().phiDesign, hitId, true); - + if (m_idHelperSvc->stationName(hitId) != m_stIdxBIL) { + digitizeHit(hitTime, locSimHitPos.x(), readOutEle->getParameters().etaDesign, hitId, false, *prdContainer, rndEngine); + digitizeHit(hitTime, locSimHitPos.y(), readOutEle->getParameters().phiDesign, hitId, true, *prdContainer, rndEngine); + } else if (!m_writeKeyBI.empty()) { + digitizeHit(hitTime, locSimHitPos.block<2,1>(0,0), readOutEle->getParameters().etaDesign, hitId, + *prd2DContainer, rndEngine); + } } return StatusCode::SUCCESS; } diff --git a/MuonSpectrometer/MuonPhaseII/MuonCnv/xAODMuonSimHitCnv/src/xAODSimHitToRpcMeasCnvAlg.h b/MuonSpectrometer/MuonPhaseII/MuonCnv/xAODMuonSimHitCnv/src/xAODSimHitToRpcMeasCnvAlg.h index ec18e075d3a8..4b6e1f9adf87 100644 --- a/MuonSpectrometer/MuonPhaseII/MuonCnv/xAODMuonSimHitCnv/src/xAODSimHitToRpcMeasCnvAlg.h +++ b/MuonSpectrometer/MuonPhaseII/MuonCnv/xAODMuonSimHitCnv/src/xAODSimHitToRpcMeasCnvAlg.h @@ -11,7 +11,10 @@ #include <StoreGate/WriteHandleKey.h> #include <xAODMuonSimHit/MuonSimHitContainer.h> + #include <xAODMuonPrepData/RpcStripContainer.h> +#include <xAODMuonPrepData/RpcStrip2DContainer.h> + #include <MuonIdHelpers/IMuonIdHelperSvc.h> #include <MuonReadoutGeometryR4/MuonDetectorManager.h> @@ -39,6 +42,31 @@ class xAODSimHitToRpcMeasCnvAlg : public AthReentrantAlgorithm { private: CLHEP::HepRandomEngine* getRandomEngine(const EventContext& ctx) const; + /** @brief Smears the local simHit position orthogonal to the strip and + * writes a 1D rpc strip measurement + */ + void digitizeHit(const double hitTime, + const double locPosOnStrip, + const MuonGMR4::StripDesignPtr& designPtr, + const Identifier& gasGapId, + const bool measuresPhi, + xAOD::RpcStripContainer& prdContainer, + CLHEP::HepRandomEngine* engine) const; + + void digitizeHit(const double hitTime, + const Amg::Vector2D& locPosOnStrip, + const MuonGMR4::StripDesignPtr& designPtr, + const Identifier& gasGapId, + xAOD::RpcStrip2DContainer& prdContainer, + CLHEP::HepRandomEngine* engine) const; + + /** @brief Returns the number of the strip that's closest to the hit position on the strip plane + * -1 is returned if the hit is outside the strip panel acceptance + * */ + int stripNumber(const MuonGMR4::StripDesign& design, + const Amg::Vector2D& locHitPosOnPlane) const; + + SG::ReadHandleKey<ActsGeometryContext> m_geoCtxKey{this, "AlignmentKey", "ActsAlignment", "cond handle key"}; SG::ReadHandleKey<xAOD::MuonSimHitContainer> m_readKey{this, "InputCollection", "xRpcSimHits", @@ -47,6 +75,8 @@ class xAODSimHitToRpcMeasCnvAlg : public AthReentrantAlgorithm { SG::WriteHandleKey<xAOD::RpcStripContainer> m_writeKey{this, "OutputContainer", "xRpcStrips", "Output container"}; + SG::WriteHandleKey<xAOD::RpcStrip2DContainer> m_writeKeyBI{this, "OutputContainerBI", "xRpcBILStrips", + "Output container of the 2D BIL rpc strips"}; /// Access to the new readout geometry const MuonGMR4::MuonDetectorManager* m_DetMgr{nullptr}; @@ -58,6 +88,8 @@ class xAODSimHitToRpcMeasCnvAlg : public AthReentrantAlgorithm { mutable std::array<std::atomic<unsigned>, 2> m_allHits ATLAS_THREAD_SAFE{}; mutable std::array<std::atomic<unsigned>, 2> m_acceptedHits ATLAS_THREAD_SAFE{}; + int m_stIdxBIL{-1}; + }; #endif \ No newline at end of file -- GitLab