ATLAS Offline Software
Loading...
Searching...
No Matches
PixelClusterSiHitDecoratorAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
12
13namespace ActsTrk {
14
16 ISvcLocator *pSvcLocator)
17 : AthReentrantAlgorithm(name, pSvcLocator)
18 {}
19
21 {
22 ATH_MSG_DEBUG( "Initializing " << name() << " ..." );
23
24 ATH_CHECK( m_inputMeasurementsKey.initialize() );
25 ATH_CHECK( m_SDOcontainer_key.initialize() );
26 ATH_CHECK( m_pixelDetEleCollKey.initialize() );
27 ATH_CHECK( m_siHitsKey.initialize() );
28
29 // Detector decoration
31
32 // SDO decorations
33 ATH_CHECK( m_sdo_words.initialize() );
34 ATH_CHECK( m_sdo_depositsBarcode.initialize() );
35 ATH_CHECK( m_sdo_depositsEnergy.initialize() );
36
37 // SiHit decorations
41 ATH_CHECK( m_sihit_pdgid_decor_key.initialize() );
42
46
50
51 ATH_CHECK( detStore()->retrieve(m_PixelHelper, "PixelID") );
52
53 return StatusCode::SUCCESS;
54 }
55
56
57 StatusCode PixelClusterSiHitDecoratorAlg::execute(const EventContext& ctx) const
58 {
59 ATH_MSG_DEBUG( "Executing " << name() << " ..." );
60
61 ATH_MSG_DEBUG( "Retrieving TrackMeasurementValidationContainer with key: " << m_inputMeasurementsKey.key() );
63 ATH_CHECK( measurementHandle.isValid() );
64 const xAOD::TrackMeasurementValidationContainer* measurements = measurementHandle.cptr();
65
66 ATH_MSG_DEBUG( "Retrieving InDetSimDataCollection with key: " << m_SDOcontainer_key.key() );
68 ATH_CHECK( sdoHandle.isValid() );
69 const InDetSimDataCollection* sdos = sdoHandle.cptr();
70
71 ATH_MSG_DEBUG("Retrieving SiHitCollection with key: " << m_siHitsKey.key());
73 ATH_CHECK(siHitsHandle.isValid());
74 const SiHitCollection* siHits = siHitsHandle.cptr();
75
77 ATH_CHECK(pixelDetEleHandle.isValid());
78 const InDetDD::SiDetectorElementCollection* pixElements = pixelDetEleHandle.cptr();
79
80 // Detector decorator
82 ATH_CHECK( decor_detectorElementID.isValid() );
83
84 // SDO decorators
88
89 // SiHit decorators
94
98
102
103 // organize the si hits in such a way we group them together by idhash
104 std::vector< std::vector< const SiHit* > > siHitsCollections(m_PixelHelper->wafer_hash_max());
105 for (const SiHit& siHit: *siHits) {
106 if (!siHit.isPixel()) {
107 ATH_MSG_ERROR("Si Hit in Pixel collection is not Pixel!!!");
108 return StatusCode::FAILURE;
109 }
110
111 Identifier wafer_id(m_PixelHelper->wafer_id(siHit.getBarrelEndcap(),
112 siHit.getLayerDisk(),
113 siHit.getPhiModule(),
114 siHit.getEtaModule()));
115 IdentifierHash wafer_hash(m_PixelHelper->wafer_hash(wafer_id));
116
117 if (wafer_hash >= m_PixelHelper->wafer_hash_max()) {
118 ATH_MSG_ERROR("There is a problem with Si Hit collection.");
119 ATH_MSG_ERROR("Wafer hash is too big");
120 return StatusCode::FAILURE;
121 }
122 siHitsCollections[wafer_hash].push_back(&siHit);
123 } // loop on si hits
124
126 pixelAccessor ( *measurements,
127 [&decor_detectorElementID] (const xAOD::TrackMeasurementValidation& cl) -> IdentifierHash { return decor_detectorElementID(cl); },
128 pixElements->size());
129
130 // run on id hashes
131 const auto& allIdHashes = pixelAccessor.allIdentifiers();
132 for (const auto& hashId : allIdHashes) {
133 const InDetDD::SiDetectorElement *element = pixElements->getDetectorElement(hashId);
134 if ( not element ) {
135 ATH_MSG_FATAL( "Invalid pixel detector element for hash " << hashId);
136 return StatusCode::FAILURE;
137 }
138
139 auto [startRange, stopRange] = pixelAccessor.rangesForIdentifierDirect(hashId).front();
140 const std::vector< const SiHit* >& siHitsWithCurrentHash = siHitsCollections.at(hashId);
141
142 for (auto itr = startRange; itr != stopRange; ++itr) {
143 const xAOD::TrackMeasurementValidation* measurement = *itr;
144
145 const std::vector< std::uint64_t > rdoIdentifierList = measurement->rdoIdentifierList();
146 // convert to RDOs
147 std::vector< Identifier > rdos( rdoIdentifierList.size() );
148 for (std::size_t i(0); i < rdoIdentifierList.size(); ++i) {
149 rdos[i].set_literal( rdoIdentifierList[i] );
150 }
151
152 auto [word, depositsUniqueID, depositsEnergy] = ActsTrk::detail::getSDOInformation(rdos, *sdos);
153 std::vector<SiHit> compatibleSiHits = findAllHitsCompatibleWithCluster(rdos, *element, siHitsWithCurrentHash, depositsUniqueID);
154
155 auto [energyDeposit, meanTime, uniqueID, pdgid,
156 startPosX, startPosY, startPosZ,
157 endPosX, endPosY, endPosZ] = ActsTrk::detail::getSiHitInformation(*element, compatibleSiHits);
158
159 // attach SDO decorations
160 decor_sdo_words(*measurement) = std::move(word);
161 decor_sdo_depositsBarcode(*measurement) = std::move(depositsUniqueID);
162 decor_sdo_depositsEnergy(*measurement) = std::move(depositsEnergy);
163
164 // attach SiHit decorations
165 decor_sihit_energyDeposit(*measurement) = std::move(energyDeposit);
166 decor_sihit_meanTime(*measurement) = std::move(meanTime);
167 decor_sihit_barcode(*measurement) = std::move(uniqueID);
168 decor_sihit_pdgid(*measurement) = std::move(pdgid);
169
170 decor_sihit_startPosX(*measurement) = std::move(startPosX);
171 decor_sihit_startPosY(*measurement) = std::move(startPosY);
172 decor_sihit_startPosZ(*measurement) = std::move(startPosZ);
173
174 decor_sihit_endPosX(*measurement) = std::move(endPosX);
175 decor_sihit_endPosY(*measurement) = std::move(endPosY);
176 decor_sihit_endPosZ(*measurement) = std::move(endPosZ);
177 } // loop on clusters
178 } // loop on hash ids
179
180 return StatusCode::SUCCESS;
181 }
182
183
184 std::vector<SiHit> PixelClusterSiHitDecoratorAlg::findAllHitsCompatibleWithCluster( const std::vector< Identifier >& rdos,
185 const InDetDD::SiDetectorElement& element,
186 const std::vector<const SiHit*>& sihits,
187 const std::vector< std::vector< int > >& sdoTracks) const
188 {
189 std::vector<SiHit> matchingHits {};
190 std::vector<const SiHit*> multiMatchingHits {};
191
192 for ( const SiHit* siHit : sihits) {
193 // Now we have all hits in the module that match lets check to see if they match the cluster
194 // Must be within +/- 1 hits of any hit in the cluster to be included
196 HepGeom::Point3D<double> averagePosition = 0.5 * (siHit->localStartPosition() + siHit->localEndPosition());
197 Amg::Vector2D pos = element.hitLocalToLocal( averagePosition.z(), averagePosition.y() );
198 InDetDD::SiCellId diode = element.cellIdOfPosition(pos);
199
200 for( const Identifier& hitIdentifier : rdos ) {
201 ATH_MSG_DEBUG("Truth Phi " << diode.phiIndex() << " Cluster Phi " << m_PixelHelper->phi_index( hitIdentifier ) );
202 ATH_MSG_DEBUG("Truth Eta " << diode.etaIndex() << " Cluster Eta " << m_PixelHelper->eta_index( hitIdentifier ) );
203 if( std::abs( static_cast<int>(diode.etaIndex()) - m_PixelHelper->eta_index( hitIdentifier ) ) <= 1 and
204 std::abs( static_cast<int>(diode.phiIndex()) - m_PixelHelper->phi_index( hitIdentifier ) ) <= 1 ) {
205 multiMatchingHits.push_back(siHit);
206 break;
207 }
208 } // list on rdos
209
210 } else { // not m_useSiHitsGeometryMatching
211 auto siHitUniqueID = HepMC::uniqueID(siHit->particleLink());
212 for ( const std::vector<int>& uniqueIDSDOColl : sdoTracks ) {
213 if (std::find(uniqueIDSDOColl.begin(), uniqueIDSDOColl.end(), siHitUniqueID) == uniqueIDSDOColl.end()) continue;
214 multiMatchingHits.push_back(siHit);
215 break;
216 }
217 }
218
219 } // loop on si hits
220
221 // Now we will now make 1 SiHit for each true particle if the SiHits "touch" other
222 std::vector<const SiHit* >::iterator siHitIter = multiMatchingHits.begin();
223 std::vector<const SiHit* >::iterator siHitIter2 = multiMatchingHits.begin();
224 for ( ; siHitIter != multiMatchingHits.end(); ++siHitIter) {
225 const SiHit* lowestXPos = *siHitIter;
226 const SiHit* highestXPos = *siHitIter;
227
228 // We will merge these hits
229 std::vector<const SiHit* > ajoiningHits;
230 ajoiningHits.push_back( *siHitIter );
231
232 siHitIter2 = siHitIter + 1;
233 while ( siHitIter2 != multiMatchingHits.end() ) {
234 // Need to come from the same truth particle
235 if ( not HepMC::is_same_particle((*siHitIter)->particleLink(),
236 (*siHitIter2)->particleLink()) ) {
237 ++siHitIter2;
238 continue;
239 }
240
241 // Check to see if the SiHits are compatible with each other.
242 if (std::abs((highestXPos->localEndPosition().x()-(*siHitIter2)->localStartPosition().x()))<0.00005 &&
243 std::abs((highestXPos->localEndPosition().y()-(*siHitIter2)->localStartPosition().y()))<0.00005 &&
244 std::abs((highestXPos->localEndPosition().z()-(*siHitIter2)->localStartPosition().z()))<0.00005 ) {
245 highestXPos = *siHitIter2;
246 ajoiningHits.push_back( *siHitIter2 );
247 // Dont use hit more than once
248 // @TODO could invalidate siHitIter
249 siHitIter2 = multiMatchingHits.erase( siHitIter2 );
250 } else if (std::abs((lowestXPos->localStartPosition().x()-(*siHitIter2)->localEndPosition().x()))<0.00005 &&
251 std::abs((lowestXPos->localStartPosition().y()-(*siHitIter2)->localEndPosition().y()))<0.00005 &&
252 std::abs((lowestXPos->localStartPosition().z()-(*siHitIter2)->localEndPosition().z()))<0.00005) {
253 lowestXPos = *siHitIter2;
254 ajoiningHits.push_back( *siHitIter2 );
255 // Dont use hit more than once
256 // @TODO could invalidate siHitIter
257 siHitIter2 = multiMatchingHits.erase( siHitIter2 );
258 } else {
259 ++siHitIter2;
260 }
261 } // while loop
262
263 if ( ajoiningHits.empty() ) {
264 ATH_MSG_WARNING("This should really never happen");
265 continue;
266 }else if ( ajoiningHits.size() == 1 ) {
267 // Copy Si Hit ready to return
268 matchingHits.push_back( *ajoiningHits[0] );
269 continue;
270 } else {
271 // Build new SiHit and merge information together.
272 ATH_MSG_DEBUG("Merging " << ajoiningHits.size() << " SiHits together." );
273
274 float energyDep {0.f};
275 float time {0.f};
276 for( const auto& siHit : ajoiningHits ){
277 energyDep += siHit->energyLoss();
278 time += siHit->meanTime();
279 }
280 time /= ajoiningHits.size();
281
282 matchingHits.emplace_back(lowestXPos->localStartPosition(),
283 highestXPos->localEndPosition(),
284 energyDep,
285 time,
286 (*siHitIter)->particleLink(),
287 0, // 0 for pixel 1 for strip
288 (*siHitIter)->getBarrelEndcap(),
289 (*siHitIter)->getLayerDisk(),
290 (*siHitIter)->getEtaModule(),
291 (*siHitIter)->getPhiModule(),
292 (*siHitIter)->getSide() );
293
294 ATH_MSG_DEBUG("Finished Merging " << ajoiningHits.size() << " SiHits together." );
295 }
296 } // loop on multi matching hits
297
298 return matchingHits;
299 }
300
301
302}
303
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
AtlasHitsVector< SiHit > SiHitCollection
Handle class for reading a decoration on an object.
Handle class for adding a decoration to an object.
SG::WriteDecorHandleKey< xAOD::TrackMeasurementValidationContainer > m_sihit_meanTime_decor_key
SG::WriteDecorHandleKey< xAOD::TrackMeasurementValidationContainer > m_sihit_barcode_decor_key
SG::WriteDecorHandleKey< xAOD::TrackMeasurementValidationContainer > m_sihit_startPosY_decor_key
SG::WriteDecorHandleKey< xAOD::TrackMeasurementValidationContainer > m_sihit_endPosY_decor_key
SG::WriteDecorHandleKey< xAOD::TrackMeasurementValidationContainer > m_sihit_startPosZ_decor_key
SG::WriteDecorHandleKey< xAOD::TrackMeasurementValidationContainer > m_sihit_energyDeposit_decor_key
SG::WriteDecorHandleKey< xAOD::TrackMeasurementValidationContainer > m_sdo_depositsEnergy
SG::ReadHandleKey< SiHitCollection > m_siHitsKey
SG::WriteDecorHandleKey< xAOD::TrackMeasurementValidationContainer > m_sihit_pdgid_decor_key
SG::WriteDecorHandleKey< xAOD::TrackMeasurementValidationContainer > m_sihit_endPosX_decor_key
SG::ReadHandleKey< InDetSimDataCollection > m_SDOcontainer_key
SG::ReadDecorHandleKey< xAOD::TrackMeasurementValidationContainer > m_measurement_detectorElementID
PixelClusterSiHitDecoratorAlg(const std::string &name, ISvcLocator *pSvcLocator)
std::vector< SiHit > findAllHitsCompatibleWithCluster(const std::vector< Identifier > &rdos, const InDetDD::SiDetectorElement &element, const std::vector< const SiHit * > &sihits, const std::vector< std::vector< int > > &sdoTracks) const
SG::WriteDecorHandleKey< xAOD::TrackMeasurementValidationContainer > m_sihit_endPosZ_decor_key
SG::WriteDecorHandleKey< xAOD::TrackMeasurementValidationContainer > m_sdo_words
SG::ReadCondHandleKey< InDetDD::SiDetectorElementCollection > m_pixelDetEleCollKey
SG::ReadHandleKey< xAOD::TrackMeasurementValidationContainer > m_inputMeasurementsKey
SG::WriteDecorHandleKey< xAOD::TrackMeasurementValidationContainer > m_sihit_startPosX_decor_key
virtual StatusCode execute(const EventContext &ctx) const override
SG::WriteDecorHandleKey< xAOD::TrackMeasurementValidationContainer > m_sdo_depositsBarcode
const ServiceHandle< StoreGateSvc > & detStore() const
An algorithm that can be simultaneously executed in multiple threads.
Class implementing how to access a container.
const boost::container::small_vector< Range, inline_size > rangesForIdentifierDirect(const identifier_t &identifier) const
Function to return the list of ranges corresponding to a given identifier.
std::vector< identifier_t > allIdentifiers() const
Function to return all available identifier (i.e. keys in the map)
size_type size() const noexcept
Returns the number of elements in the collection.
This is a "hash" representation of an Identifier.
Identifier for the strip or pixel cell.
Definition SiCellId.h:29
int phiIndex() const
Get phi index. Equivalent to strip().
Definition SiCellId.h:122
int etaIndex() const
Get eta index.
Definition SiCellId.h:114
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.
SiCellId cellIdOfPosition(const Amg::Vector2D &localPos) const
As in previous method but returns SiCellId.
Amg::Vector2D hitLocalToLocal(double xEta, double xPhi) const
Simulation/Hit local frame to reconstruction local frame.
const_pointer_type cptr()
Handle class for reading a decoration on an object.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
const_pointer_type cptr()
Dereference the pointer.
Handle class for adding a decoration to an object.
Definition SiHit.h:19
HepGeom::Point3D< double > localStartPosition() const
Definition SiHit.cxx:146
HepGeom::Point3D< double > localEndPosition() const
Definition SiHit.cxx:153
const std::vector< uint64_t > & rdoIdentifierList() const
Returns the list of RDO identifiers.
std::tuple< std::vector< float >, std::vector< float >, std::vector< int >, std::vector< int >, std::vector< float >, std::vector< float >, std::vector< float >, std::vector< float >, std::vector< float >, std::vector< float > > getSiHitInformation(const InDetDD::SiDetectorElement &element, const std::vector< SiHit > &matchingHits)
std::tuple< std::vector< int >, std::vector< std::vector< int > >, std::vector< std::vector< float > > > getSDOInformation(const std::vector< Identifier > &rdoList, const InDetSimDataCollection &sdoCollection)
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
Eigen::Matrix< double, 2, 1 > Vector2D
int uniqueID(const T &p)
bool is_same_particle(const T1 &p1, const T2 &p2)
Method to establish if two particles in the GenEvent actually represent the same particle.
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
TrackMeasurementValidation_v1 TrackMeasurementValidation
Reference the current persistent version:
TrackMeasurementValidationContainer_v1 TrackMeasurementValidationContainer
Definition of the current "TrackMeasurementValidation container version".