ATLAS Offline Software
Loading...
Searching...
No Matches
StripDigitizationTool.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
7// Mother Package includes
10
11// EDM includes
14
15// Hit class includes
16#include "InDetSimEvent/SiHit.h"
17#include "Identifier/Identifier.h"
19
20// Det Descr includes
23
24// Data Handle
27
28// Random Number Generation
30#include "CLHEP/Random/RandomEngine.h"
31
32// C++ Standard Library
33#include <cmath>
34#include <memory>
35#include <sstream>
36#include <algorithm>
37
38// Barcodes at the HepMC level are int
39
41
42namespace ITk
43{
44
46 const std::string& name,
47 const IInterface* parent) :
48 base_class(type, name, parent) {
50}
51
53
54// ----------------------------------------------------------------------
55// Initialize method:
56// ----------------------------------------------------------------------
58 ATH_MSG_DEBUG("StripDigitizationTool::initialize()");
59
60 // +++ Init the services
62
63 // +++ Get the Surface Charges Generator tool
65
66 // +++ Get the Front End tool
68
69 // +++ Initialise for disabled cells from the random disabled cells tool
70 // +++ Default off, since disabled cells taken form configuration in
71 // reconstruction stage
74 ATH_MSG_INFO("Use of Random disabled cells");
75 } else {
77 }
78
79 // check the input object name
80 if (m_hitsContainerKey.key().empty()) {
81 ATH_MSG_FATAL("Property InputObjectName not set !");
82 return StatusCode::FAILURE;
83 }
85 ATH_MSG_DEBUG("Input objects in container : '" << m_inputObjectName << "'");
86
87 // Initialize ReadHandleKey
88 ATH_CHECK(m_hitsContainerKey.initialize(true));
89
90 // +++ Initialize WriteHandleKey
91 ATH_CHECK(m_rdoContainerKey.initialize());
92 ATH_CHECK(m_simDataCollMapKey.initialize());
93
94 // Initialize ReadCondHandleKey
95 ATH_CHECK(m_stripDetEleCollKey.initialize());
96
97 ATH_MSG_DEBUG("SiDigitizationTool::initialize() complete");
98
99 return StatusCode::SUCCESS;
100}
101
102namespace {
103 class SiDigitizationSurfaceChargeInserter : public ISiSurfaceChargesInserter {
104 public:
105 SiDigitizationSurfaceChargeInserter(const InDetDD::SiDetectorElement* sielement,
106 SiChargedDiodeCollection* chargedDiodes)
107 : m_sielement(sielement),
108 m_chargedDiodes(chargedDiodes) {
109 }
110
111 void operator () (const SiSurfaceCharge& scharge);
112 private:
113 const InDetDD::SiDetectorElement* m_sielement;
114 SiChargedDiodeCollection* m_chargedDiodes;
115 };
116
117
118 void SiDigitizationSurfaceChargeInserter::operator () (const SiSurfaceCharge& scharge) {
119 // get the diode in which this charge is
120 SiCellId diode{m_sielement->cellIdOfPosition(scharge.position())};
121
122 if (diode.isValid()) {
123 // add this charge to the collection (or merge in existing charged diode)
124 m_chargedDiodes->add(diode, scharge.charge());
125 }
126 }
127
128 class MultiElementChargeInserter : public ISiSurfaceChargesInserter {
129 public:
130 MultiElementChargeInserter (SiChargedDiodeCollectionMap & chargedDiodesVec,
131 const InDetDD::SCT_ModuleSideDesign * mum)
132 : m_chargedDiodesVecForInsert(chargedDiodesVec),
133 m_mum(mum) {}
134
135 void operator () (const SiSurfaceCharge &scharge);
136 private:
137 SiChargedDiodeCollectionMap & m_chargedDiodesVecForInsert;
138 const InDetDD::SCT_ModuleSideDesign * m_mum;
139 };
140
141 void MultiElementChargeInserter::operator () (const SiSurfaceCharge &scharge) {
142 // get the diode in which this charge is
143 SiCellId motherDiode = m_mum->cellIdOfPosition(scharge.position());
144
145 if (motherDiode.isValid()) {
146 auto [strip, row] = m_mum->getStripRow(motherDiode);
147 //now use this row
148
149 if (m_chargedDiodesVecForInsert.at(row)) {
150 SiCellId diode = m_chargedDiodesVecForInsert.at(row)->element()->cellIdOfPosition(scharge.position());
151
152 if (diode.isValid()) {
153 // add this charge to the collection (or merge in existing charged diode)
154 m_chargedDiodesVecForInsert.at(row)->add(diode, scharge.charge());
155 }
156 }
157 }
158 }
159
160} // anonymous namespace
161
162
163// ----------------------------------------------------------------------
164// Initialise the surface charge generator Tool
165// ----------------------------------------------------------------------
168
169 if (m_cosmicsRun and m_tfix > -998) {
171 ATH_MSG_INFO("Use of FixedTime = " << m_tfix << " in cosmics");
172 }
173
174 ATH_MSG_DEBUG("Retrieved and initialised tool " << m_sct_SurfaceChargesGenerator);
175
176 return StatusCode::SUCCESS;
177}
178
179// ----------------------------------------------------------------------
180// Initialise the Front End electronics Tool
181// ----------------------------------------------------------------------
183 ATH_CHECK(m_sct_FrontEnd.retrieve());
184
186
187 ATH_MSG_DEBUG("Retrieved and initialised tool " << m_sct_FrontEnd);
188 return StatusCode::SUCCESS;
189}
190
191// ----------------------------------------------------------------------
192// Initialize the different services
193// ----------------------------------------------------------------------
195 // Get SCT ID helper for hash function and Store them using methods from the
196 // SiDigitization.
197 ATH_CHECK(detStore()->retrieve(m_detID, "SCT_ID"));
198
200 ATH_CHECK(m_mergeSvc.retrieve());
201 }
202 ATH_CHECK(m_rndmSvc.retrieve());
203
204 return StatusCode::SUCCESS;
205}
206
207// ----------------------------------------------------------------------
208// Initialize the disabled cells for cosmics or CTB cases
209// ----------------------------------------------------------------------
211 // +++ Retrieve the StripRandomDisabledCellGenerator
213
215
216 ATH_MSG_INFO("Retrieved the StripRandomDisabledCellGenerator tool:" << m_sct_RandomDisabledCellGenerator);
217 return StatusCode::SUCCESS;
218}
219
220StatusCode StripDigitizationTool::processAllSubEvents(const EventContext& ctx) {
221 if (prepareEvent(ctx, 0).isFailure()) {
222 return StatusCode::FAILURE;
223 }
224 // Set the RNG to use for this event.
225 ATHRNG::RNGWrapper* rngWrapper = m_rndmSvc->getEngine(this);
226 rngWrapper->setSeed( name(), ctx );
227 CLHEP::HepRandomEngine *rndmEngine = rngWrapper->getEngine(ctx);
228
229 ATH_MSG_VERBOSE("Begin digitizeAllHits");
230 if (m_enableHits and (not getNextEvent(ctx).isFailure())) {
232 } else {
233 ATH_MSG_DEBUG("no hits found in event!");
234 }
235 ATH_MSG_DEBUG("Digitized Elements with Hits");
236
237 // loop over elements without hits
238 if (not m_onlyHitElements) {
240 ATH_MSG_DEBUG("Digitized Elements without Hits");
241 }
242
243 m_thpcsi.reset(nullptr);
244
245 ATH_MSG_VERBOSE("Digitize success!");
246 return StatusCode::SUCCESS;
247}
248
249// ======================================================================
250// prepareEvent
251// ======================================================================
252StatusCode StripDigitizationTool::prepareEvent(const EventContext& ctx, unsigned int /*index*/) {
253 ATH_MSG_VERBOSE("StripDigitizationTool::prepareEvent()");
254 // Create the IdentifiableContainer to contain the digit collections Create
255 // a new RDO container
257 ATH_CHECK(m_rdoContainer.record(std::make_unique<SCT_RDO_Container>(m_detID->wafer_hash_max())));
258
259 // Create a map for the SDO and register it into StoreGate
261 ATH_CHECK(m_simDataCollMap.record(std::make_unique<InDetSimDataCollection>()));
262
263 m_processedElements.clear();
264 m_processedElements.resize(m_detID->wafer_hash_max(), false);
265
266 m_thpcsi = std::make_unique<TimedHitCollection<SiHit>>();
268 return StatusCode::SUCCESS;
269}
270
271// =========================================================================
272// mergeEvent
273// =========================================================================
274StatusCode StripDigitizationTool::mergeEvent(const EventContext& ctx) {
275 ATH_MSG_VERBOSE("StripDigitizationTool::mergeEvent()");
276
277 // Set the RNG to use for this event.
278 ATHRNG::RNGWrapper* rngWrapper = m_rndmSvc->getEngine(this);
279 rngWrapper->setSeed( name(), ctx );
280 CLHEP::HepRandomEngine *rndmEngine = rngWrapper->getEngine(ctx);
281
282 if (m_enableHits) {
284 }
285
286 if (not m_onlyHitElements) {
288 }
289
290 m_hitCollPtrs.clear();
291
292 m_thpcsi.reset(nullptr);
293
294 ATH_MSG_DEBUG("Digitize success!");
295 return StatusCode::SUCCESS;
296}
297
298void StripDigitizationTool::digitizeAllHits(const EventContext& ctx, SG::WriteHandle<SCT_RDO_Container>* rdoContainer, SG::WriteHandle<InDetSimDataCollection>* simDataCollMap, std::vector<bool>* processedElements, TimedHitCollection<SiHit>* thpcsi, CLHEP::HepRandomEngine * rndmEngine) {
300 //
301 // In order to process all element rather than just those with hits we
302 // create a vector to keep track of which elements have been processed.
303 // NB. an element is an sct module
304 //
306 ATH_MSG_DEBUG("Digitizing hits");
307 int hitcount{0}; // First, elements with hits.
308
309 //map with key representing the row of strips
310 SiChargedDiodeCollectionMap chargedDiodesMap;
311
312 while (digitizeElement(ctx, chargedDiodesMap, thpcsi, rndmEngine)) {
313
314 ATH_MSG_DEBUG("Digitizing "<<chargedDiodesMap.size()<<" Element(s)");
315
316 hitcount++; // Hitcount will be a number in the hit collection minus
317 // number of hits in missing mods
318
319 for (SiChargedDiodeCollectionIterator & chargedDiodesIter : chargedDiodesMap){
320
321 SiChargedDiodeCollection & chargedDiodes = *chargedDiodesIter.second;
322 ATH_MSG_DEBUG("Hit collection ID=" << m_detID->show_to_string(chargedDiodes.identify()));
323
324 ATH_MSG_DEBUG("in digitize elements with hits: ec - layer - eta - phi "
325 << m_detID->barrel_ec(chargedDiodes.identify()) << " - "
326 << m_detID->layer_disk(chargedDiodes.identify()) << " - "
327 << m_detID->eta_module(chargedDiodes.identify()) << " - "
328 << m_detID->phi_module(chargedDiodes.identify()) << " - "
329 << " processing hit number " << hitcount);
330
331 // Have a flag to check if the module is present or not
332 // Generally assume it is:
333
334 IdentifierHash idHash{chargedDiodes.identifyHash()};
335
336 assert(idHash < processedElements->size());
337 (*processedElements)[idHash] = true;
338
339 // create and store RDO and SDO
340
341 if (not chargedDiodes.empty()) {
342 StatusCode sc{createAndStoreRDO(&chargedDiodes, rdoContainer)};
343 if (sc.isSuccess()) { // error msg is given inside
344 // createAndStoreRDO()
345 addSDO(&chargedDiodes, simDataCollMap);
346 }
347 }
348
349 chargedDiodes.clear();
350 }
351 }
352 ATH_MSG_DEBUG("hits processed");
353}
354
355// digitize elements without hits
356void StripDigitizationTool::digitizeNonHits(const EventContext& ctx, SG::WriteHandle<SCT_RDO_Container>* rdoContainer, SG::WriteHandle<InDetSimDataCollection>* simDataCollMap, const std::vector<bool>* processedElements, CLHEP::HepRandomEngine * rndmEngine) const {
357 // Get StripDetectorElementCollection
359 const InDetDD::SiDetectorElementCollection* elements{stripDetEle.retrieve()};
360 if (elements==nullptr) {
361 ATH_MSG_FATAL(m_stripDetEleCollKey.fullKey() << " could not be retrieved");
362 return;
363 }
364
365 ATH_MSG_DEBUG("processing elements without hits");
366 SiChargedDiodeCollection chargedDiodes;
367
368 for (unsigned int i{0}; i < processedElements->size(); i++) {
369 if (not (*processedElements)[i]) {
370 IdentifierHash idHash{i};
371 if (not idHash.is_valid()) {
372 ATH_MSG_ERROR("SCT Detector element id hash is invalid = " << i);
373 }
374
375 const InDetDD::SiDetectorElement* element{elements->getDetectorElement(idHash)};
376 if (element) {
377 ATH_MSG_DEBUG("In digitize of untouched elements: layer - phi - eta "
378 << m_detID->layer_disk(element->identify()) << " - "
379 << m_detID->phi_module(element->identify()) << " - "
380 << m_detID->eta_module(element->identify()) << " - "
381 << "size: " << processedElements->size());
382
383 chargedDiodes.setDetectorElement(element);
384 ATH_MSG_DEBUG("calling applyProcessorTools() for NON hits");
385 applyProcessorTools(&chargedDiodes, rndmEngine);
386
387 // Create and store RDO and SDO
388 // Don't create empty ones.
389 if (not chargedDiodes.empty()) {
390 StatusCode sc{createAndStoreRDO(&chargedDiodes, rdoContainer)};
391 if (sc.isSuccess()) {// error msg is given inside
392 // createAndStoreRDO()
393 addSDO(&chargedDiodes, simDataCollMap);
394 }
395 }
396
397 chargedDiodes.clear();
398 }
399 }
400 }
401
402 }
403
404bool StripDigitizationTool::digitizeElement(const EventContext& ctx, SiChargedDiodeCollectionMap& chargedDiodesMap, TimedHitCollection<SiHit>*& thpcsi, CLHEP::HepRandomEngine * rndmEngine) {
405 if (nullptr == thpcsi) {
406 ATH_MSG_ERROR("thpcsi should not be nullptr!");
407
408 return false;
409 }
410
411 chargedDiodesMap.clear();
412
413 // get the iterator pairs for this DetEl
414
416 if (!thpcsi->nextDetectorElement(i, e)) { // no more hits
417 return false;
418 }
419
420 // create the identifier for the collection:
421 ATH_MSG_DEBUG("create ID for the hit collection");
422 const TimedHitPtr<SiHit>& firstHit{*i};
423 int barrel{firstHit->getBarrelEndcap()};
424 Identifier id{m_detID->wafer_id(barrel,
425 firstHit->getLayerDisk(),
426 firstHit->getPhiModule(),
427 firstHit->getEtaModule(),
428 firstHit->getSide())};
429 IdentifierHash waferHash{m_detID->wafer_hash(id)};
430
431 // Get StripDetectorElementCollection
433 const InDetDD::SiDetectorElementCollection* elements(stripDetEle.retrieve());
434 if (elements==nullptr) {
435 ATH_MSG_FATAL(m_stripDetEleCollKey.fullKey() << " could not be retrieved");
436 return false;
437 }
438
439 // get the det element from the manager
440 const InDetDD::SiDetectorElement* sielement{elements->getDetectorElement(waferHash)};
441
442 if (sielement == nullptr) {
443 ATH_MSG_DEBUG("Barrel=" << barrel << " layer=" << firstHit->getLayerDisk() << " Eta=" << firstHit->getEtaModule() << " Phi=" << firstHit->getPhiModule() << " Side=" << firstHit->getSide());
444 ATH_MSG_ERROR("detector manager could not find element with id = " << id);
445 return false;
446 }
447
448
449 //Now we have to get the sub-elements if they exist!
450 const InDetDD::SCT_ModuleSideDesign * thisDesign = static_cast<const InDetDD::SCT_ModuleSideDesign*>(&sielement->design());
451
452 const InDetDD::SCT_ModuleSideDesign * motherDesign = thisDesign->getMother();
453
454 //should become un-ordederd map
455 std::map<int, const InDetDD::SCT_ModuleSideDesign *> children;
456
457 if(motherDesign){
458 //see above
459 children = motherDesign->getChildren();
460 }
461 else {
462 //if no mother/children relationship, just use what you got intially
463 children.emplace(0,thisDesign);
464 }
465
466
467 for (const std::pair <const int, const InDetDD::SCT_ModuleSideDesign *> &subDesign : children){
468
469 //Create the charged diodes collection.
470 //We are incrementing the eta index with the number of the
471 //sub-element (child) in the returned set.
472 //This "fills in" the gaps in the SiHitIdentifiers with the
473 //number of the strip row, such that the SCT_ID is continuous
474 //once we split the single simulated sensor into multiple SiDetectorElements
475 Identifier id_child{m_detID->wafer_id(firstHit->getBarrelEndcap(), firstHit->getLayerDisk(),
476 firstHit->getPhiModule(), firstHit->getEtaModule()+subDesign.first,
477 firstHit->getSide())};
478
479 IdentifierHash hash_child = m_detID->wafer_hash(id_child);
480
481 const InDetDD::SiDetectorElement* sielement_child{elements->getDetectorElement(hash_child)};
482
483 if(sielement_child){
484
485 std::unique_ptr<SiChargedDiodeCollection> thisChargedDiode(std::make_unique<SiChargedDiodeCollection>());
486 int i_index = subDesign.first;
487 thisChargedDiode->setDetectorElement(sielement_child);
488 chargedDiodesMap.insert({i_index,std::move(thisChargedDiode)});
489
490 }
491
492 else ATH_MSG_ERROR("detector manager could not find element with id = "<<id_child<<" Barrel=" << firstHit->getBarrelEndcap() << " layer=" <<
493 firstHit->getLayerDisk() << " Eta=" << firstHit->getEtaModule()+subDesign.first <<" Phi=" << firstHit->getPhiModule()
494 << " Side=" <<firstHit->getSide());
495 }
496
497
498 // Loop over the hits and created charged diodes:
499 while (i != e) {
500 const TimedHitPtr<SiHit>& phit{*i++};
501
502 // skip hits which are more than 10us away
503 if (std::abs(phit->meanTime()) < 10000. * CLHEP::ns) {
504 ATH_MSG_DEBUG("HASH = " << m_detID->wafer_hash(m_detID->wafer_id(phit->getBarrelEndcap(),
505 phit->getLayerDisk(),
506 phit->getPhiModule(),
507 phit->getEtaModule(),
508 phit->getSide())));
509 ATH_MSG_DEBUG("calling process() for all methods");
510
511 if(!motherDesign) {
512 //no row splitting
513 //should only be one diode collection here, so just use it
514 if(chargedDiodesMap.size()>1) {
515 ATH_MSG_WARNING("More DiodesCollections("<<chargedDiodesMap.size()<<") than expected (1). Please check your configuration!");
516 }
517
518 SiDigitizationSurfaceChargeInserter inserter(sielement,chargedDiodesMap[0].get());
519 m_sct_SurfaceChargesGenerator->process(sielement, phit, inserter, rndmEngine, ctx);
520 }
521
522 else{
523 //with row splitting
524 MultiElementChargeInserter inserter(chargedDiodesMap,motherDesign);
525 m_sct_SurfaceChargesGenerator->process(sielement, phit,inserter, rndmEngine, ctx);
526 }
527
528 ATH_MSG_DEBUG("charges filled!");
529 }
530 }
531
532 //Now loop over set of diodes and apply processors
533 for (SiChargedDiodeCollectionIterator & theDiode : chargedDiodesMap){
534 if(theDiode.second) applyProcessorTools(theDiode.second.get(), rndmEngine); // !< Use of the new AlgTool surface
535 }
536 // charges generator class
537 return true;
538}
539
540// -----------------------------------------------------------------------------
541// Applies processors to the current detector element for the current element:
542// -----------------------------------------------------------------------------
543void StripDigitizationTool::applyProcessorTools(SiChargedDiodeCollection* chargedDiodes, CLHEP::HepRandomEngine * rndmEngine) const {
544 ATH_MSG_DEBUG("applyProcessorTools()");
545 int processorNumber{0};
546
548 proc->process(*chargedDiodes, rndmEngine);
549
550 processorNumber++;
551 ATH_MSG_DEBUG("Applied processor # " << processorNumber);
552 }
553}
554
556 SubEventIterator bSubEvents,
557 SubEventIterator eSubEvents) {
558 ATH_MSG_VERBOSE("StripDigitizationTool::processBunchXing() " << bunchXing);
559 // decide if this event will be processed depending on
560 // HardScatterSplittingMode & bunchXing
563 return StatusCode::SUCCESS;
564 }
566 return StatusCode::SUCCESS;
567 }
570 }
571
573 TimedHitCollList hitCollList;
574
575 if ((not (m_mergeSvc->retrieveSubSetEvtData(m_inputObjectName, hitCollList, bunchXing,
576 bSubEvents, eSubEvents).isSuccess())) and
577 hitCollList.empty()) {
578 ATH_MSG_ERROR("Could not fill TimedHitCollList");
579 return StatusCode::FAILURE;
580 } else {
581 ATH_MSG_VERBOSE(hitCollList.size() << " SiHitCollections with key " <<
582 m_inputObjectName << " found");
583 }
584
585 TimedHitCollList::iterator endColl{hitCollList.end()};
586 for (TimedHitCollList::iterator iColl{hitCollList.begin()}; iColl != endColl; ++iColl) {
587 std::unique_ptr<SiHitCollection> hitCollPtr{std::make_unique<SiHitCollection>(*iColl->second)};
588 PileUpTimeEventIndex timeIndex{iColl->first};
589 ATH_MSG_DEBUG("SiHitCollection found with " << hitCollPtr->size() <<
590 " hits");
591 ATH_MSG_VERBOSE("time index info. time: " << timeIndex.time()
592 << " index: " << timeIndex.index()
593 << " type: " << timeIndex.type());
594 m_thpcsi->insert(timeIndex, hitCollPtr.get());
595 m_hitCollPtrs.push_back(std::move(hitCollPtr));
596 }
597
598 return StatusCode::SUCCESS;
599
600}
601
602// =========================================================================
603// property handlers
604// =========================================================================
605void StripDigitizationTool::SetupRdoOutputType(Gaudi::Details::PropertyBase &) {
606}
607
608// Does nothing, but required by Gaudi
609
610// ----------------------------------------------------------------------
611// Digitisation of non hit elements
612// ----------------------------------------------------------------------
613
615{
616public:
618 m_detID{detID}, m_msgNo{-1} {
619 }
620
621 std::string msg(const InDetDD::SiDetectorElement* element) {
622 std::ostringstream ost;
623
624 ost << "Digitized unprocessed elements: layer - phi - eta - side "
625 << m_detID->layer_disk(element->identify()) << " - "
626 << m_detID->phi_module(element->identify()) << " - "
627 << m_detID->eta_module(element->identify()) << " - "
628 << m_detID->side(element->identify()) << " - "
629 << " unprocessed hit number: " << ++m_msgNo << '\n';
630
631 return ost.str();
632 }
633
634private:
637};
638
639// ----------------------------------------------------------------------//
640// createAndStoreRDO //
641// ----------------------------------------------------------------------//
643
644 // Create the RDO collection
645 std::unique_ptr<SCT_RDO_Collection> RDOColl{createRDO(chDiodeCollection)};
646 const IdentifierHash identifyHash{RDOColl->identifyHash()};
647
648 // Add it to storegate
649 Identifier id_coll{RDOColl->identify()};
650 int barrelec{m_detID->barrel_ec(id_coll)};
651
652 if ((not m_barrelonly) or (std::abs(barrelec) <= 1)) {
653 if ((*rdoContainer)->addCollection(RDOColl.release(), identifyHash).isFailure()) {
654 ATH_MSG_FATAL("SCT RDO collection could not be added to container!");
655 return StatusCode::FAILURE;
656 }
657 } else {
658 ATH_MSG_VERBOSE("Not saving SCT_RDO_Collection: " << m_detID->show_to_string(RDOColl->identify()) << " to container!");
659 }
660 return StatusCode::SUCCESS;
661} // StripDigitization::createAndStoreRDO()
662
663// ----------------------------------------------------------------------
664// createRDO
665// ----------------------------------------------------------------------
666std::unique_ptr<SCT_RDO_Collection> StripDigitizationTool::createRDO(SiChargedDiodeCollection* collection) const {
667
668 // create a new SCT RDO collection
669 std::unique_ptr<SCT_RDO_Collection> p_rdocoll;
670
671 // need the DE identifier
672 const Identifier id_de{collection->identify()};
673 IdentifierHash idHash_de{collection->identifyHash()};
674 try {
675 p_rdocoll = std::make_unique<SCT_RDO_Collection>(idHash_de);
676 } catch (const std::bad_alloc&) {
677 ATH_MSG_FATAL("Could not create a new SCT_RDORawDataCollection !");
678 }
679 p_rdocoll->setIdentifier(id_de);
680
681 SiChargedDiodeIterator i_chargedDiode{collection->begin()};
682 SiChargedDiodeIterator i_chargedDiode_end{collection->end()};
683 // Choice of producing SCT1_RawData or SCT3_RawData
684 if (m_WriteSCT1_RawData.value()) {
685 for (; i_chargedDiode != i_chargedDiode_end; ++i_chargedDiode) {
686 unsigned int flagmask{static_cast<unsigned int>((*i_chargedDiode).second.flag() & 0xFE)};
687
688 if (!flagmask) { // now check it wasn't masked:
689 // create new SCT RDO, using method 1 for mask:
690 // GroupSize=1: need readout id, make use of
691 // SiTrackerDetDescr
692 InDetDD::SiReadoutCellId roCell{(*i_chargedDiode).second.getReadoutCell()};
693 int strip{roCell.strip()};
694 if (strip > 0xffff) { // In upgrade layouts strip can be bigger
695 // than 4000
696 ATH_MSG_FATAL("Strip number too big for SCT1 raw data format.");
697 }
698 const Identifier id_readout{m_detID->strip_id(collection->identify(), strip)};
699
700 // build word, masks taken from SiTrackerEvent/SCTRawData.cxx
701 const unsigned int strip_rdo{static_cast<unsigned int>((strip & 0xFFFF) << 16)};
702
703 // user can define what GroupSize is, here 1: TC. Incorrect,
704 // GroupSize >= 1
705 int size{SiHelper::GetStripNum((*i_chargedDiode).second)};
706 unsigned int size_rdo{static_cast<unsigned int>(size & 0xFFFF)};
707
708 // TC. Need to check if there are disabled strips in the cluster
709 int cluscounter{0};
710 if (size > 1) {
711 SiChargedDiodeIterator it2{i_chargedDiode};
712 ++it2;
713 for (; it2 != i_chargedDiode_end; ++it2) {
714 ++cluscounter;
715 if (cluscounter >= size) {
716 break;
717 }
718 if (it2->second.flag() & 0xDE) {
719 int tmp{cluscounter};
720 while ((it2 != i_chargedDiode_end) and (cluscounter < size - 1) and (it2->second.flag() & 0xDE)) {
721 ++it2;
722 ++cluscounter;
723 }
724 if ((it2 != collection->end()) and !(it2->second.flag() & 0xDE)) {
725 SiHelper::ClusterUsed(it2->second, false);
726 SiHelper::SetStripNum(it2->second, size - cluscounter, &msg());
727 }
728 // groupSize=tmp;
729 size_rdo = tmp & 0xFFFF;
730 break;
731 }
732 }
733 }
734 unsigned int StripWord{strip_rdo | size_rdo};
735 SCT1_RawData* p_rdo{new SCT1_RawData(id_readout, StripWord)};
736 if (p_rdo) {
737 p_rdocoll->push_back(p_rdo);
738 }
739 }
740 }
741 } else {
742 // Under the current scheme time bin and ERRORS are hard-coded to
743 // default values.
744 int ERRORS{0};
745 static const std::vector<int> dummyvector;
746 for (; i_chargedDiode != i_chargedDiode_end; ++i_chargedDiode) {
747 unsigned int flagmask{static_cast<unsigned int>((*i_chargedDiode).second.flag() & 0xFE)};
748
749 if (!flagmask) { // Check it wasn't masked
750 int tbin{SiHelper::GetTimeBin((*i_chargedDiode).second)};
751 // create new SCT RDO
752 InDetDD::SiReadoutCellId roCell{(*i_chargedDiode).second.getReadoutCell()};
753 int strip{roCell.strip()};
754 const InDetDD::SCT_ModuleSideDesign& sctDesign{static_cast<const InDetDD::SCT_ModuleSideDesign&>(collection->design())};
755 int row2D{sctDesign.row(strip)};
756 Identifier id_readout;
757 if (row2D < 0) { // SCT sensors
758 id_readout = m_detID->strip_id(collection->identify(), strip);
759 } else { // Upgrade sensors
760 int strip2D{sctDesign.strip(strip)};
761 id_readout = m_detID->strip_id(collection->identify(), row2D, strip2D);
762 }
763
764 // build word (compatible with
765 // StripRawDataByteStreamCnv/src/StripRodDecoder.cxx)
766 int size{SiHelper::GetStripNum((*i_chargedDiode).second)};
767 int groupSize{size};
768
769 // TC. Need to check if there are disabled strips in the cluster
770 int cluscounter{0};
771 if (size > 1) {
772 SiChargedDiode* diode{i_chargedDiode->second.nextInCluster()};
773 while (diode) {//check if there is a further strip in the cluster
774 ++cluscounter;
775 if (cluscounter >= size) {
776 ATH_MSG_WARNING("Cluster size reached while neighbouring strips still defined.");
777 break;
778 }
779 if (diode->flag() & 0xDE) {//see if it is disabled/below threshold/disconnected/etc (0xDE corresponds to BT_SET | DISABLED_SET | BADTOT_SET | DISCONNECTED_SET | MASKOFF_SET)
780 int tmp{cluscounter};
781 while ((cluscounter < size - 1) and (diode->flag() & 0xDE)) { //check its not the end and still disabled
782 diode = diode->nextInCluster();
783 cluscounter++;
784 }
785 if (diode and !(diode->flag() & 0xDE)) {
786 SiHelper::ClusterUsed(*diode, false);
787 SiHelper::SetStripNum(*diode, size - cluscounter, &msg());
788 }
789 groupSize = tmp;
790 break;
791 }
792 diode = diode->nextInCluster();
793 }
794 }
795
796 int stripIn11bits{strip & 0x7ff};
797 if (stripIn11bits != strip) {
798 ATH_MSG_DEBUG("Strip number " << strip << " doesn't fit into 11 bits - will be truncated");
799 }
800
801 unsigned int StripWord{static_cast<unsigned int>(groupSize | (stripIn11bits << 11) | (tbin << 22) | (ERRORS << 25))};
802 SCT3_RawData *p_rdo{new SCT3_RawData(id_readout, StripWord, &dummyvector)};
803 if (p_rdo) {
804 p_rdocoll->push_back(p_rdo);
805 }
806 }
807 }
808 }
809 return p_rdocoll;
810} // StripDigitization::createRDO()
811
812// ------------------------------------------------------------
813// Get next event and extract collection of hit collections:
814// ------------------------------------------------------------
815StatusCode StripDigitizationTool::getNextEvent(const EventContext& ctx) {
816 ATH_MSG_DEBUG("StripDigitizationTool::getNextEvent");
817 // get the container(s)
819 // this is a list<pair<time_t, DataLink<SiHitCollection> >
820
821 // In case of single hits container just load the collection using read handles
824 if (!hitCollection.isValid()) {
825 ATH_MSG_ERROR("Could not get SCT SiHitCollection container " << hitCollection.name() << " from store " << hitCollection.store());
826 return StatusCode::FAILURE;
827 }
828
829 // create a new hits collection
830 m_thpcsi = std::make_unique<TimedHitCollection<SiHit>>(1);
831 m_thpcsi->insert(0, hitCollection.cptr());
832 ATH_MSG_DEBUG("SiHitCollection found with " << hitCollection->size() << " hits");
833
834 return StatusCode::SUCCESS;
835 }
836
837 TimedHitCollList hitCollList;
838 unsigned int numberOfSiHits{0};
839 if (not (m_mergeSvc->retrieveSubEvtsData(m_inputObjectName, hitCollList, numberOfSiHits).isSuccess()) and hitCollList.empty()) {
840 ATH_MSG_ERROR("Could not fill TimedHitCollList");
841 return StatusCode::FAILURE;
842 } else {
843 ATH_MSG_DEBUG(hitCollList.size() << " SiHitCollections with key " << m_inputObjectName << " found");
844 }
845 // create a new hits collection
846 m_thpcsi = std::make_unique<TimedHitCollection<SiHit>>(numberOfSiHits);
847 // now merge all collections into one
848 TimedHitCollList::iterator endColl{hitCollList.end()};
849 for (TimedHitCollList::iterator iColl{hitCollList.begin()}; iColl != endColl; ++iColl) {
850 // decide if this event will be processed depending on
851 // HardScatterSplittingMode & bunchXing
854 continue;
855 }
857 continue;
858 }
861 }
862 const SiHitCollection* p_collection{iColl->second};
863 m_thpcsi->insert(iColl->first, p_collection);
864 ATH_MSG_DEBUG("SiTrackerHitCollection found with " << p_collection->size() << " hits"); // loop on the hit collections
865 }
866 return StatusCode::SUCCESS;
867}
868
869// -----------------------------------------------------------------------------------------------
870// Convert a SiTotalCharge to a InDetSimData, and store it.
871// -----------------------------------------------------------------------------------------------
873
874 using list_t = SiTotalCharge::list_t;
875 std::vector<InDetSimData::Deposit> deposits;
876 deposits.reserve(5); // no idea what a reasonable number for this would be
877 // with pileup
878 // loop over the charged diodes
879 SiChargedDiodeIterator EndOfDiodeCollection{collection->end()};
880 for (SiChargedDiodeIterator i_chargedDiode{collection->begin()}; i_chargedDiode != EndOfDiodeCollection; ++i_chargedDiode) {
881 deposits.clear();
882 const list_t& charges{(*i_chargedDiode).second.totalCharge().chargeComposition()};
883
884 bool real_particle_hit{false};
885 // loop over the list
886 list_t::const_iterator EndOfChargeList{charges.end()};
887 for (list_t::const_iterator i_ListOfCharges{charges.begin()}; i_ListOfCharges != EndOfChargeList; ++i_ListOfCharges) {
888 const HepMcParticleLink& trkLink{i_ListOfCharges->particleLink()};
889 if (HepMC::ignoreTruthLink(trkLink, m_vetoPileUpTruthLinks)) {
890 continue;
891 }
892 if (not real_particle_hit) {
893 // Types of SiCharges expected from SCT
894 // Noise: barcode==0 and
895 // processType()==SiCharge::noise
896 // Delta Rays: barcode==0 and
897 // processType()==SiCharge::track
898 // Pile Up Tracks With No Truth: barcode!=0 and
899 // processType()==SiCharge::cut_track
900 // Tracks With Truth: barcode!=0 and
901 // processType()==SiCharge::track
902 if (!HepMC::no_truth_link(trkLink) && i_ListOfCharges->processType() == SiCharge::track) {
903 real_particle_hit = true;
904 }
905 }
906 // check if this track number has been already used.
907 const auto theDeposit = std::ranges::find_if(
908 deposits.rbegin(), deposits.rend(),
909 [&trkLink](const InDetSimData::Deposit& deposit) {
910 return deposit.first == trkLink;
911 });
912
913 // if the charge has already hit the Diode add it to the deposit
914 if (theDeposit != deposits.rend()) {
915 theDeposit->second += i_ListOfCharges->charge();
916 } else { // create a new deposit
917 deposits.emplace_back(trkLink, i_ListOfCharges->charge());
918 }
919 }
920
921 // add the simdata object to the map:
922 if (real_particle_hit or m_createNoiseSDO) {
923 InDetDD::SiReadoutCellId roCell{(*i_chargedDiode).second.getReadoutCell()};
924 int strip{roCell.strip()};
925 const InDetDD::SCT_ModuleSideDesign& sctDesign{dynamic_cast<const InDetDD::SCT_ModuleSideDesign&>(collection->design())};
926
927 int row2D{sctDesign.row(strip)};
928 Identifier id_readout;
929 if (row2D < 0) { // SCT sensors and new-style ITkStrip sensors
930 id_readout = m_detID->strip_id(collection->identify(),strip);
931 } else { // old-style (21.9) ITkStrip sensors
932 int strip2D{sctDesign.strip(strip)};
933 id_readout = m_detID->strip_id(collection->identify(),row2D, strip2D);
934 }
935 (*simDataCollMap)->try_emplace(id_readout, std::move(deposits), (*i_chargedDiode).second.flag());
936 }
937 }
938}
939
940} // namespace ITk
#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)
std::vector< xAOD::EventInfo::SubEvent >::const_iterator SubEventIterator
Definition IPileUpTool.h:22
static Double_t sc
This is an Identifier helper class for the SCT subdetector.
void operator()(T1)
SiChargedDiodeMap::iterator SiChargedDiodeIterator
AtlasHitsVector< SiHit > SiHitCollection
Handle class for reading from StoreGate.
size_t size() const
Number of registered mappings.
Digitize the ITkStrip using an implementation of IPileUpTool.
std::unordered_map< int, std::unique_ptr< SiChargedDiodeCollection > > SiChargedDiodeCollectionMap
std::pair< const int, std::unique_ptr< SiChargedDiodeCollection > > SiChargedDiodeCollectionIterator
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
std::string msg(const InDetDD::SiDetectorElement *element)
SG::WriteHandleKey< SCT_RDO_Container > m_rdoContainerKey
virtual StatusCode prepareEvent(const EventContext &ctx, unsigned int) override final
Called before processing physics events.
SG::WriteHandle< InDetSimDataCollection > m_simDataCollMap
SDO Map handle.
bool digitizeElement(const EventContext &ctx, SiChargedDiodeCollectionMap &chargedDiodes, TimedHitCollection< SiHit > *&thpcsi, CLHEP::HepRandomEngine *rndmEngine)
ToolHandle< ISurfaceChargesGenerator > m_sct_SurfaceChargesGenerator
ToolHandle< IFrontEnd > m_sct_FrontEnd
std::unique_ptr< TimedHitCollection< SiHit > > m_thpcsi
StripDigitizationTool(const std::string &type, const std::string &name, const IInterface *parent)
StatusCode initFrontEndTool()
Initialize the StripFrontEnd AlgTool.
const SCT_ID * m_detID
Handle to the ID helper.
void SetupRdoOutputType(Gaudi::Details::PropertyBase &)
Called when m_WriteSCT1_RawData is altered.
StatusCode getNextEvent(const EventContext &ctx)
std::vector< std::unique_ptr< SiHitCollection > > m_hitCollPtrs
StatusCode initServices()
initialize the required services
void applyProcessorTools(SiChargedDiodeCollection *chargedDiodes, CLHEP::HepRandomEngine *rndmEngine) const
ToolHandle< IRandomDisabledCellGenerator > m_sct_RandomDisabledCellGenerator
StatusCode createAndStoreRDO(SiChargedDiodeCollection *chDiodeCollection, SG::WriteHandle< SCT_RDO_Container > *rdoContainer) const
RDO and SDO methods.
void storeTool(ISiChargedDiodesProcessorTool *p_processor)
virtual StatusCode processAllSubEvents(const EventContext &ctx) override final
std::unique_ptr< SCT_RDO_Collection > createRDO(SiChargedDiodeCollection *collection) const
Create RDOs from the SiChargedDiodeCollection for the current wafer.
ServiceHandle< PileUpMergeSvc > m_mergeSvc
SG::WriteHandle< SCT_RDO_Container > m_rdoContainer
RDO container handle.
virtual StatusCode mergeEvent(const EventContext &ctx) override final
ServiceHandle< IAthRNGSvc > m_rndmSvc
Random number service.
StatusCode initSurfaceChargesGeneratorTool()
Initialize the StripSurfaceChargesGenerator AlgTool.
std::vector< bool > m_processedElements
vector of processed elements - set by digitizeHits() *‍/
virtual StatusCode initialize() override final
std::vector< ISiChargedDiodesProcessorTool * > m_diodeCollectionTools
SG::ReadCondHandleKey< InDetDD::SiDetectorElementCollection > m_stripDetEleCollKey
void digitizeAllHits(const EventContext &ctx, SG::WriteHandle< SCT_RDO_Container > *rdoContainer, SG::WriteHandle< InDetSimDataCollection > *simDataCollMap, std::vector< bool > *processedElements, TimedHitCollection< SiHit > *thpcsi, CLHEP::HepRandomEngine *rndmEngine)
digitize all hits
SG::ReadHandleKey< SiHitCollection > m_hitsContainerKey
SG::WriteHandleKey< InDetSimDataCollection > m_simDataCollMapKey
void addSDO(SiChargedDiodeCollection *collection, SG::WriteHandle< InDetSimDataCollection > *simDataCollMap) const
virtual StatusCode processBunchXing(int bunchXing, SubEventIterator bSubEvents, SubEventIterator eSubEvents) override final
void digitizeNonHits(const EventContext &ctx, SG::WriteHandle< SCT_RDO_Container > *rdoContainer, SG::WriteHandle< InDetSimDataCollection > *simDataCollMap, const std::vector< bool > *processedElements, CLHEP::HepRandomEngine *rndmEngine) const
digitize SCT without hits
StatusCode initDisabledCells()
Initialize the StripRandomDisabledCellGenerator AlgTool.
This is a "hash" representation of an Identifier.
constexpr bool is_valid() const
virtual SiCellId cellIdOfPosition(const SiLocalPosition &localPos) const =0
position -> id
Base class for the SCT module side design, extended by the Forward and Barrel module design.
virtual std::pair< int, int > getStripRow(SiCellId id) const
Get the strip and row number of the cell.
virtual int strip(int stripId1Dim) const
const std::map< int, const SCT_ModuleSideDesign * > & getChildren() const
const SCT_ModuleSideDesign * getMother() const
virtual int row(int stripId1Dim) const
Identifier for the strip or pixel cell.
Definition SiCellId.h:29
int strip() const
Get strip number. Equivalent to phiIndex().
Definition SiCellId.h:131
bool isValid() const
Test if its in a valid state.
Definition SiCellId.h:136
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 const SiDetectorDesign & design() const override final
access to the local description (inline):
Identifier for the strip or pixel readout cell.
SiCellId cellIdOfPosition(const Amg::Vector2D &localPos) const
As in previous method but returns SiCellId.
virtual Identifier identify() const override final
identifier of this detector element (inline)
std::pair< HepMcParticleLink, float > Deposit
This is an Identifier helper class for the SCT subdetector.
Definition SCT_ID.h:68
const_pointer_type retrieve()
virtual bool isValid() override final
Can the handle be successfully dereferenced?
const_pointer_type cptr()
Dereference the pointer.
std::string store() const
Return the name of the store holding the object we are proxying.
const std::string & name() const
Return the StoreGate ID for the referenced object.
virtual Identifier identify() const override final
void setDetectorElement(const InDetDD::SolidStateDetectorElementBase *SiElement)
SiChargedDiodeIterator begin()
const InDetDD::DetectorDesign & design() const
virtual IdentifierHash identifyHash() const override final
void add(const InDetDD::SiCellId &diode, const T &charge)
int flag() const
SiChargedDiode * nextInCluster()
static void ClusterUsed(SiChargedDiode &chDiode, bool flag)
Definition SiHelper.h:121
static void SetStripNum(SiChargedDiode &chDiode, int nstrip, MsgStream *log=nullptr)
Definition SiHelper.h:139
static int GetStripNum(SiChargedDiode &chDiode)
Definition SiHelper.h:199
static int GetTimeBin(SiChargedDiode &chDiode)
Definition SiHelper.h:203
const SiCharge & charge() const
const InDetDD::SiLocalPosition & position() const
std::vector< SiCharge > list_t
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
a smart pointer to a hit that also provides access to the extended timing info of the host event.
Definition TimedHitPtr.h:18
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition hcg.cxx:132
bool no_truth_link(const T &p)
Method to establish if a if the object is linked to something which was never saved to the HepMC Trut...
bool ignoreTruthLink(const T &p, bool vetoPileUp)
Helper function for SDO creation in PileUpTools.
row
Appending html table to final .html summary file.
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
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
MsgStream & msg
Definition testRead.cxx:32