ATLAS Offline Software
Loading...
Searching...
No Matches
MdtRdoToMdtPrepDataTool.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#include <cassert>
8
9namespace MuonR4{
11 // initialize handle keys
12 ATH_CHECK(m_calibrationTool.retrieve());
13 ATH_CHECK(m_idHelperSvc.retrieve());
14 ATH_CHECK(m_mdtDecoder.retrieve());
15 ATH_CHECK(detStore()->retrieve(m_detMgrR4));
17 ATH_CHECK(m_rdoContainerKey.initialize());
18 ATH_CHECK(m_cablingKey.initialize());
19 ATH_CHECK(m_xAODKey.initialize());
21 ATH_CHECK(m_geoCtxKey.initialize());
22 return StatusCode::SUCCESS;
23 }
24
25 StatusCode MdtRdoToMdtPrepDataTool::decode(const EventContext& ctx, const std::vector<IdentifierHash>& idVect) const {
26 ATH_MSG_DEBUG("MdtRdoToMdtPrepDataTool for " << idVect.size() << " offline collections called");
27 HandleCache cache = setupHandleCache(ctx);
28 if(!cache.isValid){
29 ATH_MSG_ERROR("Unable to setup valid HandleCache object");
30 return StatusCode::FAILURE;
31 }
32 // seeded or unseeded decoding
33 if (!idVect.empty()) {
34 ATH_CHECK(processPRDHashes(ctx, idVect, cache));
35 } else {
37 std::vector<IdentifierHash> rdoHashes{};
38 const MdtCsmContainer* rdoContainer{nullptr};
39 ATH_CHECK(SG::get(rdoContainer, m_rdoContainerKey, ctx));
40
41 if (rdoContainer->empty()) {
42 return StatusCode::SUCCESS;
43 }
44 rdoHashes.reserve(rdoContainer->size());
45 for (const MdtCsm* csm : *rdoContainer) {
46 rdoHashes.push_back(csm->identifyHash());
47 }
48 ATH_CHECK(processPRDHashes(ctx, rdoHashes, cache));
49 }
50 return StatusCode::SUCCESS;
51 }
52
53 StatusCode MdtRdoToMdtPrepDataTool::decode(const EventContext& ctx, const std::vector<uint32_t>& robIds) const {
54 const MuonMDT_CablingMap* cablingMap{nullptr};
55 ATH_CHECK(SG::get(cablingMap, m_cablingKey, ctx));
56 return decode(ctx, cablingMap->getMultiLayerHashVec(robIds, msgStream()));
57 }
58
59 StatusCode MdtRdoToMdtPrepDataTool::provideEmptyContainer(const EventContext& ctx) const {
60 return setupHandleCache(ctx).isValid ? StatusCode::SUCCESS : StatusCode::FAILURE;
61 }
62
63 // setter for the handle cache
65 HandleCache cache{};
66 cache.digitsForCnv.resize(m_idHelperSvc->mdtIdHelper().detectorElement_hash_max());
67 cache.isValid = cache.prdContainer.record(m_xAODKey, ctx).isSuccess() &&
68 cache.prdTwinContainer.record(m_xAODTwinKey, ctx).isSuccess() &&
69 SG::get(cache.gctx, m_geoCtxKey, ctx).isSuccess() &&
70 SG::get(cache.twinTubeMap, m_twinTubeKey, ctx).isSuccess();
71 return cache;
72 }
73
74 void MdtRdoToMdtPrepDataTool::processDigit(const EventContext& ctx,
75 DigitPtr_t&& digit,
76 HandleCache& hCache) const {
77 const MdtIdHelper& id_helper = m_idHelperSvc->mdtIdHelper();
78 Identifier channelId = digit->identify();
79 const MuonGMR4::MdtReadoutElement* reEle = m_detMgrR4->getMdtReadoutElement(channelId);
80 bool isValidChannel = reEle->isValid(reEle->measurementHash(channelId));
81
82 if (digit->isMasked() || !isValidChannel) {
83 return;
84 }
85 // Rescale ADC/TDC of chambers using HPTDC digitization chip
86 // Must create a new digit from the old one, because MdtDigit has no methods to set ADC/TDC
87 if (m_idHelperSvc->hasHPTDC(channelId)) {
88 digit->setAdc(digit->adc() / 4);
89 digit->setTdc(digit->tdc() / 4);
90 }
91 // if ADC cut too small, skip
92 if(digit->adc() < m_adcCut){
93 return;
94 }
95
96 // calibration
97 const MdtCalibInput calibIn = MdtCalibInput{*digit, *m_detMgrR4, *hCache.gctx};
98 const MdtCalibOutput calibResult{m_calibrationTool->calibrate(ctx, calibIn, false)};
99
100 // copying over create prep data over
101 // if it doesn't match adc cut, skip!
102 if(calibResult.status() == MdtDriftCircleStatus::MdtStatusUnDefined) {
103 ATH_MSG_VERBOSE("Do not create calib hit for "<<m_idHelperSvc->toString(calibIn.identify())
104 <<", adc: "<<calibIn.adc()<<" vs. "<<m_adcCut<<", calibration bailed out "
105 <<(calibResult.status() == MdtDriftCircleStatus::MdtStatusUnDefined? "si": "no"));
106 return;
107 }
108 ATH_MSG_VERBOSE("Calibrated prepdata "<<m_idHelperSvc->toString(calibIn.identify())
109 <<std::endl<<calibIn<<std::endl<<calibResult);
110 double cov{0.}, driftRadius{0.};
111 if (calibResult.status() == MdtDriftCircleStatus::MdtStatusDriftTime){
112 driftRadius = calibResult.driftRadius();
113 cov = Acts::square(calibResult.driftRadiusUncert());
114 } else {
115 cov = Acts::square(reEle->innerTubeRadius());
116 }
117
118 // setting things
119 xAOD::MdtDriftCircle* dc = hCache.prdContainer->push_back(std::make_unique<xAOD::MdtDriftCircle>());
120 const Identifier& id = calibIn.identify();
121 dc->setTdc(calibIn.tdc());
122 dc->setAdc(calibIn.adc());
123 dc->setTube(id_helper.tube(id));
124 dc->setLayer(id_helper.tubeLayer(id));
125 dc->setStatus(calibResult.status());
126 dc->setReadoutElement(reEle);
127
128 xAOD::MeasVector<1> locPos{driftRadius};
129 xAOD::MeasMatrix<1> locCov{cov};
130 dc->setMeasurement<1>(reEle->identHash(),
131 std::move(locPos),
132 std::move(locCov));
133 return;
134 }
135 void MdtRdoToMdtPrepDataTool::processDigit(const EventContext& ctx,
136 TwinDigit_t&& digit,
137 HandleCache& cache) const {
138 ATH_MSG_VERBOSE("Twin digit calibration "<<m_idHelperSvc->toString(digit[0]->identify())
139 <<", tdc: "<<digit[0]->tdc()<<", adc: "<<digit[0]->adc()<<" -- "
140 <<m_idHelperSvc->toString(digit[1]->identify())
141 <<", tdc: "<<digit[1]->tdc()<<", adc: "<<digit[1]->adc());
142 MdtCalibInput mdtCalib1st = MdtCalibInput{*digit[0], *m_detMgrR4, *cache.gctx};
143 MdtCalibInput mdtCalib2nd = MdtCalibInput{*digit[1], *m_detMgrR4, *cache.gctx};
144
145 const MdtCalibTwinOutput twinCalib = m_calibrationTool->calibrateTwinTubes(ctx,
146 std::move(mdtCalib1st),
147 std::move(mdtCalib2nd));
148
149 if (twinCalib.primaryAdc() < m_adcCut) {
150 ATH_MSG_VERBOSE("Do not create calib hit for "<<m_idHelperSvc->toString(twinCalib.primaryID())
151 <<", adc: "<<twinCalib.primaryAdc()<<" vs. "<<m_adcCut<<", calibration bailed out "
152 <<(twinCalib.primaryStatus() == MdtDriftCircleStatus::MdtStatusUnDefined? "si": "no"));
153
154 return;
155 }
156 Amg::Vector2D hitPos{twinCalib.primaryDriftR(), twinCalib.locZ()};
157 AmgSymMatrix(2) cov{AmgSymMatrix(2)::Identity()};
158 cov(0, 0) = Acts::square(twinCalib.uncertPrimaryR());
159 cov(1, 1) = Acts::square(twinCalib.sigmaZ() );
160 const MdtIdHelper& id_helper = m_idHelperSvc->mdtIdHelper();
161 const MuonGMR4::MdtReadoutElement* descriptor = mdtCalib1st.decriptor();
162 xAOD::MdtTwinDriftCircle* dc = cache.prdTwinContainer->push_back(std::make_unique<xAOD::MdtTwinDriftCircle>());
163
164 const Identifier id = twinCalib.primaryID();
165 const Identifier twin_id = twinCalib.twinID();
166 // record things into xAOD
167 dc->setTdc(twinCalib.primaryTdc());
168 dc->setAdc(twinCalib.primaryAdc());
169 dc->setTwinTdc(twinCalib.twinTdc());
170 dc->setTwinAdc(twinCalib.twinAdc());
171 dc->setTube(id_helper.tube(id));
172 dc->setLayer(id_helper.tubeLayer(id));
173 dc->setTwinTube(id_helper.tube(twin_id));
174 dc->setTwinLayer(id_helper.tubeLayer(twin_id));
175 dc->setStatus(twinCalib.primaryStatus());
176 dc->setReadoutElement(descriptor);
177 dc->setMeasurement<2>(descriptor->identHash(),
178 xAOD::toStorage(hitPos),
179 xAOD::toStorage(cov));
180
181 ATH_MSG_VERBOSE(" MADE A 2D TWINPREPDATA " << m_idHelperSvc->toString(twinCalib.primaryID()) << " & "
182 << m_idHelperSvc->toString(twinCalib.twinID()) << " "<<twinCalib);
183
184 ATH_MSG_VERBOSE("local pos center tube w/ TWIN INFO "<<Amg::toString(twinCalib.locZ() * Amg::Vector3D::UnitZ(), 2));
185 }
186 StatusCode MdtRdoToMdtPrepDataTool::processCsm(const EventContext& ctx, const MdtCsm* rdoColl, HandleCache& cache) const {
187 const MdtIdHelper& id_helper = m_idHelperSvc->mdtIdHelper();
188 // first handle the case of twin tubes
189 if (m_useTwin && cache.twinTubeMap->isTwinTubeLayer(rdoColl->identify())) {
190 return processCsmTwin(ctx, rdoColl, cache);
191 }
192 ATH_MSG_DEBUG(" ***************** Start of processCsm");
193 // initialise write handle
195 uint16_t subdetId = rdoColl->SubDetId();
196 uint16_t mrodId = rdoColl->MrodId();
197 uint16_t csmId = rdoColl->CsmId();
198 ATH_MSG_VERBOSE("Identifier = " << m_idHelperSvc->toString(id_helper.parentID(rdoColl->identify())) << " subdetId/ mrodId/ csmId = " << subdetId << " / "
199 << mrodId << " / " << csmId);
200
201 // for each Csm, loop over AmtHit, converter AmtHit to digit
202 // retrieve/create digit collection, and insert digit into collection
203 for (const MdtAmtHit* amtHit : *rdoColl) {
204 ATH_MSG_VERBOSE("Amt Hit, tdcId = " << amtHit->tdcId());
205 DigitPtr_t newDigit{m_mdtDecoder->getDigit(ctx, *amtHit, subdetId, mrodId, csmId)};
206 if (!newDigit) {
207 ATH_MSG_WARNING("Found issue MDT RDO decoder for subdetId/mrodId/csmId "
208 << subdetId << "/" << mrodId << "/" << csmId << " amtHit channelId/tdcId =" << amtHit->channelId() << "/"
209 << amtHit->tdcId());
210 continue;
211 }
212 const IdentifierHash detHash = m_idHelperSvc->detElementHash(newDigit->identify());
213 cache.digitsForCnv[detHash].push_back(std::move(newDigit));
214 }
215 return StatusCode::SUCCESS;
216 }
217
218 StatusCode MdtRdoToMdtPrepDataTool::processCsmTwin(const EventContext& ctx, const MdtCsm* rdoColl, HandleCache& cache) const {
219 ATH_MSG_DEBUG(" ***************** Start of processCsmTwin");
220 ATH_MSG_DEBUG(" Number of AmtHit in this Csm " << rdoColl->size());
221
222 uint16_t subdetId = rdoColl->SubDetId();
223 uint16_t mrodId = rdoColl->MrodId();
224 uint16_t csmId = rdoColl->CsmId();
225 ATH_MSG_VERBOSE("Identifier = " << m_idHelperSvc->toStringChamber(rdoColl->identify())
226 << " subdetId/ mrodId/ csmId = " << rdoColl->SubDetId()
227 << " / " << rdoColl->MrodId() << " / " << rdoColl->CsmId());
228
229 // for each Csm, loop over AmtHit, converter AmtHit to digit
230 // retrieve/create digit collection, and insert digit into collection
231 std::unordered_map<Identifier, TwinDigit_t> mdtDigitColl{};
232
233 for (const MdtAmtHit* amtHit : *rdoColl) {
234 DigitPtr_t newDigit{m_mdtDecoder->getDigit(ctx, *amtHit, subdetId, mrodId, csmId)};
235
236 if (!newDigit) {
237 ATH_MSG_WARNING("Error in MDT RDO decoder for subdetId/mrodId/csmId "
238 << subdetId << "/" << mrodId << "/" << csmId << " amtHit channelId/tdcId =" << amtHit->channelId() << "/"
239 << amtHit->tdcId());
240 continue;
241 } else if (newDigit->isMasked()) {
242 continue;
243 }
244 std::array<DigitPtr_t, 2> & moveTo = mdtDigitColl[newDigit->identify()];
245 if (!moveTo[0]) {
246 moveTo[0] = std::move(newDigit);
247 } else if (!moveTo[1]) {
248 moveTo[1] = std::move(newDigit);
249 } else {
250 ATH_MSG_VERBOSE(" TWIN TUBES: found a tertiary hit in a twin tube in one RdoCollection for "
251 << m_idHelperSvc->toString(newDigit->identify()) << " with adc = " << newDigit->adc()
252 << " tdc = " << newDigit->tdc());
253 }
254 } // end for-loop over rdoColl
255
256 for (auto &[id, digits] : mdtDigitColl) {
257 // get the twin hits from mdtDigitColl
258 const Identifier twinId = cache.twinTubeMap->twinId(id);
259 const IdentifierHash detHash = m_idHelperSvc->detElementHash(id);
260 assert(detHash == m_idHelperSvc->detElementHash(twinId));
262 if (id != twinId) {
263 std::array<DigitPtr_t, 2>& twinDigits = mdtDigitColl[twinId];
264 for (std::size_t k = 0 ; k < 2; ++k) {
265 if (digits[k] && twinDigits[k]) {
266 if (digits[k]->identify() > twinDigits[k]->identify()) {
267 std::swap(digits[k], twinDigits[k]);
268 }
269 cache.twinDigitsForCnv[detHash].push_back(std::array{std::move(digits[k]), std::move(twinDigits[k])});
270 } else{
271 DigitVec_t& outDigits = cache.digitsForCnv[detHash];
272 if (digits[k]) { outDigits.push_back(std::move(digits[k])); }
273 if (twinDigits[k]) { outDigits.push_back(std::move(twinDigits[k])); }
274 }
275 }
276 }
277 }
278 return StatusCode::SUCCESS;
279 }
280 StatusCode MdtRdoToMdtPrepDataTool::processPRDHashes(const EventContext& ctx,
281 const std::vector<IdentifierHash>& multiLayerHashInRobs,
282 HandleCache& cache) const{
283 // looping through each chamber
284 const MdtCsmContainer* rdoContainer{nullptr};
285 ATH_CHECK(SG::get(rdoContainer, m_rdoContainerKey, ctx));
286 if (rdoContainer->empty()) {
287 ATH_MSG_DEBUG("The container is empty");
288 return StatusCode::SUCCESS;
289 }
290 for (const IdentifierHash& hash : multiLayerHashInRobs) {
291 const MdtCsm* rdoColl = rdoContainer->indexFindPtr(hash);
292 if(!rdoColl){
293 ATH_MSG_DEBUG("The rdo container does not have the hash " << hash);
294 continue;
295 }
296 ATH_CHECK(processCsm(ctx, rdoColl, cache));
297 }
298 for (DigitVec_t& digitPerStation : cache.digitsForCnv) {
299 std::ranges::for_each(digitPerStation,
300 [&](DigitPtr_t& digit){
301 processDigit(ctx,std::move(digit),cache);
302 });
303 }
304 for (auto& [hash, digitPerStation] : cache.twinDigitsForCnv) {
305 std::ranges::for_each(digitPerStation,
306 [&](TwinDigit_t& digit){
307 processDigit(ctx,std::move(digit),cache);
308 });
309 }
310 return StatusCode::SUCCESS;
311 }
312}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
#define AmgSymMatrix(dim)
MdtCalibOutput::MdtDriftCircleStatus MdtDriftCircleStatus
size_type size() const noexcept
Returns the number of elements in the collection.
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.
MDT RDO's : data from a single channel of an AMT Atlas Muon TDC.
Definition MdtAmtHit.h:20
int16_t tdc() const
Returns the tdc counts of the hit.
const MuonGMR4::MdtReadoutElement * decriptor() const
Returns the R4 readout element.
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:22
uint16_t CsmId() const
Returns the CSM online id (online identifier inside a MROD).
Definition MdtCsm.h:65
uint16_t MrodId() const
Returns the MROD id from the CSM header.
Definition MdtCsm.h:63
Identifier identify() const
Returns the CSM offline identifier (chamber offline id).
Definition MdtCsm.h:55
uint16_t SubDetId() const
Returns the sub-detector Id.
Definition MdtCsm.h:61
int16_t adc() const
Definition MdtDigit.h:28
bool isMasked() const
Return whether the digit is masked or not.
Definition MdtDigit.h:30
int16_t tdc() const
Definition MdtDigit.h:26
Identifier parentID(const Identifier &id) const
get parent id from channel id
int tube(const Identifier &id) const
int tubeLayer(const Identifier &id) const
Identifier identify() const
Definition MuonDigit.h:30
Readout element to describe the Monitored Drift Tube (Mdt) chambers Mdt chambers usually comrpise out...
bool isValid(const IdentifierHash &measHash) const
Checks whether the passed meaurement hash corresponds to a valid tube described by the readout elemen...
double innerTubeRadius() const
Returns the inner tube radius.
static IdentifierHash measurementHash(unsigned layerNumber, unsigned tubeNumber)
Constructs a Measurement hash from layer && tube number.
IdentifierHash identHash() const
Returns the hash of the readout element which is identical to the detector element hash provided by t...
SG::ReadCondHandleKey< MuonMDT_CablingMap > m_cablingKey
ToolHandle< IMdtCalibrationTool > m_calibrationTool
const MuonGMR4::MuonDetectorManager * m_detMgrR4
virtual StatusCode initialize() override
standard Athena-Algorithm method
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
tools and services
HandleCache setupHandleCache(const EventContext &ctx) const
ToolHandle< Muon::IMDT_RDO_Decoder > m_mdtDecoder
virtual StatusCode decode(const EventContext &ctx, const std::vector< IdentifierHash > &idVect) const override
Decode method - declared in Muon::IMuonRdoToPrepDataTool.
SG::ReadCondHandleKey< Muon::TwinTubeMap > m_twinTubeKey
SG::WriteHandleKey< xAOD::MdtTwinDriftCircleContainer > m_xAODTwinKey
std::array< DigitPtr_t, 2 > TwinDigit_t
std::unique_ptr< MdtDigit > DigitPtr_t
Abrivate the digit pointer.
void processDigit(const EventContext &ctx, DigitPtr_t &&digit, HandleCache &hCache) const
Process a digit to be converted to a 1D measurement.
StatusCode processCsm(const EventContext &ctx, const MdtCsm *rdoColl, HandleCache &hCache) const
StatusCode processPRDHashes(const EventContext &ctx, const std::vector< IdentifierHash > &chamberHashInRobs, HandleCache &hCache) const
SG::ReadHandleKey< ActsTrk::GeometryContext > m_geoCtxKey
SG::WriteHandleKey< xAOD::MdtDriftCircleContainer > m_xAODKey
StatusCode processCsmTwin(const EventContext &ctx, const MdtCsm *rdoColl, HandleCache &hCache) const
SG::ReadHandleKey< MdtCsmContainer > m_rdoContainerKey
std::vector< DigitPtr_t > DigitVec_t
Store the digits per chamber to ensure sorting.
virtual StatusCode provideEmptyContainer(const EventContext &ctx) const override
void setTube(std::uint16_t tube_n)
Sets the tube number.
void setLayer(std::uint8_t layer_n)
Sets the layer number.
void setReadoutElement(const MuonGMR4::MdtReadoutElement *readoutEle)
set the pointer to the MdtReadoutElement
void setTdc(std::int16_t tdc)
Setter methods.
void setStatus(MdtDriftCircleStatus st)
Sets the status of the drift circle.
void setAdc(std::int16_t adc)
Sets the ADC counts.
void setTwinLayer(std::uint8_t layer_n)
Sets the layer number.
void setTwinAdc(std::int16_t adc)
Sets the ADC counts.
void setTwinTdc(std::int16_t tdc)
Sets the TDC counts.
void setTwinTube(std::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.
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Eigen::Matrix< double, 2, 1 > Vector2D
This header ties the generic definitions in this package.
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
void swap(ElementLinkVector< DOBJ > &lhs, ElementLinkVector< DOBJ > &rhs)
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 cache to carry the data containers needed for the dedcoding around.
bool isValid
Flag stating whether the cache is successfully initialized or not.
PrdCont_t prdContainer
The container to hold all 1D tube measurements.
const ActsTrk::GeometryContext * gctx
Geometry context to align the tubes within ATLAS.