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