ATLAS Offline Software
Loading...
Searching...
No Matches
TRTOverlay.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6#include "CLHEP/Random/RandomEngine.h"
7#include "CLHEP/Random/RandFlat.h"
9//
17//
18#include "IDC_OverlayBase/IDC_OverlayHelpers.h" //debugPrint
19//
22
23
24namespace
25{
26struct TRTRDOSorter {
27 bool operator()(TRT_RDORawData *digit1, TRT_RDORawData *digit2) {
28 return digit1->identify() < digit2->identify();
29 }
30} TRTRDOSorterObject;
31
32std::unique_ptr<TRT_RDO_Collection> copyCollection(
33 const IdentifierHash &hashId,
34 const TRT_RDO_Collection *collection,
35 DataPool<TRT_LoLumRawData>& dataItemsPool) {
36
37 auto outputCollection = std::make_unique<TRT_RDO_Collection>(hashId);
38 outputCollection->setIdentifier(collection->identify());
39
40 //Elements created here are owned by the DataPool
42 outputCollection->reserve(collection->size());
43 for (const TRT_RDORawData *existingDatum : *collection) {
44 TRT_LoLumRawData* datumCopy = dataItemsPool.nextElementPtr();
45 (*datumCopy) = TRT_LoLumRawData(existingDatum->identify(), existingDatum->getWord());
46 outputCollection->push_back(datumCopy);
47 }
48
49 return outputCollection;
50}
51
52std::unique_ptr<TRT_RDO_Collection> copyCollectionAndSort(
53 const IdentifierHash &hashId,
54 const TRT_RDO_Collection *collection,
55 DataPool<TRT_LoLumRawData>& dataItemsPool) {
56
57 std::unique_ptr<TRT_RDO_Collection> outputCollection = copyCollection(hashId, collection,dataItemsPool);
58 std::stable_sort(outputCollection->begin(), outputCollection->end(), TRTRDOSorterObject);
59 return outputCollection;
60}
61} // anonymous namespace
62
63
64TRTOverlay::TRTOverlay(const std::string &name, ISvcLocator *pSvcLocator)
65 : AthReentrantAlgorithm(name, pSvcLocator)
66{
67}
68
70{
71 ATH_MSG_DEBUG("Initializing...");
72
73 // Check and initialize keys
74 ATH_CHECK( m_bkgInputKey.initialize(!m_bkgInputKey.key().empty()) );
75 ATH_MSG_VERBOSE("Initialized ReadHandleKey: " << m_bkgInputKey);
76 ATH_CHECK( m_signalInputKey.initialize() );
77 ATH_MSG_VERBOSE("Initialized ReadHandleKey: " << m_signalInputKey);
78 ATH_CHECK( m_outputKey.initialize() );
79 ATH_MSG_VERBOSE("Initialized WriteHandleKey: " << m_outputKey);
80 ATH_CHECK( m_signalInputSDOKey.initialize() );
81 ATH_MSG_VERBOSE("Initialized ReadHandleKey for SDO: " << m_signalInputSDOKey);
82 ATH_CHECK( m_strawStatusHTKey.initialize() );
83 ATH_MSG_VERBOSE("Initialized ReadCondHandleKey: " << m_strawStatusHTKey);
84
85 // Retrieve TRT ID helper
86 if (!detStore()->retrieve(m_trtId, "TRT_ID").isSuccess() || !m_trtId) {
87 ATH_MSG_FATAL("Cannot retrieve TRT ID helper");
88 return StatusCode::FAILURE;
89 }
90
91 // Initialize random number generator
92 CHECK(m_rndmSvc.retrieve());
93
94 // Retrieve TRT local occupancy tool
96
97 return StatusCode::SUCCESS;
98}
99
100
101StatusCode TRTOverlay::execute(const EventContext& ctx) const
102{
103 ATH_MSG_DEBUG("execute() begin");
104
105 // Reading the input RDOs
106 const TRT_RDO_Container *bkgContainerPtr = nullptr;
107 if (!m_bkgInputKey.empty()) {
109 if (!bkgContainer.isValid()) {
110 ATH_MSG_ERROR("Could not get background TRT RDO container " << bkgContainer.name() << " from store " << bkgContainer.store());
111 return StatusCode::FAILURE;
112 }
113 bkgContainerPtr = bkgContainer.cptr();
114
115 ATH_MSG_DEBUG("Found background TRT RDO container " << bkgContainer.name() << " in store " << bkgContainer.store());
116 ATH_MSG_DEBUG("TRT Background = " << Overlay::debugPrint(bkgContainer.cptr()));
117 }
118
120 if (!signalContainer.isValid()) {
121 ATH_MSG_ERROR("Could not get signal TRT RDO container " << signalContainer.name() << " from store " << signalContainer.store());
122 return StatusCode::FAILURE;
123 }
124 ATH_MSG_DEBUG("Found signal TRT RDO container " << signalContainer.name() << " in store " << signalContainer.store());
125 ATH_MSG_DEBUG("TRT Signal = " << Overlay::debugPrint(signalContainer.cptr()));
126
128 if (!signalSDOContainer.isValid()) {
129 ATH_MSG_ERROR("Could not get signal TRT SDO map container " << signalSDOContainer.name() << " from store " << signalSDOContainer.store());
130 return StatusCode::FAILURE;
131 }
132 ATH_MSG_DEBUG("Found signal TRT SDO map container " << signalSDOContainer.name() << " in store " << signalSDOContainer.store());
133
134 // The DataPool, this is what will actually own the elements
135 // we create during this algorithm. The containers are
136 // views.
137 DataPool<TRT_LoLumRawData> dataItemsPool(ctx);
138 dataItemsPool.prepareToAdd(200000);
139
140 // Creating output RDO container
142 ATH_CHECK(outputContainer.record(std::make_unique<TRT_RDO_Container>(signalContainer->size())));
143 if (!outputContainer.isValid()) {
144 ATH_MSG_ERROR("Could not record output TRT RDO container " << outputContainer.name() << " to store " << outputContainer.store());
145 return StatusCode::FAILURE;
146 }
147 ATH_MSG_DEBUG("Recorded output TRT RDO container " << outputContainer.name() << " in store " << outputContainer.store());
148
149 ATH_CHECK(overlayContainer(ctx, bkgContainerPtr, signalContainer.cptr(),
150 outputContainer.ptr(), signalSDOContainer.cptr(),
151 dataItemsPool));
153 "TRT Result = " << Overlay::debugPrint(outputContainer.ptr()));
154
155 ATH_MSG_DEBUG("execute() end");
156 return StatusCode::SUCCESS;
157}
158
159
160StatusCode TRTOverlay::overlayContainer(const EventContext &ctx,
161 const TRT_RDO_Container *bkgContainer,
162 const TRT_RDO_Container *signalContainer,
163 TRT_RDO_Container *outputContainer,
164 const InDetSimDataCollection *signalSDOCollection,
165 DataPool<TRT_LoLumRawData>& dataItemsPool) const
166{
167
168 // There are some use cases where background is empty
169 if (!bkgContainer) {
170 // Only loop through the signal collections and copy them over
171 for (const auto [hashId, ptr] : signalContainer->GetAllHashPtrPair()) {
172 // Copy the signal collection
173 // pools own the individual elements
174 std::unique_ptr<TRT_RDO_Collection> signalCollection = copyCollection(hashId, ptr, dataItemsPool);
175
176 if (outputContainer->addCollection(signalCollection.get(), hashId).isFailure()) {
177 ATH_MSG_ERROR("Adding signal Collection with hashId " << hashId << " failed");
178 return StatusCode::FAILURE;
179 } else {
180 (void)signalCollection.release();
181 }
182 }
183
184 return StatusCode::SUCCESS;
185 }
186
187 // Setup the random engine
188 ATHRNG::RNGWrapper* rngWrapper = m_rndmSvc->getEngine(this);
189 rngWrapper->setSeed( name(), ctx );
190 CLHEP::HepRandomEngine *rndmEngine = rngWrapper->getEngine(ctx);
191
192 // Load TRT conditions
194 const TRTCond::StrawStatusData *strawStatusHT{*strawStatusHTHandle};
195
196 // Retrieve the occupancy map
197 std::map<int, double> occupancyMap = m_TRT_LocalOccupancyTool->getDetectorOccupancy(ctx, bkgContainer);
198
199 // The MC signal container should typically be smaller than bkgContainer,
200 // because the latter contains all the noise, minimum bias and pile up.
201 // Thus we firstly iterate over signal hashes and store them in a map.
202 std::vector < std::pair<IdentifierHash, bool> > overlapMap;
203 overlapMap.reserve(signalContainer->numberOfCollections());
204 for (const auto [hashId, ptr] : signalContainer->GetAllHashPtrPair()) {
205 overlapMap.emplace_back(hashId, false);
206 }
207
208 // Now loop through the background hashes and copy unique ones over
209 for (const auto [hashId, ptr] : bkgContainer->GetAllHashPtrPair()) {
210 auto search = std::lower_bound( overlapMap.begin(), overlapMap.end(), hashId,
211 [](const std::pair<IdentifierHash, bool> &lhs, IdentifierHash rhs) -> bool { return lhs.first < rhs; } );
212 if (search == overlapMap.end() || search->first != hashId) {
213 // Copy the background collection
214 std::unique_ptr<TRT_RDO_Collection> bkgCollection{};
215 if (m_sortBkgInput) {
216 // copy the bkg again Pool owns the individual elements
217 bkgCollection = copyCollectionAndSort(hashId, bkgContainer->indexFindPtr(hashId),dataItemsPool);
218 } else {
219 bkgCollection = copyCollection(hashId, bkgContainer->indexFindPtr(hashId),dataItemsPool);
220 }
221
222 if (outputContainer->addCollection(bkgCollection.get(), hashId).isFailure()) {
223 ATH_MSG_ERROR("Adding background Collection with hashId " << hashId << " failed");
224 return StatusCode::FAILURE;
225 } else {
226 //coverity[RESOURCE_LEAK]
227 (void)bkgCollection.release();
228 }
229 } else {
230 // Flip the overlap flag
231 search->second = true;
232 }
233 }
234
235 // Finally loop through the map and process the signal and overlay if
236 // necessary
237 for (const auto &[hashId, overlap] : overlapMap) {
238 // Copy the signal collection the pool owns the individual elements
239 std::unique_ptr<TRT_RDO_Collection> signalCollection =
240 copyCollection(hashId, signalContainer->indexFindPtr(hashId),dataItemsPool);
241
242 if (overlap) { // Do overlay
243 // Create the output collection, only works for Inner Detector
244 auto outputCollection = std::make_unique<TRT_RDO_Collection>(hashId);
245 outputCollection->setIdentifier(signalCollection->identify());
246 // This will receive merged elements from the other containers.
247 // There elements are owned actually by the DataPool
248 outputCollection->clear(SG::VIEW_ELEMENTS);
249
250 // Copy the background collection the pool owns the individual elements
251 std::unique_ptr<TRT_RDO_Collection> bkgCollection{};
252 if (m_sortBkgInput) {
253 bkgCollection = copyCollectionAndSort(hashId, bkgContainer->indexFindPtr(hashId),dataItemsPool);
254 } else {
255 bkgCollection = copyCollection(hashId, bkgContainer->indexFindPtr(hashId),dataItemsPool);
256 }
257
258 // Merge collections
259 int det = m_trtId->barrel_ec(signalCollection->identify());
260 mergeCollections(bkgCollection.get(),
261 signalCollection.get(),
262 outputCollection.get(),
263 occupancyMap[det],
264 signalSDOCollection,
265 strawStatusHT,
266 rndmEngine);
267
268 if (outputContainer->addCollection(outputCollection.get(), hashId).isFailure()) {
269 ATH_MSG_ERROR("Adding overlaid Collection with hashId " << hashId << " failed");
270 return StatusCode::FAILURE;
271 } else {
272 outputCollection.release();
273 }
274 } else { // Only write signal out
275 if (outputContainer->addCollection(signalCollection.get(), hashId).isFailure()) {
276 ATH_MSG_ERROR("Adding signal Collection with hashId " << hashId << " failed");
277 return StatusCode::FAILURE;
278 } else {
279 (void)signalCollection.release();
280 }
281 }
282 }
283
284 return StatusCode::SUCCESS;
285}
286
290 TRT_RDO_Collection *signalCollection,
291 TRT_RDO_Collection *outputCollection,
292 double occupancy,
293 const InDetSimDataCollection *signalSDOCollection,
294 const TRTCond::StrawStatusData *strawStatusHT,
295 CLHEP::HepRandomEngine *rndmEngine) const
296{
297 if (bkgCollection->identify() != signalCollection->identify()) {
298 throw std::runtime_error("mergeCollections(): collection Id mismatch");
299 }
300
301 // Merge by copying ptrs from background and signal to output collection
302 TRT_RDO_Collection::size_type ibkg = 0, isig = 0;
303
304 outputCollection->reserve(
305 std::max(bkgCollection->size(), signalCollection->size()));
306 // Below we have swapElements.
307 // Remember the elements of the signalCollection and bkgCollection
308 // containers are owned by the DataPool.
309 // tmpBkg and tmp are whaterver elements we take out of the containers.
310 //
311 // So
312 // A) We can not delete them. dataPool will do that at the end of the event.
313 // B) We can push them back only to a View so outputCollection is a view
314 // collection
315 // C) We pass nullptr so no need to get another item from the pool
316
317 while ((ibkg < bkgCollection->size()) || (isig < signalCollection->size())) {
318 // The RDO that goes to the output at the end of this step.
319 TRT_RDORawData *tmp{};
320
321 if (isig == signalCollection->size()) {
322 // just copy the remaining background digits
323 bkgCollection->swapElement(ibkg++, nullptr, tmp);
324 } else if (ibkg == bkgCollection->size()) {
325 // just copy the remaining signal digits
326 signalCollection->swapElement(isig++, nullptr, tmp);
327 } else {
328 // Need to decide which one goes first.
329 // See comments in TRTDigitization.cxx about the assumption that id1<id2 <=> hash1<hash2
330 if (signalCollection->at(isig)->identify() < bkgCollection->at(ibkg)->identify()) {
331 signalCollection->swapElement(isig++, nullptr, tmp);
332 } else if (bkgCollection->at(ibkg)->identify() < signalCollection->at(isig)->identify()) {
333 bkgCollection->swapElement(ibkg++, nullptr, tmp);
334 } else {
335 // The hits are on the same channel.
336 TRT_RDORawData *tmpBkg{};
337
338 bkgCollection->swapElement(ibkg++, nullptr, tmpBkg);
339 signalCollection->swapElement(isig++, nullptr, tmp);
340
341 TRT_LoLumRawData *sigRdo = dynamic_cast<TRT_LoLumRawData *>(tmp);
342 const TRT_LoLumRawData *bkgRdo = dynamic_cast<const TRT_LoLumRawData *>(tmpBkg);
343
344 if (sigRdo && bkgRdo) {
345 // the actual merging
346 sigRdo->merge(*bkgRdo);
347
348 // If the hit is not already a high level hit
349 if (!(sigRdo->getWord() & 0x04020100)) {
350 // Determine if the hit is from an electron or not
351 bool isElectron = false;
352 Identifier rdoId = sigRdo->identify();
353 InDetSimDataCollection::const_iterator sdoIter = signalSDOCollection->find(rdoId);
354 if (sdoIter != signalSDOCollection->end()) {
355 const std::vector<InDetSimData::Deposit> &deposits = sdoIter->second.getdeposits();
356 for (const InDetSimData::Deposit &deposit : deposits) {
357 const HepMcParticleLink &particleLink = deposit.first;
358 if (particleLink.isValid()) {
359 if (std::abs(particleLink->pdg_id()) == 11) {
360 isElectron = true;
361 break;
362 }
363 }
364 }
365 }
366
367 // Determine what type of straw was hit
368 bool isXenonStraw = false;
369 if (strawStatusHT != nullptr) {
370 if (strawStatusHT->findStatus(m_trtId->straw_hash(rdoId)) == TRTCond::StrawStatus::Good) {
371 isXenonStraw = true;
372 }
373 }
374
375 // Get random number
376 int det = m_trtId->barrel_ec(rdoId);
377 float HTOccupancyCorrection = 0.;
378 if (isXenonStraw) {
379 if (isElectron) {
380 HTOccupancyCorrection = std::abs(det) > 1 ? m_HTOccupancyCorrectionEC : m_HTOccupancyCorrectionB;
381 } else {
382 HTOccupancyCorrection = std::abs(det) > 1 ? m_HTOccupancyCorrectionEC_noE : m_HTOccupancyCorrectionB_noE;
383 }
384 } else {
385 if (isElectron) {
386 HTOccupancyCorrection = std::abs(det) > 1 ? m_HTOccupancyCorrectionEC_Ar : m_HTOccupancyCorrectionB_Ar;
387 } else {
388 HTOccupancyCorrection = std::abs(det) > 1 ? m_HTOccupancyCorrectionEC_Ar_noE : m_HTOccupancyCorrectionB_Ar_noE;
389 }
390 }
391
392 unsigned int newWord = 0;
393 if (HTOccupancyCorrection != 0. && occupancy * HTOccupancyCorrection > CLHEP::RandFlat::shoot(rndmEngine, 0, 1)) {
394 newWord += 1 << (26-9);
395 }
396
397 TRT_LoLumRawData newRdo(rdoId, newWord);
398 sigRdo->merge(newRdo);
399 }
400 } else {
401 ATH_MSG_WARNING("TRT RDO is the wrong format");
402 }
403 }
404 }
405
406 outputCollection->push_back(tmp);
407 } // <= while
408}
#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_WARNING(x)
#define ATH_MSG_DEBUG(x)
bool isElectron(const T &p)
Definition AtlasPID.h:202
#define CHECK(...)
Evaluate an expression and check for errors.
void operator()(T1)
Handle class for reading from StoreGate.
Handle class for recording to StoreGate.
size_t size() const
Number of registered mappings.
This is an Identifier helper class for the TRT subdetector.
InDetRawDataCollection< TRT_RDORawData > TRT_RDO_Collection
InDetRawDataContainer< InDetRawDataCollection< TRT_RDORawData > > TRT_RDO_Container
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
const ServiceHandle< StoreGateSvc > & detStore() const
An algorithm that can be simultaneously executed in multiple threads.
a typed memory pool that saves time spent allocation small object.
Definition DataPool.h:63
pointer nextElementPtr()
obtain the next available element in pool by pointer pool is resized if its limit has been reached On...
void prepareToAdd(unsigned int size)
Prepare to add cached elements.
typename DataVectorBase< TRT_RDORawData >::Base::size_type size_type
Definition DataVector.h:814
const RawDataT * at(size_type n) const
void swapElement(size_type index, value_type newElem, reference oldElem)
size_type size() const noexcept
virtual size_t numberOfCollections() const override final
return number of collections
virtual const T * indexFindPtr(IdentifierHash hashId) const override final
return pointer on the found entry or null if out of range using hashed index - fast version,...
virtual StatusCode addCollection(const T *coll, IdentifierHash hashId) override final
insert collection into container with id hash if IDC should not take ownership of collection,...
This is a "hash" representation of an Identifier.
virtual Identifier identify() const override final
void merge(const InDetRawData &other)
virtual Identifier identify() const override final
unsigned int getWord() const
std::pair< HepMcParticleLink, float > Deposit
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?
pointer_type ptr()
Dereference the pointer.
unsigned int findStatus(const IdentifierHash &hashID) const
Gaudi::Property< double > m_HTOccupancyCorrectionB_noE
Definition TRTOverlay.h:86
virtual StatusCode initialize() override final
virtual StatusCode execute(const EventContext &ctx) const override final
Gaudi::Property< double > m_HTOccupancyCorrectionEC_noE
Definition TRTOverlay.h:88
Gaudi::Property< double > m_HTOccupancyCorrectionB_Ar_noE
Definition TRTOverlay.h:94
Gaudi::Property< double > m_HTOccupancyCorrectionB_Ar
Definition TRTOverlay.h:90
SG::WriteHandleKey< TRT_RDO_Container > m_outputKey
Definition TRTOverlay.h:68
Gaudi::Property< double > m_HTOccupancyCorrectionEC_Ar
Definition TRTOverlay.h:92
Gaudi::Property< double > m_HTOccupancyCorrectionEC
Definition TRTOverlay.h:84
Gaudi::Property< bool > m_sortBkgInput
Definition TRTOverlay.h:59
StatusCode overlayContainer(const EventContext &ctx, const TRT_RDO_Container *bkgContainer, const TRT_RDO_Container *signalContainer, TRT_RDO_Container *outputContainer, const InDetSimDataCollection *signalSDOCollection, DataPool< TRT_LoLumRawData > &dataItemsPool) const
void mergeCollections(TRT_RDO_Collection *bkgCollection, TRT_RDO_Collection *signalCollection, TRT_RDO_Collection *outputCollection, double occupancy, const InDetSimDataCollection *signalSDOCollection, const TRTCond::StrawStatusData *strawStatusHT, CLHEP::HepRandomEngine *rndmEngine) const
Here we take 2 view containers with elements owned by the DataPool we modify some of them and push th...
SG::ReadHandleKey< TRT_RDO_Container > m_bkgInputKey
Definition TRTOverlay.h:62
ToolHandle< InDet::ITRT_LocalOccupancy > m_TRT_LocalOccupancyTool
Definition TRTOverlay.h:98
ServiceHandle< IAthRNGSvc > m_rndmSvc
Definition TRTOverlay.h:79
SG::ReadHandleKey< InDetSimDataCollection > m_signalInputSDOKey
Definition TRTOverlay.h:71
Gaudi::Property< double > m_HTOccupancyCorrectionB
Definition TRTOverlay.h:82
Gaudi::Property< double > m_HTOccupancyCorrectionEC_Ar_noE
Definition TRTOverlay.h:96
TRTOverlay(const std::string &name, ISvcLocator *pSvcLocator)
SG::ReadHandleKey< TRT_RDO_Container > m_signalInputKey
Definition TRTOverlay.h:65
SG::ReadCondHandleKey< TRTCond::StrawStatusData > m_strawStatusHTKey
Definition TRTOverlay.h:74
const TRT_ID * m_trtId
Definition TRTOverlay.h:57
void search(TDirectory *td, const std::string &s, std::string cwd, node *n)
recursive directory search for TH1 and TH2 and TProfiles
Definition hcg.cxx:743
std::string debugPrint(const IDC_Container *container, unsigned numprint=25)
Diagnostic output of Identifiable Containers.
std::unique_ptr< HGTD_RDO_Collection > copyCollection(const IdentifierHash &hashId, const HGTD_RDO_Collection *collection)
@ VIEW_ELEMENTS
this data object is a view, it does not own its elmts
void stable_sort(DataModel_detail::iterator< DVL > beg, DataModel_detail::iterator< DVL > end)
Specialization of stable_sort for DataVector/List.