ATLAS Offline Software
Loading...
Searching...
No Matches
MergeMcEventCollTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7#include "AthenaKernel/errorcheck.h" // Handy definitions for error checking
11
12#include "GaudiKernel/PhysicalConstants.h"
13using namespace Gaudi::Units;
14
15
16#include <vector>
17#include <string>
18#include <cmath>
19#include <stdexcept>
20#include <array>
21
22typedef std::pair<int, int> IndexKey;
23namespace {
24 IndexKey makekey(int signal_process_id, int event_number, int separator_hack=0) {
25 //std::size_t key(0);
26 //Check for Separtor GenEvents
27 if(signal_process_id==0 && event_number==-1) {
28 return std::make_pair(separator_hack, event_number);
29 }
30 return std::make_pair(signal_process_id, event_number);
31 }
32
33 class GenEventSorter {
34 public:
35 typedef std::map<IndexKey, int> PileUpBackgroundMap;
36 GenEventSorter(const PileUpBackgroundMap& backgroundClassificationMap) : m_backgroundClassificationMap(backgroundClassificationMap) {}
37 bool operator() (const HepMC::GenEvent *pGenEvent1, const HepMC::GenEvent *pGenEvent2) {
38 const int signal_process_id1(HepMC::signal_process_id(pGenEvent1)), event_number1(pGenEvent1->event_number()), separator_hack1(HepMC::mpi(pGenEvent1));
39 const int signal_process_id2(HepMC::signal_process_id(pGenEvent2)), event_number2(pGenEvent2->event_number()), separator_hack2(HepMC::mpi(pGenEvent2));
40 const IndexKey key1(makekey(signal_process_id1, event_number1,separator_hack1));
41 const IndexKey key2(makekey(signal_process_id2, event_number2,separator_hack2));
42 const PileUpBackgroundMap::const_iterator event1=m_backgroundClassificationMap.find(key1);
43 const PileUpBackgroundMap::const_iterator event2=m_backgroundClassificationMap.find(key2);
44 if(event1==m_backgroundClassificationMap.end()) {
45 throw std::runtime_error("GenEventSorter::operator() : IndexKey 1 not found in backgroundClassificationMap");
46 }
47 if(event2==m_backgroundClassificationMap.end()) {
48 throw std::runtime_error("GenEventSorter::operator() : IndexKey 2 not found in backgroundClassificationMap");
49 }
50
51 //Both events have the same 'type'
52 if(event1->second==event2->second) {
53 if (is_separator(signal_process_id1, event_number1)) {return true;} //separator GenEvents should go at the start of each classification
54 if (is_separator(signal_process_id2, event_number2)) {return false;}
55 //Both events are from the same dataset
56 if (signal_process_id1==signal_process_id2) {
57 return (event_number1<event_number2);
58 }
59 return (signal_process_id1<signal_process_id2);
60 }
61 return (event1->second<event2->second);
62
63 }
64 private:
65 inline bool is_separator(int signal_process_id, int event_number) const { return (0==signal_process_id && -1==event_number); }
66 const PileUpBackgroundMap& m_backgroundClassificationMap;
67 };
68} //anonymous namespace
69
71 const std::string& name,
72 const IInterface *parent) :
73 PileUpToolBase(type, name, parent)
74{
75}
76
78 ATH_MSG_DEBUG( "Initializing" );
79 if (m_doSlimming) {
80 //set all m_saveTypes based on properties
85 }
86 else {
87 m_keepUnstable = true;
88 m_saveType[INTIME] = true;
89 m_saveType[OUTOFTIME] = true;
90 m_saveType[RESTOFMB] = true;
91 m_saveType[CAVERN] = true;
92 }
94
95 return StatusCode::SUCCESS;
96}
97
98StatusCode MergeMcEventCollTool::prepareEvent(const EventContext& /*ctx*/, unsigned int nInputEvents) {
99 //clear the background classification map
101 m_newevent=true;
102
103 //Check we are getting at least one event
104 m_nInputMcEventColls = nInputEvents;
105 if (0 == m_nInputMcEventColls) {
106 msg(MSG::ERROR)
107 << "prepareEvent: TimedTruthList with key "
108 << m_truthCollInputKey.value()
109 << " is empty" << endmsg;
110 return StatusCode::RECOVERABLE;
111 }
112 ATH_MSG_DEBUG( "prepareEvent: there are " << m_nInputMcEventColls << " subevents in this event.");
113
114 return StatusCode::SUCCESS;
115}
116
117StatusCode MergeMcEventCollTool::processAllSubEvents(const EventContext& /*ctx*/) {
118 ATH_MSG_VERBOSE ( "processAllSubEvents()" );
119 if(!m_pMergeSvc) {
120 if (!(m_pMergeSvc.retrieve()).isSuccess()) {
121 ATH_MSG_FATAL ( "processAllSubEvents: Could not find PileUpMergeSvc" );
122 return StatusCode::FAILURE;
123 }
124 }
125
126 //PRECONDITIONS
127 //first get the list of McEventCollections
129 TimedTruthList truthList;
130 if (!m_pMergeSvc->retrieveSubEvtsData(m_truthCollInputKey.value(), truthList).isSuccess() ) {
131 msg(MSG::ERROR)
132 << "execute: Can not find TimedTruthList with key "
133 << m_truthCollInputKey.value() << endmsg;
134 return StatusCode::RECOVERABLE;
135 }
136
137 //clear the background classification map
139
140 //Check we are getting at least one event
141 m_nInputMcEventColls=truthList.size();
142 if (0 == m_nInputMcEventColls) {
143 msg(MSG::ERROR)
144 << "execute: TimedTruthList with key "
145 << m_truthCollInputKey.value()
146 << " is empty" << endmsg;
147 return StatusCode::RECOVERABLE;
148 }
149 ATH_MSG_DEBUG( "execute: there are " << m_nInputMcEventColls << " subevents in this event.");
150 TimedTruthList::iterator timedTruthListIter(truthList.begin()), endOfTimedTruthList(truthList.end());
151 //loop over the McEventCollections (each one assumed to containing exactly one GenEvent) of the various input events
152 m_newevent=true;
153 while (timedTruthListIter != endOfTimedTruthList) {
154 const PileUpTimeEventIndex& currentPileUpTimeEventIndex(timedTruthListIter->first);
155 const McEventCollection *pBackgroundMcEvtColl(&*(timedTruthListIter->second));
156 if (!processEvent(pBackgroundMcEvtColl, currentPileUpTimeEventIndex.time(), currentPileUpTimeEventIndex.index(), static_cast<int>(currentPileUpTimeEventIndex.type())).isSuccess()) {
157 ATH_MSG_ERROR ("Failed to process McEventCollection." );
158 return StatusCode::FAILURE;
159 }
160 ++timedTruthListIter;
161 } //timed colls
162
163 //Remove empty copies of GenEvents
165
166 //Sort the GenEvents in the output McEventCollection according to background classification
168
169 if(msgLvl(MSG::DEBUG)) {
170 ATH_MSG_DEBUG("Sorted McEventCollection OK.");
172 }
173
174 if(m_pOvrlMcEvColl->at(0)->event_number()!=-2)
175 {
176 ATH_MSG_FATAL("Signal GenEvent is not first in the list! Something has gone wrong during the GenEvent sorting!");
177 return StatusCode::FAILURE;
178 }
179 //Restore original event number
180 m_pOvrlMcEvColl->at(0)->set_event_number(m_signal_event_number);
181
182 return StatusCode::SUCCESS;
183}
184
186 SubEventIterator bSubEvents,
187 SubEventIterator eSubEvents)
188{
189 ATH_MSG_VERBOSE ( "processBunchXing()" );
190 SubEventIterator iEvt(bSubEvents);
191 //loop over the McEventCollections (each one assumed to containing exactly one GenEvent) of the various input events
192 while (iEvt != eSubEvents) {
193 const McEventCollection *pMEC(NULL);
194 if (!m_pMergeSvc->retrieveSingleSubEvtData(m_truthCollInputKey.value(), pMEC,
195 bunchXing, iEvt).isSuccess()){
196 ATH_MSG_ERROR("McEventCollection not found for event key " << m_truthCollInputKey.value());
197 return StatusCode::FAILURE;
198 }
199
200 if (!processEvent(pMEC,iEvt->time(),iEvt->index(), static_cast<int>(iEvt->type())).isSuccess()) {
201 ATH_MSG_ERROR ("processBunchXing: Failed to process McEventCollection." );
202 return StatusCode::FAILURE;
203 }
204 ++iEvt;
205 }
206 return StatusCode::SUCCESS;
207}
208
209StatusCode MergeMcEventCollTool::mergeEvent(const EventContext& /*ctx*/) {
210 ATH_MSG_DEBUG( "mergeEvent" );
212 ATH_MSG_WARNING( "mergeEvent: Expected " << m_nInputMcEventColls << " subevents, but only saw " << m_nBkgEventsReadSoFar+1 << "! The job will probably crash now..." );
213 return StatusCode::FAILURE;
214 }
215
216 //Remove empty copies of GenEvents
218
220 ATH_MSG_WARNING( "There are " << m_pOvrlMcEvColl->size() << " GenEvents in the McEventCollection, but " << m_backgroundClassificationMap.size() << " entries in the classification map." );
221 }
222 //Sort the GenEvents in the output McEventCollection according to background classification
223
225 ATH_MSG_DEBUG("Sorted McEventCollection OK.");
226 if(msgLvl(MSG::DEBUG)) { printDetailsOfMergedMcEventCollection(); }
227
228 if(m_pOvrlMcEvColl->at(0)->event_number()!=-2)
229 {
230 ATH_MSG_FATAL("Signal GenEvent is not first in the list! Something has gone wrong during the GenEvent sorting!");
231 return StatusCode::FAILURE;
232 }
233 //Restore original event number
234 m_pOvrlMcEvColl->at(0)->set_event_number(m_signal_event_number);
235
236 return StatusCode::SUCCESS;
237}
239 if (! m_pOvrlMcEvColl->empty()) {
240 ATH_MSG_INFO ( "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$" );
241 ATH_MSG_INFO ( "INTIME("<<int(INTIME)<<"), OUTOFTIME("<<int(OUTOFTIME)<<"), RESTOFMB("<<int(RESTOFMB)<<"), CAVERN("<<int(CAVERN)<<"), NOPUTYPE("<<int(NOPUTYPE)<<")" );
242 ATH_MSG_INFO ( "Current OUTPUT GenEvent: " );
243 auto outputEventItr = m_pOvrlMcEvColl->cbegin();
244 while(outputEventItr!=m_pOvrlMcEvColl->cend()) {
245 const int signal_process_id(HepMC::signal_process_id((*outputEventItr))), event_number((*outputEventItr)->event_number()), separator_hack(HepMC::mpi((*outputEventItr)));
246 const IndexKey key(makekey(signal_process_id,event_number,separator_hack));
247 const auto event = m_backgroundClassificationMap.find(key);
248 if (event == m_backgroundClassificationMap.end()) continue;
249 ATH_MSG_INFO ( "GenEvent #"<<event_number<<", signal_process_id="<<signal_process_id<<", category="<<event->second<<", number of Vertices="<<(*outputEventItr)->vertices_size() );
250 ++outputEventItr;
251 }
252 ATH_MSG_INFO ( "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$" );
253 }
254 return;
255}
256
258 StatusCode sc(StatusCode::FAILURE);
259 //Assumes the first sub-event is the signal event
260 m_pOvrlMcEvColl = new McEventCollection(*pMcEvtColl);
261 m_signal_event_number = m_pOvrlMcEvColl->at(0)->event_number();
262 m_pOvrlMcEvColl->at(0)->set_event_number(-2); //Set this to zero for the purposes of sorting. (restore after sorting).
263#ifdef HEPMC3
264 m_pOvrlMcEvColl->at(0)->add_attribute("BunchCrossingTime",std::make_shared<HepMC3::IntAttribute>(0));
265 m_pOvrlMcEvColl->at(0)->add_attribute("PileUpType",std::make_shared<HepMC3::IntAttribute>(0));
266#endif
267 updateClassificationMap(HepMC::signal_process_id(m_pOvrlMcEvColl->at(0)), m_pOvrlMcEvColl->at(0)->event_number(), 0,- 1, true);
268 m_newevent=false; //Now the McEventCollection and classification map are not empty this should be set to false.
269 ATH_MSG_DEBUG( "execute: copied original event McEventCollection" );
270 const unsigned int nBackgroundMcEventCollections(m_nInputMcEventColls-1); // -1 for original event
271 // -> reserve enough space
272 unsigned int outCollSize(m_pOvrlMcEvColl->size());
273 if(!m_onlySaveSignalTruth) { outCollSize += nBackgroundMcEventCollections; }
274 outCollSize += NOPUTYPE-1; // Adding room for the spacers
275 m_pOvrlMcEvColl->resize(outCollSize);
276 if(!m_onlySaveSignalTruth) { ATH_MSG_DEBUG ( "Number of input SubEvents = " << m_nInputMcEventColls ); }
277 ATH_MSG_DEBUG ( "Total Size of Output McEventCollection = " << outCollSize );
278
279 //now place the "separator" GenEvents. This is a hack used by clients to find/double-check where the GenEvents
280 //of a given type start in the overlay McEventCollection.
281
282 // For example if intime and cavern saving is enabled i.e.
283 // Configurable Variable in code Example Value
284 // SaveInTimeMinBias m_saveType[INTIME] true
285 // SaveOutOfTimeMinBias m_saveType[OUTOFTIME] false
286 // SaveRestOfMinBias m_saveType[RESTOFMB] false
287 // SaveCavernBackground m_saveType[CAVERN] true
288 //If we have two input GenEvents the output collection would look like
289 //SIGNAL, INTIME0, INTIME1, SEPARATOR, SEPARATOR, SEPARATOR, CAVERN0, CAVERN1
290 unsigned int currentMcEventCollectionIndex(1);
291 ATH_MSG_DEBUG ( "Event Type: SIGNAL Starts at Position 0" );
292 for (int type(OUTOFTIME); type<NOPUTYPE; ++type) {
293 //if a type is enabled leave room to insert the events of that type, otherwise place separator immediately after
294 currentMcEventCollectionIndex += 1;
295 m_pOvrlMcEvColl->at(currentMcEventCollectionIndex-1) = HepMC::newGenEvent(0, -1); //pid 0 & event_number -1 flags this GenEvent as SEPARATOR
296 HepMC::set_mpi(m_pOvrlMcEvColl->at(currentMcEventCollectionIndex-1),type);
297 updateClassificationMap(0, -1, type, type, true);
298 ATH_MSG_DEBUG ( "Placing Separator for Type: "<<type<<" at Posistion: " << currentMcEventCollectionIndex-1 );
299 }
300 m_startingIndexForBackground=currentMcEventCollectionIndex;
301 m_nBkgEventsReadSoFar=0; //number of input events/eventcolls read so far. Used to build index of output GenEvent in ovrl McEvColl
302 sc = evtStore()->record(m_pOvrlMcEvColl, m_truthCollOutputKey);//**BIG TEST**//sc=StatusCode::SUCCESS;
303 ATH_MSG_DEBUG( "Starting loop on Background events ... " );
304
305 return sc;
306}
307
309 const HepMC::GenEvent* currentBackgroundEvent = *(pMcEvtColl->begin());
310#ifdef HEPMC3
311 if (currentBackgroundEvent->particles().size()!=1) return false;
312 if (currentBackgroundEvent->particles().at(0)->pdg_id()==999) return true;
313#else
314 if (currentBackgroundEvent->particles_size()!=1) return false;
315 if ((*(currentBackgroundEvent->particles_begin()))->pdg_id()==999) return true;
316#endif
317 return false;
318}
319
320StatusCode MergeMcEventCollTool::processEvent(const McEventCollection *pMcEvtColl, const double currentEventTime, const int currentBkgEventIndex, int pileupType) {
321 ATH_MSG_VERBOSE ( "processEvent()" );
322 if(m_newevent) return processFirstSubEvent(pMcEvtColl);
323
324 if (pMcEvtColl->empty() || m_onlySaveSignalTruth) {
326 return StatusCode::SUCCESS;
327 }
328 //GenEvt is there
329
330 //Examine the properties of the GenEvent - if it looks like a TruthFiltered background event (contains a Geantino?!)
331 //then save the whole event as below, otherwise do the usual classification.
332 if(isTruthFiltertedMcEventCollection(pMcEvtColl)) {
333 if ( processTruthFilteredEvent(pMcEvtColl, currentEventTime, currentBkgEventIndex, pileupType).isSuccess() ) {
335 return StatusCode::SUCCESS;
336 }
337 else {
338 ATH_MSG_ERROR ("Failed to process a Truth Filtered GenEvent.");
339 }
340 }
341 else {
342 if ( processUnfilteredEvent(pMcEvtColl, currentEventTime, currentBkgEventIndex, pileupType).isSuccess() ) {
344 return StatusCode::SUCCESS;
345 }
346 else {
347 ATH_MSG_ERROR ("Failed to process an Unfiltered GenEvent.");
348 }
349 }
350 //If we make it here something has gone wrong.
352 return StatusCode::FAILURE;
353}
354
356{
357 if (m_pOvrlMcEvColl->at(0)->heavy_ion()) return StatusCode::SUCCESS;
358 if (pMcEvtColl->at(0)->heavy_ion())
359 {
360//It should be clarified if ne wants to get a copy or the content
361#ifdef HEPMC3
362 HepMC::GenHeavyIonPtr hinew=std::make_shared<HepMC::GenHeavyIon>(*(pMcEvtColl->at(0)->heavy_ion()));
363 m_pOvrlMcEvColl->at(0)->set_heavy_ion(std::move(hinew));
364#else
365 m_pOvrlMcEvColl->at(0)->set_heavy_ion(*(pMcEvtColl->at(0)->heavy_ion()));
366#endif
367 }
368 return StatusCode::SUCCESS;
369}
370
371StatusCode MergeMcEventCollTool::processTruthFilteredEvent(const McEventCollection *pMcEvtColl, const double currentEventTime, const int currentBkgEventIndex, int pileupType) {
372 //insert the GenEvent into the overlay McEventCollection.
373 ATH_MSG_VERBOSE ( "processTruthFilteredEvent(): Event Type: " << pileupType );
374 ATH_CHECK(this->saveHeavyIonInfo(pMcEvtColl));
375 m_pOvrlMcEvColl->at(m_startingIndexForBackground+m_nBkgEventsReadSoFar)=new HepMC::GenEvent(**(pMcEvtColl->begin()));
376 HepMC::GenEvent& currentBackgroundEvent(*(m_pOvrlMcEvColl->at(m_startingIndexForBackground+m_nBkgEventsReadSoFar)));
377 HepMC::fillBarcodesAttribute(&currentBackgroundEvent);
378#ifdef HEPMC3
379 const int bunchCrossingTime=static_cast<int>(currentEventTime);
380 currentBackgroundEvent.add_attribute("BunchCrossingTime",std::make_shared<HepMC3::IntAttribute>(bunchCrossingTime));
381 currentBackgroundEvent.add_attribute("PileUpType",std::make_shared<HepMC3::IntAttribute>(pileupType));
382#endif
383
384 currentBackgroundEvent.set_event_number(currentBkgEventIndex);
385 puType currentGenEventClassification(RESTOFMB);
386 if ( std::abs(currentEventTime)<51.0 ) {
387 currentGenEventClassification = ( std::abs(currentEventTime)<1.0 ) ? INTIME : OUTOFTIME;
388 }
390 currentBackgroundEvent.event_number(),
391 0, currentGenEventClassification, true);
392 return StatusCode::SUCCESS;
393}
394
395StatusCode MergeMcEventCollTool::processUnfilteredEvent(const McEventCollection *pMcEvtColl, const double currentEventTime, const int currentBkgEventIndex, int pileupType) {
396 ATH_MSG_VERBOSE ( "processUnfilteredEvent() Event Type: " << pileupType );
397 ATH_CHECK(this->saveHeavyIonInfo(pMcEvtColl));
398 const HepMC::GenEvent& currentBackgroundEvent(**(pMcEvtColl->begin())); //background event
399 //handle the slimming case
400 HepMC::GenVertexPtr pCopyOfGenVertex{nullptr};
401 int spi = HepMC::signal_process_id(currentBackgroundEvent);
402#ifdef HEPMC3
403 if ( HepMC::signal_process_vertex(&currentBackgroundEvent) ) pCopyOfGenVertex = std::make_shared<HepMC3::GenVertex> ( HepMC::signal_process_vertex(&currentBackgroundEvent)->data() );
404 //insert the GenEvent into the overlay McEventCollection.
405 //for configs with pile-up truth, also need to propagate barcodes to GenEvent
406 HepMC::GenEvent* evt = m_onlySaveSignalTruth ? new HepMC::GenEvent() : new HepMC::GenEvent(currentBackgroundEvent);
407 const int bunchCrossingTime=static_cast<int>(currentEventTime);
408 evt->add_attribute("BunchCrossingTime",std::make_shared<HepMC3::IntAttribute>(bunchCrossingTime));
409 evt->add_attribute("PileUpType",std::make_shared<HepMC3::IntAttribute>(pileupType));
410 //AV Not sure if one should add the vertex here
411 evt->set_event_number(currentBkgEventIndex);
412 evt->add_vertex(pCopyOfGenVertex);
413 HepMC::set_signal_process_vertex(evt,pCopyOfGenVertex);
416 updateClassificationMap(spi, currentBkgEventIndex, 0, RESTOFMB, true);
417
418 unsigned int nCollisionVerticesFound(0);
419 //loop over vertices in Background GenEvent
420 ATH_MSG_VERBOSE( "Starting a vertex loop ... " );
421 auto currentVertexIter = currentBackgroundEvent.vertices().begin();
422 auto endOfCurrentListOfVertices = currentBackgroundEvent.vertices().end();
423#else
424 if ( HepMC::signal_process_vertex(&currentBackgroundEvent) ) pCopyOfGenVertex = new HepMC::GenVertex ( *currentBackgroundEvent.signal_process_vertex() );
425 //insert the GenEvent into the overlay McEventCollection.
426 m_pOvrlMcEvColl->at(m_startingIndexForBackground+m_nBkgEventsReadSoFar) = new HepMC::GenEvent(spi, currentBkgEventIndex, pCopyOfGenVertex );
427 updateClassificationMap(spi, currentBkgEventIndex, 0, RESTOFMB, true);
428
429 unsigned int nCollisionVerticesFound(0);
430 //loop over vertices in Background GenEvent
431 ATH_MSG_VERBOSE( "Starting a vertex loop ... " );
432 auto currentVertexIter = currentBackgroundEvent.vertices_begin();
433 auto endOfCurrentListOfVertices = currentBackgroundEvent.vertices_end();
434#endif
435 for (; currentVertexIter != endOfCurrentListOfVertices; ++currentVertexIter) {
436 const auto& pCurrentVertex=*currentVertexIter;
437 HepMC::GenVertexPtr pCopyOfVertexForClassification[NOPUTYPE];
438 for (int type(INTIME); type<NOPUTYPE; ++type) pCopyOfVertexForClassification[type]=(HepMC::GenVertexPtr )nullptr;
439
440 //check for collision vertices for in-time events
441 bool isCollisionVertex(false);
442 if(m_addBackgroundCollisionVertices && nCollisionVerticesFound<2 && currentEventTime==0.0) {
443 isCollisionVertex=isInitialCollisionVertex(pCurrentVertex);
444 if(isCollisionVertex) ++nCollisionVerticesFound;
445 }
446
447 //loop over outgoing particles in the current GenVertex keeping those not classified as NOPUTYPE
448 ATH_MSG_VERBOSE( "Starting an outgoing particle loop ... " );
449 for (const HepMC::ConstGenParticlePtr& currentVertexParticle: *pCurrentVertex){
450 ATH_MSG_VERBOSE( "Found a particle at location " << std::hex << currentVertexParticle << std::dec << " with PDG ID = " << currentVertexParticle->pdg_id() );
451 HepMC::ConstGenVertexPtr pCurrentParticleProductionVertex = currentVertexParticle->production_vertex();
452 puType particleClassification(classifyVertex(currentVertexParticle, pCurrentParticleProductionVertex,currentEventTime));
453 //hack to keep the complete vertex information for the interaction vertices of in-time background events
454 if(isCollisionVertex && NOPUTYPE==particleClassification) {
455 particleClassification=INTIME;
456 }
457 //add particle to appropriate vertex
458 if (particleClassification<NOPUTYPE && m_saveType[particleClassification]) {
459 if (!pCopyOfVertexForClassification[particleClassification]) {
460 pCopyOfVertexForClassification[particleClassification] =HepMC::newGenVertexPtr(pCurrentVertex->position());
461 ATH_MSG_VERBOSE( "Added bkg vertex " << pCopyOfVertexForClassification[particleClassification] << " at position " << pCopyOfVertexForClassification[particleClassification] << " for pu type = " << particleClassification );
462 }
463#ifdef HEPMC3
464 pCopyOfVertexForClassification[particleClassification]->add_particle_out(std::make_shared<HepMC3::GenParticle>(currentVertexParticle->data()));
465#else
466 pCopyOfVertexForClassification[particleClassification]->add_particle_out( new HepMC::GenParticle(*currentVertexParticle) );
467#endif
468 ATH_MSG_VERBOSE( "Added bkg particle at location " << std::hex << currentVertexParticle << std::dec << " with PDG ID = " << currentVertexParticle->pdg_id() );
469 }
470 } //particle loop
472 if (m_saveType[INTIME] && pCopyOfVertexForClassification[INTIME]) {
473#ifdef HEPMC3
474 for (const auto& currentVertexParticle: pCurrentVertex->particles_in()) {
475 pCopyOfVertexForClassification[INTIME]->add_particle_in (std::make_shared<HepMC3::GenParticle>(currentVertexParticle->data()));
476 }
477#else
478 HepMC::GenVertex::particles_in_const_iterator currentVertexParticleIter(pCurrentVertex->particles_in_const_begin());
479 const HepMC::GenVertex::particles_in_const_iterator endOfListOfParticlesFromCurrentVertex(pCurrentVertex->particles_in_const_end());
480 for (; currentVertexParticleIter != endOfListOfParticlesFromCurrentVertex; ++currentVertexParticleIter) {
481 pCopyOfVertexForClassification[INTIME]->add_particle_in ( new HepMC::GenParticle(**currentVertexParticleIter) );
482 }
483#endif
484 }
485 //keep vertices with outgoing particles
486 for (int type(INTIME); type<NOPUTYPE; ++type) {
487 if (!pCopyOfVertexForClassification[type]) continue;
488 int n_particles_out=pCopyOfVertexForClassification[type]->particles_out_size();
489 if (m_saveType[type] && (n_particles_out > 0) ) {
490 updateClassificationMap(spi, currentBkgEventIndex, 0, type, false);
491 }
492 }
493 } //vertex loop
494
495 return StatusCode::SUCCESS;
496}
497
499//AV: The olde version was too generator specific.
500#ifdef HEPMC3
501 for (const auto& pCurrentVertexParticle: pCurrentVertex->particles_in()) {
502#else
503 auto currentVertexParticleIter = pCurrentVertex->particles_in_const_begin();
504 auto endOfListOfParticlesFromCurrentVertex = pCurrentVertex->particles_in_const_end();
505 for( ;currentVertexParticleIter != endOfListOfParticlesFromCurrentVertex; ++currentVertexParticleIter ) {
506 auto pCurrentVertexParticle = *currentVertexParticleIter;
507#endif
508 if (MC::isBeam(pCurrentVertexParticle)) return true;
509 }
510 return false;
511}
512
513MergeMcEventCollTool::puType MergeMcEventCollTool::classifyVertex(const HepMC::ConstGenParticlePtr& pCurrentVertexParticle, const HepMC::ConstGenVertexPtr& pCurrentParticleProductionVertex, double currentEventTime) {
514 //=======================================================================
515 //handle the slimming case
516 //=======================================================================
517 puType particleClassification(NOPUTYPE);
518 if ( pCurrentParticleProductionVertex ) {
519 //throw away unstable particles and particles outside eta cut
520 if ( m_keepUnstable || MC::isSimStable(pCurrentVertexParticle) ) {
522 if ( std::abs(pCurrentParticleProductionVertex->position().z()) < m_zRange ) {
523 const float xi((pCurrentParticleProductionVertex->position()).x());
524 const float yi((pCurrentParticleProductionVertex->position()).y());
525 if ( !m_doSlimming || ( (xi*xi + yi*yi < m_r2Range) && (pCurrentVertexParticle->momentum().perp() > m_ptMin) ) ) {
526 const double eta(pCurrentVertexParticle->momentum().pseudoRapidity());
527 if ( !m_doSlimming || (std::abs(eta) <= m_absEtaMax) ) {
528 const bool currentEventIsInTime((m_lowTimeToKeep<=currentEventTime) && (currentEventTime<=m_highTimeToKeep));
529 if ( currentEventIsInTime ) {
530 // cout << "the Time is " << currentEventTime << std::endl;
531 if ( 0.0==currentEventTime ) {
532 particleClassification=INTIME;
533 }
534 else if (std::abs(eta) <= m_absEtaMax_outOfTime) {
535 particleClassification=OUTOFTIME;
536 }
537 else {
538 particleClassification=RESTOFMB;
539 }
540 }
541 else {
542 particleClassification=RESTOFMB;
543 }
544 } // r2 && eta cut
545 } // ptmin cut
546 } // zrange cut
547 else {
548 // select cavern events
549 double mass(pCurrentVertexParticle->momentum().m());
550 if ( mass < 0.0 ) { mass = 0.0; }
551 const double kineticEnergy(pCurrentVertexParticle->momentum().e() - mass);
552 if ( !m_doSlimming || ( (kineticEnergy > m_minKinE) && (MC::charge(pCurrentVertexParticle->pdg_id()) != 0) ) ) {
553 particleClassification=CAVERN;
554 }
555 } // zrange cut
556 } // keep unstable
557 } // pCurrentParticleProductionVertex is not NULL
558 return particleClassification;
559}
560
562 int currentClassification=int(INTIME);
563 if (! m_pOvrlMcEvColl->empty()) {
565 while(outputEventItr!=m_pOvrlMcEvColl->end()) { //as end may change
566 const int signal_process_id(HepMC::signal_process_id((*outputEventItr))),event_number((*outputEventItr)->event_number());
567 //Check for separators
568 if(signal_process_id==0 && event_number==-1) {
569 ++outputEventItr;
570 ++currentClassification;
571 continue;
572 }
573 if((*outputEventItr)->vertices_empty()) {
574 //Delete empty GenEvent
575 outputEventItr=m_pOvrlMcEvColl->erase(outputEventItr);
576 ATH_MSG_VERBOSE( "compressOutputMcEventCollection() Removed Empty GenEvent #" << event_number << ", signal_process_id(" << signal_process_id << "), category = " << currentClassification);
577 continue;
578 }
579 ++outputEventItr;
580 }
581 }
582 return StatusCode::SUCCESS;
583}
584
585void MergeMcEventCollTool::updateClassificationMap(int signal_process_id, int event_number, int separator_hack, int classification, bool firstUpdateForThisEvent=false)
586{
588 ATH_MSG_ERROR( "updateClassidificationMap: GenEvent #" << event_number << ", signal_process_id(" << signal_process_id << "), category = " << classification );
589 ATH_MSG_ERROR ("Failed to clear background classification map! Size = "<< m_backgroundClassificationMap.size());
591 }
592 if(-1==classification && !m_newevent) {
593 ATH_MSG_ERROR( "updateClassidificationMap: GenEvent #" << event_number << ", signal_process_id(" << signal_process_id << "), category = " << classification );
594 ATH_MSG_FATAL ("Should only ever be one signal event in the background classification map! Bailing out.");
595 }
596 // Check for separators
597 IndexKey key(makekey(signal_process_id,event_number));
598 //Check for Separator GenEvents
599 if(signal_process_id==0 && event_number==-1) {
600 key=makekey(separator_hack,event_number);
601 }
602 ATH_MSG_VERBOSE( "updateClassidificationMap: GenEvent #" << event_number << ", signal_process_id(" << signal_process_id << "), category = " << classification << ", key = " << key);
603 const PileUpBackgroundMap::iterator event(m_backgroundClassificationMap.find(key));
604 if(event!=m_backgroundClassificationMap.end()) {
605 if(firstUpdateForThisEvent) {
606 ATH_MSG_ERROR( "updateClassidificationMap: Repeated KEY! "<< key <<". Previous category = " << event->second );
607 }
608 else {
609 ATH_MSG_DEBUG( "updateClassidificationMap: Updating category for existing key "<< key <<". Previous category = " << event->second << ", new category = " << classification );
610 }
611 if(int(RESTOFMB)!=event->second) {
612 if(event->second<=classification) return;
613 }
614 }
615 m_backgroundClassificationMap[key]=classification;
616 return;
617}
Scalar eta() const
pseudorapidity method
#define endmsg
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Helpers for checking error return status codes and reporting errors.
#define CHECK(...)
Evaluate an expression and check for errors.
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
ATLAS-specific HepMC functions.
std::vector< xAOD::EventInfo::SubEvent >::const_iterator SubEventIterator
Definition IPileUpTool.h:22
static Double_t sc
std::pair< int, int > IndexKey
the preferred mechanism to access information from the different event stores in a pileup job.
const T * at(size_type n) const
Access an element, as an rvalue.
DataModel_detail::iterator< DataVector > iterator
Standard iterator.
Definition DataVector.h:842
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
bool empty() const noexcept
Returns true if the collection is empty.
This defines the McEventCollection, which is really just an ObjectVector of McEvent objectsFile: Gene...
virtual StatusCode mergeEvent(const EventContext &ctx) override final
called at the end of the subevts loop.
virtual StatusCode prepareEvent(const EventContext &ctx, unsigned int nInputEvents) override final
called before the subevts loop.
BooleanProperty m_addBackgroundCollisionVertices
BooleanProperty m_onlySaveSignalTruth
ServiceHandle< PileUpMergeSvc > m_pMergeSvc
BooleanProperty m_saveRestOfPileup
MergeMcEventCollTool(const std::string &type, const std::string &name, const IInterface *parent)
virtual StatusCode initialize() override final
bool isInitialCollisionVertex(const HepMC::ConstGenVertexPtr &pCurrentVertex) const
DoubleProperty m_absEtaMax_outOfTime
McEventCollection * m_pOvrlMcEvColl
PileUpBackgroundMap m_backgroundClassificationMap
StatusCode processTruthFilteredEvent(const McEventCollection *pMcEvtColl, const double currentEventTime, const int currentBkgEventIndex, int pileupType)
StatusCode processUnfilteredEvent(const McEventCollection *pMcEvtColl, const double currentEventTime, const int currentBkgEventIndex, int pileupType)
virtual StatusCode processBunchXing(int bunchXing, SubEventIterator bSubEvents, SubEventIterator eSubEvents) override final
called for each active bunch-crossing to process current SubEvents bunchXing is in ns
BooleanProperty m_saveOutOfTimePileup
DoubleProperty m_highTimeToKeep
virtual StatusCode processAllSubEvents(const EventContext &ctx) override final
return false if not interested in certain xing times (in ns) implemented by default in PileUpToolBase...
BooleanProperty m_keepUnstable
StringProperty m_truthCollInputKey
StatusCode processEvent(const McEventCollection *pMcEvtColl, const double currentEventTime, const int currentBkgEventIndex, int pileupType)
MergeMcEventCollTool::puType classifyVertex(const HepMC::ConstGenParticlePtr &pCurrentVertexParticle, const HepMC::ConstGenVertexPtr &pCurrentParticleProductionVertex, double currentEventTime)
bool isTruthFiltertedMcEventCollection(const McEventCollection *pMcEvtColl) const
void printDetailsOfMergedMcEventCollection() const
StatusCode saveHeavyIonInfo(const McEventCollection *pMcEvtColl)
BooleanProperty m_compressOutputCollection
BooleanProperty m_saveInTimePileup
unsigned int m_startingIndexForBackground
StatusCode processFirstSubEvent(const McEventCollection *pMcEvtColl)
StatusCode compressOutputMcEventCollection()
StringProperty m_truthCollOutputKey
void updateClassificationMap(int signal_process_id, int event_number, int hack, int classification, bool firstUpdateForThisEvent)
BooleanProperty m_saveCavernBackground
PileUpToolBase(const std::string &type, const std::string &name, const IInterface *parent)
int signal_process_id(const GenEvent &e)
Definition GenEvent.h:637
void set_mpi(GenEvent *e, const int i)
Definition GenEvent.h:646
void set_signal_process_vertex(GenEvent *e, T v)
Definition GenEvent.h:652
HepMC::GenVertex * GenVertexPtr
Definition GenVertex.h:59
GenVertexPtr newGenVertexPtr(const HepMC::FourVector &pos=HepMC::FourVector(0.0, 0.0, 0.0, 0.0), const int i=0)
Definition GenVertex.h:64
void set_signal_process_id(GenEvent *e, const int i)
Definition GenEvent.h:643
void fillBarcodesAttribute(GenEvent *)
Definition GenEvent.h:628
const GenParticle * ConstGenParticlePtr
Definition GenParticle.h:38
GenVertex * signal_process_vertex(const GenEvent *e)
Definition GenEvent.h:627
int mpi(const GenEvent &e)
Definition GenEvent.h:631
const HepMC::GenVertex * ConstGenVertexPtr
Definition GenVertex.h:60
GenEvent * newGenEvent(const int a, const int b)
Definition GenEvent.h:626
bool isBeam(const T &p)
Identify if the particle is beam particle.
double charge(const T &p)
bool isSimStable(const T &p)
Identify if the particle is considered stable at the post-detector-sim stage.
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
std::list< value_t > type
type of the collection of timed data object
a struct encapsulating the identifier of a pile-up event
index_type index() const
the index of the component event in PileUpEventInfo
PileUpType type() const
the pileup type - minbias, cavern, beam halo, signal?
time_type time() const
bunch xing time in ns
MsgStream & msg
Definition testRead.cxx:32