ATLAS Offline Software
Loading...
Searching...
No Matches
PileUpMergeSvc.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
9#include "SGTools/DataProxy.h"
10#include "SGTools/DataStore.h"
12
13#include "EventInfo/EventInfo.h"
14#include "EventInfo/EventID.h"
15#include "EventInfo/EventType.h"
19
20#include "xAODEventInfo/EventInfo.h" // NEW EDM
21#include "xAODEventInfo/EventAuxInfo.h" // NEW EDM
22#include "xAODEventInfo/EventInfoContainer.h" // NEW EDM
23#include "xAODEventInfo/EventInfoAuxContainer.h" // NEW EDM
24
25#include "GaudiKernel/ISvcLocator.h"
26#include "GaudiKernel/IAlgTool.h"
27#include "GaudiKernel/GaudiException.h"
28#include "GaudiKernel/TypeNameString.h"
29#include "GaudiKernel/MsgStream.h"
30#include <algorithm>
31#include <cstdlib> /* random */
32#include <functional>
33#include <string>
34
35using std::make_pair;
36using std::string;
37
39PileUpMergeSvc::PileUpMergeSvc(const std::string& name,ISvcLocator* svc)
40 : AthService(name,svc),
41 p_overStore("StoreGateSvc", "StoreGateSvc")
42{
43}
44
47 if (m_intervals.retrieve().isSuccess()) {
48 ToolHandleArray<IPileUpXingFolder>::const_iterator
49 iXing(m_intervals.begin()), iEnd(m_intervals.end());
50 while (iXing != iEnd) {
51 const IPileUpXingFolder& xing(**iXing);
52 if (msg().level() <= MSG::DEBUG) {
53 msg() << MSG::DEBUG << "decodeIntervals: adding IPileUpXingFolder "
54 << xing.name() << endmsg;
55 }
57 item(xing.begin()), endItem(xing.end());
58 while(item != endItem) {
59 m_ranges[make_pair(item->id(), item->key())]=
60 Range(xing.firstXing(), xing.lastXing(), xing.cacheRefreshFrequency());
61 if (msg().level() <= MSG::VERBOSE) {
62 msg() << MSG::VERBOSE
63 << "decodeInterval: accepting objects of CLID " << item->id()
64 << " key " << item->key() << " in the Xing range ["
65 << xing.firstXing() << ", " << xing.lastXing() << ']'
66 << " with cache refresh frequency "
67 << xing.cacheRefreshFrequency() << endmsg;
68 }
69 ++item;
70 }
71 ++iXing;
72 }
73 }
74}
75
78StatusCode
80
81 msg() << MSG::INFO << "Initializing " << name() << ", using (xAOD::)EventInfo " << m_EventInfoKeyName << endmsg;
82
83 m_autoRetrieveTools = false;
84 m_checkToolDeps = false;
85
86 // set up the SG service:
87 if ( !(p_overStore.retrieve()).isSuccess() )
88 {
89 msg() << MSG::FATAL
90 << "Could not locate default store"
91 << endmsg;
92 return StatusCode::FAILURE;
93 }
94 if (!m_pITriggerTime.empty() && !(m_pITriggerTime.retrieve()).isSuccess() )
95 {
96 msg() << MSG::FATAL
97 << "Could not locate ITriggerTime tool"
98 << endmsg;
99 return StatusCode::FAILURE;
100 }
101 // Retrieve the converter tool:
102 CHECK(m_xAODCnvTool.retrieve());
103
105
106 // Initialize service:
107 return StatusCode::SUCCESS;
108
109}
110
111
112const xAOD::EventInfo* PileUpMergeSvc::getPileUpEvent( StoreGateSvc* sg, const std::string& einame )
113{
114 const EventContext& ctx = Gaudi::Hive::currentContext();
115
116 if( !sg ) sg = p_overStore.get();
117 const xAOD::EventInfo* xAODEventInfo = einame.empty()?
119 : sg->tryConstRetrieve<xAOD::EventInfo>( einame );
120 if( xAODEventInfo ) {
121 ATH_MSG_DEBUG("Found xAOD::EventInfo="<<xAODEventInfo<<" SG="<<sg<<" : "<<*xAODEventInfo);
122 ATH_MSG_DEBUG(" EventInfo has " << xAODEventInfo->subEvents().size() << " subevents" );
123 // recreate subevent links cache
124 xAODEventInfo->subEvents();
125 } else {
126 // Don't allow more than one thread per slot through here.
127 // Otherwise, we can get errors with multiple threads trying
128 // to record the EventInfo object.
129 std::lock_guard<std::mutex> lock (*m_slotMutex);
130
131 // Try reading old EventInfo
132 const EventInfo* pEvent = einame.empty()?
134 : sg->tryConstRetrieve< ::EventInfo >( einame );
135 if( pEvent ) {
136 ATH_MSG_DEBUG("Converting (PileUp)EventInfo "<<pEvent<<" SG="<<sg<<" to xAOD::EventInfo");
137 // Create the xAOD object(s):
138 std::unique_ptr< xAOD::EventInfo > pxAODEventInfo( new xAOD::EventInfo() );
139 std::unique_ptr< xAOD::EventAuxInfo > pxAODEventAuxInfo(new xAOD::EventAuxInfo());
140 pxAODEventInfo->setStore( pxAODEventAuxInfo.get() );
141 pxAODEventInfo->setEvtStore( sg );
142 if( !m_xAODCnvTool->convert( ctx, pEvent, pxAODEventInfo.get(), true, false ).isSuccess() ) {
143 ATH_MSG_ERROR("Failed to convert xAOD::EventInfo in SG");
144 return nullptr;
145 }
146
147 const PileUpEventInfo* pileupEvent(dynamic_cast<const PileUpEventInfo*>(pEvent));
148 if( pileupEvent ) {
149 // Create an EventInfoContainer for the pileup events:
150 std::unique_ptr< xAOD::EventInfoContainer > puei(new xAOD::EventInfoContainer());
151 std::unique_ptr< xAOD::EventInfoAuxContainer > puaux(new xAOD::EventInfoAuxContainer());
152 puei->setStore( puaux.get() );
153
154 // Sub-events for the main EventInfo object:
155 std::vector< xAOD::EventInfo::SubEvent > subEvents;
156
157 // A map translating between the AOD and xAOD pileup event types:
158 static const std::map< PileUpEventInfo::SubEvent::pileup_type,
159 xAOD::EventInfo::PileUpType > pileupTypeMap = {
160#define DECLARE_SE_TYPE( TYPE ) \
161 { PileUpTimeEventIndex::TYPE, xAOD::EventInfo::TYPE },
162
164 DECLARE_SE_TYPE( Signal )
165 DECLARE_SE_TYPE( MinimumBias )
166 DECLARE_SE_TYPE( Cavern )
167 DECLARE_SE_TYPE( HaloGas )
168 DECLARE_SE_TYPE( ZeroBias )
169
170#undef DECLARE_SE_TYPE
171 };
172
173 // A convenience type declaration:
175
176 // Create xAOD::EventInfo objects for each pileup EventInfo object:
177 auto pu_itr = pileupEvent->beginSubEvt();
178 auto pu_end = pileupEvent->endSubEvt();
179 const unsigned int countEvents = std::distance(pu_itr,pu_end);
180 ATH_MSG_VERBOSE( "CHECKING: There are " << countEvents << " subevents in this Event." );
181 for( ; pu_itr != pu_end; ++pu_itr ) {
182 // Create a new xAOD::EventInfo object:
183 std::unique_ptr< xAOD::EventInfo > ei( new xAOD::EventInfo() );
184 // Fill it with information:
185 if( ! m_xAODCnvTool->convert( ctx, pu_itr->pSubEvt, ei.get(), true, false ).isSuccess() ) {
186 ATH_MSG_ERROR("Failed to convert EventInfo to xAOD::EventInfo");
187 continue;
188 }
189
190 StoreGateSvc* tmpSG = pu_itr->pSubEvtSG;
191 if(tmpSG) {
192 ei->setEvtStore(tmpSG);
193 ATH_MSG_VERBOSE("FOUND A STOREGATE");
194 } else {
195 ATH_MSG_ERROR("FAILED TO FIND A STOREGATE");
196 }
197 // Store new EI into the container
198 puei->push_back( ei.release() );
199
200 // And now add a sub-event to the temporary list:
201 auto typeItr = pileupTypeMap.find( pu_itr->type() );
203 if( typeItr == pileupTypeMap.end() ) {
204 ATH_MSG_WARNING( "PileUpType not recognised: " << pu_itr->type() );
205 } else {
206 type = typeItr->second;
207 }
208 ATH_MSG_VERBOSE("PileUpEventInfo: time = " << pu_itr->time() << ", index = " << pu_itr->index());
209 subEvents.push_back( xAOD::EventInfo::SubEvent( pu_itr->time(),
210 pu_itr->index(),
211 type,
212 EiLink( "PileUpEventInfo", puei->size()-1, sg ))); // p_SG?
213 ATH_MSG_VERBOSE("PileUpEventInfo: time = " << subEvents.back().time() << ", index = " << subEvents.back().index());
214 }
215
216 if( subEvents.size() ) {
217 // And now update the main EventInfo object with the sub-events:
218 pxAODEventInfo->setSubEvents( subEvents );
219
220 // Record the xAOD object(s):
221 if( !sg->record( std::move( puaux ), "PileUpEventInfoAux." ).isSuccess()
222 || !sg->record( std::move( puei ), "PileUpEventInfo" ).isSuccess() ) { //MN: FIX - make keys configurable
223 ATH_MSG_ERROR("Failed to record xAOD::EventInfoContainer in SG");
224 }
225 }
226 }
227 // remember pointer to return the new EventInfo
228 // the std::launder avoids a cppcheck warning by breaking
229 // the lifetime connection between the pointer and the unique_ptr.
230 xAODEventInfo = std::launder(pxAODEventInfo.get());
231 // Record the xAOD object(s):
232 const auto ptrVal = pxAODEventInfo.get();//for use in dbg message
233 if( ! sg->record( std::move( pxAODEventAuxInfo ), "EventInfoAux." ).isSuccess() //MN: FIX? key
234 || ! sg->record( std::move( pxAODEventInfo ), "EventInfo" ).isSuccess() ) {
235 ATH_MSG_ERROR("Failed to record the new xAOD::EventInfo in SG");
236 xAODEventInfo = nullptr;
237 }
238 ATH_MSG_DEBUG("Record the new xAOD::EventInfo "<<ptrVal<<" in SG="<<sg);
239 }
240 }
241
242 if( !xAODEventInfo ) {
243 ATH_MSG_DEBUG("Could not find EventInfo '" << einame << "' in store " << sg->name());
244 }
245 return xAODEventInfo;
246}
247
248
249const xAOD::EventInfo* PileUpMergeSvc::getPileUpEvent( const EventContext& ctx, const std::string& einame )
250{
251 auto* sg = dynamic_cast<StoreGateSvc*> (Atlas::proxyDictFromEventContext(ctx));
252 return getPileUpEvent (sg, einame);
253}
254
255
256bool
257PileUpMergeSvc::isLive(CLID id, const string& dataKey, int iXing) {
258 return m_ranges[make_pair(id, dataKey)].contains(iXing);
259}
260
261bool
263 // bool result(r.contains(iXing) && r.doRefresh(double(random())/RAND_MAX));
264 // std::cerr << "doRefresh: id " << id << " key " << dataKey
265 // << " xing " << iXing << " result " << result << std::endl;
266 return (r.contains(iXing) && r.doRefresh(double(random())*(1./RAND_MAX)));
267}
268
269StatusCode
271 StatusCode sc(StatusCode::FAILURE);
272 const xAOD::EventInfo* pEvent;
273 if (0 != (pEvent=getPileUpEvent(nullptr,m_EventInfoKeyName))) {
274 // access the sub events DATA objects...
275 for( const xAOD::EventInfo::SubEvent& subEv : pEvent->subEvents() ) {
276 StoreGateSvc* pSubEvtSG( subEv.ptr()->evtStore() );
277 assert(pSubEvtSG);
278 //go object-by-object (driven by PileUpXingFolder settings)
279 for (const auto& item : m_ranges) {
280 SG::sgkey_t sgkey = pSubEvtSG->stringToKey (item.first.second,
281 item.first.first);
282 SG::DataProxy* proxy = pSubEvtSG->proxy_exact (sgkey);
283 //FIXME turning the double iEvt->time is fraught with peril. Luckily
284 //FIXME it just works, but we should have the beam xing in iEvt
285 if (proxy && doRefresh (item.second, int(subEv.time()))) {
286 proxy->setObject ((DataObject*)0);
287 if (msg().level() <= MSG::DEBUG) {
288 msg() << MSG::DEBUG
289 << "clearDataCachesByFolder: object with clid "
290 << item.first.first << " and key " << item.first.second
291 << " removed from cache "
292 << pSubEvtSG->name() << endmsg;
293 }
294 }
295 }
296 //even if we don't clear the store we need to empty the trash...
297 pSubEvtSG->emptyTrash();
298#ifndef NDEBUG
299 if (msg().level() <= MSG::VERBOSE) {
300 msg() << MSG::VERBOSE
301 << "clearDataCachesByFolder: done with store " << pSubEvtSG->name()
302 << endmsg;
303 }
304#endif
305 } //stores loop
306 sc=StatusCode::SUCCESS;
307 } //NO PILEUP EVENT?!?
308 return sc;
309}
#define endmsg
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_VERBOSE(x,...)
#define CHECK(...)
Evaluate an expression and check for errors.
This class provides a unique identification for each event, in terms of run/event number and/or a tim...
This class provides general information about an event.
uint32_t CLID
The Class ID type.
virtual void lock()=0
Interface to allow an object to lock itself when made const in SG.
an interface to SG::Folder with an attached bunch crossing interval
interface to a tool that returns the time offset of the current trigger.
static Double_t sc
This class provides information about an overlaid event.
the preferred mechanism to access information from the different event stores in a pileup job.
#define DECLARE_SE_TYPE(TYPE)
struct TBPatternUnitContext Unknown
MsgStream & msg() const
This class provides general information about an event.
an interface to SG::Folder with an attached bunch crossing interval
SG::IFolder::const_iterator const_iterator
virtual const_iterator end() const =0
virtual float cacheRefreshFrequency() const =0
controls the rate at which we clear data objs in this folder at the end of event
virtual int firstXing() const =0
virtual int lastXing() const =0
virtual const_iterator begin() const =0
This class provides information about an overlaid event.
SubEvent::iterator endSubEvt()
SubEvent::iterator beginSubEvt()
the active crossing range for a data object (CLID/key combination)
ToolHandle< ITriggerTime > m_pITriggerTime
controls PileUpTimedEventIndex for TimedData returned by retrieveSubEvts
void decodeIntervals()
setup PileUpIntervals
ToolHandleArray< IPileUpXingFolder > m_intervals
bool isLive(const KEY &key, int iXing)
is iXing live for DATA/key?
StatusCode clearDataCaches()
clear bkg event caches from unneeded data objects (as configured using PileUpXingFolder CacheRefreshF...
RangeContainer m_ranges
virtual StatusCode initialize() override
Service initialisation.
StringProperty m_EventInfoKeyName
bool doRefresh(const Range &r, int iXing)
ToolHandle< xAODMaker::IEventInfoCnvTool > m_xAODCnvTool
property: Handle to the EventInfo -> xAOD::EventInfo converter tool
PileUpMergeSvc(const std::string &name, ISvcLocator *svc)
Standard Gaudi Constructor.
ServiceHandle< StoreGateSvc > p_overStore
overlaid SG (default)
const xAOD::EventInfo * getPileUpEvent(StoreGateSvc *sg, const std::string &einame)
get EventInfo from SG, by default using p_overStore
The Athena Transient Store API.
StatusCode record(T *p2BRegistered, const TKEY &key)
Record an object with a key.
const T * tryConstRetrieve() const
void emptyTrash()
throw away bad objects
virtual sgkey_t stringToKey(const std::string &str, CLID clid) override final
Find the key for a string/CLID pair.
virtual SG::DataProxy * proxy_exact(SG::sgkey_t sgkey) const override final
Get proxy given a hashed key+clid.
Class describing the properties of one pileup sub-event.
const std::vector< SubEvent > & subEvents() const
Get the pileup events that were used in the simulation.
PileUpType
Enumerator describing the types of pileup events.
@ Unknown
Type not known/specified.
int r
Definition globals.cxx:22
IProxyDict * proxyDictFromEventContext()
Return the IProxyDict for this thread's current context.
uint32_t sgkey_t
Type used for hashed StoreGate key+CLID pairs.
Definition sgkey_t.h:32
EventInfoContainer_v1 EventInfoContainer
Define the latest version of the container.
EventInfo_v1 EventInfo
Definition of the latest event info version.
EventInfoAuxContainer_v1 EventInfoAuxContainer
Define the latest version of the auxiliary container.
EventAuxInfo_v3 EventAuxInfo
Definition of the latest event auxiliary info version.
Some out-of-line helpers for ExtendedEventContext.