ATLAS Offline Software
Loading...
Searching...
No Matches
MdtRdoToPrepDataToolMT.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7#include <algorithm>
8#include <vector>
9
10#include "GaudiKernel/PhysicalConstants.h"
12#include "MdtRDO_Decoder.h"
22
23
24using namespace MuonGM;
25using namespace Trk;
26
28
29
30namespace {
31 // the tube number of a tube in a tubeLayer is encoded in the GeoSerialIdentifier (modulo maxNTubesPerLayer)
32 constexpr unsigned int maxNTubesPerLayer = MdtIdHelper::maxNTubesPerLayer;
33
34 inline void updateClosestApproachTwin(MdtCalibInput & in) {
35 const MuonGM::MdtReadoutElement* descriptor = in.legacyDescriptor();
36 if (descriptor) {
37 if (std::abs(descriptor->getStationS()) < std::numeric_limits<double>::epsilon()) {
38 return;
39 }
40 const Amg::Vector3D nominalTubePos = descriptor->tubePos(in.identify());
41 double measuredPerp = std::sqrt(nominalTubePos.perp2() - descriptor->getStationS()* descriptor->getStationS());
42 CxxUtils::sincos tubeSC{nominalTubePos.phi()};
43 Amg::Vector3D measurePos{tubeSC.cs * measuredPerp, tubeSC.sn *measuredPerp, nominalTubePos.z()};
44 in.setClosestApproach(measurePos);
45 }
46 }
47 inline std::string print(const Muon::MdtPrepData& prd) {
48 const auto* idHelperSvc = prd.detectorElement()->idHelperSvc();
49 std::stringstream sstr{};
50 sstr<<" PrepData "<<idHelperSvc->toString(prd.identify())
51 <<" radius: "<<prd.localPosition()[Trk::locR]<<" pm "
52 <<std::sqrt(prd.localCovariance()(Trk::locR, Trk::locR))<<
53 ", tdc: "<<prd.tdc()<<", adc: "<<prd.adc()<<", status: "<<prd.status();
54 return sstr.str();
55 }
56} // namespace
57
58namespace Muon {
59
60
62 m_idHelperSvc{idHelperSvc} {
63 addedCols.resize(m_idHelperSvc->mdtIdHelper().module_hash_max());
64 }
65
67
68 IdentifierHash mdtHashId = m_idHelperSvc->moduleHash(elementId);
69
70 std::unique_ptr<MdtPrepDataCollection>& coll {addedCols[mdtHashId]};
71 if (!coll) {
72 coll = std::make_unique<MdtPrepDataCollection>(mdtHashId);
73 coll->setIdentifier(m_idHelperSvc->chamberId(elementId));
74 }
75 return coll.get();
76 }
78 const MdtIdHelper& idHelper{m_idHelperSvc->mdtIdHelper()};
79
80 for (unsigned int moduleHash =0; moduleHash < addedCols.size(); ++moduleHash) {
81 std::unique_ptr<MdtPrepDataCollection>& toInsert{addedCols[moduleHash]};
82 if (!toInsert || toInsert->empty()) continue;
83 if (xAODPrd) {
85 std::vector<const MdtPrepData*> sortMe{toInsert->begin(), toInsert->end()};
86 std::ranges::sort(sortMe, IdentifierByDetElSorter{m_idHelperSvc});
87 for (const MdtPrepData* prd : sortMe) {
88 const Identifier prdId{prd->identify()};
89 xAOD::MdtDriftCircle* dc{nullptr};
91 if (!xAODTwinPrd|| !twinTubeMap || twinTubeMap->twinId(prdId) == prdId ||
92 prd->dimension() == 1) {
93 dc = xAODPrd->push_back(std::make_unique<xAOD::MdtDriftCircle>());
94 } else {
95 dc = xAODTwinPrd->push_back(std::make_unique<xAOD::MdtTwinDriftCircle>());
96 }
98 dc->setIdentifier(prdId.get_compact());
99 dc->setTdc(prd->tdc());
100 dc->setAdc(prd->adc());
101 dc->setTube(idHelper.tube(prdId));
102 dc->setLayer(idHelper.tubeLayer(prdId));
103 dc->setStatus(prd->status());
104 if (r4DetMgr){
105 dc->setReadoutElement(r4DetMgr->getMdtReadoutElement(prdId));
106 }
107 const IdentifierHash detHash{m_idHelperSvc->detElementHash(prdId)};
108 float driftRadius{0.f}, driftCov{0.f};
109 if (prd->status() == MdtDriftCircleStatus::MdtStatusDriftTime) {
110 driftRadius = prd->localPosition().x();
111 driftCov = prd->localCovariance()(0,0);
112 } else {
114 const float maxR = r4DetMgr ? dc->readoutElement()->innerTubeRadius()
116 driftCov = std::pow(maxR, 2);
117 }
119 if (dc->numDimensions() == 1) {
121 xAOD::MeasMatrix<1> locCov{driftCov};
122 dc->setMeasurement<1>(detHash, std::move(locPos), std::move(locCov));
123 } else {
127 dc->setMeasurement<2>(detHash, xAOD::toStorage(prd->localPosition()), std::move(locCov));
128 auto* twinDC{static_cast<xAOD::MdtTwinDriftCircle*>(dc)};
129 auto* twinPRD{static_cast<const MdtTwinPrepData*>(prd)};
130 twinDC->setTwinAdc(twinPRD->adcTwin());
131 twinDC->setTwinTdc(twinPRD->tdcTwin());
132 const Identifier twinId = twinTubeMap->twinId(prdId);
133 twinDC->setTwinTube(idHelper.tube(twinId));
134 twinDC->setTwinLayer(idHelper.tubeLayer(twinId));
135 }
136 }
137 }
138 MdtPrepDataContainer::IDC_WriteHandle lock = legacyPrd->getWriteHandle(moduleHash);
139 if (lock.addOrDelete(std::move(toInsert)).isFailure()) {
140 msg << MSG::ERROR << " Failed to add prep data collection " << moduleHash << endmsg;
141 return StatusCode::FAILURE;
142 }
143 }
144 if (xAODPrd) {
145 xAODPrd->lock();
146 }
147 if (xAODTwinPrd) {
148 xAODTwinPrd->lock();
149 }
150 return StatusCode::SUCCESS;
151 }
152
154 ATH_CHECK(m_calibrationTool.retrieve());
155 ATH_MSG_VERBOSE("MdtCalibrationTool retrieved with pointer = " << m_calibrationTool);
156 ATH_CHECK(m_prdContainerCacheKey.initialize(!m_prdContainerCacheKey.key().empty()));
157 ATH_CHECK(m_idHelperSvc.retrieve());
158 // Retrieve the RDO decoder
159 ATH_CHECK(m_mdtDecoder.retrieve());
160
161 ATH_CHECK(m_twinTubeKey.initialize(m_useTwin));
162
163 m_BMGid = m_idHelperSvc->mdtIdHelper().stationNameIndex("BMG");
164 m_BMGpresent = m_BMGid != -1;
165 if (m_useNewGeo) {
166 ATH_CHECK(detStore()->retrieve(m_detMgrR4));
167 }
168 if (m_BMGpresent && !m_useNewGeo) {
169 const MuonGM::MuonDetectorManager* muDetMgr = nullptr;
170 ATH_CHECK(detStore()->retrieve(muDetMgr));
171
172 ATH_MSG_INFO("Processing configuration for layouts with BMG chambers.");
173
174 for (int phi = 6; phi < 8; phi++) { // phi sectors
175 for (int eta = 1; eta < 4; eta++) { // eta sectors
176 for (int side = -1; side < 2; side += 2) { // side
177 if (!muDetMgr->getMuonStation("BMG", side * eta, phi)) continue;
178 for (int roe = 1; roe <= (muDetMgr->getMuonStation("BMG", side * eta, phi))->nMuonReadoutElements();
179 roe++) { // iterate on readout elemets
180 const MdtReadoutElement* mdtRE = dynamic_cast<const MdtReadoutElement*>(
181 (muDetMgr->getMuonStation("BMG", side * eta, phi))->getMuonReadoutElement(roe)); // has to be an MDT
182 if (mdtRE) initDeadChannels(mdtRE);
183 }
184 }
185 }
186 }
187 } else if (m_useNewGeo) {
188 std::vector<const MuonGMR4::MdtReadoutElement*> mdtRE = m_detMgrR4->getAllMdtReadoutElements();
189 for (const MuonGMR4::MdtReadoutElement* re : mdtRE) {
190 if (re->stationName() != m_BMGid) {
191 continue;
192 }
193 for (const IdentifierHash& dead : re->getParameters().removedTubes) {
194 m_DeadChannels.insert(re->measurementId(dead));
195 }
196 }
197 }
198
199 // check if initializing of DataHandle objects success
200 ATH_CHECK(m_rdoContainerKey.initialize());
202 ATH_CHECK(m_readKey.initialize());
203 ATH_CHECK(m_muDetMgrKey.initialize());
204 ATH_CHECK(m_xAODKey.initialize(!m_xAODKey.empty()));
205 ATH_CHECK(m_xAODTwinKey.initialize(!m_xAODTwinKey.empty()));
206 ATH_CHECK(m_geoCtxKey.initialize(m_useNewGeo));
207 return StatusCode::SUCCESS;
208 }
209
210 StatusCode MdtRdoToPrepDataToolMT::decode(const EventContext& ctx, const std::vector<uint32_t>& robIds) const {
211 const MuonMDT_CablingMap* readCdo{nullptr};
212 ATH_CHECK(SG::get(readCdo, m_readKey, ctx));
213 return decode(ctx, readCdo->getMultiLayerHashVec(robIds, msgStream()));
214 }
215
216 const MdtCsmContainer* MdtRdoToPrepDataToolMT::getRdoContainer(const EventContext& ctx) const {
217 SG::ReadHandle rdoContainerHandle{m_rdoContainerKey, ctx};
218 if (rdoContainerHandle.isValid()) {
219 ATH_MSG_DEBUG("MdtgetRdoContainer success");
220 return rdoContainerHandle.cptr();
221 }
222 ATH_MSG_WARNING("Retrieval of Mdt RDO container failed !");
223 return nullptr;
224 }
225
226 StatusCode MdtRdoToPrepDataToolMT::provideEmptyContainer(const EventContext& ctx) const{
227 return setupMdtPrepDataContainer(ctx).isValid ? StatusCode::SUCCESS : StatusCode::FAILURE;
228 }
229
230 void MdtRdoToPrepDataToolMT::processPRDHashes(const EventContext& ctx, ConvCache& mdtPrepDataContainer,
231 const std::vector<IdentifierHash>& multiLayerHashInRobs) const {
232 for (const IdentifierHash& hash : multiLayerHashInRobs) {
233 if (!handlePRDHash(ctx, mdtPrepDataContainer, hash)) { ATH_MSG_DEBUG("Failed to process hash " << hash); }
234 } // ends loop over chamberhash
235 }
236
237 bool MdtRdoToPrepDataToolMT::handlePRDHash(const EventContext& ctx,
238 ConvCache& mdtPrepDataContainer,
239 IdentifierHash rdoHash) const {
240 const MdtCsmContainer* rdoContainer{getRdoContainer(ctx)};
241
242 if (rdoContainer->empty()) {
243 ATH_MSG_DEBUG("The container is empty");
244 return true;
245 }
246 const MdtCsm* rdoColl = rdoContainer->indexFindPtr(rdoHash);
247 if (!rdoColl) {
248 ATH_MSG_DEBUG("The rdo container does not have the hash " << rdoHash);
249 return true;
250 }
251 if (processCsm(ctx, mdtPrepDataContainer, rdoColl).isFailure()) {
252 ATH_MSG_WARNING("processCsm failed for RDO id " << m_idHelperSvc->toString(rdoColl->identify()));
253 return false;
254 }
255 return true;
256 }
257
258 StatusCode MdtRdoToPrepDataToolMT::decode(const EventContext& ctx,
259 const std::vector<IdentifierHash>& idVect) const {
260
261 ATH_MSG_DEBUG("decodeMdtRDO for " << idVect.size() << " offline collections called");
262
263 // setup output container
264 ConvCache mdtPrepDataContainer = setupMdtPrepDataContainer(ctx);
265 if (!mdtPrepDataContainer.isValid) {
266 return StatusCode::FAILURE;
267 }
268
269
270 if (!m_decodeData) {
271 ATH_MSG_DEBUG("Stored empty container. Decoding MDT RDO into MDT PrepRawData is switched off");
272 return StatusCode::SUCCESS;
273 }
274 // seeded or unseeded decoding
275 if (!idVect.empty()) {
276 processPRDHashes(ctx, mdtPrepDataContainer, idVect);
277 } else {
279 std::vector<IdentifierHash> rdoHashes{};
280 const MdtCsmContainer* rdoContainer = getRdoContainer(ctx);
281 if (!rdoContainer || rdoContainer->empty()) return StatusCode::SUCCESS;
282 rdoHashes.reserve(rdoContainer->size());
283 for (const MdtCsm* csm : *rdoContainer) rdoHashes.push_back(csm->identifyHash());
284
285 processPRDHashes(ctx, mdtPrepDataContainer, rdoHashes);
286 }
287 ATH_CHECK(mdtPrepDataContainer.finalize(msgStream()));
288
289 return StatusCode::SUCCESS;
290 }
291
292 std::unique_ptr<MdtPrepData> MdtRdoToPrepDataToolMT::createPrepData(const MdtCalibInput& calibInput,
293 const MdtCalibOutput& calibOutput,
294 ConvCache& cache) const {
295 if (calibInput.adc() < m_adcCut ||
296 calibOutput.status() == MdtDriftCircleStatus::MdtStatusUnDefined) {
297 ATH_MSG_VERBOSE("Do not create calib hit for "<<m_idHelperSvc->toString(calibInput.identify())
298 <<", adc: "<<calibInput.adc()<<" vs. "<<m_adcCut<<", calibration bailed out "
299 <<(calibOutput.status() == MdtDriftCircleStatus::MdtStatusUnDefined? "si": "no"));
300 return nullptr;
301 }
302 const MuonGM::MdtReadoutElement* descriptor = calibInput.legacyDescriptor();
303 if (!descriptor) {
304 if (!cache.legacyDetMgr) {
305 return nullptr;
306 }
307 descriptor = cache.legacyDetMgr->getMdtReadoutElement(calibInput.identify());
308 }
309 ATH_MSG_VERBOSE("Calibrated prepdata "<<m_idHelperSvc->toString(calibInput.identify())
310 <<std::endl<<calibInput<<std::endl<<calibOutput);
311
312 Amg::Vector2D driftRadius{Amg::Vector2D::Zero()};
313 Amg::MatrixX cov(1, 1);
314 if (calibOutput.status() == MdtDriftCircleStatus::MdtStatusDriftTime){
316 const float r = calibOutput.driftRadius();
317 const float sigR = calibOutput.driftRadiusUncert();
318 driftRadius[0] = r;
319 (cov)(0, 0) = sigR * sigR;
320 } else (cov)(0, 0) = std::pow(descriptor->innerTubeRadius(), 2);
321
322 return std::make_unique<MdtPrepData>(calibInput.identify(),
323 std::move(driftRadius),
324 std::move(cov),
325 descriptor,
326 calibInput.tdc(),
327 calibInput.adc(),
328 calibOutput.status());
329 }
330
331 StatusCode MdtRdoToPrepDataToolMT::processCsm(const EventContext& ctx, ConvCache& cache, const MdtCsm* rdoColl) const {
332 const MdtIdHelper& id_helper = m_idHelperSvc->mdtIdHelper();
333 // first handle the case of twin tubes
334 if (m_useTwin) {
335 if (cache.twinTubeMap->isTwinTubeLayer(rdoColl->identify())) {
336 return processCsmTwin(ctx, cache, rdoColl);
337 }
338 }
339
340 ATH_MSG_DEBUG(" ***************** Start of processCsm");
341
343 const Identifier elementId = id_helper.parentID(rdoColl->identify());
344
345 uint16_t subdetId = rdoColl->SubDetId();
346 uint16_t mrodId = rdoColl->MrodId();
347 uint16_t csmId = rdoColl->CsmId();
348 ATH_MSG_VERBOSE("Identifier = " << m_idHelperSvc->toString(elementId) << " subdetId/ mrodId/ csmId = " << subdetId << " / "
349 << mrodId << " / " << csmId);
350
351 // for each Csm, loop over AmtHit, converter AmtHit to digit
352 // retrieve/create digit collection, and insert digit into collection
353 unsigned mc{0};
354
355 for (const MdtAmtHit* amtHit : *rdoColl) {
356 ++mc;
357
358 // FIXME: Still use the digit class.
359 ATH_MSG_VERBOSE("Amt Hit n. " << mc << " tdcId = " << amtHit->tdcId());
360 std::unique_ptr<MdtDigit> newDigit{m_mdtDecoder->getDigit(ctx, *amtHit, subdetId, mrodId, csmId)};
361 if (!newDigit) {
362 ATH_MSG_WARNING("Found issue MDT RDO decoder for subdetId/mrodId/csmId "
363 << subdetId << "/" << mrodId << "/" << csmId << " amtHit channelId/tdcId =" << amtHit->channelId() << "/"
364 << amtHit->tdcId());
365 continue;
366 }
367 // Do something with it
368 Identifier channelId = newDigit->identify();
369 if (newDigit->isMasked() || m_DeadChannels.count(channelId)) {
370 continue;
371 }
372 // Retrieve the proper PRD container. Note that there are cases where one CSM is either split into 2 chambers (BEE / BIS78
373 // legacy) or 2 CSMs are split into one chamber
374 MdtPrepDataCollection* driftCircleColl = cache.createCollection(channelId);
375 if (!driftCircleColl) {
376 ATH_MSG_DEBUG("Corresponding multi layer " << m_idHelperSvc->toString(channelId) << " is already decoded.");
377 continue;
378 }
379
380 // check if the module ID of this channel is different from the CSM one
381 // If it's the first case, create the additional collection
382
383 ATH_MSG_VERBOSE("got digit with id ext / hash " << m_idHelperSvc->toString(channelId) << " / "
384 << driftCircleColl->identifyHash());
385
386 // Rescale ADC/TDC of chambers using HPTDC digitization chip
387 // Must create a new digit from the old one, because MdtDigit has no methods to set ADC/TDC
388 if (m_idHelperSvc->hasHPTDC(channelId)) {
389 newDigit->setAdc(newDigit->adc() / 4);
390 newDigit->setTdc(newDigit->tdc() / 4);
391 }
392 const MdtCalibInput calibIn = m_useNewGeo ? MdtCalibInput{*newDigit, *m_detMgrR4, *cache.gctx}:
393 MdtCalibInput{*newDigit, *cache.legacyDetMgr};
394 const MdtCalibOutput calibResult{m_calibrationTool->calibrate(ctx, calibIn, false)};
395
396 std::unique_ptr<MdtPrepData> newPrepData = createPrepData(calibIn, calibResult, cache);
397 if (!newPrepData) {
398 continue;
399 }
400 if (driftCircleColl->size()) {
401 MdtPrepData* prevPrd = driftCircleColl->at(driftCircleColl->size()-1);
402 if (prevPrd->identify() == channelId) {
403 std::stringstream sstr{};
404 ATH_MSG_VERBOSE("Duplicated prep data object detected: "<<std::endl
405 <<" **** "<<print(*prevPrd)<<std::endl
406 <<" **** "<<print(*newPrepData));
407 if (prevPrd->status() == MdtDriftCircleStatus::MdtStatusDriftTime) {
408 ATH_MSG_VERBOSE("Prd is already good");
409 } else if (newPrepData->status() == MdtDriftCircleStatus::MdtStatusDriftTime) {
410 (*prevPrd) = std::move(*newPrepData);
411 prevPrd->setHashAndIndex(driftCircleColl->identifyHash(), driftCircleColl->size()-1);
412 }
413 continue;
414 }
415 }
416 ATH_MSG_VERBOSE("New prd created "<<print(*newPrepData));
417 newPrepData->setHashAndIndex(driftCircleColl->identifyHash(), driftCircleColl->size());
418 driftCircleColl->push_back(std::move(newPrepData));
419 }
420 return StatusCode::SUCCESS;
421 }
422 StatusCode MdtRdoToPrepDataToolMT::processCsmTwin(const EventContext& ctx, ConvCache& cache, const MdtCsm* rdoColl) const {
423 const MdtIdHelper& id_helper = m_idHelperSvc->mdtIdHelper();
424 ATH_MSG_DEBUG(" ***************** Start of processCsmTwin");
425 ATH_MSG_DEBUG(" Number of AmtHit in this Csm " << rdoColl->size());
427 Identifier elementId = id_helper.parentID(rdoColl->identify());
428
429 uint16_t subdetId = rdoColl->SubDetId();
430 uint16_t mrodId = rdoColl->MrodId();
431 uint16_t csmId = rdoColl->CsmId();
432 ATH_MSG_VERBOSE("Identifier = " << m_idHelperSvc->toString(elementId) << " subdetId/ mrodId/ csmId = " << rdoColl->SubDetId()
433 << " / " << rdoColl->MrodId() << " / " << rdoColl->CsmId());
434
435 // for each Csm, loop over AmtHit, converter AmtHit to digit
436 // retrieve/create digit collection, and insert digit into collection
437 std::map<Identifier, std::array<std::unique_ptr<MdtDigit>, 2>> mdtDigitColl{};
438
439 for (const MdtAmtHit* amtHit : *rdoColl) {
440 std::unique_ptr<MdtDigit> newDigit{m_mdtDecoder->getDigit(ctx, *amtHit, subdetId, mrodId, csmId)};
441
442 if (!newDigit) {
443 ATH_MSG_WARNING("Error in MDT RDO decoder for subdetId/mrodId/csmId "
444 << subdetId << "/" << mrodId << "/" << csmId << " amtHit channelId/tdcId =" << amtHit->channelId() << "/"
445 << amtHit->tdcId());
446 continue;
447 }
448 std::array<std::unique_ptr<MdtDigit>, 2> & moveTo = mdtDigitColl[newDigit->identify()];
449 if (!moveTo[0]) {
450 moveTo[0] = std::move(newDigit);
451 } else if (!moveTo[1] && !m_discardSecondaryHitTwin) {
452 moveTo[1] = std::move(newDigit);
453 } else {
454 ATH_MSG_VERBOSE(" TWIN TUBES: found a tertiary hit in a twin tube in one RdoCollection for "
455 << m_idHelperSvc->toString(newDigit->identify()) << " with adc = " << newDigit->adc()
456 << " tdc = " << newDigit->tdc());
457 }
458 } // end for-loop over rdoColl
459
460 auto convertTwins = [this, &cache, &ctx](std::unique_ptr<MdtDigit> digit,
461 std::unique_ptr<MdtDigit> digit2) {
462 if (!digit || digit->isMasked() || !cache.legacyDetMgr) {
463 return;
464 }
465
466 MdtPrepDataCollection* driftCircleColl = cache.createCollection(digit->identify());
467
468 if (!digit2 || digit2->isMasked()) {
469 ATH_MSG_VERBOSE("Got single digit " << m_idHelperSvc->toString(digit->identify())<<", tdc: "
470 <<digit->tdc()<<", adc: "<<digit->adc()
471 << ", hash: "<< driftCircleColl->identifyHash());
472
473 const MdtCalibInput mdtCalibIn = m_useNewGeo ? MdtCalibInput{*digit, *m_detMgrR4, *cache.gctx}:
474 MdtCalibInput{*digit, *cache.legacyDetMgr};
475
476 const MdtCalibOutput mdtCalibOut{m_calibrationTool->calibrate(ctx, mdtCalibIn, false)};
477
479 std::unique_ptr<MdtPrepData> newPrepData = createPrepData(mdtCalibIn, mdtCalibOut, cache);
480 if (!newPrepData) return;
481
482 newPrepData->setHashAndIndex(driftCircleColl->identifyHash(), driftCircleColl->size());
483 driftCircleColl->push_back(std::move(newPrepData));
484 return;
485 }
486 ATH_MSG_VERBOSE("Twin digit calibration "<<m_idHelperSvc->toString(digit->identify())
487 <<", tdc: "<<digit->tdc()<<", adc: "<<digit->adc()<<" -- "
488 <<m_idHelperSvc->toString(digit2->identify())
489 <<", tdc: "<<digit2->tdc()<<", adc: "<<digit2->adc());
490 MdtCalibInput mdtCalib1st = m_useNewGeo ? MdtCalibInput{*digit, *m_detMgrR4, *cache.gctx}
491 : MdtCalibInput{*digit, *cache.legacyDetMgr};
492
493 MdtCalibInput mdtCalib2nd = m_useNewGeo ? MdtCalibInput{*digit2, *m_detMgrR4, *cache.gctx}
494 : MdtCalibInput{*digit2, *cache.legacyDetMgr};
495
496 updateClosestApproachTwin(mdtCalib1st);
497 updateClosestApproachTwin(mdtCalib2nd);
498
499 const MdtCalibTwinOutput twinCalib = m_calibrationTool->calibrateTwinTubes(ctx,
500 std::move(mdtCalib1st),
501 std::move(mdtCalib2nd));
502
503 Amg::Vector2D hitPos{twinCalib.primaryDriftR(), twinCalib.locZ()};
504 Amg::MatrixX cov(2, 2);
505 cov(0, 0) = twinCalib.uncertPrimaryR() * twinCalib.uncertPrimaryR();
506 cov(1, 1) = twinCalib.sigmaZ() * twinCalib.sigmaZ();
507 cov(0, 1) = cov(1, 0) = 0;
508
509 const MuonGM::MdtReadoutElement* descriptor = cache.legacyDetMgr->getMdtReadoutElement(digit->identify());
510 auto twin_newPrepData = std::make_unique<MdtTwinPrepData>(twinCalib.primaryID(),
511 std::move(hitPos),
512 std::move(cov),
513 descriptor,
514 twinCalib.primaryTdc(),
515 twinCalib.primaryAdc(),
516 twinCalib.twinTdc(),
517 twinCalib.twinAdc(),
518 twinCalib.primaryStatus());
519
520 ATH_MSG_VERBOSE(" MADE A 2D TWINPREPDATA " << m_idHelperSvc->toString(twinCalib.primaryID()) << " & "
521 << m_idHelperSvc->toString(twinCalib.twinID()) << " "<<twinCalib);
522
523 ATH_MSG_VERBOSE("global pos center tube " << Amg::toString(twin_newPrepData->globalPosition(), 2) << std::endl
524 <<"local pos center tube w/ TWIN INFO "<<Amg::toString(twinCalib.locZ() * Amg::Vector3D::UnitZ(), 2)<<std::endl
525 <<"global pos w/o TWIN INFO "<<Amg::toString(descriptor->tubePos(twinCalib.primaryID())));
526
527 twin_newPrepData->setHashAndIndex(driftCircleColl->identifyHash(), driftCircleColl->size());
528 driftCircleColl->push_back(std::move(twin_newPrepData));
529 };
530
531 // iterate over mdtDigitColl
532 for (auto &[id, digits] : mdtDigitColl) {
533 // get the twin hits from mdtDigitColl
534 const Identifier twinId = cache.twinTubeMap->twinId(id);
536 if (id != twinId) {
537 std::array<std::unique_ptr<MdtDigit>, 2>& twinDigits = mdtDigitColl[twinId];
538 ATH_MSG_VERBOSE("Convert digits: "<<digits[0].get()<<" "<<twinDigits[0].get());
539 convertTwins(std::move(digits[0]), std::move(twinDigits[0]));
540 ATH_MSG_VERBOSE("Convert digits: "<<digits[1].get()<<" "<<twinDigits[1].get());
541 convertTwins(std::move(digits[1]), std::move(twinDigits[1]));
542 } else {
543 convertTwins(std::move(digits[0]), nullptr);
544 convertTwins(std::move(digits[1]), nullptr);
545 }
546 }
547 return StatusCode::SUCCESS;
548 }
550 PVConstLink cv = mydetEl->getMaterialGeom(); // it is "Multilayer"
551 int nGrandchildren = cv->getNChildVols();
552 if (nGrandchildren <= 0) return;
553
554 std::vector<int> tubes;
555 geoGetIds([&](int id) { tubes.push_back(id); }, &*cv);
556 std::sort(tubes.begin(), tubes.end());
557
558 const Identifier detElId = mydetEl->identify();
559 const int ml = mydetEl->getMultilayer();
560 std::vector<int>::iterator it = tubes.begin();
561 for (int layer = 1; layer <= mydetEl->getNLayers(); layer++) {
562 for (int tube = 1; tube <= mydetEl->getNtubesperlayer(); tube++) {
563 int want_id = layer * maxNTubesPerLayer + tube;
564 if (it != tubes.end() && *it == want_id) {
565 ++it;
566 } else {
567 it = std::lower_bound(tubes.begin(), tubes.end(), want_id);
568 if (it != tubes.end() && *it == want_id) {
569 ++it;
570 } else {
571 Identifier deadTubeId = m_idHelperSvc->mdtIdHelper().channelID(detElId, ml, layer, tube);
572 m_DeadChannels.insert(deadTubeId);
573 ATH_MSG_VERBOSE("adding dead tube "<<m_idHelperSvc->toString(deadTubeId));
574 }
575 }
576 }
577 }
578
579 }
581
582 ConvCache cache{m_idHelperSvc.get()};
583
585 // Caching of PRD container
586 if (m_prdContainerCacheKey.key().empty()) {
587 // without the cache we just record the container
588 StatusCode status = handle.record(std::make_unique<MdtPrepDataContainer>(m_idHelperSvc->mdtIdHelper().module_hash_max()));
589 if (status.isFailure() || !handle.isValid()) {
590 ATH_MSG_FATAL("Could not record container of MDT PrepData Container at " << m_mdtPrepDataContainerKey.key());
591 return cache;
592 }
593 ATH_MSG_VERBOSE("Created container " << m_mdtPrepDataContainerKey.key());
594 cache.legacyPrd = handle.ptr();
595 } else {
596 // use the cache to get the container
598 if (!update.isValid()) {
599 ATH_MSG_FATAL("Invalid UpdateHandle " << m_prdContainerCacheKey.key());
600 return cache;
601 }
602 StatusCode status = handle.record(std::make_unique<MdtPrepDataContainer>(update.ptr()));
603 if (status.isFailure() || !handle.isValid()) {
604 ATH_MSG_FATAL("Could not record container of MDT PrepData Container using cache " << m_prdContainerCacheKey.key() << " - "
606 return cache;
607 }
608 ATH_MSG_VERBOSE("Created container using cache for " << m_prdContainerCacheKey.key());
609 cache.legacyPrd = handle.ptr();
610 }
611 if (!m_xAODTwinKey.empty()) {
612 SG::WriteHandle writeHandle{m_xAODTwinKey, ctx};
613 if (!writeHandle.recordNonConst(std::make_unique<xAOD::MdtTwinDriftCircleContainer>(),
614 std::make_unique<xAOD::MdtTwinDriftCircleAuxContainer>()).isSuccess() ||
615 !writeHandle.isValid()) {
616 ATH_MSG_FATAL("Failed to write xAOD::MdtPrepDataContainer "<<m_xAODTwinKey.fullKey());
617 return cache;
618 }
619 cache.xAODTwinPrd = writeHandle.ptr();
620 }
621 if (!m_xAODKey.empty()) {
622 SG::WriteHandle writeHandle{m_xAODKey, ctx};
623 if (!writeHandle.recordNonConst(std::make_unique<xAOD::MdtDriftCircleContainer>(),
624 std::make_unique<xAOD::MdtDriftCircleAuxContainer>()).isSuccess() ||
625 !writeHandle.isValid()) {
626 ATH_MSG_FATAL("Failed to write xAOD::MdtPrepDataContainer "<<m_xAODKey.fullKey());
627 return cache;
628 }
629 cache.xAODPrd = writeHandle.ptr();
630 }
632 if (!m_geoCtxKey.empty()) {
633 SG::ReadHandle readHandle{m_geoCtxKey, ctx};
634 if (!readHandle.isPresent()) {
635 ATH_MSG_FATAL("Failed to retrieve the geometry context "<<m_geoCtxKey.fullKey());
636 return cache;
637 }
638 cache.gctx = readHandle.cptr();
639 }
641 if (!m_muDetMgrKey.empty()) {
642 SG::ReadCondHandle detMgrHandle{m_muDetMgrKey, ctx};
643 if (!detMgrHandle.isValid()) {
644 ATH_MSG_FATAL("Failed to retrieve the detector manager from the conditions store "<<m_muDetMgrKey.fullKey());
645 return cache;
646 }
647 cache.legacyDetMgr = detMgrHandle.cptr();
648 }
649 if (m_useTwin) {
650 SG::ReadCondHandle twinTubeHandle{m_twinTubeKey, ctx};
651 if (!twinTubeHandle.isValid()) {
652 ATH_MSG_FATAL("Failed to initialize twin tube map "<<m_twinTubeKey.fullKey());
653 return cache;
654 }
655 cache.twinTubeMap = twinTubeHandle.cptr();
656 }
657 cache.r4DetMgr = m_detMgrR4;
658 // Pass the container from the handle
659 cache.isValid = true;
660 return cache;
661 }
662} // namespace Muon
const boost::regex re(r_e)
Scalar eta() const
pseudorapidity method
#define endmsg
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Visitor to collect all IDs under a GeoModel node.
void geoGetIds(FUNCTION f, const GeoGraphNode *node, int depthLimit=1)
Template helper for running the visitor.
Definition GeoGetIds.h:82
MdtCalibOutput::MdtDriftCircleStatus MdtDriftCircleStatus
void print(char *figname, TCanvas *c1)
const PrepDataT * at(size_type n) const
value_type push_back(value_type pElem)
size_type size() const noexcept
StatusCode addOrDelete(std::unique_ptr< T > ptr)
bool empty() const
return true if container is empty
virtual const T * indexFindPtr(IdentifierHash hashId) const override final
return pointer on the found entry or null if out of range using hashed index - fast version,...
size_t size() const
Duplicate of fullSize for backwards compatability.
This is a "hash" representation of an Identifier.
value_type get_compact() const
Get the compact id.
MDT RDO's : data from a single channel of an AMT Atlas Muon TDC.
Definition MdtAmtHit.h:20
const MuonGM::MdtReadoutElement * legacyDescriptor() const
Returns the legacy readout element.
void setClosestApproach(const Amg::Vector3D &approach)
Sets the closest approach.
int16_t tdc() const
Returns the tdc counts of the hit.
int16_t adc() const
Returns the amount of accumulated charge.
const Identifier & identify() const
Returns the Identifier of the hit.
double driftRadiusUncert() const
Returns the uncertainty on the drift radius.
double driftRadius() const
Returns the drift radius of the calibrated object.
Muon::MdtDriftCircleStatus MdtDriftCircleStatus
MdtDriftCircleStatus status() const
Status of the calibration.
MdtDriftCircleStatus primaryStatus() const
double primaryDriftR() const
Identifier twinID() const
Identifier primaryID() const
double uncertPrimaryR() const
This container provides acces to the MDT RDOs.
MDT RDOs : Chamber Service Module, container of AmtHits of a single Mdt chamber.
Definition MdtCsm.h:19
uint16_t CsmId() const
Returns the CSM online id (online identifier inside a MROD)
Definition MdtCsm.h:61
uint16_t MrodId() const
Returns the MROD id from the CSM header.
Definition MdtCsm.h:59
Identifier identify() const
Returns the CSM offline identifier (chamber offline id)
Definition MdtCsm.h:51
uint16_t SubDetId() const
Returns the sub-detector Id.
Definition MdtCsm.h:57
Identifier parentID(const Identifier &id) const
get parent id from channel id
int tube(const Identifier &id) const
int tubeLayer(const Identifier &id) const
static constexpr int maxNTubesPerLayer
The maxNTubesPerLayer represents the absolute maximum of tubes which are built into a single multilay...
Definition MdtIdHelper.h:68
double innerTubeRadius() const
Returns the inner tube radius.
Amg::Vector3D tubePos(const Identifier &id) const
Returns the global position of the given tube.
int getNLayers() const
Returns the number of tube layers inside the multilayer.
int getMultilayer() const
Returns the multilayer represented by the readout element.
int getNtubesperlayer() const
Returns the number of tubes in each tube layer.
double innerTubeRadius() const
Returns the inner tube radius excluding the aluminium walls.
The MuonDetectorManager stores the transient representation of the Muon Spectrometer geometry and pro...
const MdtReadoutElement * getMdtReadoutElement(const Identifier &id) const
access via extended identifier (requires unpacking)
const MuonStation * getMuonStation(const std::string &stName, int eta, int phi) const
double getStationS() const
Seems to be exclusively used by the MDTs --> Move it to MdtReadoutElement.
Identifier identify() const override final
Returns the ATLAS Identifier of the MuonReadOutElement.
std::vector< IdentifierHash > getMultiLayerHashVec(const std::vector< uint32_t > &ROBId_list, MsgStream &log) const
return a vector of HashId lists for a given list of ROD's
Interface for Helper service that creates muon Identifiers and can be used to print Identifiers.
Class to represent measurements from the Monitored Drift Tubes.
Definition MdtPrepData.h:33
int adc() const
Returns the ADC (typically range is 0 to 250)
virtual const MuonGM::MdtReadoutElement * detectorElement() const override
Returns the detector element corresponding to this PRD.
MdtDriftCircleStatus status() const
Returns the status of the measurement.
int tdc() const
Returns the TDC (typically range is 0 to 2500).
unsigned int dimension() const
Returns the dimension of the MdtPrepData.
Definition MdtPrepData.h:85
std::unique_ptr< MdtPrepData > createPrepData(const MdtCalibInput &calibInput, const MdtCalibOutput &calibOutput, ConvCache &cache) const
Creates the PRD object.
SG::ReadCondHandleKey< MuonMDT_CablingMap > m_readKey
virtual StatusCode provideEmptyContainer(const EventContext &ctx) const override
SG::ReadHandleKey< MdtCsmContainer > m_rdoContainerKey
SG::UpdateHandleKey< MdtPrepDataCollection_Cache > m_prdContainerCacheKey
This is the key for the cache for the MDT PRD containers, can be empty.
SG::ReadHandleKey< ActsTrk::GeometryContext > m_geoCtxKey
ConvCache setupMdtPrepDataContainer(const EventContext &ctx) const
Creates the prep data container to be written.
SG::WriteHandleKey< xAOD::MdtTwinDriftCircleContainer > m_xAODTwinKey
const MdtCsmContainer * getRdoContainer(const EventContext &ctx) const
Loads the input RDO container from StoreGate.
ToolHandle< IMdtCalibrationTool > m_calibrationTool
MDT calibration service.
StatusCode processCsm(const EventContext &ctx, ConvCache &mdtPrepDataContainer, const MdtCsm *rdoColl) const
SG::ReadCondHandleKey< TwinTubeMap > m_twinTubeKey
Gaudi::Property< bool > m_discardSecondaryHitTwin
SG::WriteHandleKey< Muon::MdtPrepDataContainer > m_mdtPrepDataContainerKey
MdtPrepRawData containers.
const MuonGMR4::MuonDetectorManager * m_detMgrR4
std::unordered_set< Identifier > m_DeadChannels
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
SG::WriteHandleKey< xAOD::MdtDriftCircleContainer > m_xAODKey
Gaudi::Property< int > m_adcCut
member variables for algorithm properties:
SG::ReadCondHandleKey< MuonGM::MuonDetectorManager > m_muDetMgrKey
Gaudi::Property< bool > m_useNewGeo
void processPRDHashes(const EventContext &ctx, ConvCache &mdtPrepDataContainer, const std::vector< IdentifierHash > &chamberHashInRobs) const
Gaudi::Property< bool > m_decodeData
toggle on/off the decoding of MDT RDO into MdtPrepData
virtual StatusCode decode(const EventContext &ctx, const std::vector< IdentifierHash > &idVect) const override
Decode method - declared in Muon::IMuonRdoToPrepDataTool.
virtual StatusCode initialize() override
standard Athena-Algorithm method
bool handlePRDHash(const EventContext &ctx, ConvCache &mdtPrepDataContainer, IdentifierHash rdoHash) const
void initDeadChannels(const MuonGM::MdtReadoutElement *mydetEl)
StatusCode processCsmTwin(const EventContext &ctx, ConvCache &mdtPrepDataContainer, const MdtCsm *rdoColll) const
ToolHandle< Muon::IMDT_RDO_Decoder > m_mdtDecoder
Class to represent measurements from the Monitored Drift Tubes.
virtual IdentifierHash identifyHash() const override final
bool isTwinTubeLayer(const Identifier &channelId) const
Returns whether the multilayer is equipped with twin-tubes or not.
Identifier twinId(const Identifier &channelId) const
Returns the Identifier of the mapped twin tube.
const_pointer_type cptr()
virtual bool isValid() override final
Can the handle be successfully dereferenced?
const_pointer_type cptr()
Dereference the pointer.
bool isPresent() const
Is the referenced object present in SG?
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
StatusCode recordNonConst(std::unique_ptr< T > data)
Record a non-const object to the store.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
pointer_type ptr()
Dereference the pointer.
const Amg::Vector2D & localPosition() const
return the local position reference
Identifier identify() const
return the identifier
void setHashAndIndex(unsigned short collHash, unsigned short objIndex)
TEMP for testing: might make some classes friends later ...
const Amg::MatrixX & localCovariance() const
return const ref to the error matrix
unsigned int numDimensions() const override
Override the dimensions to be 1.
void setAdc(int16_t adc)
Sets the ADC counts.
void setReadoutElement(const MuonGMR4::MdtReadoutElement *readoutEle)
set the pointer to the MdtReadoutElement
const MuonGMR4::MdtReadoutElement * readoutElement() const
Retrieve the associated MdtReadoutElement.
void setLayer(uint8_t layer_n)
Sets the layer number.
void setStatus(MdtDriftCircleStatus st)
Sets the status of the drift circle.
void setTdc(int16_t tdc)
Setter methods.
void setTube(uint16_t tube_n)
Sets the tube number.
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.
int r
Definition globals.cxx:22
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition hcg.cxx:130
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
Eigen::Matrix< double, 3, 1 > Vector3D
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.
std::string print(const MuPatSegment &)
MuonPrepDataCollection< MdtPrepData > MdtPrepDataCollection
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
Ensure that the ATLAS eigen extensions are properly loaded.
@ driftRadius
trt, straws
Definition ParamDefs.h:53
@ locR
Definition ParamDefs.h:44
@ phi
Definition ParamDefs.h:75
@ locZ
local cylindrical
Definition ParamDefs.h:42
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
MdtDriftCircle_v1 MdtDriftCircle
MdtTwinDriftCircle_v1 MdtTwinDriftCircle
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...
Helper to simultaneously calculate sin and cos of the same angle.
Definition sincos.h:39
Helper struct to parse the event data around the tool.
bool isValid
Flag set to indicate that the complete validation was successful.
const TwinTubeMap * twinTubeMap
Pointer to the map having the mapping of twin tube pairs.
const Muon::IMuonIdHelperSvc * m_idHelperSvc
xAOD::MdtTwinDriftCircleContainer * xAODTwinPrd
ConvCache(const Muon::IMuonIdHelperSvc *idHelperSvc)
std::vector< std::unique_ptr< MdtPrepDataCollection > > addedCols
StatusCode finalize(MsgStream &msg)
Copy the non-empty collections into the created prd container.
MdtPrepDataCollection * createCollection(const Identifier &id)
Creates a new MdtPrepDataCollection, if it's neccessary and also possible.
const ActsTrk::GeometryContext * gctx
Acts Geometry context.
const MuonGM::MuonDetectorManager * legacyDetMgr
Detector manager from the conditions store.
xAOD::MdtDriftCircleContainer * xAODPrd
const MuonGMR4::MuonDetectorManager * r4DetMgr
Detector manger from R4.
MsgStream & msg
Definition testRead.cxx:32