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