ATLAS Offline Software
Loading...
Searching...
No Matches
TRTOverlay.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 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 (void)bkgCollection.release();
227 }
228 } else {
229 // Flip the overlap flag
230 search->second = true;
231 }
232 }
233
234 // Finally loop through the map and process the signal and overlay if
235 // necessary
236 for (const auto &[hashId, overlap] : overlapMap) {
237 // Copy the signal collection the pool owns the individual elements
238 std::unique_ptr<TRT_RDO_Collection> signalCollection =
239 copyCollection(hashId, signalContainer->indexFindPtr(hashId),dataItemsPool);
240
241 if (overlap) { // Do overlay
242 // Create the output collection, only works for Inner Detector
243 auto outputCollection = std::make_unique<TRT_RDO_Collection>(hashId);
244 outputCollection->setIdentifier(signalCollection->identify());
245 // This will receive merged elements from the other containers.
246 // There elements are owned actually by the DataPool
247 outputCollection->clear(SG::VIEW_ELEMENTS);
248
249 // Copy the background collection the pool owns the individual elements
250 std::unique_ptr<TRT_RDO_Collection> bkgCollection{};
251 if (m_sortBkgInput) {
252 bkgCollection = copyCollectionAndSort(hashId, bkgContainer->indexFindPtr(hashId),dataItemsPool);
253 } else {
254 bkgCollection = copyCollection(hashId, bkgContainer->indexFindPtr(hashId),dataItemsPool);
255 }
256
257 // Merge collections
258 int det = m_trtId->barrel_ec(signalCollection->identify());
259 mergeCollections(bkgCollection.get(),
260 signalCollection.get(),
261 outputCollection.get(),
262 occupancyMap[det],
263 signalSDOCollection,
264 strawStatusHT,
265 rndmEngine);
266
267 if (outputContainer->addCollection(outputCollection.get(), hashId).isFailure()) {
268 ATH_MSG_ERROR("Adding overlaid Collection with hashId " << hashId << " failed");
269 return StatusCode::FAILURE;
270 } else {
271 outputCollection.release();
272 }
273 } else { // Only write signal out
274 if (outputContainer->addCollection(signalCollection.get(), hashId).isFailure()) {
275 ATH_MSG_ERROR("Adding signal Collection with hashId " << hashId << " failed");
276 return StatusCode::FAILURE;
277 } else {
278 (void)signalCollection.release();
279 }
280 }
281 }
282
283 return StatusCode::SUCCESS;
284}
285
289 TRT_RDO_Collection *signalCollection,
290 TRT_RDO_Collection *outputCollection,
291 double occupancy,
292 const InDetSimDataCollection *signalSDOCollection,
293 const TRTCond::StrawStatusData *strawStatusHT,
294 CLHEP::HepRandomEngine *rndmEngine) const
295{
296 if (bkgCollection->identify() != signalCollection->identify()) {
297 throw std::runtime_error("mergeCollections(): collection Id mismatch");
298 }
299
300 // Merge by copying ptrs from background and signal to output collection
301 TRT_RDO_Collection::size_type ibkg = 0, isig = 0;
302
303 outputCollection->reserve(
304 std::max(bkgCollection->size(), signalCollection->size()));
305 // Below we have swapElements.
306 // Remember the elements of the signalCollection and bkgCollection
307 // containers are owned by the DataPool.
308 // tmpBkg and tmp are whaterver elements we take out of the containers.
309 //
310 // So
311 // A) We can not delete them. dataPool will do that at the end of the event.
312 // B) We can push them back only to a View so outputCollection is a view
313 // collection
314 // C) We pass nullptr so no need to get another item from the pool
315
316 while ((ibkg < bkgCollection->size()) || (isig < signalCollection->size())) {
317 // The RDO that goes to the output at the end of this step.
318 TRT_RDORawData *tmp{};
319
320 if (isig == signalCollection->size()) {
321 // just copy the remaining background digits
322 bkgCollection->swapElement(ibkg++, nullptr, tmp);
323 } else if (ibkg == bkgCollection->size()) {
324 // just copy the remaining signal digits
325 signalCollection->swapElement(isig++, nullptr, tmp);
326 } else {
327 // Need to decide which one goes first.
328 // See comments in TRTDigitization.cxx about the assumption that id1<id2 <=> hash1<hash2
329 if (signalCollection->at(isig)->identify() < bkgCollection->at(ibkg)->identify()) {
330 signalCollection->swapElement(isig++, nullptr, tmp);
331 } else if (bkgCollection->at(ibkg)->identify() < signalCollection->at(isig)->identify()) {
332 bkgCollection->swapElement(ibkg++, nullptr, tmp);
333 } else {
334 // The hits are on the same channel.
335 TRT_RDORawData *tmpBkg{};
336
337 bkgCollection->swapElement(ibkg++, nullptr, tmpBkg);
338 signalCollection->swapElement(isig++, nullptr, tmp);
339
340 TRT_LoLumRawData *sigRdo = dynamic_cast<TRT_LoLumRawData *>(tmp);
341 const TRT_LoLumRawData *bkgRdo = dynamic_cast<const TRT_LoLumRawData *>(tmpBkg);
342
343 if (sigRdo && bkgRdo) {
344 // the actual merging
345 sigRdo->merge(*bkgRdo);
346
347 // If the hit is not already a high level hit
348 if (!(sigRdo->getWord() & 0x04020100)) {
349 // Determine if the hit is from an electron or not
350 bool isElectron = false;
351 Identifier rdoId = sigRdo->identify();
352 InDetSimDataCollection::const_iterator sdoIter = signalSDOCollection->find(rdoId);
353 if (sdoIter != signalSDOCollection->end()) {
354 const std::vector<InDetSimData::Deposit> &deposits = sdoIter->second.getdeposits();
355 for (const InDetSimData::Deposit &deposit : deposits) {
356 const HepMcParticleLink &particleLink = deposit.first;
357 if (particleLink.isValid()) {
358 if (std::abs(particleLink->pdg_id()) == 11) {
359 isElectron = true;
360 break;
361 }
362 }
363 }
364 }
365
366 // Determine what type of straw was hit
367 bool isXenonStraw = false;
368 if (strawStatusHT != nullptr) {
369 if (strawStatusHT->findStatus(m_trtId->straw_hash(rdoId)) == TRTCond::StrawStatus::Good) {
370 isXenonStraw = true;
371 }
372 }
373
374 // Get random number
375 int det = m_trtId->barrel_ec(rdoId);
376 float HTOccupancyCorrection = 0.;
377 if (isXenonStraw) {
378 if (isElectron) {
379 HTOccupancyCorrection = std::abs(det) > 1 ? m_HTOccupancyCorrectionEC : m_HTOccupancyCorrectionB;
380 } else {
381 HTOccupancyCorrection = std::abs(det) > 1 ? m_HTOccupancyCorrectionEC_noE : m_HTOccupancyCorrectionB_noE;
382 }
383 } else {
384 if (isElectron) {
385 HTOccupancyCorrection = std::abs(det) > 1 ? m_HTOccupancyCorrectionEC_Ar : m_HTOccupancyCorrectionB_Ar;
386 } else {
387 HTOccupancyCorrection = std::abs(det) > 1 ? m_HTOccupancyCorrectionEC_Ar_noE : m_HTOccupancyCorrectionB_Ar_noE;
388 }
389 }
390
391 unsigned int newWord = 0;
392 if (HTOccupancyCorrection != 0. && occupancy * HTOccupancyCorrection > CLHEP::RandFlat::shoot(rndmEngine, 0, 1)) {
393 newWord += 1 << (26-9);
394 }
395
396 TRT_LoLumRawData newRdo(rdoId, newWord);
397 sigRdo->merge(newRdo);
398 }
399 } else {
400 ATH_MSG_WARNING("TRT RDO is the wrong format");
401 }
402 }
403 }
404
405 outputCollection->push_back(tmp);
406 } // <= while
407}
#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.
Handle class for reading from StoreGate.
Handle class for recording to StoreGate.
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:169
CLHEP::HepRandomEngine * getEngine(const EventContext &ctx) const
Retrieve the random engine corresponding to the provided EventContext.
Definition RNGWrapper.h:134
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
const std::vector< EventContainers::hashPair< T > > & GetAllHashPtrPair() const
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:739
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.