ATLAS Offline Software
Loading...
Searching...
No Matches
PixelDigitizationTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
7#include "CLHEP/Random/RandomEngine.h"
11
12#include <limits>
13#include <cstdint>
14
16 const std::string& name,
17 const IInterface* pIID) :
18 PileUpToolBase(type, name, pIID) {
19}
20
21//=======================================
22// I N I T I A L I Z E
23//=======================================
25 ATH_MSG_DEBUG("PixelDigitizationTool::Initialize()");
26
28 ATH_CHECK(m_mergeSvc.retrieve());
29 }
30 ATH_CHECK(m_rndmSvc.retrieve());
31
32 ATH_CHECK(detStore()->retrieve(m_detID, m_pixelIDName.value()));
33 ATH_MSG_DEBUG("Pixel ID helper retrieved");
34
35 ATH_CHECK(m_chargeTool.retrieve());
36 ATH_CHECK(m_fesimTool.retrieve());
38
39 // check the input object name
40 if (m_hitsContainerKey.key().empty()) {
41 ATH_MSG_FATAL("Property InputObjectName not set !");
42 return StatusCode::FAILURE;
43 }
45 ATH_MSG_DEBUG("Input objects in container : '" << m_inputObjectName << "'");
46
47 ATH_CHECK(m_hitsContainerKey.initialize(true));
48 ATH_CHECK(m_pixelDetEleCollKey.initialize());
49 ATH_CHECK(m_rdoContainerKey.initialize());
50 ATH_CHECK(m_simDataCollKey.initialize());
51
52 return StatusCode::SUCCESS;
53}
54
55//=======================================
56// F I N A L I Z E
57//=======================================
59 return StatusCode::SUCCESS;
60}
61
62//=======================================
63// P R O C E S S S U B E V E N T S
64//=======================================
65StatusCode PixelDigitizationTool::processAllSubEventsConst(const EventContext& ctx) const {
66 // Prepare event
67 ATH_MSG_DEBUG("Prepare event");
68 EventData event_data;
69 ATH_CHECK(prepareEvent(ctx, event_data));
70
71 // Get the container(s)
73 // In case of single hits container just load the collection using read handles
76 if (!hitCollection.isValid()) {
78 "Could not get Pixel SiHitCollection container " << hitCollection.name() << " from store " <<
79 hitCollection.store());
80 return StatusCode::FAILURE;
81 }
82
83 assert(event_data.m_timedHits);
84 // create a new hits collection
85 event_data.m_timedHits->reserve(1);
86 event_data.m_timedHits->insert(0, hitCollection.cptr());
87 ATH_MSG_DEBUG("SiHitCollection found with " << hitCollection->size() << " hits");
88 } else {
89 TimedHitCollList hitCollList;
90 unsigned int numberOfSiHits(0);
91 ATH_CHECK(m_mergeSvc->retrieveSubEvtsData(m_inputObjectName, hitCollList, numberOfSiHits));
92 event_data.m_timedHits->reserve(numberOfSiHits);
93 // Now merge all collections into one
94 for (auto & iColl : hitCollList) {
95 // Decide if this event will be processed depending on HardScatterSplittingMode
97 event_data.m_HardScatterSplittingSkipper = true;
98 continue;
99 }
101 continue;
102 }
104 event_data.m_HardScatterSplittingSkipper = true;
105 }
106 const SiHitCollection* p_collection(iColl.second);
107 event_data.m_timedHits->insert(iColl.first, p_collection);
108 ATH_MSG_DEBUG("SiTrackerHitCollection found with" << p_collection->size() << " hits"); // loop on the hit collections
109 }
110 }
111 // Digitize hits
112 ATH_CHECK(digitizeEvent(ctx, event_data));
113
114 ATH_MSG_DEBUG("Digitize success!");
115 return StatusCode::SUCCESS;
116}
117
118//=======================================
119// D I G I T I Z E E V E N T (main)
120//=======================================
121StatusCode PixelDigitizationTool::digitizeEvent(const EventContext& ctx, EventData &event_data) const {
122 ATH_MSG_VERBOSE("PixelDigitizationTool::digitizeEvent()");
123
125 const InDetDD::SiDetectorElementCollection* elements(*pixelDetEleHandle);
126 if (not pixelDetEleHandle.isValid() or elements == nullptr) {
127 ATH_MSG_FATAL(m_pixelDetEleCollKey.fullKey() << " is not available.");
128 return StatusCode::FAILURE;
129 }
130
131 std::unique_ptr<SiChargedDiodeCollection> chargedDiodes = std::make_unique<SiChargedDiodeCollection>();
132 std::vector<std::pair<double, double> > trfHitRecord;
133 std::vector<double> initialConditions;
134
135 std::vector<bool> processedElements;
136 processedElements.resize(m_detID->wafer_hash_max(), false);
137
138 // Set the RNG to use for this event.
139 ATHRNG::RNGWrapper* rngWrapper = m_rndmSvc->getEngine(this);
140 rngWrapper->setSeed(name(), ctx);
141 CLHEP::HepRandomEngine* rndmEngine = rngWrapper->getEngine(ctx);
142
144
146 // **** Loop over the Detectors with hits ****
148 assert(event_data.m_timedHits);
149 while (event_data.m_timedHits->nextDetectorElement(firstHit, lastHit)) {
150 // Create the identifier for the collection
151 ATH_MSG_DEBUG("create ID for the hit collection");
152 Identifier id = m_detID->wafer_id((*firstHit)->getBarrelEndcap(),
153 (*firstHit)->getLayerDisk(),
154 (*firstHit)->getPhiModule(), (*firstHit)->getEtaModule());
155 IdentifierHash wafer_hash = m_detID->wafer_hash(id);
156
157 // Get the det element from the manager
158 const InDetDD::SiDetectorElement* sielement = elements->getDetectorElement(wafer_hash);
159
160 if (sielement == nullptr) {
162 " Barrel=" << (*firstHit)->getBarrelEndcap() << " Layer=" << (*firstHit)->getLayerDisk() << " Eta=" <<
163 (*firstHit)->getEtaModule() << " Phi=" << (*firstHit)->getPhiModule());
164 ATH_MSG_ERROR("detector manager could not find element with id = " << id);
165 break;
166 }
167
168 // Create the charged diodes collection
169 chargedDiodes->setDetectorElement(sielement);
170 const InDetDD::PixelModuleDesign* p_design = static_cast<const InDetDD::PixelModuleDesign*>(&(sielement->design()));
171
173 // **** Loop over the hits and created charged diodes ****
175 for (TimedHitCollection<SiHit>::const_iterator phit = firstHit; phit != lastHit; ++phit) {
176 //skip hits which are more than 10us away
177 if (std::abs((*phit)->meanTime()) < 10000.0 * CLHEP::ns) {
178 ATH_MSG_DEBUG("HASH = " <<
179 m_detID->wafer_hash(m_detID->wafer_id((*phit)->getBarrelEndcap(), (*phit)->getLayerDisk(),
180 (*phit)->getPhiModule(), (*phit)->getEtaModule())));
181
182 // Apply charge collection tools
183 ATH_MSG_DEBUG("Running sensor simulation.");
184
185 //Deposit energy in sensor
186 ATH_CHECK(m_energyDepositionTool->depositEnergy(*phit, *sielement, trfHitRecord, initialConditions,
187 rndmEngine, ctx));
188
189 //Create signal in sensor, loop over collection of loaded sensorTools
190 for (unsigned int itool = 0; itool < m_chargeTool.size(); itool++) {
191 ATH_MSG_DEBUG("Executing tool " << m_chargeTool[itool]->name());
192 if (m_chargeTool[itool]->induceCharge(*phit, *chargedDiodes, *sielement, *p_design, trfHitRecord,
193 initialConditions, rndmEngine, ctx) == StatusCode::FAILURE) {
194 break;
195 }
196 }
197 initialConditions.clear();
198 trfHitRecord.clear();
199 ATH_MSG_DEBUG("charges filled!");
200 }
201 }
202
203 ATH_MSG_DEBUG("Hit collection ID=" << m_detID->show_to_string(chargedDiodes->identify()));
204 ATH_MSG_DEBUG("in digitize elements with hits: ec - layer - eta - phi " <<
205 m_detID->barrel_ec(chargedDiodes->identify()) << " - " << m_detID->layer_disk(
206 chargedDiodes->identify()) << " - " << m_detID->eta_module(
207 chargedDiodes->identify()) << " - " << m_detID->phi_module(chargedDiodes->identify()));
208
209 IdentifierHash idHash = chargedDiodes->identifyHash();
210
211 assert(idHash < processedElements.size());
212 processedElements[idHash] = true;
213
215 // *** Create and store RDO and SDO ****
217 PixelRDO_Collection* RDOColl = new PixelRDO_Collection(chargedDiodes->identifyHash());
218 RDOColl->setIdentifier(chargedDiodes->identify());
219 for (unsigned int itool = 0; itool < m_fesimTool.size(); itool++) {
220 ATH_MSG_DEBUG("Executing tool " << m_fesimTool[itool]->name());
221 m_fesimTool[itool]->process(*chargedDiodes, *RDOColl, rndmEngine);
222 }
223 assert(event_data.m_rdoContainer.isValid());
224 ATH_CHECK(event_data.m_rdoContainer->addCollection(RDOColl, RDOColl->identifyHash()));
225
226 ATH_MSG_DEBUG("Pixel RDOs '" << RDOColl->identifyHash() << "' added to container");
227 addSDO(chargedDiodes.get(), event_data);
228 chargedDiodes->clear();
229 }
230 event_data.m_timedHits.reset();
231 ATH_MSG_DEBUG("hits processed");
232
234 // *** Loop over the Detectors without hits ****
236 if (!m_onlyHitElements) {
237 ATH_MSG_DEBUG("processing elements without hits");
238 for (unsigned int i = 0; i < processedElements.size(); i++) {
239 if (!processedElements[i]) {
240 IdentifierHash idHash = i;
241 if (!idHash.is_valid()) {
242 ATH_MSG_ERROR("PixelDetector element id hash is invalid = " << i);
243 }
244
245 const InDetDD::SiDetectorElement* element = elements->getDetectorElement(idHash);
246 if (element) {
247 ATH_MSG_DEBUG("In digitize of untouched elements: layer - phi - eta " <<
248 m_detID->layer_disk(element->identify()) << " - " << m_detID->phi_module(
249 element->identify()) << " - " << m_detID->eta_module(
250 element->identify()) << " - " << "size: " << processedElements.size());
251
252 chargedDiodes->setDetectorElement(element);
253 ATH_MSG_DEBUG("Digitize non hit element");
254
255 // Create and store RDO and SDO
256 PixelRDO_Collection* RDOColl = new PixelRDO_Collection(chargedDiodes->identifyHash());
257 RDOColl->setIdentifier(chargedDiodes->identify());
258 for (unsigned int itool = 0; itool < m_fesimTool.size(); itool++) {
259 ATH_MSG_DEBUG("Executing tool " << m_fesimTool[itool]->name());
260 m_fesimTool[itool]->process(*chargedDiodes, *RDOColl, rndmEngine);
261 }
262 assert( event_data.m_rdoContainer.isValid());
263 ATH_CHECK(event_data.m_rdoContainer->addCollection(RDOColl, RDOColl->identifyHash()));
264
265 ATH_MSG_DEBUG("Pixel RDOs '" << RDOColl->identifyHash() << "' added to container");
266 addSDO(chargedDiodes.get(),event_data);
267 chargedDiodes->clear();
268 }
269 }
270 }
271 }
272 ATH_MSG_DEBUG("non-hits processed");
273
274 return StatusCode::SUCCESS;
275}
276
277//=======================================
278// A D D S D O
279//=======================================
280// Convert a SiTotalCharge to a InDetSimData, and store it. (this needs working...)
281//-----------------------------------------------------------------------------------------------
283 using list_t = SiTotalCharge::list_t;
284
285 std::vector<InDetSimData::Deposit> deposits;
286 deposits.reserve(5); // no idea what a reasonable number for this would be with pileup
287
288 // loop over the charged diodes
289 SiChargedDiodeIterator EndOfDiodeCollection = collection->end();
290 for (SiChargedDiodeIterator i_chargedDiode = collection->begin(); i_chargedDiode != EndOfDiodeCollection;
291 ++i_chargedDiode) {
292 deposits.clear();
293 const list_t& charges = (*i_chargedDiode).second.totalCharge().chargeComposition();
294
295 bool real_particle_hit = false;
296 // loop over the list
297 list_t::const_iterator EndOfChargeList = charges.end();
298 for (list_t::const_iterator i_ListOfCharges = charges.begin(); i_ListOfCharges != EndOfChargeList;
299 ++i_ListOfCharges) {
300 const HepMcParticleLink& trkLink = i_ListOfCharges->particleLink();
302 continue;
303 }
304 if (!real_particle_hit) {
305 real_particle_hit = trkLink.isValid();
306 }
307 // check if this track number has been already used.
308 std::vector<InDetSimData::Deposit>::reverse_iterator theDeposit = deposits.rend(); //dummy value
309 std::vector<InDetSimData::Deposit>::reverse_iterator depositsR_end = deposits.rend();
310 std::vector<InDetSimData::Deposit>::reverse_iterator i_Deposit = deposits.rbegin();
311 for (; i_Deposit != depositsR_end; ++i_Deposit) {
312 if ((*i_Deposit).first == trkLink) {
313 theDeposit = i_Deposit;
314 break;
315 }
316 }
317
318 // if the charge has already hit the Diode add it to the deposit
319 if (theDeposit != depositsR_end) (*theDeposit).second += i_ListOfCharges->charge();
320 else { // create a new deposit
321 deposits.emplace_back(trkLink, i_ListOfCharges->charge());
322 }
323 }
324 // add the simdata object to the map:
325 if (real_particle_hit || m_createNoiseSDO) {
326 assert( event_data.m_simDataColl.isValid());
327 event_data.m_simDataColl->try_emplace(collection->getId((*i_chargedDiode).first),
328 std::move(deposits), (*i_chargedDiode).second.flag());
329 }
330 }
331}
332
333//=======================================
334// P R E P A R E E V E N T
335//=======================================
336StatusCode PixelDigitizationTool::prepareEvent(const EventContext& ctx, EventData &event_data) const {
337 ATH_MSG_VERBOSE("PixelDigitizationTool::prepareEvent()");
338
339 // Prepare event
341 ATH_CHECK(event_data.m_rdoContainer.record(std::make_unique<PixelRDO_Container>(m_detID->wafer_hash_max())));
342 ATH_MSG_DEBUG("PixelRDO_Container " << event_data.m_rdoContainer.name() << " registered in StoreGate");
343
345 ATH_CHECK(event_data.m_simDataColl.record(std::make_unique<InDetSimDataCollection>()));
346 ATH_MSG_DEBUG("InDetSimDataCollection " << event_data.m_simDataColl.name() << " registered in StoreGate");
347
348 // Create hit collection
349 event_data.m_timedHits = std::make_unique<TimedHitCollection<SiHit> >();
350
351 event_data.m_HardScatterSplittingSkipper = false;
352 return StatusCode::SUCCESS;
353}
354
355//=======================================
356// M E R G E E V E N T
357//=======================================
358StatusCode PixelDigitizationTool::mergeEvent(const EventContext& ctx) {
359 ATH_MSG_VERBOSE("PixelDigitizationTool::mergeEvent()");
360
361 // Digitize hits
363
364 for (auto & hitCollPtr : m_hitCollPtrs) {
365 hitCollPtr->Clear();
366 delete hitCollPtr;
367 }
368 m_hitCollPtrs.clear();
369
370 return StatusCode::SUCCESS;
371}
372
373//=======================================
374// P R O C E S S B U N C H X I N G
375//=======================================
377 SubEventIterator eSubEvents) {
378 ATH_MSG_VERBOSE("PixelDigitizationTool::processBunchXing() " << bunchXing);
379 //decide if this event will be processed depending on HardScatterSplittingMode & bunchXing
380 EventData &event_data = getCurrentEventData();
382 event_data.m_HardScatterSplittingSkipper = true;
383 return StatusCode::SUCCESS;
384 }
386 return StatusCode::SUCCESS;
387 }
389 event_data.m_HardScatterSplittingSkipper = true;
390 }
391
393 TimedHitCollList hitCollList;
394
395 if (!(m_mergeSvc->retrieveSubSetEvtData(m_inputObjectName, hitCollList, bunchXing,
396 bSubEvents, eSubEvents).isSuccess()) &&
397 hitCollList.empty()) {
398 ATH_MSG_ERROR("Could not fill TimedHitCollList");
399 return StatusCode::FAILURE;
400 } else {
401 ATH_MSG_VERBOSE(hitCollList.size() << " SiHitCollections with key " << m_inputObjectName << " found");
402 }
403
404 TimedHitCollList::iterator iColl(hitCollList.begin());
405 TimedHitCollList::iterator endColl(hitCollList.end());
406
407 for (; iColl != endColl; ++iColl) {
408 SiHitCollection* hitCollPtr = new SiHitCollection(*iColl->second);
409 PileUpTimeEventIndex timeIndex(iColl->first);
410 ATH_MSG_DEBUG("SiHitCollection found with " << hitCollPtr->size() << " hits");
412 "time index info. time: " << timeIndex.time() << " index: " << timeIndex.index() << " type: " <<
413 timeIndex.type());
414 assert(event_data.m_timedHits);
415 event_data.m_timedHits->insert(timeIndex, hitCollPtr);
416 m_hitCollPtrs.push_back(hitCollPtr);
417 }
418 return StatusCode::SUCCESS;
419}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_DEBUG(x)
std::vector< xAOD::EventInfo::SubEvent >::const_iterator SubEventIterator
Definition IPileUpTool.h:22
This is an Identifier helper class for the Pixel subdetector.
InDetRawDataCollection< PixelRDORawData > PixelRDO_Collection
SiChargedDiodeMap::iterator SiChargedDiodeIterator
AtlasHitsVector< SiHit > SiHitCollection
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
This is a "hash" representation of an Identifier.
bool is_valid() const
Check if id is in a valid state.
Class used to describe the design of a module (diode segmentation and readout scheme)
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):
virtual Identifier identify() const override final
identifier of this detector element (inline)
virtual IdentifierHash identifyHash() const override final
void setIdentifier(Identifier id)
Gaudi::Property< int > m_vetoPileUpTruthLinks
PileUpToolBase(const std::string &type, const std::string &name, const IInterface *parent)
StatusCode digitizeEvent(const EventContext &ctx, EventData &event_data) const
virtual StatusCode initialize() override
virtual StatusCode finalize() override
StatusCode processAllSubEventsConst(const EventContext &ctx) const
ServiceHandle< IAthRNGSvc > m_rndmSvc
Random number service.
Gaudi::Property< bool > m_createNoiseSDO
virtual StatusCode prepareEvent(const EventContext &ctx, unsigned int) override
Gaudi::Property< bool > m_onlyHitElements
ToolHandle< EnergyDepositionTool > m_energyDepositionTool
Gaudi::Property< std::string > m_pixelIDName
ServiceHandle< PileUpMergeSvc > m_mergeSvc
std::vector< SiHitCollection * > m_hitCollPtrs
ToolHandleArray< SensorSimTool > m_chargeTool
void addSDO(SiChargedDiodeCollection *collection, EventData &event_data) const
ToolHandleArray< FrontEndSimTool > m_fesimTool
SG::ReadHandleKey< SiHitCollection > m_hitsContainerKey
Gaudi::Property< bool > m_onlyUseContainerName
virtual StatusCode processBunchXing(int bunchXing, SubEventIterator bSubEvents, SubEventIterator eSubEvents) override final
SG::ReadCondHandleKey< InDetDD::SiDetectorElementCollection > m_pixelDetEleCollKey
SG::WriteHandleKey< PixelRDO_Container > m_rdoContainerKey
virtual StatusCode mergeEvent(const EventContext &ctx) override
Gaudi::Property< int > m_HardScatterSplittingMode
SG::WriteHandleKey< InDetSimDataCollection > m_simDataCollKey
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.
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
SiChargedDiodeIterator begin()
Identifier getId(const InDetDD::SiCellId &id) const
std::vector< SiCharge > list_t
void reserve(unsigned int numberOfHits)
reserve a timed vector numberOfHits in size.
bool nextDetectorElement(const_iterator &b, const_iterator &e)
sets an iterator range with the hits of current detector element returns a bool when done
TimedVector::const_iterator const_iterator
void insert(const PileUpTimeEventIndex &timeEventIndex, const AtlasHitsVector< HIT > *inputCollection)
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
SG::WriteHandle< InDetSimDataCollection > m_simDataColl
std::unique_ptr< TimedHitCollection< SiHit > > m_timedHits
SG::WriteHandle< PixelRDO_Container > m_rdoContainer