ATLAS Offline Software
Loading...
Searching...
No Matches
PixelPrepDataToxAOD.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// PixelPrepDataToxAOD.cxx
7// Implementation file for class PixelPrepDataToxAOD
9
10#include "PixelPrepDataToxAOD.h"
11
13
17
18#include "Identifier/Identifier.h"
21#include "PixelConditionsData/ChargeCalibParameters.h" //for LegacyFitParameters
22
23
28#include "InDetSimEvent/SiHit.h"
31
32#include "CLHEP/Geometry/Point3D.h"
33
34#include <numbers>
35#include <map>
36
37#define AUXDATA(OBJ, TYP, NAME) \
38 static const SG::AuxElement::Accessor<TYP> acc_##NAME (#NAME); acc_##NAME(*(OBJ))
39
40namespace {
41 unsigned int makeKey(short phi, char eta, char layer) {
42 return phi | (eta << 16) | (layer << 24);
43 }
44 using std::numbers::pi;
45}
46
47
49//
50// Initialize method:
51//
54{
55 ATH_CHECK( detStore()->retrieve(m_PixelHelper, "PixelID") );
56
57 //make sure we don't write what we don't have
58 if (not m_useTruthInfo) {
59 m_writeSDOs = false;
60 m_writeSiHits = false;
61 }
62
63 ATH_CHECK(m_pixelReadout.retrieve());
65
66 ATH_CHECK(m_condDCSStateKey.initialize());
67 ATH_CHECK(m_condDCSStatusKey.initialize());
68 ATH_CHECK(m_readKeyTemp.initialize());
69 ATH_CHECK(m_readKeyHV.initialize());
70
72 DisableTool{!(m_writeRDOinformation || m_writeModuleStatus)} ));
73
74 ATH_CHECK(m_lorentzAngleTool.retrieve());
75
82
83 ATH_CHECK(m_write_xaod_key.initialize());
84 ATH_CHECK(m_write_offsets.initialize());
85
87
88 return StatusCode::SUCCESS;
89}
90
92//
93// Execute method:
94//
96StatusCode PixelPrepDataToxAOD::execute(const EventContext& ctx)
97{
98 //Mandatory. Require if the algorithm is scheduled.
100
101 if ( !PixelClusterContainer.isValid() )
102 {
103 ATH_MSG_ERROR("Failed to retrieve PixelClusterContainer with key" << PixelClusterContainer.key() );
104 return StatusCode::FAILURE;
105 }
106
107 const PRD_MultiTruthCollection* prdmtColl(nullptr);
108 const xAODTruthParticleLinkVector *truth_particle_links{nullptr};
109 if (m_useTruthInfo) {
111 if (prdmtCollHandle.isValid()) {
112 prdmtColl = &*prdmtCollHandle;
113 }
114 if (!m_truthParticleLinks.empty()) {
116 if (truthParticleLinksHandle.isValid()) {
117 truth_particle_links = truthParticleLinksHandle.cptr();
118 }
119 }
120 }
121
122 const InDetSimDataCollection* sdoCollection(nullptr);
123 if (m_writeSDOs) {
125 if (sdoCollectionHandle.isValid()) {
126 sdoCollection = &*sdoCollectionHandle;
127 } else if (m_firstEventWarnings) {
128 ATH_MSG_WARNING("SDO information requested, but SDO collection not available!");
129 }
130 }
131
133 bool foundSplitProbContainer = false;
134 if (!m_clusterSplitProbContainer.key().empty()) {
136 if (!splitProbContainer.isValid()) {
137 ATH_MSG_FATAL("Failed to get cluster splitting probability container " << m_clusterSplitProbContainer);
138 }
139 foundSplitProbContainer = true;
140 }
141
142 std::vector<std::vector<const SiHit*>> siHits(m_PixelHelper->wafer_hash_max());
143 if (m_need_sihits) {
144 SG::ReadHandle<SiHitCollection> siHitCollectionHandle(m_sihitContainer_key, ctx);
145 if (siHitCollectionHandle.isValid()) {
146 for (const SiHit& siHit: *siHitCollectionHandle) {
147 // Check if it is a Pixel hit
148 if (!siHit.isPixel()) continue;
149
150 Identifier wafer_id(m_PixelHelper->wafer_id(siHit.getBarrelEndcap(),
151 siHit.getLayerDisk(),
152 siHit.getPhiModule(),
153 siHit.getEtaModule()));
154 IdentifierHash wafer_hash(m_PixelHelper->wafer_hash(wafer_id));
155 if (wafer_hash>=m_PixelHelper->wafer_hash_max()) continue;
156 siHits[wafer_hash].push_back(&siHit);
157 }
158 } else if (m_firstEventWarnings) {
159 ATH_MSG_WARNING("SiHit information requested, but SiHit collection not available!");
160 }
161 }
162
163 const PixelChargeCalibCondData *calibData=nullptr;
166 if (!calibData_handle.isValid()) {
167 ATH_MSG_FATAL("Failed to get PixelChargeCalibCondData with key " << m_chargeDataKey);
168 }
169 calibData=calibData_handle.cptr();
170 }
171
172 // Create the xAOD container and its auxiliary store:
174 ATH_CHECK(xaod.record(std::make_unique<xAOD::TrackMeasurementValidationContainer>(),
175 std::make_unique<xAOD::TrackMeasurementValidationAuxContainer>()));
176
178 ATH_CHECK(offsets.record(std::make_unique<std::vector<unsigned int>>(m_PixelHelper->wafer_hash_max(), 0)));
179
180 unsigned int have_truth_link=0u;
181 unsigned int missing_truth_particle=0u;
182 unsigned int missing_parent_particle=0u;
183 // Loop over the container
184 unsigned int counter(0);
185
189
190 std::unordered_map< unsigned int , std::vector<unsigned int> > cluster_map;
191 for( const auto clusterCollection : * PixelClusterContainer ){
192
193 //Fill Offset container
194 (*offsets)[clusterCollection->identifyHash()] = counter;
195
196 // skip empty collections
197 if( clusterCollection->empty() ) continue;
198
199 // loop over collection and convert to xAOD
200 for( const InDet::PixelCluster* prd : *clusterCollection ){
201 ++counter;
202
203 Identifier clusterId = prd->identify();
204 if ( !clusterId.is_valid() ) {
205 ATH_MSG_WARNING("Pixel cluster identifier is not valid");
206 }
207
208 // create and add xAOD object
210 unsigned int cluster_idx = xaod->size();
211 xaod->push_back(xprd);
212
213 //Set Identifier
214 xprd->setIdentifier( clusterId.get_compact() );
215
216 //Set Global Position
217 Amg::Vector3D gpos = prd->globalPosition();
218 xprd->setGlobalPosition(gpos.x(),gpos.y(),gpos.z());
219
220 //Set Local Position
221 const Amg::Vector2D& locpos = prd->localPosition();
222
223 // Set local error matrix
224 xprd->setLocalPosition( locpos.x(), locpos.y() );
225
226 const Amg::MatrixX& localCov = prd->localCovariance();
227 if(localCov.size() == 1){
228 xprd->setLocalPositionError( localCov(0,0), 0., 0. );
229 } else if(localCov.size() == 4){
230 xprd->setLocalPositionError( localCov(0,0), localCov(1,1), localCov(0,1) );
231 } else {
232 xprd->setLocalPositionError(0.,0.,0.);
233 }
234
235 // Set vector of hit identifiers
236 std::vector< uint64_t > rdoIdentifierList;
237 rdoIdentifierList.reserve(prd->rdoList().size());
238 int rowmin=9999; int rowmax=-9999;
239 int colmin=9999; int colmax=-9999;
240 for( const auto &hitIdentifier : prd->rdoList() ){
241 rdoIdentifierList.push_back( hitIdentifier.get_compact() );
242 //May want to addinformation about the individual hits here
243 int row = m_PixelHelper->phi_index(hitIdentifier);
244 int col = m_PixelHelper->eta_index(hitIdentifier);
245 if(rowmin > row) rowmin = row;
246 if(rowmax < row) rowmax = row;
247 if(colmin > col) colmin = col;
248 if(colmax < col) colmax = col;
249 }
250 xprd->setRdoIdentifierList(rdoIdentifierList);
251
252 //Add pixel cluster properties
253 AUXDATA(xprd,int,bec) = m_PixelHelper->barrel_ec(clusterId) ;
254 char the_layer = m_PixelHelper->layer_disk(clusterId) ;
255 char the_eta = m_PixelHelper->eta_module(clusterId) ;
256 short the_phi = m_PixelHelper->phi_module(clusterId) ;
257 AUXDATA(xprd,int,layer) = the_layer ;
258 AUXDATA(xprd,int,phi_module) = the_phi ;
259 AUXDATA(xprd,int,eta_module) = the_eta ;
260 AUXDATA(xprd,int,eta_pixel_index) = m_PixelHelper->eta_index(clusterId);
261 AUXDATA(xprd,int,phi_pixel_index) = m_PixelHelper->phi_index(clusterId);
262
263 // only consumed by the SiHit module-overlap pass below
264 if (m_writeSiHits) {
265 cluster_map[ makeKey(the_phi, the_eta, the_layer)].push_back(cluster_idx);
266 }
267
268 const InDet::SiWidth cw = prd->width();
269 AUXDATA(xprd,int,sizePhi) = (int)cw.colRow()[0];
270 AUXDATA(xprd,int,sizeZ) = (int)cw.colRow()[1];
271 AUXDATA(xprd,int,nRDO) = (int)prd->rdoList().size();
272
273 AUXDATA(xprd,float,charge) = prd->totalCharge();
274 AUXDATA(xprd,int,ToT) = prd->totalToT();
275 AUXDATA(xprd,int,LVL1A) = prd->LVL1A();
276
277 AUXDATA(xprd,char,isFake) = (char)prd->isFake();
278 AUXDATA(xprd,char,gangedPixel) = (char)prd->gangedPixel();
280 splitProb = foundSplitProbContainer ? splitProbContainer->splitProbability(prd) : Trk::ClusterSplitProbabilityContainer::getNoSplitProbability();
281 AUXDATA(xprd,char,isSplit) = static_cast<char>(splitProb.isSplit());
282 AUXDATA(xprd,float,splitProbability1) = splitProb.splitProbability1();
283 AUXDATA(xprd,float,splitProbability2) = splitProb.splitProbability2();
284
285 // Need to add something to Add the NN splitting information
286 if(m_writeNNinformation) addNNInformation( xprd, prd, 7, 7);
287
288 // module status flags, also wanted without the RDO information
290 IdentifierHash moduleHash = clusterCollection->identifyHash();
291 AUXDATA(xprd,int,hasBSError) = (int)m_pixelSummary->hasBSError(moduleHash, ctx);
292 AUXDATA(xprd,int,DCSState) = dcsState->getModuleStatus(moduleHash);
293 }
294
295 // Add information for each contributing hit
297 IdentifierHash moduleHash = clusterCollection->identifyHash();
298
299 float deplVoltage = 0.0;
300 AUXDATA(xprd,float,BiasVoltage) = dcsHV->getBiasVoltage(moduleHash);
301 AUXDATA(xprd,float,Temperature) = dcsTemp->getTemperature(moduleHash);
302 AUXDATA(xprd,float,DepletionVoltage) = deplVoltage;
303
304 AUXDATA(xprd,float,LorentzShift) = (float)m_lorentzAngleTool->getLorentzShift(moduleHash,ctx);
305
306 assert (calibData);
307 addRdoInformation(xprd, prd, calibData);
308 }
309
310
311 // Add the Detector element ID -- not sure if needed as we have the informations above
312 const InDetDD::SiDetectorElement* de = prd->detectorElement();
313 uint64_t detElementId(0);
314 if(de){
315 Identifier detId = de->identify();
316 if ( detId.is_valid() ) {
317 detElementId = detId.get_compact();
318 }
319 }
320 AUXDATA(xprd,uint64_t,detectorElementID) = detElementId;
321
323 AUXDATA(xprd,int,waferID) = m_PixelHelper->wafer_hash(de->identify());
324
325 const InDetDD::PixelModuleDesign* design = static_cast<const InDetDD::PixelModuleDesign*>(&de->design());
326 InDetDD::SiLocalPosition pos1 = design->positionFromColumnRow(colmin,rowmin);
327 InDetDD::SiLocalPosition pos2 = design->positionFromColumnRow(colmax,rowmin);
328 InDetDD::SiLocalPosition pos3 = design->positionFromColumnRow(colmin,rowmax);
329 InDetDD::SiLocalPosition pos4 = design->positionFromColumnRow(colmax,rowmax);
330 InDetDD::SiLocalPosition centroid = 0.25*(pos1+pos2+pos3+pos4);
331
332 AUXDATA(xprd,float,centroid_xphi) = centroid.xPhi();
333 AUXDATA(xprd,float,centroid_xeta) = centroid.xEta();
334
335 AUXDATA(xprd,float,omegax) = prd->omegax();
336 AUXDATA(xprd,float,omegay) = prd->omegay();
337 }
338
339 // Use the MultiTruth Collection to get a list of all true particle contributing to the cluster
340 if (prdmtColl) {
341 auto range{prdmtColl->equal_range(clusterId)};
342 if (truth_particle_links) {
343 std::vector<unsigned int> tp_indices;
344 for (auto i{range.first}; i!=range.second; ++i) {
345 ElementLink<xAOD::TruthParticleContainer> a_truth_particle_link = truth_particle_links->find(i->second);
346 if (a_truth_particle_link) {
347 const xAOD::TruthParticle *truth_particle = *a_truth_particle_link;
348 if (truth_particle) {
349 ++have_truth_link;
350 tp_indices.push_back(static_cast<int>(truth_particle->index()));
351 }
352 else {
353 ++missing_parent_particle;
354 }
355 }
356 else {
357 tp_indices.push_back(std::numeric_limits<unsigned int>::max());
358 ++missing_truth_particle;
359 }
360 }
361 // @TODO provide possibility to move tp_indices to its final destination
362 AUXDATA(xprd,std::vector<unsigned int>, truth_index) = std::move(tp_indices);
363 }
364 std::vector<int> uniqueIDs;
365 for (auto i = range.first; i != range.second; ++i) {
366 uniqueIDs.push_back( HepMC::uniqueID(i->second) );
367 }
368 AUXDATA(xprd,std::vector<int>, truth_barcode) = std::move(uniqueIDs); // TODO rename variable to be consistent?
369 }
370
371 std::vector< std::vector< int > > sdo_tracks;
372 // Use the SDO Collection to get a list of all true particle contributing to the cluster per readout element
373 // Also get the energy deposited by each true particle per readout element
374 if (sdoCollection) {
375 sdo_tracks = addSDOInformation(xprd, prd, *sdoCollection);
376 }
377
378 // Now Get the most detailed truth from the SiHits
379 // Note that this could get really slow if there are a lot of hits and clusters
380 if (m_need_sihits) {
381 const std::vector<SiHit> matched_hits = findAllHitsCompatibleWithCluster(prd, &siHits[prd->detectorElement()->identifyHash()], sdo_tracks);
382 if (m_writeSiHits) {
383 addSiHitInformation(xprd, prd, matched_hits);
384 }
385
387 addNNTruthInfo(xprd, prd, matched_hits);
388 }
389 }
390 }
391 }
392
393 for ( auto clusItr = xaod->begin(); clusItr != xaod->end(); ++clusItr ) {
394 AUXDATA(*clusItr,char,broken) = false;
395 }
396 m_haveTruthLink += have_truth_link;
397 m_missingTruthParticle += missing_truth_particle;
398 m_missingParentParticle += missing_parent_particle;
399
400 // Flag clusters that share a SiHit with another cluster on the same module.
401 // Needs sihit_barcode, so it only means anything with the SiHit truth on.
402 if (m_writeSiHits) {
403 static const SG::AuxElement::Accessor<int> acc_layer ("layer");
404 static const SG::AuxElement::Accessor<int> acc_phi_module ("phi_module");
405 static const SG::AuxElement::Accessor<int> acc_eta_module ("eta_module");
406 static const SG::AuxElement::Accessor<std::vector<int> > acc_sihit_barcode ("sihit_barcode"); // TODO rename variable to be consistent?
407 for ( auto clusItr = xaod->begin(); clusItr != xaod->end(); ++clusItr)
408 {
409 auto pixelCluster = *clusItr;
410 int layer = acc_layer(*pixelCluster);
411 std::vector<int> uniqueIDs = acc_sihit_barcode(*pixelCluster); // TODO rename variable to be consistent?
412
413 const std::vector< unsigned int> &cluster_idx_list = cluster_map.at( makeKey(acc_phi_module(*pixelCluster), acc_eta_module(*pixelCluster), acc_layer(*pixelCluster) ));
414 for (unsigned int cluster_idx : cluster_idx_list) {
415 auto pixelCluster2 = xaod->at(cluster_idx);
416 if ( acc_layer(*pixelCluster2) != layer )
417 continue;
418 if ( acc_eta_module(*pixelCluster) != acc_eta_module(*pixelCluster2) )
419 continue;
420 if ( acc_phi_module(*pixelCluster) != acc_phi_module(*pixelCluster2) )
421 continue;
422
423 std::vector<int> uniqueIDs2 = acc_sihit_barcode(*pixelCluster2); // TODO rename variable to be consistent?
424
425 for ( auto uid : uniqueIDs ) {
426 if (std::find(uniqueIDs2.begin(), uniqueIDs2.end(), uid ) == uniqueIDs2.end()) continue;
427 static const SG::AuxElement::Accessor<char> acc_broken ("broken");
428 acc_broken(*pixelCluster) = true;
429 acc_broken(*pixelCluster2) = true;
430 break;
431 }
432 }
433 }
434 }
435
436 ATH_MSG_DEBUG( " recorded PixelPrepData objects: size " << xaod->size() );
437
438 m_firstEventWarnings = false;
439
440 return StatusCode::SUCCESS;
441}
442
443
445 const InDet::PixelCluster* prd,
446 const InDetSimDataCollection& sdoCollection ) const
447{
448 std::vector<int> sdo_word;
449 std::vector< std::vector< int > > sdo_depositsUniqueID;
450 std::vector< std::vector< float > > sdo_depositsEnergy;
451 // find hit
452 for( const auto &hitIdentifier : prd->rdoList() ){
453 auto pos = sdoCollection.find(hitIdentifier);
454 if( pos == sdoCollection.end() ) continue;
455 sdo_word.push_back( pos->second.word() ) ;
456 std::vector<int> sdoDepUID(pos->second.getdeposits().size(), HepMC::INVALID_PARTICLE_ID);
457 std::vector<float> sdoDepEnergy(pos->second.getdeposits().size());
458 unsigned int nDepos{0};
459 for (auto& deposit: pos->second.getdeposits()) {
460 if (deposit.first) sdoDepUID[nDepos] = HepMC::uniqueID(deposit.first);
461 ATH_MSG_DEBUG(" SDO Energy Deposit " << deposit.second ) ;
462 sdoDepEnergy[nDepos] = deposit.second;
463 nDepos++;
464 }
465 sdo_depositsUniqueID.push_back( std::move(sdoDepUID) );
466 sdo_depositsEnergy.push_back( std::move(sdoDepEnergy) );
467 }
468 AUXDATA(xprd,std::vector<int>,sdo_words) = std::move(sdo_word);
469 AUXDATA(xprd,std::vector< std::vector<int> >,sdo_depositsBarcode) = sdo_depositsUniqueID; // TODO rename variable to be consistent?
470 AUXDATA(xprd,std::vector< std::vector<float> >,sdo_depositsEnergy) = std::move(sdo_depositsEnergy);
471
472 return sdo_depositsUniqueID;
473}
474
475
476
478 const InDet::PixelCluster* prd,
479 const std::vector<SiHit> & matchingHits ) const
480{
481
482 int numHits = matchingHits.size();
483
484 std::vector<float> sihit_energyDeposit(numHits,0);
485 std::vector<float> sihit_meanTime(numHits,0);
486 std::vector<int> sihit_uniqueID(numHits,HepMC::UNDEFINED_ID);
487 std::vector<int> sihit_pdgid(numHits,0);
488
489 std::vector<float> sihit_startPosX(numHits,0);
490 std::vector<float> sihit_startPosY(numHits,0);
491 std::vector<float> sihit_startPosZ(numHits,0);
492
493 std::vector<float> sihit_endPosX(numHits,0);
494 std::vector<float> sihit_endPosY(numHits,0);
495 std::vector<float> sihit_endPosZ(numHits,0);
496
497 int hitNumber(0);
499 if(de){
500 for ( const auto& sihit : matchingHits ) {
501 sihit_energyDeposit[hitNumber] = sihit.energyLoss() ;
502 sihit_meanTime[hitNumber] = sihit.meanTime() ;
503 const HepMcParticleLink& HMPL = sihit.particleLink();
504 sihit_uniqueID[hitNumber] = HepMC::uniqueID(HMPL) ;
505 if(HMPL.isValid()){
506 sihit_pdgid[hitNumber] = HMPL->pdg_id();
507 }
508
509 // Convert Simulation frame into reco frame
510 const HepGeom::Point3D<double>& startPos=sihit.localStartPosition();
511
512 Amg::Vector2D pos= de->hitLocalToLocal( startPos.z(), startPos.y() );
513 sihit_startPosX[hitNumber] = pos[0];
514 sihit_startPosY[hitNumber] = pos[1];
515 sihit_startPosZ[hitNumber] = startPos.x();
516
517
518 const HepGeom::Point3D<double>& endPos=sihit.localEndPosition();
519 pos= de->hitLocalToLocal( endPos.z(), endPos.y() );
520 sihit_endPosX[hitNumber] = pos[0];
521 sihit_endPosY[hitNumber] = pos[1];
522 sihit_endPosZ[hitNumber] = endPos.x();
523 ++hitNumber;
524 }
525 }
526
527 AUXDATA(xprd,std::vector<float>,sihit_energyDeposit) = std::move(sihit_energyDeposit);
528 AUXDATA(xprd,std::vector<float>,sihit_meanTime) = std::move(sihit_meanTime);
529 AUXDATA(xprd,std::vector<int>,sihit_barcode) = std::move(sihit_uniqueID); // TODO rename variable to be consistent?
530 AUXDATA(xprd,std::vector<int>,sihit_pdgid) = std::move(sihit_pdgid);
531
532 AUXDATA(xprd,std::vector<float>,sihit_startPosX) = std::move(sihit_startPosX);
533 AUXDATA(xprd,std::vector<float>,sihit_startPosY) = std::move(sihit_startPosY);
534 AUXDATA(xprd,std::vector<float>,sihit_startPosZ) = std::move(sihit_startPosZ);
535
536 AUXDATA(xprd,std::vector<float>,sihit_endPosX) = std::move(sihit_endPosX);
537 AUXDATA(xprd,std::vector<float>,sihit_endPosY) = std::move(sihit_endPosY);
538 AUXDATA(xprd,std::vector<float>,sihit_endPosZ) = std::move(sihit_endPosZ);
539
540
541}
542
543
544
545
546
547
549 const std::vector<const SiHit*>* sihits,
550 std::vector< std::vector< int > > & trkUIDs ) const
551{
552 ATH_MSG_VERBOSE( "Got " << sihits->size() << " SiHits to look through" );
553 std::vector<SiHit> matchingHits;
554
555 // Check if we have detector element -- needed to find the local position of the SiHits
557 if(!de)
558 return matchingHits;
559
560 std::vector<const SiHit* > multiMatchingHits;
561
562 for ( const SiHit* siHit : *sihits) {
563 // Match by geometry (SiHit centroid within +/-1 cell of a cluster RDO) or,
564 // failing that, by the SiHit's truth particle having deposited charge in
565 // one of the cluster's RDOs.
566 bool matched = false;
568 {
569 HepGeom::Point3D<double> averagePosition = siHit->localStartPosition() + siHit->localEndPosition();
570 averagePosition *= 0.5;
571 Amg::Vector2D pos = de->hitLocalToLocal( averagePosition.z(), averagePosition.y() );
572 InDetDD::SiCellId diode = de->cellIdOfPosition(pos);
573
574 for( const auto &hitIdentifier : prd->rdoList() ){
575 ATH_MSG_DEBUG("Truth Phi " << diode.phiIndex() << " Cluster Phi " << m_PixelHelper->phi_index( hitIdentifier ) );
576 ATH_MSG_DEBUG("Truth Eta " << diode.etaIndex() << " Cluster Eta " << m_PixelHelper->eta_index( hitIdentifier ) );
577 if( abs( int(diode.etaIndex()) - m_PixelHelper->eta_index( hitIdentifier ) ) <=1
578 && abs( int(diode.phiIndex()) - m_PixelHelper->phi_index( hitIdentifier ) ) <=1 )
579 {
580 multiMatchingHits.push_back(siHit);
581 matched = true;
582 break;
583 }
584 }
585 }
586 if (!matched)
587 {
588 auto uid = HepMC::uniqueID(siHit->particleLink());
589 for ( const auto& uniqueIDSDOColl : trkUIDs ) {
590 if (std::find(uniqueIDSDOColl.begin(),uniqueIDSDOColl.end(),uid) == uniqueIDSDOColl.end() ) continue;
591 multiMatchingHits.push_back(siHit);
592 break;
593 }
594 }
595 }
596 //Now we will now make 1 SiHit for each true particle if the SiHits "touch" other
597 std::vector<const SiHit* >::iterator siHitIter = multiMatchingHits.begin();
598 std::vector<const SiHit* >::iterator siHitIter2 = multiMatchingHits.begin();
599 ATH_MSG_DEBUG( "Found " << multiMatchingHits.size() << " SiHit " );
600 for ( ; siHitIter != multiMatchingHits.end(); ++siHitIter) {
601 const SiHit* lowestXPos = *siHitIter;
602 const SiHit* highestXPos = *siHitIter;
603
604
605 // We will merge these hits
606 std::vector<const SiHit* > ajoiningHits;
607 ajoiningHits.push_back( *siHitIter );
608
609 siHitIter2 = siHitIter+1;
610 while ( siHitIter2 != multiMatchingHits.end() ) {
611 // Need to come from the same truth particle
612
613 if( !HepMC::is_same_particle((*siHitIter)->particleLink(),(*siHitIter2)->particleLink()) ){
614 ++siHitIter2;
615 continue;
616 }
617
618 // Check to see if the SiHits are compatible with each other.
619 if (std::abs((highestXPos->localEndPosition().x()-(*siHitIter2)->localStartPosition().x()))<0.00005 &&
620 std::abs((highestXPos->localEndPosition().y()-(*siHitIter2)->localStartPosition().y()))<0.00005 &&
621 std::abs((highestXPos->localEndPosition().z()-(*siHitIter2)->localStartPosition().z()))<0.00005 )
622 {
623 highestXPos = *siHitIter2;
624 ajoiningHits.push_back( *siHitIter2 );
625 // Dont use hit more than once
626 // @TODO could invalidate siHitIter
627 siHitIter2 = multiMatchingHits.erase( siHitIter2 );
628 }else if (std::abs((lowestXPos->localStartPosition().x()-(*siHitIter2)->localEndPosition().x()))<0.00005 &&
629 std::abs((lowestXPos->localStartPosition().y()-(*siHitIter2)->localEndPosition().y()))<0.00005 &&
630 std::abs((lowestXPos->localStartPosition().z()-(*siHitIter2)->localEndPosition().z()))<0.00005)
631 {
632 lowestXPos = *siHitIter2;
633 ajoiningHits.push_back( *siHitIter2 );
634 // Dont use hit more than once
635 // @TODO could invalidate siHitIter
636 siHitIter2 = multiMatchingHits.erase( siHitIter2 );
637 } else {
638 ++siHitIter2;
639 }
640 }
641
642 if( ajoiningHits.size() == 0){
643 ATH_MSG_WARNING("This should really never happen");
644 continue;
645 }else if(ajoiningHits.size() == 1){
646 // Copy Si Hit ready to return
647 matchingHits.push_back( *ajoiningHits[0] );
648 continue;
649 } else {
650 // Build new SiHit and merge information together.
651 ATH_MSG_DEBUG("Merging " << ajoiningHits.size() << " SiHits together." );
652
653
654 float energyDep(0);
655 float time(0);
656 for( const auto& siHit : ajoiningHits){
657 energyDep += siHit->energyLoss();
658 time += siHit->meanTime();
659 }
660 time /= (float)ajoiningHits.size();
661
662 matchingHits.emplace_back(lowestXPos->localStartPosition(),
663 highestXPos->localEndPosition(),
664 energyDep,
665 time,
666 (*siHitIter)->particleLink(),
667 0, // 0 for pixel 1 for Pixel
668 (*siHitIter)->getBarrelEndcap(),
669 (*siHitIter)->getLayerDisk(),
670 (*siHitIter)->getEtaModule(),
671 (*siHitIter)->getPhiModule(),
672 (*siHitIter)->getSide() );
673 ATH_MSG_DEBUG("Finished Merging " << ajoiningHits.size() << " SiHits together." );
674
675 }
676 }
677
678
679 return matchingHits;
680
681}
682
684 const InDet::PixelCluster* pixelCluster,
685 const PixelChargeCalibCondData *calibData) const
686{
687 ATH_MSG_VERBOSE( " Starting creating input from cluster " );
688
689
690 const std::vector<Identifier>& rdos = pixelCluster->rdoList();
691
692 const std::vector<float> &chList = pixelCluster->chargeList();
693 const std::vector<int> &totList = pixelCluster->totList();
694
695 // std::vector<int> rowList;
696 // std::vector<int> colList;
697 std::vector<int> etaIndexList;
698 std::vector<int> phiIndexList;
699 std::vector<float> CTerm;
700 std::vector<float> ATerm;
701 std::vector<float> ETerm;
702
703 ATH_MSG_VERBOSE( "Number of RDOs: " << rdos.size() );
704
705 //Itererate over all elements hits in the cluster and fill the charge and tot matricies
706 std::vector<Identifier>::const_iterator rdosBegin = rdos.begin();
707 std::vector<Identifier>::const_iterator rdosEnd = rdos.end();
708
709 ATH_MSG_VERBOSE(" Putting together the n. " << rdos.size() << " rdos into a matrix.");
710
711 phiIndexList.reserve( rdos.size());
712 etaIndexList.reserve( rdos.size());
713 CTerm.reserve( rdos.size());
714 ATerm.reserve( rdos.size());
715 ETerm.reserve( rdos.size());
716 for (; rdosBegin!= rdosEnd; ++rdosBegin)
717 {
718 Identifier rId = *rdosBegin;
719 phiIndexList.push_back( m_PixelHelper->phi_index(rId) );
720 etaIndexList.push_back( m_PixelHelper->eta_index(rId) );
721
722 // charge calibration parameters
723 Identifier moduleID = m_PixelHelper->wafer_id(rId);
724 IdentifierHash moduleHash = m_PixelHelper->wafer_hash(moduleID); // wafer hash
725 unsigned int FE = m_pixelReadout->getFE(rId, moduleID);
726 InDetDD::PixelDiodeType type = m_pixelReadout->getDiodeType(rId);
727 if (type == InDetDD::PixelDiodeType::NONE) continue;
728 const auto & parameters = calibData->getLegacyFitParameters(type, moduleHash, FE);
729 CTerm.emplace_back(parameters.C);
730 ATerm.emplace_back(parameters.A);
731 ETerm.emplace_back(parameters.E);
732
733 }//end iteration on rdos
734
735
736 AUXDATA(xprd, std::vector<int>,rdo_phi_pixel_index) = std::move(phiIndexList);
737 AUXDATA(xprd, std::vector<int>,rdo_eta_pixel_index) = std::move(etaIndexList);
738 AUXDATA(xprd, std::vector<float>,rdo_charge) = chList;
739 AUXDATA(xprd, std::vector<int>,rdo_tot) = totList;
740
741 AUXDATA(xprd, std::vector<float>,rdo_Cterm) = std::move(CTerm);
742 AUXDATA(xprd, std::vector<float>,rdo_Aterm) = std::move(ATerm);
743 AUXDATA(xprd, std::vector<float>,rdo_Eterm) = std::move(ETerm);
744
745}
746
747
749 const InDet::PixelCluster* pixelCluster,
750 const unsigned int sizeX, const unsigned int sizeY ) const
751{
752 ATH_MSG_VERBOSE( " Starting creating input from cluster " );
753
754 const InDetDD::SiDetectorElement* de = pixelCluster->detectorElement();
755 if (de==nullptr) {
756 ATH_MSG_ERROR("Could not get detector element");
757 return;
758 }
759
760
761 const InDetDD::PixelModuleDesign* design(dynamic_cast<const InDetDD::PixelModuleDesign*>(&de->design()));
762 if (not design) {
763 ATH_MSG_WARNING("PixelModuleDesign was not retrieved in function 'addNNInformation'");
764 return;
765 }
766 const std::vector<Identifier>& rdos = pixelCluster->rdoList();
767
768 const std::vector<float>& chList = pixelCluster->chargeList();
769 const std::vector<int>& totList = pixelCluster->totList();
770
771 ATH_MSG_VERBOSE( "Number of RDOs: " << rdos.size() );
772 ATH_MSG_VERBOSE( "Number of charges: " << chList.size() );
773 ATH_MSG_VERBOSE( "Number of TOT: " << totList.size() );
774
775
776 //Calculate the centre of the cluster
777 int phiPixelIndexMin, phiPixelIndexMax, etaPixelIndexMin, etaPixelIndexMax;
778 InDetDD::SiCellId cellIdWeightedPosition= getCellIdWeightedPosition( pixelCluster, &phiPixelIndexMin, &phiPixelIndexMax, &etaPixelIndexMin, &etaPixelIndexMax);
779
780 if (!cellIdWeightedPosition.isValid())
781 {
782 ATH_MSG_WARNING( "Weighted position is on invalid CellID." );
783 }
784
785 int etaPixelIndexWeightedPosition=cellIdWeightedPosition.etaIndex();
786 int phiPixelIndexWeightedPosition=cellIdWeightedPosition.phiIndex();
787
788
789 ATH_MSG_DEBUG(" weighted pos phiPixelIndex: " << phiPixelIndexWeightedPosition << " etaPixelIndex: " << etaPixelIndexWeightedPosition );
790
791 // SiLocalPosition PixelModuleDesign::positionFromColumnRow(const int column, const int row) const;
792 //
793 // Given row and column index of diode, returns position of diode center
794 // ALTERNATIVE/PREFERED way is to use localPositionOfCell(const SiCellId & cellId) or
795 // rawLocalPositionOfCell method in SiDetectorElement.
796 // DEPRECATED (but used in numerous places)
797 //
798 // Comment by Hide (referring the original comment in the code) : 2015-02-04
799 // I automatically replaced column to etaPixelIndex and row to phiPixelIndex here. It was bofore:
800 // InDetDD::SiLocalPosition siLocalPosition( design->positionFromColumnRow(columnWeightedPosition,rowWeightedPosition) );
801 //
802 // Then I assume the argument of column/row in this function is in offline manner, not the real hardware column/row.
803 //
804 InDetDD::SiLocalPosition w = design->positionFromColumnRow(etaPixelIndexWeightedPosition,phiPixelIndexWeightedPosition);
805
806
807 double localEtaPixelIndexWeightedPosition = w.xEta();
808 double localPhiPixelIndexWeightedPosition = w.xPhi();
809
810 int centralIndexX=(sizeX-1)/2;
811 int centralIndexY=(sizeY-1)/2;
812
813
814
815 // Check to see if the cluster is too big for the NN
816
817 if (abs(phiPixelIndexWeightedPosition-phiPixelIndexMin)>centralIndexX ||
818 abs(phiPixelIndexWeightedPosition-phiPixelIndexMax)>centralIndexX)
819 {
820 ATH_MSG_DEBUG(" Cluster too large phiPixelIndexMin " << phiPixelIndexMin << " phiPixelIndexMax " << phiPixelIndexMax << " centralX " << centralIndexX);
821 //return;
822 }
823
824 if (abs(etaPixelIndexWeightedPosition-etaPixelIndexMin)>centralIndexY ||
825 abs(etaPixelIndexWeightedPosition-etaPixelIndexMax)>centralIndexY)
826 {
827 ATH_MSG_DEBUG(" Cluster too large etaPixelIndexMin" << etaPixelIndexMin << " etaPixelIndexMax " << etaPixelIndexMax << " centralY " << centralIndexY);
828 //return;
829 }
830
831 std::vector< std::vector<float> > matrixOfToT (sizeX, std::vector<float>(sizeY,0) );
832 std::vector< std::vector<float> > matrixOfCharge(sizeX, std::vector<float>(sizeY,0));
833 // Fill the pitch of every window cell from the design, not only the cells
834 // with an RDO, so padding cells carry their real pitch. Cells beyond the
835 // sensor edge resolve to the nearest sub-matrix and take its pitch.
836 std::vector<float> vectorOfPitchesY(sizeY, 0.f);
837 std::vector<float> vectorOfPitchesX(sizeX, 0.f);
838 for (unsigned int iy = 0; iy < sizeY; ++iy) {
839 const int etaIdx = etaPixelIndexWeightedPosition + (static_cast<int>(iy) - centralIndexY);
840 const InDetDD::SiCellId cellId(phiPixelIndexWeightedPosition, etaIdx);
841 vectorOfPitchesY[iy] = design->parameters(cellId).width().xEta();
842 }
843 for (unsigned int ix = 0; ix < sizeX; ++ix) {
844 const int phiIdx = phiPixelIndexWeightedPosition + (static_cast<int>(ix) - centralIndexX);
845 const InDetDD::SiCellId cellId(phiIdx, etaPixelIndexWeightedPosition);
846 vectorOfPitchesX[ix] = design->parameters(cellId).width().xPhi();
847 }
848
849
850 //Itererate over all elements hits in the cluster and fill the charge and tot matrices
851 std::vector<Identifier>::const_iterator rdosBegin = rdos.begin();
852 std::vector<Identifier>::const_iterator rdosEnd = rdos.end();
853 auto charge = chList.begin();
854 auto tot = totList.begin();
855
856 ATH_MSG_VERBOSE(" Putting together the n. " << rdos.size() << " rdos into a matrix.");
857
858 for (; rdosBegin!= rdosEnd; ++rdosBegin)
859 {
860
861 Identifier rId = *rdosBegin;
862 int absphiPixelIndex = m_PixelHelper->phi_index(rId)-phiPixelIndexWeightedPosition + centralIndexX;
863 int absetaPixelIndex = m_PixelHelper->eta_index(rId)-etaPixelIndexWeightedPosition + centralIndexY;
864
865 // rdos, chList and totList are parallel: take this RDO's charge and ToT
866 // before the window checks below, or the entries of an RDO outside the
867 // window are shifted onto the RDOs that follow it.
868 float thisCharge = -1.f;
869 int thisToT = -1;
870 if ((not chList.empty()) && charge != chList.end()) { thisCharge = *charge; ++charge; }
871 if ((not totList.empty()) && tot != totList.end()) { thisToT = *tot; ++tot; }
872
873 ATH_MSG_VERBOSE( " Phi Index: " << m_PixelHelper->phi_index(rId)
874 << " absphiPixelIndex: " << absphiPixelIndex
875 << " eta Idx: " << m_PixelHelper->eta_index(rId)
876 << " absetaPixelIndex: " << absetaPixelIndex
877 << " charge " << thisCharge );
878
879 if (absphiPixelIndex <0 || absphiPixelIndex >= (int)sizeX)
880 {
881 ATH_MSG_DEBUG(" problem with index: " << absphiPixelIndex << " min: " << 0 << " max: " << sizeX);
882 continue;
883 }
884
885 if (absetaPixelIndex <0 || absetaPixelIndex >= (int)sizeY)
886 {
887 ATH_MSG_DEBUG(" problem with index: " << absetaPixelIndex << " min: " << 0 << " max: " << sizeY);
888 continue;
889 }
890
891 matrixOfToT[absphiPixelIndex][absetaPixelIndex] = thisToT;
892 matrixOfCharge[absphiPixelIndex][absetaPixelIndex] = thisCharge;
893 }//end iteration on rdos
894
895
896 ATH_MSG_VERBOSE( " End RDO LOOP " );
897
898 // Using the centre of the module and beam spot calculate
899 // the incidence angles of the tracks
900 const Amg::Vector2D& prdLocPos = pixelCluster->localPosition();
901 InDetDD::SiLocalPosition centroid(prdLocPos);
902
903 Amg::Vector3D globalPos = de->globalPosition(centroid);
904 Amg::Vector3D trackDir = globalPos; // - beamSpotPosition;
905 trackDir.normalize();
906
907 Amg::Vector3D module_normal = de->normal();
908 Amg::Vector3D module_phiax = de->phiAxis();
909 Amg::Vector3D module_etaax = de->etaAxis();
910
911 // Calculate the phi incidence angle
912 float trkphicomp = trackDir.dot(module_phiax);
913 float trketacomp = trackDir.dot(module_etaax);
914 float trknormcomp = trackDir.dot(module_normal);
915 double bowphi = atan2(trkphicomp,trknormcomp);
916 double boweta = atan2(trketacomp,trknormcomp);
917 double tanl = m_lorentzAngleTool->getTanLorentzAngle(de->identifyHash(),Gaudi::Hive::currentContext());
918 if(bowphi > pi/2) bowphi -= pi;
919 if(bowphi < -pi/2) bowphi += pi;
920 int readoutside = design->readoutSide();
921 double angle = atan(tan(bowphi)-readoutside*tanl);
922
923
924 // Calculate the theta incidence angle
925 ATH_MSG_VERBOSE( " Angle theta bef corr: " << boweta );
926 if (boweta>pi/2.) boweta-=pi;
927 if (boweta<-pi/2.) boweta+=pi;
928
929
930 ATH_MSG_VERBOSE(" Angle phi: " << angle << " theta: " << boweta );
931 ATH_MSG_VERBOSE(" PhiPixelIndexWeightedPosition: " << phiPixelIndexWeightedPosition << " EtaPixelIndexWeightedPosition: " << etaPixelIndexWeightedPosition );
932
933 // store the matrixOfToT in a vector
934 std::vector<float> vectorOfCharge(sizeX*sizeY,0);
935 std::vector<float> vectorOfToT(sizeX*sizeY,0);
936 int counter(0);
937 for (unsigned int u=0;u<sizeX;u++)
938 {
939 for (unsigned int s=0;s<sizeY;s++)
940 {
941 vectorOfToT[counter] = matrixOfToT[u][s];
942 vectorOfCharge[counter] = matrixOfCharge[u][s];
943 ++counter;
944 }
945 }
946
947 ATH_MSG_VERBOSE( "matrixOfToT converted in a std::vector<float> " );
948
949 ATH_MSG_VERBOSE( "... and saved " );
950 // Add information to xAOD
951 AUXDATA(xprd, int, NN_sizeX) = sizeX;
952 AUXDATA(xprd, int, NN_sizeY) = sizeY;
953
954 AUXDATA(xprd, float, NN_phiBS) = angle;
955 AUXDATA(xprd, float, NN_thetaBS) = boweta;
956
957 AUXDATA(xprd, std::vector<float>, NN_matrixOfToT) = std::move(vectorOfToT);
958 AUXDATA(xprd, std::vector<float>, NN_matrixOfCharge) = std::move(vectorOfCharge);
959 AUXDATA(xprd, std::vector<float>, NN_vectorOfPitchesY) = std::move(vectorOfPitchesY);
960 AUXDATA(xprd, std::vector<float>, NN_vectorOfPitchesX) = std::move(vectorOfPitchesX);
961
962
963 AUXDATA(xprd, int, NN_etaPixelIndexWeightedPosition) = etaPixelIndexWeightedPosition;
964 AUXDATA(xprd, int, NN_phiPixelIndexWeightedPosition) = phiPixelIndexWeightedPosition;
965
966 AUXDATA(xprd, float, NN_localEtaPixelIndexWeightedPosition) = localEtaPixelIndexWeightedPosition;
967 AUXDATA(xprd, float, NN_localPhiPixelIndexWeightedPosition) = localPhiPixelIndexWeightedPosition;
968
969 ATH_MSG_VERBOSE( "NN training Written" );
970}
971
973 const InDet::PixelCluster* pixelCluster,
974 const std::vector<SiHit> & matchingHits ) const
975{
976
977
978 unsigned int numberOfSiHits = matchingHits.size();
979
980 std::vector<float> positionsX(numberOfSiHits,0);
981 std::vector<float> positionsY(numberOfSiHits,0);
982
983 std::vector<float> positions_indexX(numberOfSiHits,0);
984 std::vector<float> positions_indexY(numberOfSiHits,0);
985
986 std::vector<float> theta(numberOfSiHits,0);
987 std::vector<float> phi(numberOfSiHits,0);
988
989 std::vector<int> uniqueID(numberOfSiHits,HepMC::UNDEFINED_ID);
990 std::vector<int> pdgid(numberOfSiHits,0);
991 std::vector<float> chargeDep(numberOfSiHits,0);
992 std::vector<float> truep(numberOfSiHits,0);
993
994 std::vector<float> pathlengthX(numberOfSiHits,0);
995 std::vector<float> pathlengthY(numberOfSiHits,0);
996 std::vector<float> pathlengthZ(numberOfSiHits,0);
997
998 std::vector<int> motherUniqueID(numberOfSiHits,HepMC::UNDEFINED_ID);
999 std::vector<int> motherPdgid(numberOfSiHits,0);
1000
1001
1002
1003 // Check if we have detector element -- needed to find the local position of the SiHits
1004 const InDetDD::SiDetectorElement* de = pixelCluster->detectorElement();
1005 if(!de)
1006 return;
1007
1008 InDetDD::SiCellId cellIdWeightedPosition = getCellIdWeightedPosition( pixelCluster );
1009
1010 const InDetDD::PixelModuleDesign* design(dynamic_cast<const InDetDD::PixelModuleDesign*>(&de->design()));
1011 if (not design) {
1012 ATH_MSG_WARNING("PixelModuleDesign was not retrieved in function 'addNNTruthInfo'");
1013 return;
1014 }
1015 // lorentz shift correction
1016 double shift = m_lorentzAngleTool->getLorentzShift(de->identifyHash(),Gaudi::Hive::currentContext());
1017 unsigned hitNumber(0);
1018 for( const auto& siHit : matchingHits ){
1019
1020 HepGeom::Point3D<double> averagePosition = (siHit.localStartPosition() + siHit.localEndPosition()) * 0.5;
1021
1022 ATH_MSG_VERBOSE("Truth Part X: " << averagePosition.y() << " shift " << shift << " Y: " << averagePosition.z() );
1023
1024 // position lorentz shift corrected
1025 float YposC = averagePosition.y()-shift;
1026
1027 if (std::abs(YposC)>design->width()/2 &&
1028 std::abs(averagePosition.y())<design->width()/2)
1029 {
1030 if (YposC>design->width()/2)
1031 {
1032 YposC=design->width()/2-1e-6;
1033 } else if (YposC<-design->width()/2)
1034 {
1035 YposC=-design->width()/2+1e-6;
1036 }
1037 }
1038
1039 positionsX[hitNumber] = YposC;
1040 positionsY[hitNumber] = averagePosition.z();
1041
1042 HepGeom::Point3D<double> deltaPosition = siHit.localEndPosition() - siHit.localStartPosition();
1043
1044 pathlengthX[hitNumber] = deltaPosition.y();
1045 pathlengthY[hitNumber] = deltaPosition.z();
1046 pathlengthZ[hitNumber] = deltaPosition.x();
1047
1048
1049 // Here we convert the hit position to the right frame
1050 Amg::Vector2D siLocalTruthPosition = de->hitLocalToLocal(averagePosition.z(), YposC);
1051 InDetDD::SiCellId cellIdOfTruthPosition = design->cellIdOfPosition(siLocalTruthPosition);
1052
1053
1054// InDetDD::SiLocalPosition siLocalTruthPosition(averagePosition.z(),YposC ) ;
1055// InDetDD::SiCellId cellIdOfTruthPosition =design->cellIdOfPosition(siLocalTruthPosition);
1056
1057 int truthEtaIndex = cellIdOfTruthPosition.etaIndex();
1058 int truthPhiIndex = cellIdOfTruthPosition.phiIndex();
1059
1060 InDetDD::SiDiodesParameters diodeParameters = design->parameters(cellIdOfTruthPosition);
1061 double pitchY = diodeParameters.width().xEta();
1062 double pitchX = diodeParameters.width().xPhi();
1063
1064 // pixel center
1065 // SiLocalPosition PixelModuleDesign::positionFromColumnRow(const int column, const int row) const;
1066 //
1067 // Given row and column index of diode, returns position of diode center
1068 // ALTERNATIVE/PREFERED way is to use localPositionOfCell(const SiCellId & cellId) or
1069 // rawLocalPositionOfCell method in SiDetectorElement.
1070 // DEPRECATED (but used in numerous places)
1071 //
1072 // Comment by Hide (referring the original comment in the code) : 2015-02-04
1073 // I automatically replaced column to etaPixelIndex and row to phiPixelIndex here. It was bofore:
1074 // InDetDD::SiLocalPosition siLocalPosition( design->positionFromColumnRow(truthColumn,truthRow) );
1075 //
1076 // Then I assume the argument of column/row in this function is in offline manner, not the real hardware column/row.
1077 //
1078 InDetDD::SiLocalPosition siLocalPositionCenter(design->positionFromColumnRow(truthEtaIndex,truthPhiIndex));
1079 double pixelCenterY = siLocalPositionCenter.xEta();
1080 double pixelCenterX = siLocalPositionCenter.xPhi();
1081
1082
1083 // truth index
1084// double truthIndexY = truthEtaIndex + (averagePosition.z() - pixelCenterY)/pitchY;
1085// double truthIndexX = truthPhiIndex + (YposC - pixelCenterX)/pitchX;
1086 double truthIndexY = truthEtaIndex + (siLocalTruthPosition[Trk::distEta] - pixelCenterY)/pitchY;
1087 double truthIndexX = truthPhiIndex + (siLocalTruthPosition[Trk::distPhi] - pixelCenterX)/pitchX;
1088
1089
1090 positions_indexX[hitNumber] = truthIndexX - cellIdWeightedPosition.phiIndex();
1091 positions_indexY[hitNumber] = truthIndexY - cellIdWeightedPosition.etaIndex();
1092
1093 HepGeom::Point3D<double> diffPositions = (siHit.localEndPosition() - siHit.localStartPosition());
1094 double bowphi = std::atan2( diffPositions.y(), diffPositions.x() );
1095
1096
1097 //Truth Track incident angle theta
1098 theta[hitNumber] = std::atan2(diffPositions.z() ,diffPositions.x());
1099 //Truth track incident angle phi -- correct for lorentz angle
1100 float tanlorentz = m_lorentzAngleTool->getTanLorentzAngle(de->identifyHash(),Gaudi::Hive::currentContext());
1101
1102 int readoutside = design->readoutSide();
1103 phi[hitNumber] = std::atan(std::tan(bowphi)-readoutside*tanlorentz);
1104 const HepMcParticleLink& HMPL = siHit.particleLink();
1105 if (HMPL.isValid()){
1106 uniqueID[hitNumber] = HepMC::uniqueID(HMPL);
1107 const auto particle = HMPL.cptr();
1108 pdgid[hitNumber] = particle->pdg_id();
1109 HepMC::FourVector mom=particle->momentum();
1110 truep[hitNumber] = std::sqrt(mom.x()*mom.x()+mom.y()*mom.y()+mom.z()*mom.z());
1111 const auto vertex = particle->production_vertex();
1112//AV Please note that taking the first particle as a mother is ambiguous.
1113 if ( vertex && !vertex->particles_in().empty()){
1114 const auto& mother_of_particle=vertex->particles_in().front();
1115 motherUniqueID[hitNumber] = HepMC::uniqueID(mother_of_particle);
1116 motherPdgid[hitNumber] = mother_of_particle->pdg_id();
1117 }
1118 }
1119 chargeDep[hitNumber] = siHit.energyLoss() ;
1120
1121 ++hitNumber;
1122 }
1123
1124
1125 AUXDATA(xprd, std::vector<float>, NN_positionsX) = std::move(positionsX);
1126 AUXDATA(xprd, std::vector<float>, NN_positionsY) = std::move(positionsY);
1127
1128 AUXDATA(xprd, std::vector<float>, NN_positions_indexX) = std::move(positions_indexX);
1129 AUXDATA(xprd, std::vector<float>, NN_positions_indexY) = std::move(positions_indexY);
1130
1131 AUXDATA(xprd, std::vector<float>, NN_theta) = std::move(theta);
1132 AUXDATA(xprd, std::vector<float>, NN_phi) = std::move(phi);
1133
1134 AUXDATA(xprd, std::vector<int>, NN_barcode) = std::move(uniqueID); // TODO Rename variable to be consistent?
1135 AUXDATA(xprd, std::vector<int>, NN_pdgid) = std::move(pdgid);
1136 AUXDATA(xprd, std::vector<float>, NN_energyDep) = std::move(chargeDep);
1137 AUXDATA(xprd, std::vector<float>, NN_trueP) = std::move(truep);
1138
1139 AUXDATA(xprd, std::vector<int>, NN_motherBarcode) = std::move(motherUniqueID); // TODO Rename variable to be consistent?
1140 AUXDATA(xprd, std::vector<int>, NN_motherPdgid) = std::move(motherPdgid);
1141
1142
1143
1144 AUXDATA(xprd, std::vector<float>, NN_pathlengthX) = std::move(pathlengthX);
1145 AUXDATA(xprd, std::vector<float>, NN_pathlengthY) = std::move(pathlengthY);
1146 AUXDATA(xprd, std::vector<float>, NN_pathlengthZ) = std::move(pathlengthZ);
1147
1148
1149}
1150
1151
1152
1153
1155 int *rphiPixelIndexMin,
1156 int *rphiPixelIndexMax,
1157 int *retaPixelIndexMin,
1158 int *retaPixelIndexMax ) const
1159{
1160
1161 const InDetDD::SiDetectorElement* de = pixelCluster->detectorElement();
1162 if (de==nullptr) {
1163 ATH_MSG_ERROR("Could not get detector element");
1164 return {};
1165 }
1166
1167 const InDetDD::PixelModuleDesign* design(dynamic_cast<const InDetDD::PixelModuleDesign*>(&de->design()));
1168 if (not design) {
1169 ATH_MSG_WARNING("PixelModuleDesign was not retrieved in function 'getCellIdWeightedPosition'");
1170 return {};
1171 }
1172 const std::vector<Identifier>& rdos = pixelCluster->rdoList();
1173
1174 ATH_MSG_VERBOSE( "Number of RDOs: " << rdos.size() );
1175 const std::vector<float>& chList = pixelCluster->chargeList();
1176
1177 ATH_MSG_VERBOSE( "Number of charges: " << chList.size() );
1178 std::vector<Identifier>::const_iterator rdosBegin = rdos.begin();
1179 std::vector<Identifier>::const_iterator rdosEnd = rdos.end();
1180
1181 auto charge = chList.begin();
1182
1183 InDetDD::SiLocalPosition sumOfWeightedPositions(0,0,0);
1184 double sumOfCharge=0;
1185
1186 int phiPixelIndexMin = 99999;
1187 int phiPixelIndexMax = -99999;
1188 int etaPixelIndexMin = 99999;
1189 int etaPixelIndexMax = -99999;
1190
1191 for (; rdosBegin!= rdosEnd; ++rdosBegin, ++charge)
1192 {
1193
1194 Identifier rId = *rdosBegin;
1195 int phiPixelIndex = m_PixelHelper->phi_index(rId);
1196 int etaPixelIndex = m_PixelHelper->eta_index(rId);
1197
1198 ATH_MSG_VERBOSE(" Adding pixel phiPixelIndex: " << phiPixelIndex << " etaPixelIndex: " << etaPixelIndex << " charge: " << *charge );
1199
1200 // SiLocalPosition PixelModuleDesign::positionFromColumnRow(const int column, const int row) const;
1201 //
1202 // Given row and column index of diode, returns position of diode center
1203 // ALTERNATIVE/PREFERED way is to use localPositionOfCell(const SiCellId & cellId) or
1204 // rawLocalPositionOfCell method in SiDetectorElement.
1205 // DEPRECATED (but used in numerous places)
1206 //
1207 // Comment by Hide (referring the original comment in the code): 2015-02-04
1208 // I automatically replaced column to etaPixelIndex and row to phiPixelIndex here. It was bofore:
1209 // InDetDD::SiLocalPosition siLocalPosition( design->positionFromColumnRow(column,row) );
1210 //
1211 // Then I assume the argument of column/row in this function is in offline manner, not the real hardware column/row.
1212 //
1213 InDetDD::SiLocalPosition siLocalPosition( design->positionFromColumnRow(etaPixelIndex,phiPixelIndex) );
1214 ATH_MSG_VERBOSE ( "Local Position: Row = " << siLocalPosition.xRow() << ", Col = " << siLocalPosition.xColumn() );
1215
1216 sumOfWeightedPositions += (*charge)*siLocalPosition;
1217 sumOfCharge += (*charge);
1218
1219 if (phiPixelIndex < phiPixelIndexMin)
1220 phiPixelIndexMin = phiPixelIndex;
1221
1222 if (phiPixelIndex > phiPixelIndexMax)
1223 phiPixelIndexMax = phiPixelIndex;
1224
1225 if (etaPixelIndex < etaPixelIndexMin)
1226 etaPixelIndexMin = etaPixelIndex;
1227
1228 if (etaPixelIndex > etaPixelIndexMax)
1229 etaPixelIndexMax = etaPixelIndex;
1230
1231 }
1232 sumOfWeightedPositions /= sumOfCharge;
1233
1234 ATH_MSG_VERBOSE ( "Wighted position: Row = " << sumOfWeightedPositions.xRow() << ", Col = " << sumOfWeightedPositions.xColumn() );
1235
1236 if(rphiPixelIndexMin) *rphiPixelIndexMin = phiPixelIndexMin;
1237 if(rphiPixelIndexMax) *rphiPixelIndexMax = phiPixelIndexMax;
1238 if(retaPixelIndexMin) *retaPixelIndexMin = etaPixelIndexMin;
1239 if(retaPixelIndexMax) *retaPixelIndexMax = etaPixelIndexMax;
1240
1241 //what you want to know is simple:
1242 //just the phiPixelIndex and etaPixelIndex of this average position!
1243
1244 InDetDD::SiCellId cellIdWeightedPosition=design->cellIdOfPosition(sumOfWeightedPositions);
1245
1246
1247 return cellIdWeightedPosition;
1248
1249}
1250
1251
1252
1254//
1255// Finalize method:
1256//
1259{
1260 if (m_useTruthInfo && !m_truthParticleLinks.empty()) {
1261 ATH_MSG_INFO("Missing truth particles " << m_missingTruthParticle << " missing parent: " << m_missingParentParticle
1262 << " have " << m_haveTruthLink);
1263 }
1264 return StatusCode::SUCCESS;
1265}
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
Scalar theta() const
theta method
#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,...)
double charge(const T &p)
Definition AtlasPID.h:1003
Structs for holding charge calibration parameterisation and data.
This is an Identifier helper class for the Pixel subdetector.
#define AUXDATA(OBJ, TYP, NAME)
double angle(const GeoTrf::Vector2D &a, const GeoTrf::Vector2D &b)
const double width
#define pi
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.
int readoutSide() const
ReadoutSide.
Class used to describe the design of a module (diode segmentation and readout scheme).
virtual SiDiodesParameters parameters(const SiCellId &cellId) const
readout or diode id -> position, size
SiLocalPosition positionFromColumnRow(const int column, const int row) const
Given row and column index of a diode, return position of diode center ALTERNATIVE/PREFERED way is to...
virtual SiCellId cellIdOfPosition(const SiLocalPosition &localPos) const
position -> id
virtual double width() const
Method to calculate average width of a module.
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
int etaIndex() const
Get eta index.
Definition SiCellId.h:114
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 handle the position of the centre and the width of a diode or a cluster of diodes Version 1....
const SiLocalPosition & width() const
width of the diodes:
Class to represent a position in the natural frame of a silicon sensor, for Pixel and SCT For Pixel: ...
double xPhi() const
position along phi direction:
double xColumn() const
positions for Pixel:
double xEta() const
position along eta direction:
SiCellId cellIdOfPosition(const Amg::Vector2D &localPos) const
As in previous method but returns SiCellId.
virtual const Amg::Vector3D & normal() const override final
Get reconstruction local normal axes in global frame.
virtual IdentifierHash identifyHash() const override final
identifier hash (inline)
HepGeom::Point3D< double > globalPosition(const HepGeom::Point3D< double > &localPos) const
transform a reconstruction local position into a global position (inline):
virtual Identifier identify() const override final
identifier of this detector element (inline)
Amg::Vector2D hitLocalToLocal(double xEta, double xPhi) const
Simulation/Hit local frame to reconstruction local frame.
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.
PixelChargeCalib::LegacyFitParameters getLegacyFitParameters(InDetDD::PixelDiodeType type, unsigned int moduleHash, unsigned int FE) const
void addNNInformation(xAOD::TrackMeasurementValidation *xprd, const InDet::PixelCluster *pixelCluster, const unsigned int SizeX, const unsigned int SizeY) const
SG::WriteHandleKey< std::vector< unsigned int > > m_write_offsets
Gaudi::Property< bool > m_writeExtendedPRDinformation
void addRdoInformation(xAOD::TrackMeasurementValidation *xprd, const InDet::PixelCluster *pixelCluster, const PixelChargeCalibCondData *calibData) const
std::atomic< unsigned int > m_missingTruthParticle
const PixelID * m_PixelHelper
Gaudi::Property< bool > m_writeNNinformation
Gaudi::Property< bool > m_writeRDOinformation
SG::ReadCondHandleKey< PixelDCSHVData > m_readKeyHV
SG::ReadHandleKey< SiHitCollection > m_sihitContainer_key
SG::ReadCondHandleKey< PixelChargeCalibCondData > m_chargeDataKey
void addSiHitInformation(xAOD::TrackMeasurementValidation *xprd, const InDet::PixelCluster *prd, const std::vector< SiHit > &matchingHits) const
SG::ReadHandleKey< Trk::ClusterSplitProbabilityContainer > m_clusterSplitProbContainer
virtual StatusCode execute(const EventContext &ctx)
Execute method.
std::vector< SiHit > findAllHitsCompatibleWithCluster(const InDet::PixelCluster *prd, const std::vector< const SiHit * > *sihits, std::vector< std::vector< int > > &trkBCs) const
Gaudi::Property< bool > m_useSiHitsGeometryMatching
ToolHandle< IInDetConditionsTool > m_pixelSummary
Gaudi::Property< bool > m_useTruthInfo
SG::ReadHandleKey< xAODTruthParticleLinkVector > m_truthParticleLinks
SG::ReadCondHandleKey< PixelDCSTempData > m_readKeyTemp
InDetDD::SiCellId getCellIdWeightedPosition(const InDet::PixelCluster *pixelCluster, int *rrowMin=0, int *rrowMax=0, int *rcolMin=0, int *rcolMax=0) const
SG::ReadHandleKey< InDetSimDataCollection > m_SDOcontainer_key
Gaudi::Property< bool > m_writeSDOs
SG::ReadCondHandleKey< PixelDCSStatusData > m_condDCSStatusKey
std::atomic< unsigned int > m_missingParentParticle
void addNNTruthInfo(xAOD::TrackMeasurementValidation *xprd, const InDet::PixelCluster *prd, const std::vector< SiHit > &matchingHits) const
Gaudi::Property< bool > m_writeModuleStatus
virtual StatusCode finalize()
SG::ReadHandleKey< InDet::PixelClusterContainer > m_clustercontainer_key
SG::ReadHandleKey< PRD_MultiTruthCollection > m_multiTruth_key
SG::ReadCondHandleKey< PixelDCSStateData > m_condDCSStateKey
SG::WriteHandleKey< xAOD::TrackMeasurementValidationContainer > m_write_xaod_key
ToolHandle< ISiLorentzAngleTool > m_lorentzAngleTool
ServiceHandle< InDetDD::IPixelReadoutManager > m_pixelReadout
std::vector< std::vector< int > > addSDOInformation(xAOD::TrackMeasurementValidation *xprd, const InDet::PixelCluster *prd, const InDetSimDataCollection &sdoCollection) const
virtual StatusCode initialize()
Gaudi::Property< bool > m_writeSiHits
std::atomic< unsigned int > m_haveTruthLink
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
static const ProbabilityInfo & getNoSplitProbability()
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
HepMC3::FourVector FourVector
int uniqueID(const T &p)
constexpr int UNDEFINED_ID
bool is_same_particle(const T1 &p1, const T2 &p2)
Method to establish if two particles in the GenEvent actually represent the same particle.
@ distEta
readout for silicon
Definition ParamDefs.h:51
@ distPhi
Definition ParamDefs.h:50
TrackMeasurementValidation_v1 TrackMeasurementValidation
Reference the current persistent version:
TruthParticle_v1 TruthParticle
Typedef to implementation.