ATLAS Offline Software
Loading...
Searching...
No Matches
SCT_PrepDataToxAOD.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6// SCT_PrepDataToxAOD.cxx
7// Implementation file for class SCT_PrepDataToxAOD
9
10#include "SCT_PrepDataToxAOD.h"
11
12#include "Identifier/Identifier.h"
15#include "InDetSimEvent/SiHit.h"
25
27
28#include "CLHEP/Geometry/Point3D.h"
29
30#include <algorithm>
31#include <cmath>
32
33#define AUXDATA(OBJ, TYP, NAME) \
34 static const SG::AuxElement::Accessor<TYP> acc_##NAME (#NAME); acc_##NAME(*(OBJ))
35
36
38//
39// Initialize method:
40//
43{
44 ATH_CHECK(detStore()->retrieve(m_SCTHelper, "SCT_ID"));
45
46 //make sure we don't write what we don't have
47 if (not m_useTruthInfo) {
48 m_writeSDOs.set(false);
49 m_writeSiHits.set(false);
50 }
51
52 ATH_CHECK(m_clustercontainer.initialize());
57 ATH_CHECK(m_xAodContainer.initialize());
58 ATH_CHECK(m_xAodOffset.initialize());
60
61 ATH_CHECK(m_SCTDetEleCollKey.initialize());
62
63 return StatusCode::SUCCESS;
64}
65
67//
68// Execute method:
69//
71StatusCode SCT_PrepDataToxAOD::execute(const EventContext& ctx) const
72{
73 // the cluster ambiguity map
74 std::map<Identifier, const SCT_RDORawData*> idToRAWDataMap;
77 if (rdoContainer.isValid()) {
78 // get all the RIO_Collections in the container
79 for (const auto collection: *rdoContainer) {
80 //get all the RDOs in the collection
81 for (const auto rdo : *collection) {
82 if (rdo==nullptr) {
83 ATH_MSG_WARNING("Null SCT RDO. Skipping it");
84 continue;
85 }
86 Identifier rdoId{rdo->identify()};
87 idToRAWDataMap.insert(std::pair<Identifier, const SCT_RDORawData*>{rdoId, rdo});
88 } // collection
89 } // Have container;
90 } else if (m_firstEventWarnings) {
91 ATH_MSG_WARNING("Failed to retrieve SCT RDO container");
92 }
93 }
94 ATH_MSG_DEBUG("Size of RDO map is " << idToRAWDataMap.size());
95
96 const PRD_MultiTruthCollection* prdmtColl{nullptr};
97 const xAODTruthParticleLinkVector *truth_particle_links{nullptr};
98 if (m_useTruthInfo) {
100 if (prdmtCollHandle.isValid()) {
101 prdmtColl = &*prdmtCollHandle;
102 }
103 if (!m_truthParticleLinks.empty()) {
105 if (truthParticleLinksHandle.isValid()) {
106 truth_particle_links = truthParticleLinksHandle.cptr();
107 }
108 }
109 }
110
111 const InDetSimDataCollection* sdoCollection{nullptr};
112 if (m_writeSDOs) {
114 if (sdoCollectionHandle.isValid()) {
115 sdoCollection = &*sdoCollectionHandle;
116 }
117 }
118
119 std::vector<std::vector<const SiHit*>> siHits(m_SCTHelper->wafer_hash_max());
120 if (m_writeSiHits) {
122 // ITk split sensors: a SiHit carries the mother sensor's eta_module while
123 // the cluster lives on a child-row wafer (eta_module = mother + row), so
124 // route each hit to its child wafer hash as StripDigitizationTool does.
125 // Unsplit sensors have no mother and are unaffected. Without the element
126 // collection the hits stay on the mother wafer.
128 const InDetDD::SiDetectorElementCollection* sctElements =
129 sctDetEleHandle.isValid() ? sctDetEleHandle.cptr() : nullptr;
130 if (sihitCollection.isValid()) {
131 for (const SiHit& siHit: *sihitCollection) {
132 // Check if it is an SCT hit
133 if (not siHit.isSCT()) continue;
134
135 Identifier wafer_id{m_SCTHelper->wafer_id(siHit.getBarrelEndcap(),
136 siHit.getLayerDisk(),
137 siHit.getPhiModule(),
138 siHit.getEtaModule(),
139 siHit.getSide())};
140 IdentifierHash wafer_hash{m_SCTHelper->wafer_hash(wafer_id)};
141
142 if (sctElements) {
143 const InDetDD::SiDetectorElement* baseEl = sctElements->getDetectorElement(wafer_hash);
144 if (baseEl) {
145 const auto* design =
146 dynamic_cast<const InDetDD::SCT_ModuleSideDesign*>(&baseEl->design());
147 const InDetDD::SCT_ModuleSideDesign* mother = design ? design->getMother() : nullptr;
148 if (mother) {
149 HepGeom::Point3D<double> avg{siHit.localStartPosition() + siHit.localEndPosition()};
150 avg *= 0.5;
151 // {xPhi, xEta, xDepth}; the mother-design row is the child eta offset.
152 const HepGeom::Point3D<double> p3{baseEl->hitLocalToLocal3D(avg)};
153 const InDetDD::SiLocalPosition slp(p3.y(), p3.x()); // (xEta along, xPhi across)
154 const InDetDD::SiCellId mDiode = mother->cellIdOfPosition(slp);
155 if (mDiode.isValid()) {
156 const int rowOffset = mother->getStripRow(mDiode).second;
157 if (rowOffset != 0) {
158 const Identifier child_id{m_SCTHelper->wafer_id(siHit.getBarrelEndcap(),
159 siHit.getLayerDisk(),
160 siHit.getPhiModule(),
161 siHit.getEtaModule() + rowOffset,
162 siHit.getSide())};
163 wafer_hash = m_SCTHelper->wafer_hash(child_id);
164 }
165 }
166 }
167 }
168 }
169
170 if (wafer_hash < siHits.size()) {
171 siHits[wafer_hash].push_back(&siHit);
172 } else {
173 ATH_MSG_WARNING("SiHit routed to an unknown SCT wafer (eta_module "
174 << siHit.getEtaModule() << ", hash " << wafer_hash << "), dropped");
175 }
176 }
177 }
178 }
179
180 // Mandatory. This is needed and required if this algorithm is scheduled.
182 if (not sctClusterContainer.isValid()) {
183 ATH_MSG_FATAL("Cannot retrieve SCT PrepDataContainer " << m_clustercontainer.key());
184 return StatusCode::FAILURE;
185 }
186
187 // Create the xAOD container and its auxiliary store:
189 ATH_CHECK(xaod.record(std::make_unique<xAOD::TrackMeasurementValidationContainer>(),
190 std::make_unique<xAOD::TrackMeasurementValidationAuxContainer>()));
191
193 ATH_CHECK(offsets.record(std::make_unique<std::vector<unsigned int>>(m_SCTHelper->wafer_hash_max(), 0)));
194
195 unsigned int have_truth_link=0u;
196 unsigned int missing_truth_particle=0u;
197 unsigned int missing_parent_particle=0u;
198 // Loop over the container
199 unsigned int counter{0};
200 for (const auto clusterCollection: *sctClusterContainer) {
201 //Fill Offset container
202 (*offsets)[clusterCollection->identifyHash()] = counter;
203
204 // skip empty collections
205 if (clusterCollection->empty()) continue;
206
207 xaod->resize(counter + clusterCollection->size());
208 // loop over collection and convert to xAOD
209 for (const InDet::SCT_Cluster* prd: *clusterCollection) {
210 Identifier clusterId{prd->identify()};
211 if (not clusterId.is_valid()) {
212 ATH_MSG_WARNING("SCT cluster identifier is not valid!");
213 }
214
215 // create and add xAOD object
217 xaod->at(counter) = xprd;
218 ++counter;
219
220 //Set Identifier
221 xprd->setIdentifier(clusterId.get_compact());
222
223 //Set Global Position
224 Amg::Vector3D gpos{prd->globalPosition()};
225 xprd->setGlobalPosition(gpos.x(), gpos.y(), gpos.z());
226
227 //Set Local Position
228 const Amg::Vector2D& locpos{prd->localPosition()};
229 float locY{0.};
230 float locX{static_cast<float>(locpos.x())};
231 if ((not std::isinf(locpos.y()) or std::isnan(locpos.y()))) {
232 if (locpos.y()>=1e-07) locY = locpos.y();
233 } else {
234 locY = -9999.;
235 }
236
237 // Set local error matrix
238 xprd->setLocalPosition(locX, locY);
239
240 const Amg::MatrixX& localCov{prd->localCovariance()};
241 if (localCov.size() == 1) {
242 xprd->setLocalPositionError(localCov(0, 0), 0., 0.);
243 } else if (localCov.size() == 4) {
244 xprd->setLocalPositionError(localCov(0, 0), localCov(1, 1), localCov(0, 1));
245 } else {
246 xprd->setLocalPositionError(0., 0., 0.);
247 }
248
249 // Set vector of hit identifiers
250 std::vector<uint64_t> rdoIdentifierList;
251 rdoIdentifierList.reserve(prd->rdoList().size());
252 for (const auto& hitIdentifier: prd->rdoList()) {
253 rdoIdentifierList.push_back(hitIdentifier.get_compact());
254 }
255 xprd->setRdoIdentifierList(rdoIdentifierList);
256
257 //Add SCT specific information
258 const InDet::SiWidth cw{prd->width()};
259 AUXDATA(xprd, int, SiWidth) = static_cast<int>(cw.colRow()[0]);
260 AUXDATA(xprd, int, hitsInThirdTimeBin) = static_cast<int>(prd->hitsInThirdTimeBin());
261
262 AUXDATA(xprd, int, bec) = m_SCTHelper->barrel_ec(clusterId);
263 AUXDATA(xprd, int, layer) = m_SCTHelper->layer_disk(clusterId);
264 AUXDATA(xprd, int, phi_module) = m_SCTHelper->phi_module(clusterId);
265 AUXDATA(xprd, int, eta_module) = m_SCTHelper->eta_module(clusterId);
266 AUXDATA(xprd, int, side) = m_SCTHelper->side(clusterId);
267
268 // Add the Detector element ID -- not sure if needed as we have the informations above
269 const InDetDD::SiDetectorElement* de{prd->detectorElement()};
270
271 uint64_t detElementId{0};
272 if (de) {
273 Identifier detId{de->identify()};
274 if (detId.is_valid()) {
275 detElementId = detId.get_compact();
276 }
277 }
278 AUXDATA(xprd, uint64_t, detectorElementID) = detElementId;
279
280 //Add details about the individual hits
282 addRDOInformation(xprd, prd, idToRAWDataMap);
283 }
284
285 // Use the MultiTruth Collection to get a list of all true particle contributing to the cluster
286 if (m_useTruthInfo) {
287 if (prdmtColl) {
288 auto range{prdmtColl->equal_range(clusterId)};
289 if (truth_particle_links) {
290 std::vector<unsigned int> tp_indices;
291 for (auto i{range.first}; i!=range.second; ++i) {
292 ElementLink<xAOD::TruthParticleContainer> a_truth_particle_link = truth_particle_links->find(i->second);
293 if (a_truth_particle_link) {
294 const xAOD::TruthParticle *truth_particle = *a_truth_particle_link;
295 if (truth_particle) {
296 ++have_truth_link;
297 tp_indices.push_back(static_cast<int>(truth_particle->index()));
298 }
299 else {
300 ++missing_parent_particle;
301 }
302 }
303 else {
304 tp_indices.push_back(std::numeric_limits<unsigned int>::max());
305 ++missing_truth_particle;
306 }
307 }
308 AUXDATA(xprd, std::vector<unsigned int>, truth_index) = std::move(tp_indices);
309 }
310 std::vector<int> uniqueIDs;
311 for (auto& i{range.first}; i!=range.second; ++i) {
312 uniqueIDs.push_back(HepMC::uniqueID(i->second));
313 }
314 AUXDATA(xprd, std::vector<int>, truth_barcode) = std::move(uniqueIDs); // TODO rename variable to be consistent?
315 }
316 }
317
318 // Use the SDO Collection to get a list of all true particle contributing to the cluster per readout element
319 // Also get the energy deposited by each true particle per readout element
320 std::vector<std::vector<int>> sdoTruthUIDs;
321 if (m_writeSDOs) {
322 if (sdoCollection) {
323 sdoTruthUIDs = addSDOInformation(xprd, prd, sdoCollection);
324 }
325 }
326
327 // Now Get the most detailed truth from the SiHits
328 // Note that this could get really slow if there are a lot of hits and clusters
329 if (m_writeSiHits) {
330 addSiHitInformation(xprd, prd, &siHits[prd->detectorElement()->identifyHash()], sdoTruthUIDs);
331 }
332 }
333 }
334 ATH_MSG_DEBUG(" recorded SCT_PrepData objects: size " << xaod->size());
335
336 m_haveTruthLink += have_truth_link;
337 m_missingTruthParticle += missing_truth_particle;
338 m_missingParentParticle += missing_parent_particle;
339 m_firstEventWarnings = false; //disable one-time warnings
340
341 return StatusCode::SUCCESS;
342}
343
345 const InDet::SCT_Cluster* prd,
346 const InDetSimDataCollection* sdoCollection) const
347{
348 std::vector<int> sdo_word;
349 std::vector<std::vector<int>> sdo_depositsUniqueID;
350 std::vector<std::vector<float>> sdo_depositsEnergy;
351 // find hit
352 for (const auto& hitIdentifier: prd->rdoList()) {
353 auto pos{sdoCollection->find(hitIdentifier)};
354 if (pos == sdoCollection->end()) continue;
355 sdo_word.push_back(pos->second.word());
356 std::vector<int> sdoDepUniqueID(pos->second.getdeposits().size(), HepMC::INVALID_PARTICLE_ID);
357 std::vector<float> sdoDepEnergy(pos->second.getdeposits().size());
358 unsigned int nDepos{0};
359 for (auto& deposit: pos->second.getdeposits()) {
360 if (deposit.first) sdoDepUniqueID[nDepos] = HepMC::uniqueID(deposit.first);
361 ATH_MSG_DEBUG(" SDO Energy Deposit " << deposit.second);
362 sdoDepEnergy[nDepos] = deposit.second;
363 nDepos++;
364 }
365 sdo_depositsUniqueID.push_back(std::move(sdoDepUniqueID));
366 sdo_depositsEnergy.push_back(std::move(sdoDepEnergy));
367 }
368 AUXDATA(xprd, std::vector<int>, sdo_words) = std::move(sdo_word);
369 AUXDATA(xprd, std::vector<std::vector<int>>, sdo_depositsBarcode) = sdo_depositsUniqueID; // TODO rename variable to be consistent?
370 AUXDATA(xprd, std::vector<std::vector<float>>, sdo_depositsEnergy) = std::move(sdo_depositsEnergy);
371 return sdo_depositsUniqueID;
372}
373
374
376 const InDet::SCT_Cluster* prd,
377 const std::vector<const SiHit*>* siHits,
378 const std::vector<std::vector<int>>& sdoTruthUIDs) const
379{
380 std::vector<SiHit> matchingHits;
381 findAllHitsCompatibleWithCluster(prd, siHits, sdoTruthUIDs, matchingHits);
382
383 long unsigned int numHits{matchingHits.size()};
384
385 std::vector<float> sihit_energyDeposit(numHits, 0.);
386 std::vector<float> sihit_meanTime(numHits, 0.);
387 std::vector<int> sihit_uniqueID(numHits, HepMC::UNDEFINED_ID);
388
389 std::vector<float> sihit_startPosX(numHits, 0.);
390 std::vector<float> sihit_startPosY(numHits, 0.);
391 std::vector<float> sihit_startPosZ(numHits, 0.);
392
393 std::vector<float> sihit_endPosX(numHits, 0);
394 std::vector<float> sihit_endPosY(numHits, 0);
395 std::vector<float> sihit_endPosZ(numHits, 0);
396
397 int hitNumber{0};
399 if (de) {
400 // ITk split sensors: hitLocalToLocal3D is an axis permutation without
401 // translation, so the along-strip coordinate comes out in the mother frame.
402 // Subtract the child's row shift to land in the child (cluster) frame.
403 // StripBoxDesign keeps that shift as a translation along the design's
404 // local x, which is the strip direction (it calls it zShift because the
405 // strips run along global z in the barrel); in the {xPhi, xEta, xDepth}
406 // frame returned by hitLocalToLocal3D it acts on xEta. StripGmxInterface
407 // signs the shift per side, but the mother eta direction is the same on
408 // both sides, so undo the sign on side 1.
409 double alongStripShift = 0.;
410 if (const auto* d = dynamic_cast<const InDetDD::SCT_ModuleSideDesign*>(&de->design())) {
411 if (d->getMother()) {
412 alongStripShift = d->moduleShift().translation().x();
413 if (m_SCTHelper->side(prd->identify()) != 0) alongStripShift = -alongStripShift;
414 }
415 }
416 for (const SiHit& sihit : matchingHits) {
417 sihit_energyDeposit[hitNumber] = sihit.energyLoss();
418 sihit_meanTime[hitNumber] = sihit.meanTime();
419 sihit_uniqueID[hitNumber] = HepMC::uniqueID(sihit.particleLink());
420
421 // hitLocalToLocal3D respects each design's axes (Run-3 SCT and ITk strips
422 // order the SiHit components differently) and returns {xPhi, xEta, xDepth}.
423 const HepGeom::Point3D<double> s{de->hitLocalToLocal3D(sihit.localStartPosition())};
424 sihit_startPosX[hitNumber] = s.x();
425 sihit_startPosY[hitNumber] = s.y() - alongStripShift; // xEta, along the strip
426 sihit_startPosZ[hitNumber] = s.z();
427
428 const HepGeom::Point3D<double> e{de->hitLocalToLocal3D(sihit.localEndPosition())};
429 sihit_endPosX[hitNumber] = e.x();
430 sihit_endPosY[hitNumber] = e.y() - alongStripShift;
431 sihit_endPosZ[hitNumber] = e.z();
432 ++hitNumber;
433 }
434 }
435
436 AUXDATA(xprd, std::vector<float>, sihit_energyDeposit) = std::move(sihit_energyDeposit);
437 AUXDATA(xprd, std::vector<float>, sihit_meanTime) = std::move(sihit_meanTime);
438 AUXDATA(xprd, std::vector<int>, sihit_barcode) = std::move(sihit_uniqueID); // TODO rename variable to be consistent?
439
440 AUXDATA(xprd, std::vector<float>, sihit_startPosX) = std::move(sihit_startPosX);
441 AUXDATA(xprd, std::vector<float>, sihit_startPosY) = std::move(sihit_startPosY);
442 AUXDATA(xprd, std::vector<float>, sihit_startPosZ) = std::move(sihit_startPosZ);
443
444 AUXDATA(xprd, std::vector<float>, sihit_endPosX) = std::move(sihit_endPosX);
445 AUXDATA(xprd, std::vector<float>, sihit_endPosY) = std::move(sihit_endPosY);
446 AUXDATA(xprd, std::vector<float>, sihit_endPosZ) = std::move(sihit_endPosZ);
447}
448
450 const std::vector<const SiHit*>* siHits,
451 const std::vector<std::vector<int>>& sdoTruthUIDs,
452 std::vector<SiHit>& matchingHits) const
453{
454 ATH_MSG_VERBOSE("Got " << siHits->size() << " SiHits to look through");
455
456 // Check if we have detector element -- needed to find the local position of the SiHits
458 if (de==nullptr) return;
459
460 std::vector<const SiHit*> multiMatchingHits;
461
462 for (const SiHit* siHit: *siHits) {
463 // Match by geometry (SiHit centroid within +/-1 strip of a cluster RDO) or,
464 // failing that, by the SiHit's truth particle having deposited charge in one
465 // of the cluster's RDOs. Charge sharing and steep angles on ITk strips push
466 // the centroid several strips away from the fired strips.
467 bool matched = false;
469 HepGeom::Point3D<double> averagePosition{siHit->localStartPosition() + siHit->localEndPosition()};
470 averagePosition *= 0.5;
471 const HepGeom::Point3D<double> p3{de->hitLocalToLocal3D(averagePosition)};
472 const Amg::Vector2D pos{p3.x(), p3.y()}; // (xPhi across, xEta along)
473 InDetDD::SiCellId diode{de->cellIdOfPosition(pos)};
474
475 for (const auto& hitIdentifier: prd->rdoList()) {
476 ATH_MSG_DEBUG("Truth Strip " << diode.phiIndex() << " Cluster Strip " << m_SCTHelper->strip(hitIdentifier));
477
478 if (std::abs(static_cast<int>(diode.phiIndex()) - m_SCTHelper->strip(hitIdentifier))<=1) {
479 multiMatchingHits.push_back(siHit);
480 matched = true;
481 break;
482 }
483 }
484 }
485 if (!matched) {
486 const auto uid = HepMC::uniqueID(siHit->particleLink());
487 for (const auto& uniqueIDSDOColl: sdoTruthUIDs) {
488 if (std::find(uniqueIDSDOColl.begin(), uniqueIDSDOColl.end(), uid) == uniqueIDSDOColl.end()) continue;
489 multiMatchingHits.push_back(siHit);
490 break;
491 }
492 }
493 }
494
495 matchingHits.reserve(multiMatchingHits.size());
496 //Now we will now make 1 SiHit for each true particle if the SiHits "touch" other
497 std::vector<const SiHit*>::iterator siHitIter{multiMatchingHits.begin()};
498 std::vector<const SiHit*>::iterator siHitIter2{multiMatchingHits.begin()};
499 ATH_MSG_DEBUG("Found " << multiMatchingHits.size() << " SiHit ");
500 for (; siHitIter != multiMatchingHits.end(); ++siHitIter) {
501 const SiHit* lowestXPos{*siHitIter};
502 const SiHit* highestXPos{*siHitIter};
503
504 // We will merge these hits
505 std::vector<const SiHit*> ajoiningHits;
506 ajoiningHits.push_back(*siHitIter);
507
508 siHitIter2 = siHitIter+1;
509 auto uniqueID = HepMC::uniqueID((*siHitIter)->particleLink());
510 while (siHitIter2 != multiMatchingHits.end()) {
511 // Need to come from the same truth particle
512 if ( uniqueID != HepMC::uniqueID((*siHitIter2)->particleLink())) {
513 ++siHitIter2;
514 continue;
515 }
516
517 constexpr double maxDiff = 0.00005;
518 // Check to see if the SiHits are compatible with each other.
519 if (std::abs((highestXPos->localEndPosition().x()-(*siHitIter2)->localStartPosition().x()))<maxDiff and
520 std::abs((highestXPos->localEndPosition().y()-(*siHitIter2)->localStartPosition().y()))<maxDiff and
521 std::abs((highestXPos->localEndPosition().z()-(*siHitIter2)->localStartPosition().z()))<maxDiff) {
522 highestXPos = *siHitIter2;
523 ajoiningHits.push_back(*siHitIter2);
524 // Dont use hit more than once
525 siHitIter2 = multiMatchingHits.erase(siHitIter2);
526 } else if (std::abs((lowestXPos->localStartPosition().x()-(*siHitIter2)->localEndPosition().x()))<maxDiff and
527 std::abs((lowestXPos->localStartPosition().y()-(*siHitIter2)->localEndPosition().y()))<maxDiff and
528 std::abs((lowestXPos->localStartPosition().z()-(*siHitIter2)->localEndPosition().z()))<maxDiff) {
529 lowestXPos = *siHitIter2;
530 ajoiningHits.push_back(*siHitIter2);
531 // Dont use hit more than once
532 siHitIter2 = multiMatchingHits.erase(siHitIter2);
533 } else {
534 ++siHitIter2;
535 }
536 }
537
538 if (ajoiningHits.size()==0) {
539 ATH_MSG_ERROR("This should really never happen");
540 continue;
541 } else if (ajoiningHits.size()==1) {
542 // Copy Si Hit ready to return
543 matchingHits.emplace_back(*ajoiningHits[0]);
544 continue;
545 } else {
546 // Build new SiHit and merge information together.
547 ATH_MSG_DEBUG("Merging " << ajoiningHits.size() << " SiHits together.");
548 float energyDep{0.};
549 float time{0.};
550 for (auto& siHit: ajoiningHits) {
551 energyDep += siHit->energyLoss();
552 time += siHit->meanTime();
553 }
554 time /= static_cast<float>(ajoiningHits.size());
555 matchingHits.emplace_back(lowestXPos->localStartPosition(),
556 highestXPos->localEndPosition(),
557 energyDep,
558 time,
559 (*siHitIter)->particleLink(),
560 1, // 0 for pixel 1 for SCT
561 (*siHitIter)->getBarrelEndcap(),
562 (*siHitIter)->getLayerDisk(),
563 (*siHitIter)->getEtaModule(),
564 (*siHitIter)->getPhiModule(),
565 (*siHitIter)->getSide());
566 }
567 }
568}
569
571 const InDet::SCT_Cluster* prd,
572 const std::map<Identifier, const SCT_RDORawData*>& idToRAWDataMap) const {
573 std::vector<int> strip(prd->rdoList().size(), -1);
574 std::vector<int> timebin(prd->rdoList().size(), -1);
575 std::vector<int> groupsize(prd->rdoList().size(), -1);
576
577 unsigned int nRDOs{0};
578 for (const auto& hitIdentifier: prd->rdoList()) {
579 auto result{idToRAWDataMap.find(hitIdentifier)};
580 if (result != idToRAWDataMap.end()) {
581 const SCT_RDORawData* sctRdo{result->second};
582 if (sctRdo){
583 strip[nRDOs] = m_SCTHelper->strip(sctRdo->identify());
584 const SCT3_RawData* rdo3{dynamic_cast<const SCT3_RawData*>(sctRdo)};
585 if (rdo3) {
586 timebin[nRDOs] = rdo3->getTimeBin();
587 groupsize[nRDOs] = rdo3->getGroupSize();
588 }
589 }
590 }
591 nRDOs++;
592 }
593
594 AUXDATA(xprd, std::vector<int>, rdo_strip) = std::move(strip);
595 AUXDATA(xprd, std::vector<int>, rdo_timebin) = std::move(timebin);
596 AUXDATA(xprd, std::vector<int>, rdo_groupsize) = std::move(groupsize);
597}
598
600//
601// Finalize method:
602//
605{
606 if (m_useTruthInfo && !m_truthParticleLinks.empty()) {
607 ATH_MSG_INFO("Missing truth particles " << m_missingTruthParticle << " missing parent: " << m_missingParentParticle
608 << " have " << m_haveTruthLink);
609 }
610 return StatusCode::SUCCESS;
611}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_VERBOSE(x,...)
#define ATH_MSG_INFO(x,...)
#define ATH_MSG_FATAL(x,...)
#define AUXDATA(OBJ, TYP, NAME)
This is an Identifier helper class for the SCT subdetector.
Handle class for reading from StoreGate.
Handle class for recording to StoreGate.
const ServiceHandle< StoreGateSvc > & detStore() const
This is a "hash" representation of an Identifier.
bool is_valid() const
Check if id is in a valid state.
value_type get_compact() const
Get the compact id.
virtual SiCellId cellIdOfPosition(const SiLocalPosition &localPos) const =0
position -> id
Base class for the SCT module side design, extended by the Forward and Barrel module design.
virtual std::pair< int, int > getStripRow(SiCellId id) const
Get the strip and row number of the cell.
const SCT_ModuleSideDesign * getMother() const
Identifier for the strip or pixel cell.
Definition SiCellId.h:29
int phiIndex() const
Get phi index. Equivalent to strip().
Definition SiCellId.h:122
bool isValid() const
Test if its in a valid state.
Definition SiCellId.h:136
Class to hold the SiDetectorElement objects to be put in the detector store.
const SiDetectorElement * getDetectorElement(const IdentifierHash &hash) const
Class to hold geometrical description of a silicon detector element.
virtual const SiDetectorDesign & design() const override final
access to the local description (inline):
Class to represent a position in the natural frame of a silicon sensor, for Pixel and SCT For Pixel: ...
HepGeom::Point3D< double > hitLocalToLocal3D(const HepGeom::Point3D< double > &hitPosition) const
Same as previuos method but 3D.
SiCellId cellIdOfPosition(const Amg::Vector2D &localPos) const
As in previous method but returns SiCellId.
virtual Identifier identify() const override final
identifier of this detector element (inline)
virtual Identifier identify() const override final
virtual const InDetDD::SiDetectorElement * detectorElement() const override final
return the detector element corresponding to this PRD The pointer will be zero if the det el is not d...
const Amg::Vector2D & colRow() const
Definition SiWidth.h:115
A PRD is mapped onto all contributing particles.
int getTimeBin() const
virtual int getGroupSize() const override final
std::atomic< unsigned int > m_missingParentParticle
void findAllHitsCompatibleWithCluster(const InDet::SCT_Cluster *prd, const std::vector< const SiHit * > *siHits, const std::vector< std::vector< int > > &sdoTruthUIDs, std::vector< SiHit > &matchingHits) const
BooleanProperty m_useSiHitsGeometryMatching
SG::ReadHandleKey< SiHitCollection > m_sihitContainer
SG::ReadHandleKey< PRD_MultiTruthCollection > m_multiTruth
SG::ReadHandleKey< SCT_RDO_Container > m_rdoContainer
BooleanProperty m_writeSDOs
SG::ReadHandleKey< InDetSimDataCollection > m_SDOcontainer
SG::ReadCondHandleKey< InDetDD::SiDetectorElementCollection > m_SCTDetEleCollKey
virtual StatusCode execute(const EventContext &ctx) const override
std::atomic_bool m_firstEventWarnings
BooleanProperty m_writeSiHits
SG::WriteHandleKey< xAOD::TrackMeasurementValidationContainer > m_xAodContainer
std::vector< std::vector< int > > addSDOInformation(xAOD::TrackMeasurementValidation *xprd, const InDet::SCT_Cluster *prd, const InDetSimDataCollection *sdoCollection) const
Decorate the cluster with SDO truth information and return, per RDO, the uniqueIDs of the truth parti...
virtual StatusCode finalize() override
SG::WriteHandleKey< std::vector< unsigned int > > m_xAodOffset
void addSiHitInformation(xAOD::TrackMeasurementValidation *xprd, const InDet::SCT_Cluster *prd, const std::vector< const SiHit * > *siHits, const std::vector< std::vector< int > > &sdoTruthUIDs) const
BooleanProperty m_writeRDOinformation
const SCT_ID * m_SCTHelper
SG::ReadHandleKey< xAODTruthParticleLinkVector > m_truthParticleLinks
std::atomic< unsigned int > m_missingTruthParticle
SG::ReadHandleKey< InDet::SCT_ClusterContainer > m_clustercontainer
void addRDOInformation(xAOD::TrackMeasurementValidation *, const InDet::SCT_Cluster *, const std::map< Identifier, const SCT_RDORawData * > &idToRAWDataMap) const
std::atomic< unsigned int > m_haveTruthLink
BooleanProperty m_useTruthInfo
virtual StatusCode initialize() override
const_pointer_type cptr()
virtual bool isValid() override final
Can the handle be successfully dereferenced?
const_pointer_type cptr()
Dereference the pointer.
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
Definition SiHit.h:19
HepGeom::Point3D< double > localStartPosition() const
Definition SiHit.cxx:146
HepGeom::Point3D< double > localEndPosition() const
Definition SiHit.cxx:153
Identifier identify() const
return the identifier
const std::vector< Identifier > & rdoList() const
return the List of rdo identifiers (pointers)
ElementLink< xAOD::TruthParticleContainer > find(const HepMcParticleLink &hepMCLink) const
void setRdoIdentifierList(const std::vector< uint64_t > &rdoIdentifierList)
Sets the list of RDO identifiers.
void setLocalPositionError(float localXError, float localYError, float localXYCorrelation)
Sets the local position error.
void setLocalPosition(float localX, float localY)
Sets the local position.
void setIdentifier(uint64_t identifier)
Sets the identifier.
void setGlobalPosition(float globalX, float globalY, float globalZ)
Sets the global position.
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic Matrix - dynamic allocation.
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
constexpr int INVALID_PARTICLE_ID
int uniqueID(const T &p)
constexpr int UNDEFINED_ID
TrackMeasurementValidation_v1 TrackMeasurementValidation
Reference the current persistent version:
TruthParticle_v1 TruthParticle
Typedef to implementation.