ATLAS Offline Software
Loading...
Searching...
No Matches
StripClusterSiHitDecoratorAlg.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_stripDetEleCollKey.initialize() );
27 ATH_CHECK( m_siHitsKey.initialize() );
28
29 // Detector decorator
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_StripHelper, "SCT_ID") );
52
53 return StatusCode::SUCCESS;
54 }
55
56 StatusCode StripClusterSiHitDecoratorAlg::execute(const EventContext& ctx) const
57 {
58 ATH_MSG_DEBUG( "Executing " << name() << " ..." );
59
60 ATH_MSG_DEBUG( "Retrieving TrackMeasurementValidationContainer with key: " << m_inputMeasurementsKey.key() );
62 ATH_CHECK( measurementHandle.isValid() );
63 const xAOD::TrackMeasurementValidationContainer* measurements = measurementHandle.cptr();
64
65 ATH_MSG_DEBUG( "Retrieving InDetSimDataCollection with key: " << m_SDOcontainer_key.key() );
67 ATH_CHECK( sdoHandle.isValid() );
68 const InDetSimDataCollection* sdos = sdoHandle.cptr();
69
70 ATH_MSG_DEBUG("Retrieving SiHitCollection with key: " << m_siHitsKey.key());
72 ATH_CHECK(siHitsHandle.isValid());
73 const SiHitCollection* siHits = siHitsHandle.cptr();
74
76 ATH_CHECK(stripDetEleHandle.isValid());
77 const InDetDD::SiDetectorElementCollection* stripElements = stripDetEleHandle.cptr();
78
79 // Detector decorator
81 ATH_CHECK( decor_detectorElementID.isValid() );
82
83 // SDO decorators
87
88 // SiHit decorators
93
97
101
102 // organize the si hits in such a way we group them together by idhash
103 std::vector< std::vector< const SiHit* > > siHitsCollections(m_StripHelper->wafer_hash_max());
104 for (const SiHit& siHit: *siHits) {
105 if ( not siHit.isSCT() ) {
106 ATH_MSG_ERROR("Si Hit in Strip collection is not Strip!!!");
107 return StatusCode::FAILURE;
108 }
109
110 Identifier wafer_id(m_StripHelper->wafer_id(siHit.getBarrelEndcap(),
111 siHit.getLayerDisk(),
112 siHit.getPhiModule(),
113 siHit.getEtaModule(),
114 siHit.getSide()));
115 IdentifierHash wafer_hash(m_StripHelper->wafer_hash(wafer_id));
116
117 if (wafer_hash >= m_StripHelper->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
125
127 stripAccessor ( *measurements,
128 [&decor_detectorElementID] (const xAOD::TrackMeasurementValidation& cl) -> IdentifierHash { return decor_detectorElementID(cl); },
129 stripElements->size());
130
131 // run on id hashes
132 const auto& allIdHashes = stripAccessor.allIdentifiers();
133 for (const auto& hashId : allIdHashes) {
134 const InDetDD::SiDetectorElement *element = stripElements->getDetectorElement(hashId);
135 if ( not element ) {
136 ATH_MSG_FATAL( "Invalid strip detector element for hash " << hashId);
137 return StatusCode::FAILURE;
138 }
139
140 auto [startRange, stopRange] = stripAccessor.rangesForIdentifierDirect(hashId).front();
141 const std::vector< const SiHit* >& siHitsWithCurrentHash = siHitsCollections.at(hashId);
142
143 for (auto itr = startRange; itr != stopRange; ++itr) {
144 const xAOD::TrackMeasurementValidation* measurement = *itr;
145
146 const std::vector< std::uint64_t > rdoIdentifierList = measurement->rdoIdentifierList();
147 // convert to RDOs
148 std::vector< Identifier > rdos( rdoIdentifierList.size() );
149 for (std::size_t i(0); i < rdoIdentifierList.size(); ++i) {
150 rdos[i].set_literal( rdoIdentifierList[i] );
151 }
152
153 auto [word, depositsUniqueID, depositsEnergy] = ActsTrk::detail::getSDOInformation(rdos, *sdos);
154 std::vector<SiHit> compatibleSiHits = findAllHitsCompatibleWithCluster(rdos, *element, siHitsWithCurrentHash);
155
156 auto [energyDeposit, meanTime, uniqueID, pdgid,
157 startPosX, startPosY, startPosZ,
158 endPosX, endPosY, endPosZ] = ActsTrk::detail::getSiHitInformation(*element, compatibleSiHits);
159
160 // attach SDO decorations
161 decor_sdo_words(*measurement) = std::move(word);
162 decor_sdo_depositsBarcode(*measurement) = std::move(depositsUniqueID);
163 decor_sdo_depositsEnergy(*measurement) = std::move(depositsEnergy);
164
165 // attach SiHit decorations
166 decor_sihit_energyDeposit(*measurement) = std::move(energyDeposit);
167 decor_sihit_meanTime(*measurement) = std::move(meanTime);
168 decor_sihit_barcode(*measurement) = std::move(uniqueID);
169 decor_sihit_pdgid(*measurement) = std::move(pdgid);
170
171 decor_sihit_startPosX(*measurement) = std::move(startPosX);
172 decor_sihit_startPosY(*measurement) = std::move(startPosY);
173 decor_sihit_startPosZ(*measurement) = std::move(startPosZ);
174
175 decor_sihit_endPosX(*measurement) = std::move(endPosX);
176 decor_sihit_endPosY(*measurement) = std::move(endPosY);
177 decor_sihit_endPosZ(*measurement) = std::move(endPosZ);
178 } // loop on clusters
179 } // loop on hash ids
180
181 return StatusCode::SUCCESS;
182 }
183
184
185 std::vector<SiHit> StripClusterSiHitDecoratorAlg::findAllHitsCompatibleWithCluster( const std::vector< Identifier >& rdos,
186 const InDetDD::SiDetectorElement& element,
187 const std::vector<const SiHit*>& siHits) 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
195 HepGeom::Point3D<double> averagePosition = 0.5 * (siHit->localStartPosition() + siHit->localEndPosition());
196 Amg::Vector2D pos = element.hitLocalToLocal(averagePosition.z(), averagePosition.y());
197 InDetDD::SiCellId diode = element.cellIdOfPosition(pos);
198
199 for (const auto& hitIdentifier: rdos) {
200 ATH_MSG_DEBUG("Truth Strip " << diode.phiIndex() << " Cluster Strip " << m_StripHelper->strip(hitIdentifier));
201
202 if (std::abs( static_cast<int>(diode.phiIndex()) - m_StripHelper->strip(hitIdentifier) ) <= 1) {
203 multiMatchingHits.push_back(siHit);
204 break;
205 }
206 }
207 } // loop on si hits
208
209 // Now we will now make 1 SiHit for each true particle if the SiHits "touch" other
210 std::vector<const SiHit* >::iterator siHitIter = multiMatchingHits.begin();
211 std::vector<const SiHit* >::iterator siHitIter2 = multiMatchingHits.begin();
212 for ( ; siHitIter != multiMatchingHits.end(); ++siHitIter) {
213 const SiHit* lowestXPos = *siHitIter;
214 const SiHit* highestXPos = *siHitIter;
215
216 // We will merge these hits
217 std::vector<const SiHit* > ajoiningHits;
218 ajoiningHits.push_back( *siHitIter );
219
220 siHitIter2 = siHitIter + 1;
221 while ( siHitIter2 != multiMatchingHits.end() ) {
222 // Need to come from the same truth particle
223 if ( not HepMC::is_same_particle((*siHitIter)->particleLink(),
224 (*siHitIter2)->particleLink()) ) {
225 ++siHitIter2;
226 continue;
227 }
228
229 // Check to see if the SiHits are compatible with each other.
230 if (std::abs((highestXPos->localEndPosition().x()-(*siHitIter2)->localStartPosition().x()))<0.00005 &&
231 std::abs((highestXPos->localEndPosition().y()-(*siHitIter2)->localStartPosition().y()))<0.00005 &&
232 std::abs((highestXPos->localEndPosition().z()-(*siHitIter2)->localStartPosition().z()))<0.00005 ) {
233 highestXPos = *siHitIter2;
234 ajoiningHits.push_back( *siHitIter2 );
235 // Dont use hit more than once
236 // @TODO could invalidate siHitIter
237 siHitIter2 = multiMatchingHits.erase( siHitIter2 );
238 } else if (std::abs((lowestXPos->localStartPosition().x()-(*siHitIter2)->localEndPosition().x()))<0.00005 &&
239 std::abs((lowestXPos->localStartPosition().y()-(*siHitIter2)->localEndPosition().y()))<0.00005 &&
240 std::abs((lowestXPos->localStartPosition().z()-(*siHitIter2)->localEndPosition().z()))<0.00005) {
241 lowestXPos = *siHitIter2;
242 ajoiningHits.push_back( *siHitIter2 );
243 // Dont use hit more than once
244 // @TODO could invalidate siHitIter
245 siHitIter2 = multiMatchingHits.erase( siHitIter2 );
246 } else {
247 ++siHitIter2;
248 }
249 } // while loop
250
251 if ( ajoiningHits.empty() ) {
252 ATH_MSG_WARNING("This should really never happen");
253 continue;
254 } else if ( ajoiningHits.size() == 1 ) {
255 // Copy Si Hit ready to return
256 matchingHits.push_back( *ajoiningHits[0] );
257 continue;
258 } else {
259 // Build new SiHit and merge information together.
260 ATH_MSG_DEBUG("Merging " << ajoiningHits.size() << " SiHits together." );
261
262 float energyDep {0.f};
263 float time {0.f};
264 for( const auto& siHit : ajoiningHits ){
265 energyDep += siHit->energyLoss();
266 time += siHit->meanTime();
267 }
268 time /= ajoiningHits.size();
269
270 matchingHits.emplace_back(lowestXPos->localStartPosition(),
271 highestXPos->localEndPosition(),
272 energyDep,
273 time,
274 (*siHitIter)->particleLink(),
275 1, // 0 for pixel 1 for strip
276 (*siHitIter)->getBarrelEndcap(),
277 (*siHitIter)->getLayerDisk(),
278 (*siHitIter)->getEtaModule(),
279 (*siHitIter)->getPhiModule(),
280 (*siHitIter)->getSide() );
281
282 ATH_MSG_DEBUG("Finished Merging " << ajoiningHits.size() << " SiHits together." );
283 }
284 } // loop on multi matching hits
285
286 return matchingHits;
287 }
288
289
290}
291
#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_startPosY_decor_key
SG::WriteDecorHandleKey< xAOD::TrackMeasurementValidationContainer > m_sihit_pdgid_decor_key
std::vector< SiHit > findAllHitsCompatibleWithCluster(const std::vector< Identifier > &rdos, const InDetDD::SiDetectorElement &element, const std::vector< const SiHit * > &sihits) const
StripClusterSiHitDecoratorAlg(const std::string &name, ISvcLocator *pSvcLocator)
SG::WriteDecorHandleKey< xAOD::TrackMeasurementValidationContainer > m_sihit_endPosX_decor_key
SG::WriteDecorHandleKey< xAOD::TrackMeasurementValidationContainer > m_sihit_meanTime_decor_key
SG::WriteDecorHandleKey< xAOD::TrackMeasurementValidationContainer > m_sdo_depositsEnergy
SG::WriteDecorHandleKey< xAOD::TrackMeasurementValidationContainer > m_sdo_depositsBarcode
SG::WriteDecorHandleKey< xAOD::TrackMeasurementValidationContainer > m_sihit_endPosY_decor_key
SG::WriteDecorHandleKey< xAOD::TrackMeasurementValidationContainer > m_sihit_startPosX_decor_key
SG::ReadHandleKey< SiHitCollection > m_siHitsKey
SG::ReadDecorHandleKey< xAOD::TrackMeasurementValidationContainer > m_measurement_detectorElementID
SG::WriteDecorHandleKey< xAOD::TrackMeasurementValidationContainer > m_sihit_energyDeposit_decor_key
SG::WriteDecorHandleKey< xAOD::TrackMeasurementValidationContainer > m_sdo_words
virtual StatusCode execute(const EventContext &ctx) const override
SG::WriteDecorHandleKey< xAOD::TrackMeasurementValidationContainer > m_sihit_startPosZ_decor_key
SG::WriteDecorHandleKey< xAOD::TrackMeasurementValidationContainer > m_sihit_endPosZ_decor_key
SG::ReadHandleKey< xAOD::TrackMeasurementValidationContainer > m_inputMeasurementsKey
SG::ReadHandleKey< InDetSimDataCollection > m_SDOcontainer_key
SG::WriteDecorHandleKey< xAOD::TrackMeasurementValidationContainer > m_sihit_barcode_decor_key
SG::ReadCondHandleKey< InDetDD::SiDetectorElementCollection > m_stripDetEleCollKey
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
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
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".