ATLAS Offline Software
Loading...
Searching...
No Matches
PixelFastDigitizationTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6// PixelFastDigitizationTool.cxx
7// Implementation file for class PixelFastDigitizationTool
9
10// Pixel digitization includes
12#include "PixelConditionsData/ChargeCalibParameters.h" //for Thresholds
13
14// Det Descr
15#include "Identifier/Identifier.h"
16
22
23// Random numbers
25#include "CLHEP/Random/RandGaussZiggurat.h"
26#include "CLHEP/Random/RandFlat.h"
27#include "CLHEP/Random/RandLandau.h"
28
29// Pile-up
30
32
33// Fatras
42
45
46//Package For New Tracking:
47// Amg includes
50// Trk includes
51
54
60
61
62using namespace InDetDD;
63using namespace InDet;
64
65// Constructor with parameters:
66PixelFastDigitizationTool::PixelFastDigitizationTool(const std::string &type, const std::string &name,
67 const IInterface* parent):
68
69 PileUpToolBase(type, name, parent)
70{
71}
72
78
79// Initialize method:
81{
82
83 ATH_MSG_DEBUG ( "PixelDigitizationTool::initialize()" );
84
85 ATH_CHECK(m_pixelReadout.retrieve());
86 ATH_CHECK(m_chargeDataKey.initialize());
87 ATH_CHECK(m_offlineCalibDataKey.initialize());
88 ATH_CHECK(m_pixelDetEleCollKey.initialize());
89
90 //locate the AtRndmGenSvc and initialize our local ptr
91 if (!m_rndmSvc.retrieve().isSuccess())
92 {
93 ATH_MSG_ERROR ( "Could not find given RndmSvc" );
94 return StatusCode::FAILURE;
95 }
96
97 if (detStore()->retrieve(m_pixel_ID, "PixelID").isFailure()) {
98 ATH_MSG_ERROR ( "Could not get Pixel ID helper" );
99 return StatusCode::FAILURE;
100 }
101
102 if (m_inputObjectName.empty())
103 {
104 ATH_MSG_FATAL ( "Property InputObjectName not set !" );
105 return StatusCode::FAILURE;
106 }
107 else
108 {
109 ATH_MSG_DEBUG ( "Input objects: '" << m_inputObjectName << "'" );
110 }
111
112 // retrieve the offline cluster maker : for pixel and/or sct
114 if (m_clusterMaker.retrieve().isFailure()){
115 ATH_MSG_WARNING( "Could not retrieve " << m_clusterMaker );
116 ATH_MSG_WARNING( "-> Switching to simplified cluster creation!" );
117 m_pixUseClusterMaker = false;
118 m_clusterMaker.disable();
119 }
120 } else {
121 m_clusterMaker.disable();
122 }
123
125 ATH_CHECK(m_distortionKey.initialize());
126 }
127
128 //locate the PileUpMergeSvc and initialize our local ptr
129 if (!m_mergeSvc.retrieve().isSuccess()) {
130 ATH_MSG_ERROR ( "Could not find PileUpMergeSvc" );
131 return StatusCode::FAILURE;
132 }
133
134
135 // get the InDet::PixelGangedAmbiguitiesFinder
136 if ( m_gangedAmbiguitiesFinder.retrieve().isFailure() ) {
137 ATH_MSG_FATAL( m_gangedAmbiguitiesFinder.propertyName() << ": Failed to retrieve tool " << m_gangedAmbiguitiesFinder.type() );
138 return StatusCode::FAILURE;
139 } else {
140 ATH_MSG_DEBUG ( m_gangedAmbiguitiesFinder.propertyName() << ": Retrieved tool " << m_gangedAmbiguitiesFinder.type() );
141 }
142
143 ATH_CHECK(m_lorentzAngleTool.retrieve());
144
145 return StatusCode::SUCCESS;
146}
147
148
149
150StatusCode PixelFastDigitizationTool::prepareEvent(const EventContext& /*ctx*/, unsigned int)
151{
152
153 m_siHitCollList.clear();
156 return StatusCode::SUCCESS;
157}
158
159
161 SubEventIterator bSubEvents,
162 SubEventIterator eSubEvents)
163{
164 //decide if this event will be processed depending on HardScatterSplittingMode & bunchXing
165 if (m_HardScatterSplittingMode == 2 && !m_HardScatterSplittingSkipper ) { m_HardScatterSplittingSkipper = true; return StatusCode::SUCCESS; }
166 if (m_HardScatterSplittingMode == 1 && m_HardScatterSplittingSkipper ) { return StatusCode::SUCCESS; }
168
170 TimedHitCollList hitCollList;
171
172 if (!(m_mergeSvc->retrieveSubSetEvtData(m_inputObjectName.value(), hitCollList, bunchXing,
173 bSubEvents, eSubEvents).isSuccess()) &&
174 hitCollList.empty()) {
175 ATH_MSG_ERROR("Could not fill TimedHitCollList");
176 return StatusCode::FAILURE;
177 } else {
178 ATH_MSG_VERBOSE(hitCollList.size() << " SiHitCollections with key " <<
179 m_inputObjectName << " found");
180 }
181
182 TimedHitCollList::iterator iColl(hitCollList.begin());
183 TimedHitCollList::iterator endColl(hitCollList.end());
184
185 for( ; iColl != endColl; ++iColl) {
186 SiHitCollection *siHitColl = new SiHitCollection(*iColl->second);
187 PileUpTimeEventIndex timeIndex(iColl->first);
188 ATH_MSG_DEBUG("SiHitCollection found with " << siHitColl->size() <<
189 " hits");
190 ATH_MSG_VERBOSE("time index info. time: " << timeIndex.time()
191 << " index: " << timeIndex.index()
192 << " type: " << timeIndex.type());
193 m_thpcsi->insert(timeIndex, siHitColl);
194 m_siHitCollList.push_back(siHitColl);
195 }
196
197 return StatusCode::SUCCESS;
198}
199
200
201StatusCode PixelFastDigitizationTool::processAllSubEvents(const EventContext& ctx) {
202
203 // --------------------------------------
204 // Pixel Cluster container registration
205 unsigned int nwafer = m_pixel_ID->wafer_hash_max();
207 ATH_CHECK( wh.record (std::make_unique<InDet::PixelClusterContainer>(nwafer)) );
208 m_pixelClusterContainer = wh.ptr();
209 m_pixelClusterContainer->cleanup();
210
211 // symlink the Pixel Cluster Container
212 // FIXME: This results in a hard cast, which is undefined behavior as per C++.
214
215 // truth info
216
218
220 if((evtStore()->retrieve(m_pixPrdTruth, m_prdTruthNamePixel)).isFailure()){
221 ATH_MSG_FATAL("Could not retrieve collection " << m_prdTruthNamePixel);
222 return StatusCode::FAILURE;
223 }
224 }else{
225 if((evtStore()->record(m_pixPrdTruth, m_prdTruthNamePixel)).isFailure()){
226 ATH_MSG_FATAL("Could not record collection " << m_prdTruthNamePixel);
227 return StatusCode::FAILURE;
228 }
229 }
230
231
232 m_ambiguitiesMap =new PixelGangedClusterAmbiguities();
233
234
235 // get the container(s)
237
238 //this is a list<pair<time_t, DataLink<SCTUncompressedHitCollection> > >
239 TimedHitCollList hitCollList;
240 unsigned int numberOfSimHits(0);
241 if ( !(m_mergeSvc->retrieveSubEvtsData(m_inputObjectName.value(), hitCollList, numberOfSimHits).isSuccess()) && hitCollList.empty() ) {
242 ATH_MSG_ERROR ( "Could not fill TimedHitCollList" );
243 return StatusCode::FAILURE;
244 } else {
245 ATH_MSG_DEBUG ( hitCollList.size() << " SiHitCollections with key " << m_inputObjectName << " found" );
246 }
247
248 // Define Hit Collection
249 TimedHitCollection<SiHit> thpcsi(numberOfSimHits);
250
251 //now merge all collections into one
252 TimedHitCollList::iterator iColl(hitCollList.begin());
253 TimedHitCollList::iterator endColl(hitCollList.end() );
254
256 // loop on the hit collections
257 while ( iColl != endColl ) {
258 //decide if this event will be processed depending on HardScatterSplittingMode & bunchXing
260 if (m_HardScatterSplittingMode == 1 && m_HardScatterSplittingSkipper ) { ++iColl; continue; }
262 const SiHitCollection* p_collection(iColl->second);
263 thpcsi.insert(iColl->first, p_collection);
264 ATH_MSG_DEBUG ( "SiHitCollection found with " << p_collection->size() << " hits" );
265 ++iColl;
266 }
267
268 // Process the Hits straw by straw: get the iterator pairs for given straw
269 if(this->digitize(ctx, thpcsi).isFailure()) {
270 ATH_MSG_FATAL ( "digitize method failed!" );
271 return StatusCode::FAILURE;
272 }
273
274 if (createAndStoreRIOs(ctx).isFailure()) {
275 ATH_MSG_FATAL ( "createAndStoreRIOs() failed!" );
276 return StatusCode::FAILURE;
277 }
278 else {
279 ATH_MSG_DEBUG ( "createAndStoreRIOs() succeeded" );
280 }
281
282
283 if ((evtStore()->setConst(m_pixelClusterContainer)).isFailure()) {
284 ATH_MSG_ERROR("[ ---- ] Could not set Pixel ROT container ");
285 }
286 ATH_MSG_DEBUG ("Ambiguities map has " << m_ambiguitiesMap->size() << " elements" );
287 StatusCode sc = evtStore()->record(m_ambiguitiesMap,m_pixelClusterAmbiguitiesMapName,false);
288 if (sc.isFailure()){
289 ATH_MSG_FATAL ( "PixelClusterAmbiguitiesMap could not be recorded in StoreGate !" );
290 return StatusCode::FAILURE;
291 }else{
292 ATH_MSG_DEBUG ( "PixelClusterAmbiguitiesMap recorded in StoreGate" );
293 }
294
295
296
297
298 return StatusCode::SUCCESS;
299
300}
301
302
303
304StatusCode PixelFastDigitizationTool::mergeEvent(const EventContext& ctx)
305{
306
307 // --------------------------------------
308 // Pixel_Cluster container registration
309 unsigned int nwafer = m_pixel_ID->wafer_hash_max();
311 ATH_CHECK( wh.record (std::make_unique<InDet::PixelClusterContainer>(nwafer)) );
312 m_pixelClusterContainer = wh.ptr();
313 m_pixelClusterContainer->cleanup();
314
315 // symlink the Pixel Cluster Container
316 // FIXME: This results in a hard cast, which is undefined behavior as per C++.
318
319 // truth info
321
323 if((evtStore()->retrieve(m_pixPrdTruth, m_prdTruthNamePixel)).isFailure()){
324 ATH_MSG_FATAL("Could not retrieve collection " << m_prdTruthNamePixel);
325 return StatusCode::FAILURE;
326 }
327 }else{
328 if((evtStore()->record(m_pixPrdTruth, m_prdTruthNamePixel)).isFailure()){
329 ATH_MSG_FATAL("Could not record collection " << m_prdTruthNamePixel);
330 return StatusCode::FAILURE;
331 }
332 }
333
334 m_ambiguitiesMap =new PixelGangedClusterAmbiguities();
335
336 if (m_thpcsi != nullptr) {
337 if(digitize(ctx, *m_thpcsi).isFailure()) {
338 ATH_MSG_FATAL ( "Pixel digitize method failed!" );
339 return StatusCode::FAILURE;
340 }
341 }
342
343 delete m_thpcsi;
344 for(SiHitCollection* ptr : m_siHitCollList) delete ptr;
345 m_siHitCollList.clear();
346
347
348 if (createAndStoreRIOs(ctx).isFailure()) {
349 ATH_MSG_FATAL ( "createAndStoreRIOs() failed!" );
350 return StatusCode::FAILURE;
351 }
352 else {
353 ATH_MSG_DEBUG ( "createAndStoreRIOs() succeeded" );
354 }
355
356 if ((evtStore()->setConst(m_pixelClusterContainer)).isFailure()) {
357 ATH_MSG_ERROR("[ ---- ] Could not set Pixel ROT container ");
358 }
359 ATH_MSG_DEBUG ("Ambiguities map has " << m_ambiguitiesMap->size() << " elements" );
360 StatusCode sc = evtStore()->record(m_ambiguitiesMap,m_pixelClusterAmbiguitiesMapName,false);
361 if (sc.isFailure()){
362 ATH_MSG_FATAL ( "PixelClusterAmbiguitiesMap could not be recorded in StoreGate !" );
363 return StatusCode::FAILURE;
364 }else{
365 ATH_MSG_DEBUG ( "PixelClusterAmbiguitiesMap recorded in StoreGate" );
366 }
367
368
369
370 return StatusCode::SUCCESS;
371}
372
373
374StatusCode PixelFastDigitizationTool::digitize(const EventContext& ctx,
376{
377 // Set the RNG to use for this event.
378 ATHRNG::RNGWrapper* rngWrapper = m_rndmSvc->getEngine(this, m_randomEngineName);
379 const std::string rngName = name()+m_randomEngineName;
380 rngWrapper->setSeed( rngName, ctx );
381 CLHEP::HepRandomEngine *rndmEngine = rngWrapper->getEngine(ctx);
382
384 const InDetDD::SiDetectorElementCollection* elements(*pixelDetEleHandle);
385 if (not pixelDetEleHandle.isValid() or elements==nullptr) {
386 ATH_MSG_FATAL(m_pixelDetEleCollKey.fullKey() << " is not available.");
387 return StatusCode::FAILURE;
388 }
389
391
393 else { m_pixelClusterMap->clear(); }
394
396 const PixelChargeCalibCondData *calibData = *calibDataHandle;
398 std::vector<int> truthIdList;
399 std::vector<Identifier> detEl;
400
401 while (thpcsi.nextDetectorElement(i, e)) {
402
403 Pixel_detElement_RIO_map PixelDetElClusterMap;
404
405 truthIdList.clear();
406 detEl.clear();
407
408 while (i != e) {
409
410 const TimedHitPtr<SiHit>& hit(*i++);
411 // check the status of truth information for this SiHit
412 // some Truth information is cut for pile up events
413 const HepMcParticleLink currentLink = HepMcParticleLink::getRedirectedLink(hit->particleLink(), hit.eventId(), ctx); // This link should now correctly resolve to the TruthEvent McEventCollection in the main StoreGateSvc.
414 const int barrelEC = hit->getBarrelEndcap();
415 const int layerDisk = hit->getLayerDisk();
416 const int phiModule = hit->getPhiModule();
417 const int etaModule = hit->getEtaModule();
418
419 const Identifier moduleID = m_pixel_ID->wafer_id(barrelEC, layerDisk, phiModule, etaModule);
420 const IdentifierHash waferHash = m_pixel_ID->wafer_hash(moduleID);
421 const InDetDD::SiDetectorElement* hitSiDetElement = elements->getDetectorElement(waferHash);
422 if (!hitSiDetElement) {ATH_MSG_ERROR( " could not get detector element "); continue;}
423
424 if (!(hitSiDetElement->isPixel())) {continue;}
425
426
427
428 std::vector<HepMcParticleLink> hit_vector; //Store the hits in merged cluster
429
430 const int truthID = (currentLink.barcode() !=0 && currentLink.id() == 0) ? 3 : currentLink.id(); // FIXME barcode-based Patch for reading in legacy barcode-based EDM - if the barcode is non-zero, but the id is zero then we must be looking at a particle linked to suppressed pile-up truth - such SiHits would be linked to the third GenParticle in their GenEvents (if they were present)
431
432 const Identifier hitId = hitSiDetElement->identify(); // Isn't this is identical to moduleID?
433 //const IdentifierHash hitIdHash = hitSiDetElement->identifyHash();
434
435
436 bool isRep = false;
437
438 for (int j : truthIdList) {
439 for (auto & k : detEl) {
440 if ((truthID > 0) && (truthID == j) && (hitId == k)) {isRep = true; break;}
441 }
442 if (isRep) break;
443 }
444
445 if (isRep) continue;
446
447 truthIdList.push_back(truthID);
448 detEl.push_back(hitId);
449
450 HepGeom::Point3D<double> localStartPosition = hit->localStartPosition();
451 HepGeom::Point3D<double> localEndPosition = hit->localEndPosition();
452
453 localStartPosition = hitSiDetElement->hitLocalToLocal3D(localStartPosition);
454 localEndPosition = hitSiDetElement->hitLocalToLocal3D(localEndPosition);
455
456 int isEndcap = (barrelEC==0) ? 0:1;
457
458 double shiftX = isEndcap ? m_pixDiffShiftEndCX : m_pixDiffShiftBarrX;
459 double shiftY = isEndcap ? m_pixDiffShiftEndCY : m_pixDiffShiftBarrY;
460
461 // std::cout<<"Thr "<<m_ThrConverted<<std::endl;
462
463 //New function to tune the cluster size
464 Diffuse(localStartPosition, localEndPosition, shiftX, shiftY);
465
466 const Amg::Vector3D localDirection(localEndPosition.x()-localStartPosition.x(), localEndPosition.y()-localStartPosition.y(), localEndPosition.z()-localStartPosition.z());
467
468 Amg::Vector3D entryPoint(localStartPosition.x(),localStartPosition.y(),localStartPosition.z());
469 Amg::Vector3D exitPoint(localEndPosition.x(),localEndPosition.y(),localEndPosition.z());
470
471 const InDetDD::PixelModuleDesign* design(dynamic_cast<const InDetDD::PixelModuleDesign*>(&hitSiDetElement->design()));
472 if (not design){
473 ATH_MSG_FATAL("Failed to cast the hitSiDetElement::design pointer to a PixelModuleDesign*; aborting due to null pointer");
474 return StatusCode::FAILURE;
475 }
476 const Amg::Vector2D localEntry(localStartPosition.x(),localStartPosition.y());
477 const Amg::Vector2D localExit(localEndPosition.x(),localEndPosition.y());
478
479 Identifier entryId = hitSiDetElement->identifierOfPosition(localEntry);
480 Identifier exitId = hitSiDetElement->identifierOfPosition(localExit);
481
482 InDetDD::SiCellId entryCellId = hitSiDetElement->cellIdFromIdentifier(entryId);
483 InDetDD::SiCellId exitCellId = hitSiDetElement->cellIdFromIdentifier(exitId);
484
485 double halfthickness = hitSiDetElement->thickness()*0.5;
486
487 bool EntryValid(entryCellId.isValid());
488 bool ExitValid(exitCellId.isValid());
489
490 double pixMinimalPathCut= 1. / m_pixPathLengthTotConv;
491
492 Identifier diodeID = hitId;
493 unsigned int FE = m_pixelReadout->getFE(diodeID, moduleID);
494 InDetDD::PixelDiodeType type = m_pixelReadout->getDiodeType(diodeID);
495
496 double th0 = calibData->getThresholds(type, waferHash, FE).value/ m_ThrConverted;
497
498 // if (old_th != th0) std::cout<<"converted threshold "<<th0<<std::endl, old_th= th0;
499
500 //Avoid to store pixels with 0 ToT
501 //if (m_pixMinimalPathCut > pixMinimalPathCut) pixMinimalPathCut=m_pixMinimalPathCut;
502 //if (th0 > pixMinimalPathCut) ;
503 pixMinimalPathCut=th0;
504
505 if (!EntryValid || !ExitValid)
506 {
507 //If entry or exit aren't valid search for the valid entry/exit of the hit as Intersection with the module
508
509 if ( !EntryValid && !ExitValid) continue;
510
511 Amg::Vector3D Point = EntryValid ? entryPoint : exitPoint ;
512
513 Amg::Vector3D Intersection = CalculateIntersection(Point, localDirection, Amg::Vector2D(design->width() * 0.5,design->length() * 0.5),halfthickness);
514
515 if( Intersection == Amg::Vector3D(0.,0.,0.))
516 {
517 ATH_MSG_WARNING("ATTENTION THE INTERSECTION COORDINATE IS OUT OF THE MODULE");
518 continue;
519 }
520
521 const Amg::Vector2D Intersection_2d(Intersection.x(),Intersection.y());
522 Identifier Intersection_2dId = hitSiDetElement->identifierOfPosition(Intersection_2d);
523
524 InDetDD::SiCellId Intersection_2dCellId = hitSiDetElement->cellIdFromIdentifier(Intersection_2dId);
525
526
527 if(!Intersection_2dCellId.isValid()) continue;
528
529 if(EntryValid)
530 exitPoint = Intersection;
531 else
532 entryPoint = Intersection;
533
534
535 }
536
537
538
539 Trk::DigitizationModule * digitizationModule = buildDetectorModule(hitSiDetElement);
540 if(!digitizationModule){
541 ATH_MSG_FATAL( " could not get build detector module ");
542 return StatusCode::FAILURE;
543 }
544
545 // Getting the steps in the sensor
546 std::vector<Trk::DigitizationStep> digitizationSteps = m_digitizationStepper->cellSteps(*digitizationModule,entryPoint,exitPoint);
547
548
549
550 // the pixel positions and other needed stuff for the geometrical clustering
551 std::unique_ptr<InDet::PixelCluster> pixelCluster = nullptr;
552 Amg::Vector2D clusterPosition(0.,0.);
553
554 std::vector<Identifier> rdoList;
555 std::vector<int> totList;
556
557 const bool isGanged = false;
558 int lvl1a = 0;
559
560 double accumulatedPathLength=0.;
561
562 //ATTENTION index max e min da rdo + manager
563 int phiIndexMax = -999999;
564 int phiIndexMin = 1000000;
565 int etaIndexMax = -999999;
566 int etaIndexMin = 1000000;
567
568
569 for (auto& dStep : digitizationSteps){
570
571 double pathlength = dStep.stepLength;
572 // two options fro charge smearing: landau / gauss
573 if ( m_pixSmearPathLength > 0. ) {
574 // create the smdar parameter
575 double sPar = m_pixSmearLandau ?
576 m_pixSmearPathLength*CLHEP::RandLandau::shoot(rndmEngine) :
577 m_pixSmearPathLength*CLHEP::RandGaussZiggurat::shoot(rndmEngine);
578 pathlength *= (1.+sPar);
579 }
580
581
582 if (pathlength < pixMinimalPathCut) continue;
583
584 // position on the diode map
585 Trk::DigitizationCell cell(dStep.stepCell.first,dStep.stepCell.second);
586 Amg::Vector2D PositionOnModule = digitizationModule->segmentation().cellPosition(cell);
587 InDetDD::SiCellId diode = hitSiDetElement->cellIdOfPosition(PositionOnModule);
588
589
590 if (!diode.isValid())
591 continue;
592
593 Amg::Vector2D chargeCenterPosition = hitSiDetElement->rawLocalPositionOfCell(diode);
594
595 const Identifier rdoId = hitSiDetElement->identifierOfPosition(chargeCenterPosition);
596 clusterPosition += pathlength * chargeCenterPosition;
597
598 int currentEtaIndex = diode.etaIndex();
599 int currentPhiIndex = diode.phiIndex();
600 if(currentEtaIndex > etaIndexMax) etaIndexMax = currentEtaIndex;
601 if(currentEtaIndex < etaIndexMin) etaIndexMin = currentEtaIndex;
602 if(currentPhiIndex > phiIndexMax) phiIndexMax = currentPhiIndex;
603 if(currentPhiIndex < phiIndexMin) phiIndexMin = currentPhiIndex;
604
605
606 // record - positions, rdoList and totList
607 accumulatedPathLength += pathlength;
608 //Fail
609 rdoList.push_back(rdoId);
610 totList.push_back(int(pathlength*m_pixPathLengthTotConv));
611
612 }
613
614 delete digitizationModule;
615
616 // the col/row
617 int siDeltaPhiCut = phiIndexMax-phiIndexMin+1;
618 int siDeltaEtaCut = etaIndexMax-etaIndexMin+1;
619
620 int totalToT=std::accumulate(totList.begin(), totList.end(), 0);;
621
622 // bail out if 0 pixel or path length problem
623 if (rdoList.empty() || accumulatedPathLength < pixMinimalPathCut || totalToT == 0) {
624 if (totalToT == 0 && !rdoList.empty() ) ATH_MSG_WARNING("The total ToT of the cluster is 0, this should never happen");
625 continue;
626 }
627
628 // weight the cluster position
629 //accumulatedPathLength was checked in previous lines
630 //coverity[DIVIDE_BY_ZERO:FALSE]
631 clusterPosition *= 1./accumulatedPathLength;
632 Identifier clusterId = hitSiDetElement->identifierOfPosition(clusterPosition);
633
634
635 // merging clusters
636
637 bool merged = false;
638 if(m_mergeCluster){ // merge to the current cluster "near" cluster in the cluster map, in the current detector element
639
640 for(Pixel_detElement_RIO_map::iterator currentClusIter = PixelDetElClusterMap.begin(); currentClusIter != PixelDetElClusterMap.end();) {
641 //make a temporary to use within the loop and possibly erase - increment the main interator at the same time.
642 Pixel_detElement_RIO_map::iterator clusIter = currentClusIter++;
643 InDet::PixelCluster* currentCluster = clusIter->second;
644 const std::vector<Identifier> &currentRdoList = currentCluster->rdoList();
645 bool areNb = false;
646 for (auto rdoIter : rdoList) {
647 areNb = PixelFastDigitizationTool::areNeighbours(currentRdoList, rdoIter, hitSiDetElement,*m_pixel_ID);
648 if (areNb) { break; }
649 }
650 if (areNb) {
651 const std::vector<int> &currentTotList = currentCluster->totList();
652 rdoList.insert(rdoList.end(), currentRdoList.begin(), currentRdoList.end() );
653 totList.insert(totList.end(), currentTotList.begin(), currentTotList.end() );
654 Amg::Vector2D currentClusterPosition(currentCluster->localPosition());
655 float c1 = (float)currentRdoList.size();
656 float c2 = (float)rdoList.size();
657 clusterPosition = (clusterPosition*c2 + currentClusterPosition*c1)/((c1 + c2));
658 clusterId = hitSiDetElement->identifierOfPosition(clusterPosition);
659 merged = true;
660 PixelDetElClusterMap.erase(clusIter);
661
662 //Store HepMcParticleLink connected to the cluster removed from the collection
663 std::pair<PRD_MultiTruthCollection::iterator,PRD_MultiTruthCollection::iterator> saved_hit = m_pixPrdTruth->equal_range(currentCluster->identify());
664 for (PRD_MultiTruthCollection::iterator this_hit = saved_hit.first; this_hit != saved_hit.second; ++this_hit)
665 {
666 hit_vector.push_back(this_hit->second);
667 }
668 //Delete all the occurency of the currentCluster from the multi map
669 if (saved_hit.first != saved_hit.second) m_pixPrdTruth->erase(currentCluster->identify());
670 delete currentCluster;
671 //break; //commenting out this break statement allows for multiple existing clusters to be merged.
672 }
673 }
674 }
675
676 bool not_valid = false;
677 for (auto & entry : rdoList) {
678 if (!(entry.is_valid())) { not_valid = true; break;}
679 }
680
681 if (not_valid) continue;
682
683 if(merged) {
684 //Hacks for merged clusters
685 for (auto rdoIter : rdoList) {
686 const InDetDD::SiCellId& chargeCellId = hitSiDetElement->cellIdFromIdentifier(rdoIter);
687 // phi/ eta index
688 int chargePhiIndex = chargeCellId.phiIndex();
689 int chargeEtaIndex = chargeCellId.etaIndex();
690 // set max min
691 phiIndexMin = chargePhiIndex < phiIndexMin ? chargePhiIndex : phiIndexMin;
692 phiIndexMax = chargePhiIndex > phiIndexMax ? chargePhiIndex : phiIndexMax;
693 etaIndexMin = chargeEtaIndex < etaIndexMin ? chargeEtaIndex : etaIndexMin;
694 etaIndexMax = chargeEtaIndex > etaIndexMax ? chargeEtaIndex : etaIndexMax;
695 }
696 siDeltaPhiCut = (phiIndexMax-phiIndexMin)+1;
697 siDeltaEtaCut = (etaIndexMax-etaIndexMin)+1;
698 }
699
700 // ---------------------------------------------------------------------------------------------
701 // PART 2: Cluster && ROT creation
702
703
704 //ATTENTION
705 // // correct shift implied by the scaling of the Lorentz angle
706 // double newshift = 0.5*thickness*tanLorAng;
707 // double corr = ( shift - newshift );
708 // 2a) Cluster creation ------------------------------------
710
711 // from InDetReadoutGeometry: width from eta
712 const auto* pixModDesign =
713 dynamic_cast<const InDetDD::PixelModuleDesign*>(
714 &hitSiDetElement->design());
715 if (!pixModDesign) {
716 return StatusCode::FAILURE;
717 }
718 double etaWidth =
719 pixModDesign->widthFromColumnRange(etaIndexMin, etaIndexMax);
720 // from InDetReadoutGeometry : width from phi
721 double phiWidth =
722 pixModDesign->widthFromRowRange(phiIndexMin, phiIndexMax);
723
724 InDet::SiWidth siWidth(Amg::Vector2D(siDeltaPhiCut, siDeltaEtaCut),
725 Amg::Vector2D(phiWidth, etaWidth));
726
727 // use the cluster maker from the offline software
728 pixelCluster =
729 std::make_unique<PixelCluster>(m_clusterMaker->pixelCluster(
730 clusterId, clusterPosition, std::move(rdoList),
731 lvl1a, std::move(totList), siWidth,
732 hitSiDetElement, isGanged, m_pixErrorStrategy, *m_pixel_ID,
733 false, 0.0, 0.0, calibData, *offlineCalibData, ctx));
734 if (isGanged) {
735 pixelCluster->setGangedPixel(isGanged);
736 }
737 } else {
739 "[ cluster - pix ] No pixels errors provided, but configured to "
740 "use them.");
742 " -> No pixels cluster will be created.");
743 continue;
744 }
745
746 if (!(pixelCluster->identify().is_valid())) {
747 pixelCluster.reset();
748 continue;
749 }
750
751 if (!(m_pixel_ID->is_pixel(pixelCluster->identify()))) {
752 pixelCluster.reset();
753 continue;
754 }
755
756 const auto it =
757 PixelDetElClusterMap.insert(Pixel_detElement_RIO_map::value_type(
758 waferHash, pixelCluster.release()));
759 const PixelCluster* insertedCluster = it->second;
760
761 if (currentLink.isValid()) {
763 m_pixPrdTruth->insert(
764 std::make_pair(insertedCluster->identify(), currentLink));
765 ATH_MSG_DEBUG("Truth map filled with cluster"
766 << insertedCluster
767 << " and link = " << currentLink);
768 }
769 } else {
771 "Particle link NOT valid!! Truth map NOT filled with cluster"
772 << insertedCluster << " and link = " << currentLink);
773 }
774
775 // Add all hit that was connected to the cluster
776 for (const HepMcParticleLink& p : hit_vector) {
777
778 m_pixPrdTruth->insert(std::make_pair(insertedCluster->identify(), p ));
779 }
780
781 hit_vector.clear();
782 } // end hit while
783
784
785 (void) m_pixelClusterMap->insert(PixelDetElClusterMap.begin(), PixelDetElClusterMap.end());
786
787
788 } // end nextDetectorElement while
789
790
791 return StatusCode::SUCCESS;
792}
793
794StatusCode PixelFastDigitizationTool::createAndStoreRIOs(const EventContext& ctx)
795{
797 const InDetDD::SiDetectorElementCollection* elements(*pixelDetEleHandle);
798 if (not pixelDetEleHandle.isValid() or elements==nullptr) {
799 ATH_MSG_FATAL(m_pixelDetEleCollKey.fullKey() << " is not available.");
800 return StatusCode::FAILURE;
801 }
802
803 Pixel_detElement_RIO_map::iterator i = m_pixelClusterMap->begin();
804 Pixel_detElement_RIO_map::iterator e = m_pixelClusterMap->end();
805
806 //InDet::PixelClusterCollection* clusterCollection = nullptr;
807 IdentifierHash waferHash;
808
809 for (; i != e; i = m_pixelClusterMap->upper_bound(i->first)){
810 std::pair <Pixel_detElement_RIO_map::iterator, Pixel_detElement_RIO_map::iterator> range;
811 range = m_pixelClusterMap->equal_range(i->first);
812 Pixel_detElement_RIO_map::iterator firstDetElem;
813 firstDetElem = range.first;
814 waferHash = firstDetElem->first;
815 const InDetDD::SiDetectorElement* detElement = elements->getDetectorElement(waferHash);
816 auto clusterCollection = std::make_unique<InDet::PixelClusterCollection>(waferHash);
817 clusterCollection->setIdentifier(detElement->identify());
818 for ( Pixel_detElement_RIO_map::iterator iter = range.first; iter != range.second; ++iter){
819 InDet::PixelCluster* pixelCluster = (*iter).second;
820 pixelCluster->setHashAndIndex(clusterCollection->identifyHash(),clusterCollection->size());
821 clusterCollection->push_back(pixelCluster);
822 }
823 if (!clusterCollection->empty()) {
824 ATH_MSG_DEBUG ( "Filling ambiguities map" );
825 m_gangedAmbiguitiesFinder->execute(clusterCollection.get(),*m_ambiguitiesMap);
826 ATH_MSG_DEBUG ( "Ambiguities map: " << m_ambiguitiesMap->size() << " elements" );
827 if ((m_pixelClusterContainer->addCollection(clusterCollection.release(), waferHash)).isFailure()){
828 ATH_MSG_WARNING( "Could not add collection to Identifyable container !" );
829 }
830 }
831 } // end for
832
833 m_pixelClusterMap->clear();
834
835 return StatusCode::SUCCESS;
836}
837// copied from PixelClusteringToolBase
839(const std::vector<Identifier>& group,
840 const Identifier& rdoID,
841 const InDetDD::SiDetectorElement* /*element*/,
842 const PixelID& pixelID)
843{
844 // note: in the PixelClusteringToolBase, m_splitClusters is a variable; here
845 // splitClusters was explicitly set to zero, acceptDiagonalClusters = 1
846 // so much of the original code is redundant and only one path through the code
847 // is possible.
848
849 std::vector<Identifier>::const_iterator groupBegin = group.begin();
850 std::vector<Identifier>::const_iterator groupEnd = group.end();
851
852 int row2 = pixelID.phi_index(rdoID);
853 int col2 = pixelID.eta_index(rdoID);
854
855 int rowmax = row2;
856 bool match=false;
857 while (groupBegin!=groupEnd)
858 {
859 Identifier id = *groupBegin;
860 int row1 = pixelID.phi_index(id);
861 int col1 = pixelID.eta_index(id);
862 if(row1 > rowmax) rowmax = row1;
863 int deltarow = abs(row2-row1);
864 int deltacol = abs(col2-col1);
865
866 // a side in common
867 if(deltacol+deltarow < 2) match = true;
868 //condition "if (acceptDiagonalClusters !=0") is redundant
869 if(deltacol == 1 && deltarow == 1) match = true;
870
871 ++groupBegin;
872 }
873
874
875 return match;
876}
877
879
880 const InDetDD::PixelModuleDesign* design(dynamic_cast<const InDetDD::PixelModuleDesign*>(&hitSiDetElement->design()));
881
882 if (!design) {
883 ATH_MSG_DEBUG ( "Could not get design"<< design) ;
884 return nullptr;
885 }
886
887 //Read from the SiDetectorElement information to build the digitization module
888 const double halfThickness = hitSiDetElement->thickness() * 0.5;
889 const double halfWidth = design->width() * 0.5;
890 const double halfLength = design->length() * 0.5;
891
892 int binsX = design->rows();
893 int binsY = design->columns();
894 double numberOfChip = design->numberOfCircuits();
895
896 InDetDD::SiCellId cell(0,binsY/2);
897 float LongPitch =design->parameters(cell).width().xEta();
898 //std::cout<<"numberOfChip "<<numberOfChip<<" LongPitch "<<LongPitch<<std::endl;
899
900 ATH_MSG_VERBOSE("Retrieving infos: halfThickness = " << halfThickness << " --- halfWidth = " << halfWidth << " --- halfLength = " << halfLength );
901 ATH_MSG_VERBOSE("Retrieving infos: binsX = " << binsX << " --- binsY = " << binsY << " --- numberOfChip = " << numberOfChip);
902
903 int readoutDirection = design->readoutSide();
904
905 const bool useLorentzAngle{true};
906 const IdentifierHash detElHash = hitSiDetElement->identifyHash();
907 float lorentzAngle = useLorentzAngle ? hitSiDetElement->hitDepthDirection()*hitSiDetElement->hitPhiDirection()*std::atan(m_lorentzAngleTool->getTanLorentzAngle(detElHash, Gaudi::Hive::currentContext())) : 0.;
908
909 // added for degugging
910
911 // std::cout << "barrel_ec = " << m_detID->barrel_ec(hitSiDetElement->identify())
912 // << " -- layer_disk = " << m_detID->layer_disk(hitSiDetElement->identify())
913 // << " -- eta_module = " << m_detID->eta_module(hitSiDetElement->identify())
914 // << " -- lorentzAngle = " << lorentzAngle
915 // << " -- lorentzCorrection = " << shift
916 // << " -- readoutDirection = " << readoutDirection << std::endl;
917 // std::cout << "element->hitDepthDirection() = " << hitSiDetElement->hitDepthDirection()
918 // << " -- element->hitPhiDirection() = " << hitSiDetElement->hitPhiDirection() << std::endl;
919
920 // rectangle bounds
921 auto rectangleBounds = std::make_shared<const Trk::RectangleBounds>(halfWidth,halfLength);
922 ATH_MSG_VERBOSE("Initialized rectangle Bounds");
923 // create the segmentation
924 std::shared_ptr<const Trk::Segmentation> rectangleSegmentation(new Trk::RectangularSegmentation(std::move(rectangleBounds),(size_t)binsX,LongPitch,(size_t)binsY, numberOfChip));
925 // build the module
926 ATH_MSG_VERBOSE("Initialized rectangleSegmentation");
927 Trk::DigitizationModule * digitizationModule = new Trk::DigitizationModule(std::move(rectangleSegmentation),
928 halfThickness,
929 readoutDirection,
930 lorentzAngle);
931 ATH_MSG_VERBOSE("Building Rectangle Segmentation with dimensions (halfX, halfY) = (" << halfWidth << ", " << halfLength << ")");
932
933 // success return
934 return digitizationModule;
935}
936
937
939{
940 Amg::Vector3D Intersection(0.,0.,0.);
941
942 //Using parameter definition of a line in 3d z=z_point + direction_z t
943 std::vector<double> parameters;
944 parameters.push_back((PlaneBorder.x() - Point.x())/Direction.x());
945 parameters.push_back((-PlaneBorder.x() - Point.x())/Direction.x());
946 parameters.push_back((PlaneBorder.y() - Point.y())/Direction.y());
947 parameters.push_back((-PlaneBorder.y() - Point.y())/Direction.y());
948
949 for(double parameter: parameters)
950 {
951 double z = Point.z() + Direction.z() * parameter;
952 if( std::abs(z) > halfthickness )
953 continue;
954
955
956 double x = Point.x() + Direction.x() * parameter;
957 double y = Point.y() + Direction.y() * parameter;
958
959 if(std::abs(x) > PlaneBorder.x() || std::abs(y) > PlaneBorder.y())
960 continue;
961
962
963 Intersection = Amg::Vector3D(x,y,z);
964 break;
965
966 }
967
968 return Intersection;
969}
970
971void PixelFastDigitizationTool::Diffuse(HepGeom::Point3D<double>& localEntry, HepGeom::Point3D<double>& localExit, double shiftX, double shiftY) {
972
973 double localEntryX = localEntry.x();
974 double localEntryY = localEntry.y();
975 double localExitX = localExit.x();
976 double localExitY = localExit.y();
977
978 double signX = localExitX>localEntryX ? 1:-1 ;
979 double signY = localExitY>localEntryY ? 1:-1 ;
980
981 localEntryX += shiftX*signX*(-1);
982 localExitX += shiftX*signX;
983 localEntryY += shiftY*signY*(-1);
984 localExitY += shiftY*signY;
985
986 localEntry.setX(localEntryX);
987 localEntry.setY(localEntryY);
988 localExit.setX(localExitX);
989 localExit.setY(localExitY);
990
991}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_VERBOSE(x,...)
#define ATH_MSG_FATAL(x,...)
Structs for holding charge calibration parameterisation and data.
std::vector< xAOD::EventInfo::SubEvent >::const_iterator SubEventIterator
Definition IPileUpTool.h:22
bool hit(const Container &ids, int pdgId)
static Double_t sc
This is an Identifier helper class for the Pixel subdetector.
AtlasHitsVector< SiHit > SiHitCollection
#define y
#define x
#define z
A wrapper class for event-slot-local random engines.
Definition RNGWrapper.h:56
void setSeed(const std::string &algName, const EventContext &ctx)
Set the random seed using a string (e.g.
Definition RNGWrapper.h:154
CLHEP::HepRandomEngine * getEngine(const EventContext &ctx) const
Retrieve the random engine corresponding to the provided EventContext.
Definition RNGWrapper.h:108
size_type size() const
This is a "hash" representation of an Identifier.
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
int columns() const
Number of cell columns per module:
virtual double length() const
Method to calculate length of a module.
int rows() const
Number of cell rows per module:
double widthFromColumnRange(const int colMin, const int colMax) const
Method to calculate eta width from a column range.
int numberOfCircuits() const
Total number of circuits:
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 the SiDetectorElement objects to be put in the detector store.
const SiDetectorElement * getDetectorElement(const IdentifierHash &hash) const
Class to hold geometrical description of a silicon detector element.
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):
const SiLocalPosition & width() const
width of the diodes:
double xEta() const
position along eta direction:
HepGeom::Point3D< double > hitLocalToLocal3D(const HepGeom::Point3D< double > &hitPosition) const
Same as previuos method but 3D.
SiCellId cellIdOfPosition(const Amg::Vector2D &localPos) const
As in previous method but returns SiCellId.
double hitPhiDirection() const
See previous method.
virtual IdentifierHash identifyHash() const override final
identifier hash (inline)
virtual Identifier identify() const override final
identifier of this detector element (inline)
double hitDepthDirection() const
Directions of hit depth,phi,eta axes relative to reconstruction local position axes (LocalPosition).
Identifier identifierOfPosition(const Amg::Vector2D &localPos) const
Full identifier of the cell for a given position: assumes a raw local position (no Lorentz shift).
Amg::Vector2D rawLocalPositionOfCell(const SiCellId &cellId) const
Returns position (center) of cell.
A PRD is mapped onto all contributing particles.
Gaudi::Property< int > m_vetoPileUpTruthLinks
PileUpToolBase(const std::string &type, const std::string &name, const IInterface *parent)
PixelChargeCalib::Thresholds getThresholds(InDetDD::PixelDiodeType type, unsigned int moduleHash, unsigned int FE) const
SG::ReadCondHandleKey< InDetDD::SiDetectorElementCollection > m_pixelDetEleCollKey
const PixelID * m_pixel_ID
Handle to the ID helper.
StatusCode mergeEvent(const EventContext &ctx)
StatusCode processAllSubEvents(const EventContext &ctx)
StringProperty m_randomEngineName
Name of the random number stream.
BooleanProperty m_pixUseClusterMaker
use the pixel cluster maker or not
SG::ReadCondHandleKey< PixelCalib::PixelOfflineCalibData > m_offlineCalibDataKey
StatusCode createAndStoreRIOs(const EventContext &ctx)
PublicToolHandle< Trk::IModuleStepper > m_digitizationStepper
static void Diffuse(HepGeom::Point3D< double > &localEntry, HepGeom::Point3D< double > &localExit, double shiftX, double shiftY)
ServiceHandle< InDetDD::IPixelReadoutManager > m_pixelReadout
DoubleProperty m_pixPathLengthTotConv
from path length to tot
DoubleProperty m_pixSmearPathLength
the 2.
BooleanProperty m_pixModuleDistortion
simulationn of module bowing
InDet::PixelGangedClusterAmbiguities * m_ambiguitiesMap
static bool areNeighbours(const std::vector< Identifier > &group, const Identifier &rdoID, const InDetDD::SiDetectorElement *, const PixelID &pixelID)
bool m_mergeCluster
enable the merging of neighbour Pixel clusters >
StatusCode digitize(const EventContext &ctx, TimedHitCollection< SiHit > &thpcsi)
PublicToolHandle< InDet::PixelGangedAmbiguitiesFinder > m_gangedAmbiguitiesFinder
SG::ReadCondHandleKey< PixelChargeCalibCondData > m_chargeDataKey
BooleanProperty m_pixSmearLandau
if true : landau else: gauss
std::vector< SiHitCollection * > m_siHitCollList
name of the sub event hit collections.
StatusCode processBunchXing(int bunchXing, SubEventIterator bSubEvents, SubEventIterator eSubEvents)
ServiceHandle< IAthRNGSvc > m_rndmSvc
Random number service.
StatusCode prepareEvent(const EventContext &ctx, unsigned int)
TimedHitCollection< SiHit > * m_thpcsi
IntegerProperty m_HardScatterSplittingMode
Process all SiHit or just those from signal or background events.
SG::ReadCondHandleKey< PixelDistortionData > m_distortionKey
PRD_MultiTruthCollection * m_pixPrdTruth
the PRD truth map for Pixel measurements
ToolHandle< ISiLorentzAngleTool > m_lorentzAngleTool
static Amg::Vector3D CalculateIntersection(const Amg::Vector3D &Point, const Amg::Vector3D &Direction, Amg::Vector2D PlaneBorder, double halfthickness)
Pixel_detElement_RIO_map * m_pixelClusterMap
std::multimap< IdentifierHash, InDet::PixelCluster * > Pixel_detElement_RIO_map
Trk::DigitizationModule * buildDetectorModule(const InDetDD::SiDetectorElement *) const
InDet::PixelClusterContainer * m_pixelClusterContainer
the PixelClusterContainer
ServiceHandle< PileUpMergeSvc > m_mergeSvc
PileUp Merge service.
PublicToolHandle< InDet::ClusterMakerTool > m_clusterMaker
ToolHandle to ClusterMaker.
IntegerProperty m_pixErrorStrategy
error strategy for the ClusterMaker
This is an Identifier helper class for the Pixel subdetector.
Definition PixelID.h:69
int eta_index(const Identifier &id) const
Definition PixelID.h:640
int phi_index(const Identifier &id) const
Definition PixelID.h:634
Property holding a SG store/key/clid from which a WriteHandle is made.
bool nextDetectorElement(const_iterator &b, const_iterator &e)
sets an iterator range with the hits of current detector element returns a bool when done
TimedVector::const_iterator const_iterator
void insert(const PileUpTimeEventIndex &timeEventIndex, const AtlasHitsVector< HIT > *inputCollection)
a smart pointer to a hit that also provides access to the extended timing info of the host event.
Definition TimedHitPtr.h:18
Class that holds the surfaces for a planar digitization detector module.
const Segmentation & segmentation() const
return the segmenation
const Amg::Vector2D & localPosition() const
return the local position reference
Identifier identify() const
return the identifier
const std::vector< Identifier > & rdoList() const
return the List of rdo identifiers (pointers)
virtual const Amg::Vector2D cellPosition(const DigitizationCell &dCell) const =0
calculate the cell Position from the Id
bool contains(const std::string &s, const std::string &regx)
does a string contain the substring
Definition hcg.cxx:116
bool match(std::string s1, std::string s2)
match the individual directories of two strings
Definition hcg.cxx:359
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
bool ignoreTruthLink(const T &p, bool vetoPileUp)
Helper function for SDO creation in PileUpTools.
Message Stream Member.
Primary Vertex Finder.
std::pair< size_t, size_t > DigitizationCell
std::list< value_t > type
type of the collection of timed data object
a struct encapsulating the identifier of a pile-up event
index_type index() const
the index of the component event in PileUpEventInfo
PileUpType type() const
the pileup type - minbias, cavern, beam halo, signal?
time_type time() const
bunch xing time in ns