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