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