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