ATLAS Offline Software
Loading...
Searching...
No Matches
RegionSelectorCondAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
5
6
10
11#include "Acts/Surfaces/PlanarBounds.hpp"
12#include "Acts/Surfaces/RectangleBounds.hpp"
13#include "Acts/Surfaces/TrapezoidBounds.hpp"
14#include "Acts/Geometry/Volume.hpp"
15#include "Acts/Geometry/CuboidVolumeBounds.hpp"
16#include "Acts/Geometry/TrapezoidVolumeBounds.hpp"
17#include "Acts/Visualization/ObjVisualization3D.hpp"
18#include "Acts/Visualization/GeometryView3D.hpp"
19
20
23
24namespace MuonR4{
26 ATH_CHECK(detStore()->retrieve(m_detMgr));
27 ATH_CHECK(m_tableKey.initialize());
28 ATH_CHECK(m_alignKey.initialize());
32 return StatusCode::SUCCESS;
33 }
34 template <typename Key_t,
35 typename... OtherKey_t>
36 StatusCode RegionSelectorCondAlg::addCondDependency(const EventContext& ctx,
39 OtherKey_t... others) const {
40 if (!key.empty()) {
41 SG::ReadCondHandle readHandle{key, ctx};
42 if (!readHandle.isValid()){
43 ATH_MSG_FATAL("Failed to retrieve "<<key.fullKey()<<".");
44 return StatusCode::FAILURE;
45 }
46 writeHandle.addDependency(readHandle);
47 }
48 if constexpr(sizeof...(others) > 0) {
49 ATH_CHECK(addCondDependency(ctx, writeHandle, others...));
50 }
51 return StatusCode::SUCCESS;
52 }
53
55 switch (type) {
56 using enum ActsTrk::DetectorType;
57 case Mdt:
58 return m_idHelperSvc->mdtIdHelper();
59 case Rpc:
60 return m_idHelperSvc->rpcIdHelper();
61 case Tgc:
62 return m_idHelperSvc->tgcIdHelper();
63 case Mm:
64 return m_idHelperSvc->mmIdHelper();
65 case sTgc:
66 return m_idHelperSvc->stgcIdHelper();
67 default:
68 THROW_EXCEPTION("Unknown detector type "<<ActsTrk::to_string(type));
69 }
70 }
71
72 std::set<std::uint32_t> RegionSelectorCondAlg::getRobIDs(const EventContext& ctx,
73 const Identifier& moduleID) const {
74
75 switch(m_idHelperSvc->technologyIndex(moduleID)) {
77 case MDT: {
78 const MuonMDT_CablingMap* cabling{};
79 if (!SG::get(cabling, m_cablingMdtKey, ctx).isSuccess()) {
80 THROW_EXCEPTION("Failed to load Mdt cabling "<<m_cablingMdtKey.fullKey());
81 }
82 return {cabling->getROBId(m_idHelperSvc->moduleHash(moduleID), msgStream())};
83 } case RPC: {
84 const Muon::RpcCablingMap* cabling{};
85 if (!SG::get(cabling, m_cablingRpcKey, ctx).isSuccess()) {
86 THROW_EXCEPTION("Failed to load Rpc cabling "<<m_cablingRpcKey.fullKey());
87 }
88 return {cabling->getROBId(m_idHelperSvc->moduleHash(moduleID), msgStream())};
89 } case TGC: {
90 const Muon::TgcCablingMap* cabling{};
91 if (!SG::get(cabling, m_cablingTgcKey, ctx).isSuccess()) {
92 THROW_EXCEPTION("Failed to load Tgc cabling");
93 }
94 int subDetectorId{}, rodId{};
95 cabling->getReadoutIDfromElementID(moduleID, subDetectorId, rodId);
96 return {static_cast<std::uint32_t>(((0x0ff) & subDetectorId)<<16 | rodId)};
97 } case MM:
98 case STGC:{
100 m_idHelperSvc->stationNameString(moduleID),
101 static_cast<int8_t>(m_idHelperSvc->stationEta(moduleID)),
102 static_cast<uint8_t>(m_idHelperSvc->stationPhi(moduleID))};
103 return std::set<std::uint32_t>(robIdHelper.get_ids().begin(), robIdHelper.get_ids().end());
104 } default: {
105 THROW_EXCEPTION("Invalid identifier "<<m_idHelperSvc->toStringChamber(moduleID));
106 }
107 }
108 return {};
109 }
110
111 StatusCode RegionSelectorCondAlg::execute(const EventContext& ctx) const {
112 SG::WriteCondHandle writeHandle{m_tableKey, ctx};
113 if (writeHandle.isValid()) {
114 ATH_MSG_DEBUG("Region selector "<<m_tableKey<<" is still valid");
115 return StatusCode::SUCCESS;
116 }
120
121 auto writeCdo = std::make_unique<RegSelSiLUT>();
122 const ActsTrk::DetectorAlignStore* alignDeltas{nullptr};
123 ATH_CHECK(SG::get(alignDeltas, m_alignKey, ctx));
124
126 if (m_splitTrfCache) {
127 gctx.setStore(MuonGMR4::copyDeltas(*alignDeltas));
128 } else {
129 gctx.setStore(std::make_unique<ActsTrk::DetectorAlignStore>(*alignDeltas));
130 }
131 const MuonIdHelper& idHelper{getIdHelper(alignDeltas->detType)};
132
135 struct TempSelTable {
136 std::optional<double> centralPhi{};
137 double zMin{std::numeric_limits<double>::max()};
138 double zMax{-std::numeric_limits<double>::max()};
139 double rMin{std::numeric_limits<double>::max()};
140 double rMax{-std::numeric_limits<double>::max()};
141 double dPhiMin{std::numeric_limits<double>::max()};
142 double dPhiMax{-std::numeric_limits<double>::max()};
143
144 void update(const Amg::Vector3D& v) {
145 const double dPhi = xAOD::P4Helpers::deltaPhi(v.phi(), centralPhi.value_or(0.));
146 rMin = std::min(rMin, v.perp()); rMax = std::max(rMax, v.perp());
147 zMin = std::min(zMin, v.z()); zMax = std::max(zMax, v.z());
148 dPhiMin = std::min(dPhiMin, dPhi); dPhiMax = std::max(dPhiMax, dPhi);
149 }
150
151 };
152 std::vector<TempSelTable> luts(idHelper.module_hash_max());
153 IdentifierHash modHash{};
155 std::vector<std::unique_ptr<Acts::Volume>> objVolumes{};
156 for (const MuonGMR4::MuonReadoutElement* reEle: m_detMgr->getAllReadoutElements(alignDeltas->detType)) {
157
158 const Acts::Surface& surface{reEle->surface()};
159
160 const double halfTck = 0.5*reEle->thickness();
161
162 std::vector<Amg::Vector3D> localVertices{};
163 localVertices.reserve(8);
164 ATH_MSG_VERBOSE(__LINE__<<" - Fetch edge points from surface: "<<m_idHelperSvc->toStringDetEl(reEle->identify()));
165 std::ranges::for_each(static_cast<const Acts::PlanarBounds&>(surface.bounds()).vertices(),
166 [&](const Amg::Vector2D& v){
167 ATH_MSG_VERBOSE(__LINE__<<" - Local vertex: "<<Amg::toString(v)<<", half thickness: "<<halfTck);
168 localVertices.emplace_back(v.x(), v.y(), halfTck);
169 localVertices.emplace_back(v.x(), v.y(), -halfTck);
170 });
171
172 if (m_dumpObjVolumes) {
173 std::unique_ptr<Acts::VolumeBounds> volBounds{};
174 switch (surface.bounds().type()) {
175 using enum Acts::SurfaceBounds::BoundsType;
176 case eRectangle:{
177 using vEnum = Acts::RectangleBounds::BoundValues;
178 const auto& bounds{static_cast<const Acts::RectangleBounds&>(surface.bounds())};
179 volBounds = std::make_unique<Acts::CuboidVolumeBounds>(bounds.get(vEnum::eMaxX),
180 bounds.get(vEnum::eMaxY),
181 halfTck);
182 break;
183 } case eTrapezoid: {
184 using vEnum = Acts::TrapezoidBounds::BoundValues;
185 const auto& bounds{static_cast<const Acts::TrapezoidBounds&>(surface.bounds())};
186 volBounds = std::make_unique<Acts::TrapezoidVolumeBounds>(bounds.get(vEnum::eHalfLengthXnegY),
187 bounds.get(vEnum::eHalfLengthXposY),
188 bounds.get(vEnum::eHalfLengthY),
189 halfTck);
190 break;
191 } default:
192 THROW_EXCEPTION("Unsupported bounds "<<surface.bounds());
193 }
194 objVolumes.emplace_back(std::make_unique<Acts::Volume>(surface.localToGlobalTransform(gctx.context()),
195 std::move(volBounds)));
196 }
197
198 ATH_MSG_VERBOSE(__LINE__<<" - Fetched "<<localVertices.size()<<" vertices.");
199 const Amg::Transform3D& loc2Glob{surface.localToGlobalTransform(gctx.context())};
200 idHelper.get_module_hash(reEle->identify(), modHash);
201 auto& lut = luts.at(modHash);
202 if (!lut.centralPhi) {
203 lut.centralPhi = loc2Glob.translation().phi();
204 }
205 for (const Amg::Vector3D& locVtx : localVertices) {
206 const Amg::Vector3D globVtx = loc2Glob * locVtx;
207 ATH_MSG_VERBOSE(__LINE__<<" - Expand LUT with vertex "
208 <<std::format("{:.2f}/{:.2f}/{:.2f}", globVtx.perp(), globVtx.z(), globVtx.phi()));
209 lut.update(globVtx);
210 }
211 }
212 const auto modCtx = idHelper.module_context();
214 for (auto module_itr = idHelper.module_begin();
215 module_itr != idHelper.module_end(); ++module_itr) {
216 idHelper.get_module_hash(*module_itr, modHash);
217 const auto& lut = luts.at(modHash);
218
219 if(!lut.centralPhi) {
220 continue;
221 }
222
223 ExpandedIdentifier exp_id{};
224 if (idHelper.get_expanded_id(*module_itr, exp_id, &modCtx)) {
225 ATH_MSG_DEBUG(__LINE__<<" - Failed retrieving ExpandedIdentifier for PRD Identifier = "
226 << m_idHelperSvc->toString(*module_itr) << ". Skipping to the next PRD.");
227 continue;
228 }
229 const int detid = ( exp_id[2]<0 ? -1 : 1 );
230 const int layerid = exp_id[1]+1;
231
232 const double phiMin = lut.centralPhi.value_or(0) + lut.dPhiMin;
233 const double phiMax = lut.centralPhi.value_or(0) + lut.dPhiMax;
234
235
236 for (const std::uint32_t robID : getRobIDs(ctx, *module_itr)) {
237 RegSelModule m{lut.zMin, lut.zMax, lut.rMin, lut.rMax,
238 phiMin, phiMax, layerid, detid, robID, modHash};
239 ATH_MSG_VERBOSE(__LINE__<<" - Insert new entry "<<m_idHelperSvc->chamberNameString(*module_itr)
240 <<", "<<m);
241 writeCdo->addModule(m);
242 }
243 }
244
245 if (m_printTable) {
246 if (const auto *lut = dynamic_cast<const RegSelSiLUT*>(writeCdo.get())) {
247 lut->write(std::format("{:}.map", name()));
248 }
249 }
250 if (!objVolumes.empty()) {
251 Acts::ObjVisualization3D visualHelper{};
252 for (const auto& volume : objVolumes) {
253 Acts::GeometryView3D::drawVolume(visualHelper, *volume,
254 gctx.context());
255 }
256 visualHelper.write(std::format("RegSelVolumes_{:}.obj", alignDeltas->detType));
257
258 }
259
260 ATH_CHECK(writeHandle.record(std::make_unique<IRegSelLUTCondData>(std::move(writeCdo))));
261 return StatusCode::SUCCESS;
262 }
263}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_FATAL(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_DEBUG(x)
@ STGC
Definition RegSelEnums.h:39
@ MM
Definition RegSelEnums.h:38
@ RPC
Definition RegSelEnums.h:32
@ MDT
Definition RegSelEnums.h:31
DetectorType detType
The aligned detector element type.
Acts::GeometryContext context() const
void setStore(AlignmentStorePtr store)
Adds the store to the Geometry context.
const ServiceHandle< StoreGateSvc > & detStore() const
static EventIDRange infiniteRunLB()
Produces an EventIDRange that is infinite in RunLumi and invalid in Time.
This is a "hash" representation of an Identifier.
MuonReadoutElement is an abstract class representing the geometry of a muon detector.
const_id_iterator module_end() const
int get_expanded_id(const Identifier &id, ExpandedIdentifier &exp_id, const IdContext *context) const
Create expanded id from compact id (return == 0 for OK).
const_id_iterator module_begin() const
Iterators over full set of ids.
virtual int get_module_hash(const Identifier &id, IdentifierHash &hash_id) const
size_type module_hash_max() const
the maximum hash value
IdContext module_context() const
id for module
virtual StatusCode initialize() override final
Gaudi::Property< bool > m_printTable
SG::ReadCondHandleKey< Muon::TgcCablingMap > m_cablingTgcKey
Dependency on the Tgc cabling map.
const MuonGMR4::MuonDetectorManager * m_detMgr
Detector manager.
SG::ReadCondHandleKey< Muon::RpcCablingMap > m_cablingRpcKey
Dependency on the phase II Rpc cabling map.
Gaudi::Property< bool > m_splitTrfCache
Instantiate a new transform cache to ensure lazy transform population in the event processing.
const MuonIdHelper & getIdHelper(const ActsTrk::DetectorType type) const
Retrieve the idHelper for the given detector technology.
Gaudi::Property< bool > m_dumpObjVolumes
Dump the volumes from which the region selector tables are built.
virtual StatusCode execute(const EventContext &ctx) const override final
SG::ReadCondHandleKey< ActsTrk::DetectorAlignStore > m_alignKey
Dependency on the alignment constants.
SG::WriteCondHandleKey< IRegSelLUTCondData > m_tableKey
Region selector table written by the algorithm.
StatusCode addCondDependency(const EventContext &ctx, SG::WriteCondHandle< IRegSelLUTCondData > &writeHandle, const SG::ReadCondHandleKey< Key_t > &key, OtherKey_t... others) const
Declare the dependency of the region selector table on the other keys set.
std::set< std::uint32_t > getRobIDs(const EventContext &ctx, const Identifier &moduleID) const
Returns the list of ROB ids associated with the module.
SG::ReadCondHandleKey< MuonMDT_CablingMap > m_cablingMdtKey
Dependency on the Mdt cabling map.
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
const std::vector< uint32_t > & get_ids() const
void addDependency(const EventIDRange &range)
StatusCode record(const EventIDRange &range, T *t)
record handle, with explicit range DEPRECATED
DetectorType
Simple enum to Identify the Type of the ACTS sub detector.
std::string to_string(const DetectorType &type)
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
std::unique_ptr< ActsTrk::DetectorAlignStore > copyDeltas(const ActsTrk::DetectorAlignStore &inStore)
Copy the alignment deltas from the inStore to a new alignment store.
This header ties the generic definitions in this package.
TechnologyIndex
enum to classify the different layers in the muon spectrometer
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
Definition TgcBase.h:6
double deltaPhi(double phiA, double phiB)
delta Phi in range [-pi,pi[
#define THROW_EXCEPTION(MESSAGE)
Definition throwExcept.h:10