ATLAS Offline Software
Loading...
Searching...
No Matches
SCT_DigitizationTool.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
39
41 const std::string& name,
42 const IInterface* parent) :
43 base_class(type, name, parent) {
45}
46
48
49// ----------------------------------------------------------------------
50// Initialize method:
51// ----------------------------------------------------------------------
53 ATH_MSG_DEBUG("SCT_DigitizationTool::initialize()");
54
55 // +++ Init the services
57
58 // +++ Get the Surface Charges Generator tool
60
61 // +++ Get the Front End tool
63
64 // +++ Initialise for disabled cells from the random disabled cells tool
65 // +++ Default off, since disabled cells taken form configuration in
66 // reconstruction stage
69 ATH_MSG_INFO("Use of Random disabled cells");
70 } else {
72 }
73
74 // check the input object name
75 if (m_hitsContainerKey.key().empty()) {
76 ATH_MSG_FATAL("Property InputObjectName not set !");
77 return StatusCode::FAILURE;
78 }
80 ATH_MSG_DEBUG("Input objects in container : '" << m_inputObjectName << "'");
81
82 // Initialize ReadHandleKey
83 ATH_CHECK(m_hitsContainerKey.initialize(true));
84
85 // +++ Initialize WriteHandleKey
86 ATH_CHECK(m_rdoContainerKey.initialize());
87 ATH_CHECK(m_simDataCollMapKey.initialize());
88
89 // Initialize ReadCondHandleKey
90 ATH_CHECK(m_SCTDetEleCollKey.initialize());
91
92 ATH_MSG_DEBUG("SiDigitizationTool::initialize() complete");
93
94 return StatusCode::SUCCESS;
95}
96
97namespace {
98 class SiDigitizationSurfaceChargeInserter
100 {
101 public:
102 SiDigitizationSurfaceChargeInserter(const InDetDD::SiDetectorElement* sielement,
103 SiChargedDiodeCollection* chargedDiodes)
104 : m_sielement(sielement),
105 m_chargedDiodes(chargedDiodes) {
106 }
107
108 void operator () (const SiSurfaceCharge& scharge);
109 private:
110 const InDetDD::SiDetectorElement* m_sielement;
111 SiChargedDiodeCollection* m_chargedDiodes;
112 };
113
114
115 void SiDigitizationSurfaceChargeInserter::operator ()
116 (const SiSurfaceCharge& scharge) {
117 // get the diode in which this charge is
118 SiCellId diode{m_sielement->cellIdOfPosition(scharge.position())};
119
120 if (diode.isValid()) {
121 // add this charge to the collection (or merge in existing charged diode)
122 m_chargedDiodes->add(diode, scharge.charge());
123 }
124 }
125} // anonymous namespace
126
127// ----------------------------------------------------------------------
128// Initialise the surface charge generator Tool
129// ----------------------------------------------------------------------
132
133 if (m_cosmicsRun and m_tfix > -998) {
135 ATH_MSG_INFO("Use of FixedTime = " << m_tfix << " in cosmics");
136 }
137
138 ATH_MSG_DEBUG("Retrieved and initialised tool " << m_sct_SurfaceChargesGenerator);
139
140 return StatusCode::SUCCESS;
141}
142
143// ----------------------------------------------------------------------
144// Initialise the Front End electronics Tool
145// ----------------------------------------------------------------------
147 ATH_CHECK(m_sct_FrontEnd.retrieve());
148
150
151 ATH_MSG_DEBUG("Retrieved and initialised tool " << m_sct_FrontEnd);
152 return StatusCode::SUCCESS;
153}
154
155// ----------------------------------------------------------------------
156// Initialize the different services
157// ----------------------------------------------------------------------
159 // Get SCT ID helper for hash function and Store them using methods from the
160 // SiDigitization.
161 ATH_CHECK(detStore()->retrieve(m_detID, "SCT_ID"));
162
164 ATH_CHECK(m_mergeSvc.retrieve());
165 }
166 ATH_CHECK(m_rndmSvc.retrieve());
167
168 return StatusCode::SUCCESS;
169}
170
171// ----------------------------------------------------------------------
172// Initialize the disabled cells for cosmics or CTB cases
173// ----------------------------------------------------------------------
175 // +++ Retrieve the SCT_RandomDisabledCellGenerator
177
179
180 ATH_MSG_INFO("Retrieved the SCT_RandomDisabledCellGenerator tool:" << m_sct_RandomDisabledCellGenerator);
181 return StatusCode::SUCCESS;
182}
183
184StatusCode SCT_DigitizationTool::processAllSubEvents(const EventContext& ctx) {
185 if (prepareEvent(ctx, 0).isFailure()) {
186 return StatusCode::FAILURE;
187 }
188 // Set the RNG to use for this event.
189 ATHRNG::RNGWrapper* rngWrapper = m_rndmSvc->getEngine(this);
190 rngWrapper->setSeed( name(), ctx );
191 CLHEP::HepRandomEngine *rndmEngine = rngWrapper->getEngine(ctx);
192
193 ATH_MSG_VERBOSE("Begin digitizeAllHits");
194 if (m_enableHits and (not getNextEvent(ctx).isFailure())) {
196 } else {
197 ATH_MSG_DEBUG("no hits found in event!");
198 }
199 ATH_MSG_DEBUG("Digitized Elements with Hits");
200
201 // loop over elements without hits
202 if (not m_onlyHitElements) {
204 ATH_MSG_DEBUG("Digitized Elements without Hits");
205 }
206
207 m_thpcsi.reset(nullptr);
208
209 ATH_MSG_VERBOSE("Digitize success!");
210 return StatusCode::SUCCESS;
211}
212
213// ======================================================================
214// prepareEvent
215// ======================================================================
216StatusCode SCT_DigitizationTool::prepareEvent(const EventContext& ctx, unsigned int /*index*/) {
217 ATH_MSG_VERBOSE("SCT_DigitizationTool::prepareEvent()");
218 // Create the IdentifiableContainer to contain the digit collections Create
219 // a new RDO container
221 ATH_CHECK(m_rdoContainer.record(std::make_unique<SCT_RDO_Container>(m_detID->wafer_hash_max())));
222
223 // Create a map for the SDO and register it into StoreGate
225 ATH_CHECK(m_simDataCollMap.record(std::make_unique<InDetSimDataCollection>()));
226
227 m_processedElements.clear();
228 m_processedElements.resize(m_detID->wafer_hash_max(), false);
229
230 m_thpcsi = std::make_unique<TimedHitCollection<SiHit>>();
232 return StatusCode::SUCCESS;
233}
234
235// =========================================================================
236// mergeEvent
237// =========================================================================
238StatusCode SCT_DigitizationTool::mergeEvent(const EventContext& ctx) {
239 ATH_MSG_VERBOSE("SCT_DigitizationTool::mergeEvent()");
240
241 // Set the RNG to use for this event.
242 ATHRNG::RNGWrapper* rngWrapper = m_rndmSvc->getEngine(this);
243 rngWrapper->setSeed( name(), ctx );
244 CLHEP::HepRandomEngine *rndmEngine = rngWrapper->getEngine(ctx);
245
246 if (m_enableHits) {
248 }
249
250 if (not m_onlyHitElements) {
252 }
253
254 m_hitCollPtrs.clear();
255
256 m_thpcsi.reset(nullptr);
257
258 ATH_MSG_DEBUG("Digitize success!");
259 return StatusCode::SUCCESS;
260}
261
262void SCT_DigitizationTool::digitizeAllHits(const EventContext& ctx, SG::WriteHandle<SCT_RDO_Container>* rdoContainer, SG::WriteHandle<InDetSimDataCollection>* simDataCollMap, std::vector<bool>* processedElements, TimedHitCollection<SiHit>* thpcsi, CLHEP::HepRandomEngine * rndmEngine) {
264 //
265 // In order to process all element rather than just those with hits we
266 // create a vector to keep track of which elements have been processed.
267 // NB. an element is an sct module
268 //
270 ATH_MSG_DEBUG("Digitizing hits");
271 int hitcount{0}; // First, elements with hits.
272
273 SiChargedDiodeCollection chargedDiodes;
274
275 while (digitizeElement(ctx, &chargedDiodes, thpcsi, rndmEngine)) {
276 ATH_MSG_DEBUG("Hit collection ID=" << m_detID->show_to_string(chargedDiodes.identify()));
277
278 hitcount++; // Hitcount will be a number in the hit collection minus
279 // number of hits in missing mods
280
281 ATH_MSG_DEBUG("in digitize elements with hits: ec - layer - eta - phi "
282 << m_detID->barrel_ec(chargedDiodes.identify()) << " - "
283 << m_detID->layer_disk(chargedDiodes.identify()) << " - "
284 << m_detID->eta_module(chargedDiodes.identify()) << " - "
285 << m_detID->phi_module(chargedDiodes.identify()) << " - "
286 << " processing hit number " << hitcount);
287
288 // Have a flag to check if the module is present or not
289 // Generally assume it is:
290
291 IdentifierHash idHash{chargedDiodes.identifyHash()};
292
293 assert(idHash < processedElements->size());
294 (*processedElements)[idHash] = true;
295
296 // create and store RDO and SDO
297
298 if (not chargedDiodes.empty()) {
299 StatusCode sc{createAndStoreRDO(&chargedDiodes, rdoContainer)};
300 if (sc.isSuccess()) { // error msg is given inside
301 // createAndStoreRDO()
302 addSDO(&chargedDiodes, simDataCollMap);
303 }
304 }
305
306 chargedDiodes.clear();
307 }
308 ATH_MSG_DEBUG("hits processed");
309}
310
311// digitize elements without hits
312void SCT_DigitizationTool::digitizeNonHits(const EventContext& ctx, SG::WriteHandle<SCT_RDO_Container>* rdoContainer, SG::WriteHandle<InDetSimDataCollection>* simDataCollMap, const std::vector<bool>* processedElements, CLHEP::HepRandomEngine * rndmEngine) const {
313 // Get SCT_DetectorElementCollection
315 const InDetDD::SiDetectorElementCollection* elements{sctDetEle.retrieve()};
316 if (elements==nullptr) {
317 ATH_MSG_FATAL(m_SCTDetEleCollKey.fullKey() << " could not be retrieved");
318 return;
319 }
320
321 ATH_MSG_DEBUG("processing elements without hits");
322 SiChargedDiodeCollection chargedDiodes;
323
324 for (unsigned int i{0}; i < processedElements->size(); i++) {
325 if (not (*processedElements)[i]) {
326 IdentifierHash idHash{i};
327 if (not idHash.is_valid()) {
328 ATH_MSG_ERROR("SCT Detector element id hash is invalid = " << i);
329 }
330
331 const InDetDD::SiDetectorElement* element{elements->getDetectorElement(idHash)};
332 if (element) {
333 ATH_MSG_DEBUG("In digitize of untouched elements: layer - phi - eta "
334 << m_detID->layer_disk(element->identify()) << " - "
335 << m_detID->phi_module(element->identify()) << " - "
336 << m_detID->eta_module(element->identify()) << " - "
337 << "size: " << processedElements->size());
338
339 chargedDiodes.setDetectorElement(element);
340 ATH_MSG_DEBUG("calling applyProcessorTools() for NON hits");
341 applyProcessorTools(&chargedDiodes, rndmEngine);
342
343 // Create and store RDO and SDO
344 // Don't create empty ones.
345 if (not chargedDiodes.empty()) {
346 StatusCode sc{createAndStoreRDO(&chargedDiodes, rdoContainer)};
347 if (sc.isSuccess()) {// error msg is given inside
348 // createAndStoreRDO()
349 addSDO(&chargedDiodes, simDataCollMap);
350 }
351 }
352
353 chargedDiodes.clear();
354 }
355 }
356 }
357
358 }
359
360bool SCT_DigitizationTool::digitizeElement(const EventContext& ctx, SiChargedDiodeCollection* chargedDiodes, TimedHitCollection<SiHit>*& thpcsi, CLHEP::HepRandomEngine * rndmEngine) {
361 if (nullptr == thpcsi) {
362 ATH_MSG_ERROR("thpcsi should not be nullptr!");
363
364 return false;
365 }
366
367 // get the iterator pairs for this DetEl
368
370 if (!thpcsi->nextDetectorElement(i, e)) { // no more hits
371 return false;
372 }
373
374 // create the identifier for the collection:
375 ATH_MSG_DEBUG("create ID for the hit collection");
376 const TimedHitPtr<SiHit>& firstHit{*i};
377 int barrel{firstHit->getBarrelEndcap()};
378 Identifier id{m_detID->wafer_id(barrel,
379 firstHit->getLayerDisk(),
380 firstHit->getPhiModule(),
381 firstHit->getEtaModule(),
382 firstHit->getSide())};
383 IdentifierHash waferHash{m_detID->wafer_hash(id)};
384
385 // Get SCT_DetectorElementCollection
387 const InDetDD::SiDetectorElementCollection* elements(sctDetEle.retrieve());
388 if (elements==nullptr) {
389 ATH_MSG_FATAL(m_SCTDetEleCollKey.fullKey() << " could not be retrieved");
390 return false;
391 }
392
393 // get the det element from the manager
394 const InDetDD::SiDetectorElement* sielement{elements->getDetectorElement(waferHash)};
395
396 if (sielement == nullptr) {
397 ATH_MSG_DEBUG("Barrel=" << barrel << " layer=" << firstHit->getLayerDisk() << " Eta=" << firstHit->getEtaModule() << " Phi=" << firstHit->getPhiModule() << " Side=" << firstHit->getSide());
398 ATH_MSG_ERROR("detector manager could not find element with id = " << id);
399 return false;
400 }
401 // create the charged diodes collection
402 chargedDiodes->setDetectorElement(sielement);
403
404 // Loop over the hits and created charged diodes:
405 while (i != e) {
406 const TimedHitPtr<SiHit>& phit{*i++};
407
408 // skip hits which are more than 10us away
409 if (std::abs(phit->meanTime()) < 10000. * CLHEP::ns) {
410 ATH_MSG_DEBUG("HASH = " << m_detID->wafer_hash(m_detID->wafer_id(phit->getBarrelEndcap(),
411 phit->getLayerDisk(),
412 phit->getPhiModule(),
413 phit->getEtaModule(),
414 phit->getSide())));
415 ATH_MSG_DEBUG("calling process() for all methods");
416 SiDigitizationSurfaceChargeInserter inserter(sielement, chargedDiodes);
417 m_sct_SurfaceChargesGenerator->process(sielement, phit, inserter, rndmEngine, ctx);
418 ATH_MSG_DEBUG("charges filled!");
419 }
420 }
421 applyProcessorTools(chargedDiodes, rndmEngine); // !< Use of the new AlgTool surface
422 // charges generator class
423 return true;
424}
425
426// -----------------------------------------------------------------------------
427// Applies processors to the current detector element for the current element:
428// -----------------------------------------------------------------------------
429void SCT_DigitizationTool::applyProcessorTools(SiChargedDiodeCollection* chargedDiodes, CLHEP::HepRandomEngine * rndmEngine) const {
430 ATH_MSG_DEBUG("applyProcessorTools()");
431 int processorNumber{0};
432
434 proc->process(*chargedDiodes, rndmEngine);
435
436 processorNumber++;
437 ATH_MSG_DEBUG("Applied processor # " << processorNumber);
438 }
439}
440
442 SubEventIterator bSubEvents,
443 SubEventIterator eSubEvents) {
444 ATH_MSG_VERBOSE("SCT_DigitizationTool::processBunchXing() " << bunchXing);
445 // decide if this event will be processed depending on
446 // HardScatterSplittingMode & bunchXing
449 return StatusCode::SUCCESS;
450 }
452 return StatusCode::SUCCESS;
453 }
456 }
457
459 TimedHitCollList hitCollList;
460
461 if ((not (m_mergeSvc->retrieveSubSetEvtData(m_inputObjectName, hitCollList, bunchXing,
462 bSubEvents, eSubEvents).isSuccess())) and
463 hitCollList.empty()) {
464 ATH_MSG_ERROR("Could not fill TimedHitCollList");
465 return StatusCode::FAILURE;
466 } else {
467 ATH_MSG_VERBOSE(hitCollList.size() << " SiHitCollections with key " <<
468 m_inputObjectName << " found");
469 }
470
471 const TimedHitCollList::iterator endColl{hitCollList.end()};
472 for (TimedHitCollList::iterator iColl{hitCollList.begin()}; iColl != endColl; ++iColl) {
473 std::unique_ptr<SiHitCollection> hitCollPtr{std::make_unique<SiHitCollection>(*iColl->second)};
474 PileUpTimeEventIndex timeIndex{iColl->first};
475 ATH_MSG_DEBUG("SiHitCollection found with " << hitCollPtr->size() <<
476 " hits");
477 ATH_MSG_VERBOSE("time index info. time: " << timeIndex.time()
478 << " index: " << timeIndex.index()
479 << " type: " << timeIndex.type());
480 m_thpcsi->insert(timeIndex, hitCollPtr.get());
481 m_hitCollPtrs.push_back(std::move(hitCollPtr));
482 }
483
484 return StatusCode::SUCCESS;
485
486}
487
488// =========================================================================
489// property handlers
490// =========================================================================
491void SCT_DigitizationTool::SetupRdoOutputType(Gaudi::Details::PropertyBase &) {
492}
493
494// Does nothing, but required by Gaudi
495
496// ----------------------------------------------------------------------
497// Digitisation of non hit elements
498// ----------------------------------------------------------------------
499
501{
502public:
504 m_detID{detID}, m_msgNo{-1} {
505 }
506
507 std::string msg(const InDetDD::SiDetectorElement* element) {
508 std::ostringstream ost;
509
510 ost << "Digitized unprocessed elements: layer - phi - eta - side "
511 << m_detID->layer_disk(element->identify()) << " - "
512 << m_detID->phi_module(element->identify()) << " - "
513 << m_detID->eta_module(element->identify()) << " - "
514 << m_detID->side(element->identify()) << " - "
515 << " unprocessed hit number: " << ++m_msgNo << '\n';
516
517 return ost.str();
518 }
519
520private:
523};
524
525// ----------------------------------------------------------------------//
526// createAndStoreRDO //
527// ----------------------------------------------------------------------//
529
530 // Create the RDO collection
531 std::unique_ptr<SCT_RDO_Collection> RDOColl{createRDO(chDiodeCollection)};
532 const IdentifierHash identifyHash{RDOColl->identifyHash()};
533
534 // Add it to storegate
535 Identifier id_coll{RDOColl->identify()};
536 int barrelec{m_detID->barrel_ec(id_coll)};
537
538 if ((not m_barrelonly) or (std::abs(barrelec) <= 1)) {
539 if ((*rdoContainer)->addCollection(RDOColl.release(), identifyHash).isFailure()) {
540 ATH_MSG_FATAL("SCT RDO collection could not be added to container!");
541 return StatusCode::FAILURE;
542 }
543 } else {
544 ATH_MSG_VERBOSE("Not saving SCT_RDO_Collection: " << m_detID->show_to_string(RDOColl->identify()) << " to container!");
545 }
546 return StatusCode::SUCCESS;
547} // SCT_Digitization::createAndStoreRDO()
548
549// ----------------------------------------------------------------------
550// createRDO
551// ----------------------------------------------------------------------
552std::unique_ptr<SCT_RDO_Collection> SCT_DigitizationTool::createRDO(SiChargedDiodeCollection* collection) const {
553
554 // create a new SCT RDO collection
555 std::unique_ptr<SCT_RDO_Collection> p_rdocoll;
556
557 // need the DE identifier
558 const Identifier id_de{collection->identify()};
559 IdentifierHash idHash_de{collection->identifyHash()};
560 try {
561 p_rdocoll = std::make_unique<SCT_RDO_Collection>(idHash_de);
562 } catch (const std::bad_alloc&) {
563 ATH_MSG_FATAL("Could not create a new SCT_RDORawDataCollection !");
564 }
565 p_rdocoll->setIdentifier(id_de);
566
567 SiChargedDiodeIterator i_chargedDiode{collection->begin()};
568 const SiChargedDiodeIterator i_chargedDiode_end{collection->end()};
569 // Choice of producing SCT1_RawData or SCT3_RawData
570 if (m_WriteSCT1_RawData.value()) {
571 for (; i_chargedDiode != i_chargedDiode_end; ++i_chargedDiode) {
572 unsigned int flagmask{static_cast<unsigned int>((*i_chargedDiode).second.flag() & 0xFE)};
573
574 if (!flagmask) { // now check it wasn't masked:
575 // create new SCT RDO, using method 1 for mask:
576 // GroupSize=1: need readout id, make use of
577 // SiTrackerDetDescr
578 InDetDD::SiReadoutCellId roCell{(*i_chargedDiode).second.getReadoutCell()};
579 int strip{roCell.strip()};
580 if (strip > 0xffff) { // In upgrade layouts strip can be bigger
581 // than 4000
582 ATH_MSG_FATAL("Strip number too big for SCT1 raw data format.");
583 }
584 const Identifier id_readout{m_detID->strip_id(collection->identify(), strip)};
585
586 // build word, masks taken from SiTrackerEvent/SCTRawData.cxx
587 const unsigned int strip_rdo{static_cast<unsigned int>((strip & 0xFFFF) << 16)};
588
589 // user can define what GroupSize is, here 1: TC. Incorrect,
590 // GroupSize >= 1
591 int size{SiHelper::GetStripNum((*i_chargedDiode).second)};
592 unsigned int size_rdo{static_cast<unsigned int>(size & 0xFFFF)};
593
594 // TC. Need to check if there are disabled strips in the cluster
595 int cluscounter{0};
596 if (size > 1) {
597 SiChargedDiodeIterator it2{i_chargedDiode};
598 ++it2;
599 for (; it2 != i_chargedDiode_end; ++it2) {
600 ++cluscounter;
601 if (cluscounter >= size) {
602 break;
603 }
604 if (it2->second.flag() & 0xDE) {
605 int tmp{cluscounter};
606 while ((it2 != i_chargedDiode_end) and (cluscounter < size - 1) and (it2->second.flag() & 0xDE)) {
607 ++it2;
608 ++cluscounter;
609 }
610 if ((it2 != collection->end()) and !(it2->second.flag() & 0xDE)) {
611 SiHelper::ClusterUsed(it2->second, false);
612 SiHelper::SetStripNum(it2->second, size - cluscounter, &msg());
613 }
614 // groupSize=tmp;
615 size_rdo = tmp & 0xFFFF;
616 break;
617 }
618 }
619 }
620 unsigned int SCT_Word{strip_rdo | size_rdo};
621 SCT1_RawData* p_rdo{new SCT1_RawData(id_readout, SCT_Word)};
622 if (p_rdo) {
623 p_rdocoll->push_back(p_rdo);
624 }
625 }
626 }
627 } else {
628 // Under the current scheme time bin and ERRORS are hard-coded to
629 // default values.
630 int ERRORS{0};
631 static const std::vector<int> dummyvector;
632 for (; i_chargedDiode != i_chargedDiode_end; ++i_chargedDiode) {
633 unsigned int flagmask{static_cast<unsigned int>((*i_chargedDiode).second.flag() & 0xFE)};
634
635 if (!flagmask) { // Check it wasn't masked
636 int tbin{SiHelper::GetTimeBin((*i_chargedDiode).second)};
637 // create new SCT RDO
638 InDetDD::SiReadoutCellId roCell{(*i_chargedDiode).second.getReadoutCell()};
639 int strip{roCell.strip()};
640 const InDetDD::SCT_ModuleSideDesign& sctDesign{static_cast<const InDetDD::SCT_ModuleSideDesign&>(collection->design())};
641 int row2D{sctDesign.row(strip)};
642 Identifier id_readout;
643 if (row2D < 0) { // SCT sensors
644 id_readout = m_detID->strip_id(collection->identify(), strip);
645 } else { // Upgrade sensors
646 int strip2D{sctDesign.strip(strip)};
647 id_readout = m_detID->strip_id(collection->identify(), row2D, strip2D);
648 }
649
650 // build word (compatible with
651 // SCT_RawDataByteStreamCnv/src/SCT_RodDecoder.cxx)
652 int size{SiHelper::GetStripNum((*i_chargedDiode).second)};
653 int groupSize{size};
654
655 // TC. Need to check if there are disabled strips in the cluster
656 int cluscounter{0};
657 if (size > 1) {
658 SiChargedDiode* diode{i_chargedDiode->second.nextInCluster()};
659 while (diode) {//check if there is a further strip in the cluster
660 ++cluscounter;
661 if (cluscounter >= size) {
662 ATH_MSG_WARNING("Cluster size reached while neighbouring strips still defined.");
663 break;
664 }
665 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)
666 int tmp{cluscounter};
667 while ((cluscounter < size - 1) and (diode->flag() & 0xDE)) { //check its not the end and still disabled
668 diode = diode->nextInCluster();
669 cluscounter++;
670 }
671 if (diode and !(diode->flag() & 0xDE)) {
672 SiHelper::ClusterUsed(*diode, false);
673 SiHelper::SetStripNum(*diode, size - cluscounter, &msg());
674 }
675 groupSize = tmp;
676 break;
677 }
678 diode = diode->nextInCluster();
679 }
680 }
681
682 int stripIn11bits{strip & 0x7ff};
683 if (stripIn11bits != strip) {
684 ATH_MSG_DEBUG("Strip number " << strip << " doesn't fit into 11 bits - will be truncated");
685 }
686
687 unsigned int SCT_Word{static_cast<unsigned int>(groupSize | (stripIn11bits << 11) | (tbin << 22) | (ERRORS << 25))};
688 SCT3_RawData *p_rdo{new SCT3_RawData(id_readout, SCT_Word, &dummyvector)};
689 if (p_rdo) {
690 p_rdocoll->push_back(p_rdo);
691 }
692 }
693 }
694 }
695 return p_rdocoll;
696} // SCT_Digitization::createRDO()
697
698// ------------------------------------------------------------
699// Get next event and extract collection of hit collections:
700// ------------------------------------------------------------
701StatusCode SCT_DigitizationTool::getNextEvent(const EventContext& ctx) {
702 ATH_MSG_DEBUG("SCT_DigitizationTool::getNextEvent");
703 // get the container(s)
705 // this is a list<pair<time_t, DataLink<SiHitCollection> >
706
707 // In case of single hits container just load the collection using read handles
710 if (!hitCollection.isValid()) {
711 ATH_MSG_ERROR("Could not get SCT SiHitCollection container " << hitCollection.name() << " from store " << hitCollection.store());
712 return StatusCode::FAILURE;
713 }
714
715 // create a new hits collection
716 m_thpcsi = std::make_unique<TimedHitCollection<SiHit>>(1);
717 m_thpcsi->insert(0, hitCollection.cptr());
718 ATH_MSG_DEBUG("SiHitCollection found with " << hitCollection->size() << " hits");
719
720 return StatusCode::SUCCESS;
721 }
722
723 TimedHitCollList hitCollList;
724 unsigned int numberOfSiHits{0};
725 if (not (m_mergeSvc->retrieveSubEvtsData(m_inputObjectName, hitCollList, numberOfSiHits).isSuccess()) and hitCollList.empty()) {
726 ATH_MSG_ERROR("Could not fill TimedHitCollList");
727 return StatusCode::FAILURE;
728 } else {
729 ATH_MSG_DEBUG(hitCollList.size() << " SiHitCollections with key " << m_inputObjectName << " found");
730 }
731 // create a new hits collection
732 m_thpcsi = std::make_unique<TimedHitCollection<SiHit>>(numberOfSiHits);
733 // now merge all collections into one
734 TimedHitCollList::iterator endColl{hitCollList.end()};
735 for (TimedHitCollList::iterator iColl{hitCollList.begin()}; iColl != endColl; ++iColl) {
736 // decide if this event will be processed depending on
737 // HardScatterSplittingMode & bunchXing
740 continue;
741 }
743 continue;
744 }
747 }
748 const SiHitCollection* p_collection{iColl->second};
749 m_thpcsi->insert(iColl->first, p_collection);
750 ATH_MSG_DEBUG("SiTrackerHitCollection found with " << p_collection->size() << " hits"); // loop on the hit collections
751 }
752 return StatusCode::SUCCESS;
753}
754
755// -----------------------------------------------------------------------------------------------
756// Convert a SiTotalCharge to a InDetSimData, and store it.
757// -----------------------------------------------------------------------------------------------
759 using list_t = SiTotalCharge::list_t;
760 std::vector<InDetSimData::Deposit> deposits;
761 const InDetDD::SCT_ModuleSideDesign& sctDesign{dynamic_cast<const InDetDD::SCT_ModuleSideDesign&>(collection->design())};
762 const auto collectionid = collection->identify();
763 //Check for optimization
764 static_assert(std::is_nothrow_move_constructible<InDetSimData::Deposit>::value);
765 deposits.reserve(5); // no idea what a reasonable number for this would be
766 // with pileup
767 // loop over the charged diodes
768 const SiChargedDiodeIterator EndOfDiodeCollection{collection->end()};
769 for (SiChargedDiodeIterator i_chargedDiode{collection->begin()}; i_chargedDiode != EndOfDiodeCollection; ++i_chargedDiode) {
770 deposits.clear();
771 const list_t& charges{(*i_chargedDiode).second.totalCharge().chargeComposition()};
772
773 bool real_particle_hit{false};
774 // loop over the list
775 const list_t::const_iterator EndOfChargeList{charges.end()};
776 for (list_t::const_iterator i_ListOfCharges{charges.begin()}; i_ListOfCharges != EndOfChargeList; ++i_ListOfCharges) {
777 const HepMcParticleLink& trkLink{i_ListOfCharges->particleLink()};
778 if (HepMC::ignoreTruthLink(trkLink, m_vetoPileUpTruthLinks)) {
779 continue;
780 }
781 if (!real_particle_hit) {
782 // Types of SiCharges expected from SCT
783 // Noise: barcode==0 and
784 // processType()==SiCharge::noise
785 // Delta Rays: barcode==0 and
786 // processType()==SiCharge::track
787 // Pile Up Tracks With No Truth: barcode!=0 and
788 // processType()==SiCharge::cut_track
789 // Tracks With Truth: barcode!=0 and
790 // processType()==SiCharge::track
791 if (!HepMC::no_truth_link(trkLink) && i_ListOfCharges->processType() == SiCharge::track) {
792 real_particle_hit = true;
793 }
794 }
795
796 auto theDeposit = std::ranges::find_if(deposits|std::views::reverse,
797 [&](const InDetSimData::Deposit& deposit){ return deposit.first == trkLink;
798 });
799
800 // if the charge has already hit the Diode add it to the deposit
801 if (theDeposit != deposits.rend()) {
802 (*theDeposit).second += i_ListOfCharges->charge();
803 } else { // create a new deposit
804 deposits.emplace_back(trkLink, i_ListOfCharges->charge());
805 }
806 }
807
808 // add the simdata object to the map:
809 if (real_particle_hit or m_createNoiseSDO) {
810 InDetDD::SiReadoutCellId roCell{(*i_chargedDiode).second.getReadoutCell()};
811 const int strip{roCell.strip()};
812 const int row2D{sctDesign.row(strip)};
813 Identifier id_readout = row2D < 0 ? m_detID->strip_id(collectionid,strip) : m_detID->strip_id(collectionid,row2D, sctDesign.strip(strip));
814 (*simDataCollMap)->try_emplace(id_readout, std::move(deposits),(*i_chargedDiode).second.flag());
815 }
816 }
817}
#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
Digitize the SCT using an implementation of IPileUpTool.
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.
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)
DigitizeNonHitElementsDebugPrinter(const SCT_ID *detID)
This is a "hash" representation of an Identifier.
constexpr bool is_valid() const
Base class for the SCT module side design, extended by the Forward and Barrel module design.
virtual int strip(int stripId1Dim) 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.
Identifier for the strip or pixel readout cell.
virtual Identifier identify() const override final
identifier of this detector element (inline)
std::pair< HepMcParticleLink, float > Deposit
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
ToolHandle< IFrontEnd > m_sct_FrontEnd
StatusCode createAndStoreRDO(SiChargedDiodeCollection *chDiodeCollection, SG::WriteHandle< SCT_RDO_Container > *rdoContainer) const
RDO and SDO methods.
BooleanProperty m_WriteSCT1_RawData
std::vector< std::unique_ptr< SiHitCollection > > m_hitCollPtrs
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
StatusCode initServices()
initialize the required services
ToolHandle< IRandomDisabledCellGenerator > m_sct_RandomDisabledCellGenerator
virtual ~SCT_DigitizationTool()
ToolHandle< ISurfaceChargesGenerator > m_sct_SurfaceChargesGenerator
SG::WriteHandle< InDetSimDataCollection > m_simDataCollMap
SDO Map handle.
StatusCode initDisabledCells()
Initialize the SCT_RandomDisabledCellGenerator AlgTool.
std::vector< ISiChargedDiodesProcessorTool * > m_diodeCollectionTools
SG::WriteHandleKey< InDetSimDataCollection > m_simDataCollMapKey
SCT_DigitizationTool(const std::string &type, const std::string &name, const IInterface *parent)
const SCT_ID * m_detID
Handle to the ID helper.
virtual StatusCode initialize() override final
SG::WriteHandle< SCT_RDO_Container > m_rdoContainer
RDO container handle.
virtual StatusCode mergeEvent(const EventContext &ctx) override final
StatusCode getNextEvent(const EventContext &ctx)
bool digitizeElement(const EventContext &ctx, SiChargedDiodeCollection *chargedDiodes, TimedHitCollection< SiHit > *&thpcsi, CLHEP::HepRandomEngine *rndmEngine)
ServiceHandle< IAthRNGSvc > m_rndmSvc
Random number service.
StatusCode initSurfaceChargesGeneratorTool()
Initialize the SCT_SurfaceChargesGenerator AlgTool.
BooleanProperty m_onlyHitElements
virtual StatusCode processAllSubEvents(const EventContext &ctx) override final
std::unique_ptr< TimedHitCollection< SiHit > > m_thpcsi
ServiceHandle< PileUpMergeSvc > m_mergeSvc
IntegerProperty m_HardScatterSplittingMode
void SetupRdoOutputType(Gaudi::Details::PropertyBase &)
Called when m_WriteSCT1_RawData is altered.
StatusCode initFrontEndTool()
Initialize the SCT_FrontEnd AlgTool.
void storeTool(ISiChargedDiodesProcessorTool *p_processor)
BooleanProperty m_createNoiseSDO
void addSDO(SiChargedDiodeCollection *collection, SG::WriteHandle< InDetSimDataCollection > *simDataCollMap) const
SG::ReadHandleKey< SiHitCollection > m_hitsContainerKey
virtual StatusCode prepareEvent(const EventContext &ctx, unsigned int) override final
Called before processing physics events.
SG::WriteHandleKey< SCT_RDO_Container > m_rdoContainerKey
virtual StatusCode processBunchXing(int bunchXing, SubEventIterator bSubEvents, SubEventIterator eSubEvents) override final
std::unique_ptr< SCT_RDO_Collection > createRDO(SiChargedDiodeCollection *collection) const
Create RDOs from the SiChargedDiodeCollection for the current wafer.
void applyProcessorTools(SiChargedDiodeCollection *chargedDiodes, CLHEP::HepRandomEngine *rndmEngine) const
BooleanProperty m_randomDisabledCells
BooleanProperty m_onlyUseContainerName
std::vector< bool > m_processedElements
vector of processed elements - set by digitizeHits() *‍/
SG::ReadCondHandleKey< InDetDD::SiDetectorElementCollection > m_SCTDetEleCollKey
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
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
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
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.
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