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