ATLAS Offline Software
Loading...
Searching...
No Matches
sTgcRdoToPrepDataToolMT.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6
14
15using namespace MuonGM;
16using namespace Trk;
17using namespace Muon;
18
19namespace {
20 std::atomic<bool> hitNegativeCharge{false};
21}
22
23//============================================================================
25{
26 ATH_MSG_DEBUG(" in initialize()");
27 ATH_CHECK( m_idHelperSvc.retrieve() );
28 // check if the initialization of the data container is success
30 ATH_CHECK(m_rdoContainerKey.initialize());
31 ATH_CHECK(m_muDetMgrKey.initialize());
32 ATH_CHECK(m_calibTool.retrieve());
33 ATH_CHECK(m_prdContainerCacheKey.initialize(!m_prdContainerCacheKey.key().empty()) );
34
35 if (m_useNewGeo) {
36 ATH_CHECK(detStore()->retrieve(m_detMgrR4));
37 }
38
39 ATH_CHECK(m_xAODStripKey.initialize(!m_xAODStripKey.empty()));
40 ATH_CHECK(m_xAODWireKey.initialize(!m_xAODWireKey.empty()));
41 ATH_CHECK(m_xAODPadKey.initialize(!m_xAODPadKey.empty()));
42 return StatusCode::SUCCESS;
43}
44
45
46//============================================================================
47StatusCode Muon::sTgcRdoToPrepDataToolMT::processCollection(const EventContext& ctx,
48 outputCache& xAODcontainers,
49 const STGC_RawDataCollection *rdoColl) const {
50
51 const sTgcIdHelper& id_helper = m_idHelperSvc->stgcIdHelper();
52 const IdentifierHash hash = rdoColl->identifyHash();
53
54 ATH_MSG_DEBUG(" ***************** Start of process STGC Collection with hash Id: " << hash);
55
56 auto stgcPrepDataContainer = xAODcontainers.prd;
57 // check if the collection already exists, otherwise add it
58 if ( stgcPrepDataContainer->indexFindPtr(hash) != nullptr ) {
59 ATH_MSG_DEBUG("In processCollection: collection already contained in the sTGC PrepData container");
60 return StatusCode::FAILURE;
61
62 }
63
64 // Get write handle for this collection
65 sTgcPrepDataContainer::IDC_WriteHandle lock = stgcPrepDataContainer->getWriteHandle( hash );
66 // Check if collection already exists (via the cache, i.e. in online trigger mode)
68 ATH_MSG_DEBUG("In processCollection: collection already available in the sTgc PrepData container (via cache)");
69 return StatusCode::SUCCESS;
70 }
71
72 // Make the PRD collection (will be added to container later
73 std::unique_ptr<sTgcPrepDataCollection> prdColl = std::make_unique<sTgcPrepDataCollection>(hash);
74
75 // set the offline identifier of the collection Id
76 IdContext context = id_helper.module_context();
77 Identifier moduleId;
78 int getId = id_helper.get_id(hash, moduleId, &context);
79 if ( getId != 0 ) {
80 ATH_MSG_ERROR("Could not convert the hash Id: " << hash << " to identifier");
81 } else {
82 prdColl->setIdentifier(moduleId);
83 }
84
85 // vectors to hold PRDs decoded for this RDO collection
86 std::vector<sTgcPrepData> sTgcStripPrds;
87 std::vector<sTgcPrepData> sTgcWirePrds;
88 std::vector<sTgcPrepData> sTgcPadPrds;
89 sTgcStripPrds.reserve(rdoColl->size());
90 sTgcPadPrds.reserve(rdoColl->size());
91 sTgcWirePrds.reserve(rdoColl->size());
92
93 // Count hits with negative charge, which indicates bad calibration
94
95
96 // MuonDetectorManager from the conditions store
97 const MuonGM::MuonDetectorManager* muonDetMgr{nullptr};
98 ATH_CHECK(SG::get(muonDetMgr,m_muDetMgrKey,ctx));
99 // convert the RDO collection to a PRD collection
100 for ( const STGC_RawData* rdo : * rdoColl) {
101
102 ATH_MSG_DEBUG("Adding a new sTgc PrepRawData");
103
104 const Identifier rdoId = rdo->identify();
105
106 std::vector<Identifier> rdoList{rdoId};
107
108 // get the local and global positions
109 const MuonGM::sTgcReadoutElement* detEl = muonDetMgr->getsTgcReadoutElement(rdoId);
110 Amg::Vector2D localPos{Amg::Vector2D::Zero()};
111
112 int channelType = id_helper.channelType(rdoId);
113 if (channelType < 0 || channelType > 2) {
114 ATH_MSG_ERROR("Unknown sTGC channel type");
115 return StatusCode::FAILURE;
116 }
117 if (!detEl->stripPosition(rdoId, localPos)) {
118 ATH_MSG_ERROR("Could not get the local strip position for "<<m_idHelperSvc->toString(rdoId));
119 return StatusCode::FAILURE;
120 }
121
122 // get the resolution from strip width
123 // to be fixed: for now do not set the resolution, it will be added in the next update
124 const int gasGap = id_helper.gasGap(rdoId);
125 const int channel = id_helper.channel(rdoId);
126
127 NSWCalib::CalibratedStrip calibStrip;
128 ATH_CHECK (m_calibTool->calibrateStrip(ctx, rdo, calibStrip));
129 int calibratedCharge = static_cast<int>(calibStrip.charge);
130 if (calibratedCharge < 0 && channelType == 1) { // we only want to protect against negatively charged strips and we should not lose wire or pad hits because of bad calibrations since charge does not matter for them in reco.
131 if (!hitNegativeCharge) {
132 ATH_MSG_DEBUG("One sTGC RDO or more, such as one with pdo = "<<rdo->charge() << " counts, corresponds to a negative charge (" << calibratedCharge << "). Skipping these RDOs");
133 hitNegativeCharge = true;
134 }
135 continue;
136 }
137
138 double width{0.};
139 if (channelType == sTgcIdHelper::sTgcChannelTypes::Pad) { // Pads
140 const MuonGM::MuonPadDesign* design = detEl->getPadDesign(rdoId);
141 if (!design) {
142 ATH_MSG_WARNING("Failed to get design for sTGC pad" );
143 } else {
144 width = design->channelWidth(localPos, true);
145 }
146 } else { // Strips and wires
147 const MuonGM::MuonChannelDesign* design = detEl->getDesign(rdoId);
148 if (!design) {
149 ATH_MSG_WARNING("Failed to get design for sTGC strip/wire" );
150 } else {
151 width = design->channelWidth();
152 }
153 }
154
155 const double resolution = width/ std::sqrt(12.);
156 auto cov = Amg::MatrixX(1,1);
157 cov.setIdentity();
158 (cov)(0,0) = resolution*resolution;
159
160 ATH_MSG_DEBUG("Adding a new STGC PRD, gasGap: " << gasGap << " channel: " << channel << " type: " << channelType << " resolution " << resolution );
161
162 if(m_merge) {
163 std::vector<sTgcPrepData>& sTgcPrds = channelType == sTgcIdHelper::Pad ? sTgcPadPrds :
164 (channelType == sTgcIdHelper::Strip ? sTgcStripPrds : sTgcWirePrds);
165
166 // check if the same RdoId is already present; keep the one with the smallest time
167 auto it = std::find_if(sTgcPrds.begin(), sTgcPrds.end(), [&rdoId](const sTgcPrepData& prd) {
168 return (prd.identify() == rdoId);
169 });
170 if (it == sTgcPrds.end()) {
171 sTgcPrds.emplace_back(rdoId, hash, std::move(localPos), std::move(rdoList), std::move(cov), detEl, calibratedCharge, calibStrip.time);
172 sTgcPrds.back().setAuthor(sTgcPrepData::Author::RdoToPrdConverter);
173 } else if (it->time() > calibStrip.time) {
174 *it = sTgcPrepData(rdoId, hash, std::move(localPos), std::move(rdoList), std::move(cov), detEl, calibratedCharge, calibStrip.time);
176 }
177
178 // TODO - add merging for xAOD
179
180 } else {
181 // if not merging just add the PRD to the collection
182 prdColl->push_back(std::make_unique<sTgcPrepData>(rdoId,
183 hash,
184 std::move(localPos),
185 std::move(rdoList),
186 std::move(cov),
187 detEl,
188 calibratedCharge,
189 calibStrip.time));
190 }
191 }
192
193 if(m_merge) {
194 // merge strip prds that fire closeby channels (not clusterizing wires and pads)
195 std::vector<std::unique_ptr<Muon::sTgcPrepData>> sTgcStripClusters;
196 ATH_CHECK(m_clusterBuilderTool->getClusters(ctx, std::move(sTgcStripPrds), sTgcStripClusters)); // Clusterize strips
197
198 for ( std::unique_ptr<Muon::sTgcPrepData>& it : sTgcStripClusters ) {
199 it->setHashAndIndex(prdColl->identifyHash(), prdColl->size());
200 prdColl->push_back(std::move(it));
201 }
202 for ( Muon::sTgcPrepData& prd : sTgcWirePrds ) {
203 prd.setHashAndIndex(prdColl->identifyHash(), prdColl->size());
204 prdColl->push_back(std::make_unique<sTgcPrepData>(std::move(prd)));
205 }
206 for (Muon::sTgcPrepData& prd : sTgcPadPrds ) {
207 prd.setHashAndIndex(prdColl->identifyHash(), prdColl->size());
208 prdColl->push_back(std::make_unique<sTgcPrepData>(std::move(prd)));
209 }
210 }
211 const bool convertXAOD = !m_xAODPadKey.empty() || !m_xAODStripKey.empty() ||
212 !m_xAODWireKey.empty();
213
214 if (convertXAOD) {
215 for (const Muon::sTgcPrepData* prd : *prdColl) {
216 const Identifier prdId = prd->identify();
217 const int gasGap = id_helper.gasGap(prdId);
218 const int channel = id_helper.channel(prdId);
219 const int chType = id_helper.channelType(prdId);
220 xAOD::sTgcMeasurement* outHit{nullptr};
221 ATH_MSG_VERBOSE("Convert "
222 <<m_idHelperSvc->toString(prdId)<<". "<<Amg::toString(prd->localPosition())
223 <<", cov: "<<prd->localCovariance()(0,0)
224 <<" global pos: "<<Amg::toString(prd->globalPosition()));
227 lCov(1,1) = prd->localCovariance()(0,0);
229 if(m_detMgrR4){
230 const MuonGMR4::sTgcReadoutElement* readoutEle = m_detMgrR4->getsTgcReadoutElement(prdId);
231 lCov(0,0) = Acts::square(0.5* readoutEle->padHeight(readoutEle->measurementHash(prdId)));
232
233 }
234 // lCov(1,1) = prd->localCovariance()(1,1);
235 //skip for now measurements with zero covariance
236 if (lCov.determinant() == 0) {
237 ATH_MSG_WARNING("sTgcPadHit with zero covariance, skip filling xAOD");
238 continue;
239 }
240 outHit = xAODcontainers.pad->push_back(std::make_unique<xAOD::sTgcPadHit>());
241 outHit->setMeasurement<2>(m_idHelperSvc->detElementHash(prdId),
242 xAOD::toStorage(Eigen::Rotation2D{-M_PI_2}*prd->localPosition()),
243 std::move(lCov));
245 outHit = xAODcontainers.wire->push_back(std::make_unique<xAOD::sTgcWireHit>());
247 auto stripHit = xAODcontainers.strip->push_back(std::make_unique<xAOD::sTgcStripCluster>());
248 stripHit->setStripCharges(prd->stripCharges());
249 stripHit->setStripNumbers(prd->stripNumbers());
250 stripHit->setStripTimes(prd->stripTimes());
251 outHit = stripHit;
252 }
253 if (!outHit) {
254 continue;
255 }
259 const double locPos = (chType == sTgcIdHelper::sTgcChannelTypes::Wire ? -1. : 1.) * prd->localPosition().x();
261 xAOD::MeasMatrix<1> lCov{};
262 lCov(0,0) = prd->localCovariance()(0,0);
263 outHit->setMeasurement<1>(m_idHelperSvc->detElementHash(prdId),
264 std::move(lPos),
265 std::move(lCov));
266
267 }
268 outHit->setChannelNumber(channel);
269 outHit->setGasGap(gasGap);
270 outHit->setAuthor(prd->author());
271 outHit->setTime(prd->time());
272 outHit->setCharge(prd->charge());
273 outHit->setIdentifier(prdId.get_compact());
274 if (m_detMgrR4) {
275 outHit->setReadoutElement(m_detMgrR4->getsTgcReadoutElement(prdId));
276 }
277 }
278 }
279
280
281 // now add the collection to the container
282 ATH_CHECK( lock.addOrDelete(std::move( prdColl ) ) );
283 ATH_MSG_DEBUG("PRD hash " << hash << " has been moved to container");
284
285 return StatusCode::SUCCESS;
286}
287
288
289//============================================================================
291{
292 auto rdoContainerHandle = SG::makeHandle(m_rdoContainerKey, ctx);
293 if(rdoContainerHandle.isValid()) {
294 ATH_MSG_DEBUG("STGC_getRdoContainer success");
295 return rdoContainerHandle.cptr();
296 }
297 ATH_MSG_WARNING("Retrieval of STGC_RawDataContainer failed !");
298
299 return nullptr;
300}
301
302
303//============================================================================
305 outputCache& xAODcontainers,
306 const std::vector<IdentifierHash>& idsToDecode) const
307{
308 ATH_MSG_DEBUG("In processRDOContainer");
309 const STGC_RawDataContainer* rdoContainer = getRdoContainer(ctx);
310 if (!rdoContainer) return;
311
312 // run in unseeded mode
313 for (const STGC_RawDataCollection* rdoColl : *rdoContainer) {
314 if (rdoColl->empty()) continue;
315 ATH_MSG_DEBUG("New RDO collection with " << rdoColl->size() << "STGC Hits");
316
317 const IdentifierHash hash = rdoColl->identifyHash();
318
319 // check if we actually want to decode this RDO collection
320 if(!idsToDecode.empty() and std::find(idsToDecode.begin(), idsToDecode.end(), hash)==idsToDecode.end()) {
321 ATH_MSG_DEBUG("Hash ID " << hash << " not in input list, ignore");
322 continue;
323 } else ATH_MSG_DEBUG("Going to decode " << hash);
324
325 if(processCollection(ctx, xAODcontainers, rdoColl).isFailure()) {
326 ATH_MSG_DEBUG("processCsm returns a bad StatusCode - keep going for new data collections in this event");
327 }
328 }
329}
330
331// methods for ROB-based decoding
332//============================================================================
333StatusCode Muon::sTgcRdoToPrepDataToolMT::decode(const EventContext& ctx,
334 const std::vector<IdentifierHash>& idVect) const {
335 ATH_MSG_DEBUG("Size of the input hash id vector: " << idVect.size());
336
337 outputCache outCache = setupOutputContainers(ctx);
338 if (!outCache.isValid) return StatusCode::FAILURE;
339
340 processRDOContainer(ctx, outCache, idVect);
341 return StatusCode::SUCCESS;
342}
343
344
345//============================================================================
346StatusCode Muon::sTgcRdoToPrepDataToolMT::decode(const EventContext&, const std::vector<uint32_t>& ) const {
347 ATH_MSG_FATAL("ROB based decoding is not supported....");
348 return StatusCode::FAILURE;
349}
350StatusCode Muon::sTgcRdoToPrepDataToolMT::provideEmptyContainer(const EventContext& ctx) const {
351 return setupOutputContainers(ctx).isValid ? StatusCode::SUCCESS : StatusCode::FAILURE;
352}
353
354
356 sTgcRdoToPrepDataToolMT::setupOutputContainers(const EventContext& ctx) const {
357 outputCache containers;
358 if (!m_xAODStripKey.empty()) {
360 if (!containers.strip.record(std::make_unique<xAOD::sTgcStripContainer>(),
361 std::make_unique<xAOD::sTgcStripAuxContainer>()).isSuccess()){
362 ATH_MSG_FATAL("Failed to record "<<m_xAODStripKey.fullKey());
363 return containers;
364 }
365 }
366 if (!m_xAODPadKey.empty()) {
368 if (!containers.pad.record(std::make_unique<xAOD::sTgcPadContainer>(),
369 std::make_unique<xAOD::sTgcPadAuxContainer>()).isSuccess()){
370 ATH_MSG_FATAL("Failed to record "<<m_xAODPadKey.fullKey());
371 return containers;
372 }
373 }
374 if (!m_xAODWireKey.empty()) {
376 if (!containers.wire.record(std::make_unique<xAOD::sTgcWireContainer>(),
377 std::make_unique<xAOD::sTgcWireAuxContainer>()).isSuccess()){
378 ATH_MSG_FATAL("Failed to record "<<m_xAODWireKey.fullKey());
379 return containers;
380 }
381 }
382
384 if(m_prdContainerCacheKey.key().empty()) {
385 // No external cache, just record the container
386 const int hashMax = m_idHelperSvc->stgcIdHelper().module_hash_max();
387 if (!containers.prd.record(std::make_unique<Muon::sTgcPrepDataContainer>(hashMax)).isSuccess()){
388 ATH_MSG_FATAL("Faile to record "<<m_stgcPrepDataContainerKey.fullKey());
389 return containers;
390 }
391 } else {
394 if (!update.isValid()) {
395 ATH_MSG_FATAL("Invalid UpdateHandle " << m_prdContainerCacheKey.key());
396 return containers;
397 }
398 if (!containers.prd.record(std::make_unique<Muon::sTgcPrepDataContainer>(update.ptr())).isSuccess()) {
399 ATH_MSG_FATAL("Failed to record "<<m_stgcPrepDataContainerKey.fullKey()
400 <<" from "<<m_prdContainerCacheKey.fullKey());
401 return containers;
402 }
403 }
404 containers.isValid = true;
405 return containers;
406}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
const double width
size_type size() const noexcept
Returns the number of elements in the collection.
This class saves the "context" of an expanded identifier (ExpandedIdentifier) for compact or hash ver...
Definition IdContext.h:26
bool OnlineAndPresentInAnotherView()
This method is to avoid calling an expensive operation in the offline case.
StatusCode addOrDelete(std::unique_ptr< T > ptr)
This is a "hash" representation of an Identifier.
value_type get_compact() const
Get the compact id.
IdentifierHash measurementHash(const Identifier &measId) const override final
Constructs the identifier hash from the full measurement Identifier.
double padHeight(const IdentifierHash &measHash) const
Returns the height of all the pads that are not adjacent to the bottom edge of the trapezoid active a...
The MuonDetectorManager stores the transient representation of the Muon Spectrometer geometry and pro...
const sTgcReadoutElement * getsTgcReadoutElement(const Identifier &id) const
access via extended identifier (requires unpacking)
An sTgcReadoutElement corresponds to a single STGC module; therefore typicaly a barrel muon station c...
const MuonPadDesign * getPadDesign(const Identifier &id) const
returns the MuonChannelDesign class for the given identifier
virtual bool stripPosition(const Identifier &id, Amg::Vector2D &pos) const override final
strip position - should be renamed to channel position If the strip number is outside the range of va...
const MuonChannelDesign * getDesign(const Identifier &id) const
returns the MuonChannelDesign class for the given identifier
virtual int get_id(const IdentifierHash &hash_id, Identifier &id, const IdContext *context=0) const override
Create compact id from hash id (return == 0 for OK)
IdContext module_context() const
id for module
const IdentifierHash & identifyHash() const
Class to represent sTgc measurements.
StatusCode provideEmptyContainer(const EventContext &ctx) const override
StatusCode processCollection(const EventContext &ctx, outputCache &xAODcontainers, const STGC_RawDataCollection *rdoColl) const
ToolHandle< INSWCalibTool > m_calibTool
ToolHandle< ISTgcClusterBuilderTool > m_clusterBuilderTool
SG::WriteHandleKey< sTgcPrepDataContainer > m_stgcPrepDataContainerKey
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
SG::ReadHandleKey< STGC_RawDataContainer > m_rdoContainerKey
SG::WriteHandleKey< xAOD::sTgcWireContainer > m_xAODWireKey
SG::UpdateHandleKey< sTgcPrepDataCollection_Cache > m_prdContainerCacheKey
This is the key for the cache for the sTGC PRD containers, can be empty.
const MuonGMR4::MuonDetectorManager * m_detMgrR4
outputCache setupOutputContainers(const EventContext &ctx) const
SG::WriteHandleKey< xAOD::sTgcStripContainer > m_xAODStripKey
SG::WriteHandleKey< xAOD::sTgcPadContainer > m_xAODPadKey
StatusCode decode(const EventContext &ctx, const std::vector< IdentifierHash > &idVect) const override
Decode RDO to PRD A vector of IdentifierHash are passed in, and the data corresponding to this list...
void processRDOContainer(const EventContext &ctx, outputCache &xAODcontainers, const std::vector< IdentifierHash > &idsToDecode) const
const STGC_RawDataContainer * getRdoContainer(const EventContext &ctx) const
virtual StatusCode initialize() override
Standard AthAlgTool initialize method.
SG::ReadCondHandleKey< MuonGM::MuonDetectorManager > m_muDetMgrKey
int channelType(const Identifier &id) const
int channel(const Identifier &id) const override
int gasGap(const Identifier &id) const override
get the hashes
void setMeasurement(const DetectorIDHashType idHash, MeasVector< N > locPos, MeasMatrix< N > locCov)
Sets IdentifierHash, local position and local covariance of the measurement.
void setIdentifier(const DetectorIdentType measId)
Sets the full Identifier of the measurement.
void setTime(short int t)
: Set the calibrated time of the wire measurement
void setAuthor(Author a)
Set the author of the producing algorithm.
void setCharge(int q)
: Set the collected charge on the wire
void setChannelNumber(uint16_t channel)
Set the channel number of the measurement.
void setReadoutElement(const MuonGMR4::sTgcReadoutElement *readoutEle)
set the pointer to the sTgcReadoutElement
void setGasGap(uint8_t gap)
Set the associated gas gap of the measurement.
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic Matrix - dynamic allocation.
Eigen::Matrix< double, 2, 1 > Vector2D
Ensure that the Athena extensions are properly loaded.
Definition GeoMuonHits.h:27
NRpcCablingAlg reads raw condition data and writes derived condition data to the condition store.
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
Ensure that the ATLAS eigen extensions are properly loaded.
Eigen::Matrix< float, N, N > MeasMatrix
Eigen::Matrix< float, N, 1 > MeasVector
Abrivation of the Matrix & Covariance definitions.
MeasVector< N > toStorage(const AmgVector(N)&amgVec)
Converts the double precision of the AmgVector into the floating point storage precision of the MeasV...
sTgcMeasurement_v1 sTgcMeasurement
double channelWidth() const
calculate local channel width
Parameters defining the design of the readout sTGC pads.
double channelWidth(const Amg::Vector2D &pos, bool measPhi, bool preciseMeas=false) const
calculate local channel width
SG::WriteHandle< xAOD::sTgcWireContainer > wire
SG::WriteHandle< Muon::sTgcPrepDataContainer > prd
SG::WriteHandle< xAOD::sTgcStripContainer > strip
SG::WriteHandle< xAOD::sTgcPadContainer > pad