4 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
7#include <algorithm> /* make_pair */
11#include "GaudiKernel/System.h"
12#include "GaudiKernel/StatusCode.h"
13#include "GaudiKernel/ThreadLocalContext.h"
15#include "AthenaKernel/ITriggerTime.h"
16#include "StoreGate/StoreGateSvc.h"
17#include "AthenaKernel/ClassID_traits.h"
18#include "AthenaBaseComps/AthMsgStreamMacros.h"
21 template <typename KEY>
22 std::string mkHSKey(const KEY& k) {
23 return "HS" + std::string(k);
26 template <class DATALINK, typename KEY>
27 void fillLink(DATALINK& l, const KEY& k, IProxyDict* sg = 0) {
28 l.toIdentifiedObject(k, sg);
30 l.toIdentifiedObject(mkHSKey(k), sg);
35 //MsgStream& operator <<(MsgStream& os, const NoKey&) { os << "Default"; return os; }
37 template <class DATALINK>
38 void fillLink(DATALINK&, const NoKey&, IProxyDict*)
39 { /*leave it in default state*/ }
41 [[maybe_unused]] // suppress clang warning (false positive?)
42 PileUpTimeEventIndex::PileUpType getOldPileUpType(const xAOD::EventInfo_v1::PileUpType &newType) {
43 PileUpTimeEventIndex::PileUpType oldType = PileUpTimeEventIndex::Unknown;
45 case xAOD::EventInfo_v1::Signal :
46 oldType = PileUpTimeEventIndex::Signal;
48 case xAOD::EventInfo_v1::MinimumBias:
49 oldType = PileUpTimeEventIndex::MinimumBias;
51 case xAOD::EventInfo_v1::Cavern:
52 oldType = PileUpTimeEventIndex::Cavern;
54 case xAOD::EventInfo_v1::HaloGas:
55 oldType = PileUpTimeEventIndex::HaloGas;
57 case xAOD::EventInfo_v1::HighPtMinimumBias:
58 oldType = PileUpTimeEventIndex::HighPtMinimumBias;
60 case xAOD::EventInfo_v1::ZeroBias:
61 oldType = PileUpTimeEventIndex::ZeroBias;
70///retrieve keyed DATA obj for the original event
71template <typename KEY, typename DATA>
73PileUpMergeSvc::retrieveOriginal(const KEY& dataKey, const DATA*& data) {
74 StatusCode sc(StatusCode::FAILURE);
75 const xAOD::EventInfo* pEvent = getPileUpEvent(nullptr,m_EventInfoKeyName);
77 // access the sub events DATA objects...
78 if( pEvent->subEvents().size() ) {
79 //here we assume that the original event is the first in pEvent list
80 sc = pEvent->subEvents()[0].ptr()->evtStore()->retrieve(data, dataKey);
82 sc = pEvent->subEvents()[0].ptr()->evtStore()->retrieve(data, mkHSKey(dataKey));
89/// retrieve keyed DATA objs for all sub-events and attach a time to them
90template <typename KEY, typename TIMEDDATA>
92PileUpMergeSvc::retrieveSubEvtsData(const KEY &dataKey, // orig evt key
94 unsigned int &numberOfSimHits) {
96 typedef typename TIMEDDATA::value_type value_type; // pair<time_t,DataLink..
97 typedef typename value_type::second_type DataLink_t;
98 typedef typename DataLink_t::value_type data_t;
99 // the tdefs above in practice check that TIMEDDATA is what we want
100 // FIXME we still have to check we are dealing with a sequence:
101 // boost::function_requires < boost::SequenceConcept<TIMEDDATA> > ();
102 const xAOD::EventInfo* pEvent = getPileUpEvent(nullptr,m_EventInfoKeyName);
104 ATH_MSG_DEBUG ( "retrieveSubEvtsData: object of type "
105 << System::typeinfoName(typeid(data_t)) << " with key "
106 << dataKey<< " ei="<<pEvent );
109 if(pEvent->subEvents().size()==0) {
110 ATH_MSG_DEBUG ( "no subEvents for xAOD::EventInfo '"<<m_EventInfoKeyName<<"'" );
113 fillLink(dLink, dataKey);
114 if (dLink.isValid()) {
115 timedData.push_back(std::make_pair(0, dLink));
117 return StatusCode::SUCCESS;
119 // access the sub events DATA objects...
120 for (const xAOD::EventInfo::SubEvent &subEv : pEvent->subEvents()) {
121 // skip if dobj not active for this xing
122 // FIXME if (!isLive<data_t>(dataKey, int(iEvt->time()))) {
123 // FIXME turning the double iEvt->time() is fraught with peril. Luckily
124 // FIXME it just works, but we should have the beam xing in iEvt
125 if (!isLive(ClassID_traits<data_t>::ID(), dataKey, int(subEv.time()))) {
127 ATH_MSG_VERBOSE("retrieveSubEvtsData: object of type "
128 << System::typeinfoName(typeid(data_t)) << " with key "
129 << dataKey << " OUT OF XING RANGE: SKIPPING ");
132 subEv.ptr()->evtStore()->makeCurrent();
133 StoreGateSvc *pSubEvtSG = subEv.ptr()->evtStore();
135 fillLink(dLink, dataKey, pSubEvtSG);
137 unsigned int evtIndex(0);
138 if (dLink.isValid()) {
139 if (m_returnTimedData.value()) {
140 sigTime = subEv.time();
141 if (!m_pITriggerTime.empty())
142 sigTime -= m_pITriggerTime->time();
143 evtIndex = subEv.index();
145 value_type tData(PileUpTimeEventIndex(int(sigTime), evtIndex,
146 getOldPileUpType(subEv.type())),
148 numberOfSimHits += tData.second->size();
149 timedData.push_back(tData);
150 ATH_MSG_DEBUG("added entry from store "
151 << pSubEvtSG->name() << " for object of type "
152 << System::typeinfoName(typeid(data_t))
153 << "\n with key " << dataKey);
156 if (msg().level() <= MSG::VERBOSE) {
157 msg() << MSG::VERBOSE << "SubEvt EventInfo : "
158 << " event: " << subEv.ptr()->eventNumber()
159 << " run: " << subEv.ptr()->runNumber();
160 if (m_returnTimedData.value()) {
161 msg() << " time offset: " << sigTime
162 << " event index: " << evtIndex;
169 // reset active store pointer to default event store FIXME DANGEROUS
170 p_overStore->makeCurrent();
172 ATH_MSG_DEBUG("default PileUpEventInfo not found, trying any EventInfo");
173 // check for EventInfo with any key name
174 pEvent = getPileUpEvent(Gaudi::Hive::currentContext(), "");
177 fillLink(dLink, dataKey);
178 if (dLink.isValid()) {
179 timedData.push_back(std::make_pair(0, dLink));
182 ATH_MSG_FATAL("no EventInfo object found!");
183 return StatusCode::FAILURE;
186 return StatusCode::SUCCESS;
189///retrieve keyed DATA objs for subset of sub-events
190template <typename KEY, typename TIMEDDATA>
192PileUpMergeSvc::retrieveSubSetEvtData(const KEY& dataKey, //orig evt key
193 TIMEDDATA& timedData, int bunchXing,
194 SubEventIterator bSubEvents, SubEventIterator eSubEvents)
196 typedef typename TIMEDDATA::value_type value_type; //pair<time_t,DataLink..
197 typedef typename value_type::second_type DataLink_t;
199 SubEventIterator iEvt = bSubEvents;
200 for (; iEvt != eSubEvents; ++iEvt) {
202 StoreGateSvc &seStore = *iEvt->ptr()->evtStore();
203 ATH_MSG_VERBOSE("SubEvt StoreGate " << seStore.name() << " :"
204 << " bunch crossing : " << bunchXing
205 << " time offset : " << iEvt->time()
206 << " event number : " <<
207 iEvt->ptr()->eventNumber()
208 << " run number : " <<
209 iEvt->ptr()->runNumber());
212 fillLink(dLink, dataKey, iEvt->ptr()->evtStore());
213 if (dLink.isValid()) {
216 unsigned int evtIndex(0);
218 if (m_returnTimedData.value()) {
219 sigTime=iEvt->time();
220 evtIndex = iEvt->index();
223 value_type tData(PileUpTimeEventIndex(int(sigTime),evtIndex), dLink);
224 timedData.push_back(tData);
228 ATH_MSG_FATAL("Could not retrieve hit collection from: " << seStore.name() << " with key: " << dataKey);
229 return StatusCode::FAILURE;
234 return StatusCode::SUCCESS;
238///retrieve keyed DATA objs for single sub-event (un-timed)
239template <typename KEY, typename DATA>
241PileUpMergeSvc::retrieveSingleSubEvtData(const KEY& dataKey, const DATA*& data, int bunchXing, SubEventIterator iEvt){
243 ATH_MSG_VERBOSE("In PileUpMergeSvc::retrieveSingleSubEvtData evt="<<*iEvt->ptr()<<" SG="<<iEvt->ptr()->evtStore());
244 StoreGateSvc &seStore = *iEvt->ptr()->evtStore();
245 ATH_MSG_VERBOSE("SubEvt StoreGate " << seStore.name() << " :"
246 << " bunch crossing : " << bunchXing
247 << " time offset : " << iEvt->time()
248 << " event number : " <<
249 iEvt->ptr()->eventNumber()
250 << " run number : " <<
251 iEvt->ptr()->runNumber());
253 StatusCode sc = seStore.retrieve(data, dataKey);
255 sc = seStore.retrieve(data, mkHSKey(dataKey));
261/// retrieve keyed DATA objs for all sub-events and attach a time to them
262template <typename KEY, typename TIMEDDATA>
264PileUpMergeSvc::retrieveSubEvtsData(const KEY &dataKey, // orig evt key
265 TIMEDDATA &timedData) {
266 typedef typename TIMEDDATA::value_type value_type; // pair<time_t,DataLink..
267 typedef typename value_type::second_type DataLink_t;
268 typedef typename DataLink_t::value_type data_t;
269 // the tdefs above in practice check that TIMEDDATA is what we want
270 // FIXME we still have to check we are dealing with a sequence:
271 // boost::function_requires < boost::SequenceConcept<TIMEDDATA> > ();
272 const xAOD::EventInfo* pEvent = getPileUpEvent(nullptr,m_EventInfoKeyName);
274 ATH_MSG_DEBUG ( "retrieveSubEvtsData: object of type "
275 << System::typeinfoName(typeid(data_t)) << " with key "
276 << dataKey<< " ei="<<pEvent );
279 if(pEvent->subEvents().size()==0) {
280 ATH_MSG_DEBUG ( "no subEvents for xAOD::EventInfo '"<<m_EventInfoKeyName<<"'" );
283 fillLink(dLink, dataKey);
284 if (dLink.isValid()) {
285 timedData.push_back(std::make_pair(0, dLink));
287 return StatusCode::SUCCESS;
290 // access the sub events DATA objects...
291 for (const xAOD::EventInfo::SubEvent &subEv : pEvent->subEvents()) {
292 // skip if dobj not active for this xing
293 // FIXME if (!isLive<data_t>(dataKey, int(iEvt->time()))) {
294 // FIXME turning the double iEvt->time() is fraught with peril. Luckily
295 // FIXME it just works, but we should have the beam xing in iEvt
296 if (!isLive(ClassID_traits<data_t>::ID(), dataKey, int(subEv.time()))) {
298 ATH_MSG_VERBOSE("retrieveSubEvtsData: object of type "
299 << System::typeinfoName(typeid(data_t)) << " with key "
300 << dataKey << " OUT OF XING RANGE: SKIPPING ");
303 subEv.ptr()->evtStore()->makeCurrent();
304 StoreGateSvc *pSubEvtSG = subEv.ptr()->evtStore();
306 fillLink(dLink, dataKey, pSubEvtSG);
308 unsigned int evtIndex(0);
309 if (dLink.isValid()) {
310 if (m_returnTimedData.value()) {
311 sigTime = subEv.time();
312 if (!m_pITriggerTime.empty())
313 sigTime -= m_pITriggerTime->time();
314 evtIndex = subEv.index();
316 value_type tData(PileUpTimeEventIndex(int(sigTime), evtIndex,
317 getOldPileUpType(subEv.type())),
319 timedData.push_back(tData);
320 ATH_MSG_DEBUG("added entry from store "
321 << pSubEvtSG->name() << " for object of type "
322 << System::typeinfoName(typeid(data_t))
323 << "\n with key " << dataKey);
326 if (msg().level() <= MSG::VERBOSE) {
327 msg() << MSG::VERBOSE << "SubEvt EventInfo : "
328 << " event: " << subEv.ptr()->eventNumber()
329 << " run: " << subEv.ptr()->runNumber();
330 if (m_returnTimedData.value()) {
331 msg() << " time offset: " << sigTime
332 << " event index: " << evtIndex;
339 // reset active store pointer to default event store FIXME DANGEROUS
340 p_overStore->makeCurrent();
342 ATH_MSG_DEBUG("default PileUpEventInfo not found, trying any EventInfo");
343 // check for EventInfo with any key name
344 pEvent = getPileUpEvent(Gaudi::Hive::currentContext(), "");
347 fillLink(dLink, dataKey);
348 if (dLink.isValid()) {
349 timedData.push_back(std::make_pair(0, dLink));
352 ATH_MSG_FATAL("no EventInfo object found!");
353 return StatusCode::FAILURE;
356 return StatusCode::SUCCESS;
359// ///retrieve default DATA objs for all sub-events and attach a time to them
360// template <typename TIMEDDATA>
362// PileUpMergeSvc::retrieveSubEvtsData(TIMEDDATA& timedData)
364// return retrieveSubEvtsData(NoKey(), timedData);
368template <typename DATA, typename KEY>
370PileUpMergeSvc::isLive(const KEY& dataKey, int iXing) {
371 return isLive(ClassID_traits<DATA>::ID(), std::string(dataKey), iXing);