ATLAS Offline Software
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 
5 #include "MergeMcEventCollTool.h"
6 
7 #include "AthenaKernel/errorcheck.h" // Handy definitions for error checking
11 
12 #include "GaudiKernel/PhysicalConstants.h"
13 using namespace Gaudi::Units;
14 
15 
16 #include <vector>
17 #include <string>
18 #include <cmath>
19 #include <stdexcept>
20 #include <array>
21 
22 typedef std::pair<int, int> IndexKey;
23 namespace {
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) :
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 
98 StatusCode 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 
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
167  std::sort(m_pOvrlMcEvColl->begin(), m_pOvrlMcEvColl->end(), GenEventSorter(m_backgroundClassificationMap));
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 
209 StatusCode 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 
219  if(m_backgroundClassificationMap.size()!=m_pOvrlMcEvColl->size()) {
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 
224  std::sort(m_pOvrlMcEvColl->begin(), m_pOvrlMcEvColl->end(), GenEventSorter(m_backgroundClassificationMap));
225  ATH_MSG_DEBUG("Sorted McEventCollection OK.");
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 
320 StatusCode 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 
371 StatusCode 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  }
389  updateClassificationMap(HepMC::signal_process_id(currentBackgroundEvent),
390  currentBackgroundEvent.event_number(),
391  0, currentGenEventClassification, true);
392  return StatusCode::SUCCESS;
393 }
394 
395 StatusCode 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 
513 MergeMcEventCollTool::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 
585 void MergeMcEventCollTool::updateClassificationMap(int signal_process_id, int event_number, int separator_hack, int classification, bool firstUpdateForThisEvent=false)
586 {
587  if(m_newevent && !m_backgroundClassificationMap.empty()) {
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);
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 }
HepMC::GenVertexPtr
HepMC::GenVertex * GenVertexPtr
Definition: GenVertex.h:59
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
MergeMcEventCollTool::m_rRange
DoubleProperty m_rRange
Definition: MergeMcEventCollTool.h:93
data
char data[hepevt_bytes_allocation_ATLAS]
Definition: HepEvt.cxx:11
python.handimod.spi
spi
Definition: handimod.py:532
IndexKey
std::pair< int, int > IndexKey
Definition: MergeMcEventCollTool.cxx:22
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
MergeMcEventCollTool::m_saveOutOfTimePileup
BooleanProperty m_saveOutOfTimePileup
Definition: MergeMcEventCollTool.h:103
MergeMcEventCollTool::m_truthCollOutputKey
StringProperty m_truthCollOutputKey
Definition: MergeMcEventCollTool.h:86
MergeMcEventCollTool::INTIME
@ INTIME
Definition: MergeMcEventCollTool.h:54
MergeMcEventCollTool::prepareEvent
virtual StatusCode prepareEvent(const EventContext &ctx, unsigned int nInputEvents) override final
called before the subevts loop.
Definition: MergeMcEventCollTool.cxx:98
MergeMcEventCollTool::m_saveInTimePileup
BooleanProperty m_saveInTimePileup
Definition: MergeMcEventCollTool.h:101
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
Base_Fragment.mass
mass
Definition: Sherpa_i/share/common/Base_Fragment.py:59
MergeMcEventCollTool::initialize
virtual StatusCode initialize() override final
Definition: MergeMcEventCollTool.cxx:77
MergeMcEventCollTool::printDetailsOfMergedMcEventCollection
void printDetailsOfMergedMcEventCollection() const
Definition: MergeMcEventCollTool.cxx:238
MergeMcEventCollTool::CAVERN
@ CAVERN
Definition: MergeMcEventCollTool.h:54
eta
Scalar eta() const
pseudorapidity method
Definition: AmgMatrixBasePlugin.h:83
MergeMcEventCollTool::m_signal_event_number
int m_signal_event_number
Definition: MergeMcEventCollTool.h:127
HepMC::signal_process_id
int signal_process_id(const GenEvent &e)
Definition: GenEvent.h:635
MergeMcEventCollTool.h
MergeMcEventCollTool::classifyVertex
MergeMcEventCollTool::puType classifyVertex(const HepMC::ConstGenParticlePtr &pCurrentVertexParticle, const HepMC::ConstGenVertexPtr &pCurrentParticleProductionVertex, double currentEventTime)
Definition: MergeMcEventCollTool.cxx:513
MergeMcEventCollTool::processUnfilteredEvent
StatusCode processUnfilteredEvent(const McEventCollection *pMcEvtColl, const double currentEventTime, const int currentBkgEventIndex, int pileupType)
Definition: MergeMcEventCollTool.cxx:395
MergeMcEventCollTool::m_lowTimeToKeep
DoubleProperty m_lowTimeToKeep
Definition: MergeMcEventCollTool.h:90
McEventCollection
McEventCollection
Definition: GeneratorObjectsTPCnv.cxx:60
MergeMcEventCollTool::m_saveType
bool m_saveType[NOPUTYPE]
Definition: MergeMcEventCollTool.h:111
MergeMcEventCollTool::processFirstSubEvent
StatusCode processFirstSubEvent(const McEventCollection *pMcEvtColl)
Definition: MergeMcEventCollTool.cxx:257
HepMC::newGenEvent
GenEvent * newGenEvent(const int a, const int b)
Definition: GenEvent.h:624
MergeMcEventCollTool::processEvent
StatusCode processEvent(const McEventCollection *pMcEvtColl, const double currentEventTime, const int currentBkgEventIndex, int pileupType)
Definition: MergeMcEventCollTool.cxx:320
PileUpTimeEventIndex::index
index_type index() const
the index of the component event in PileUpEventInfo
Definition: PileUpTimeEventIndex.cxx:76
MergeMcEventCollTool::m_newevent
bool m_newevent
Definition: MergeMcEventCollTool.h:115
LArG4FSStartPointFilter.evt
evt
Definition: LArG4FSStartPointFilter.py:42
MergeMcEventCollTool::m_truthCollInputKey
StringProperty m_truthCollInputKey
Definition: MergeMcEventCollTool.h:85
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
MergeMcEventCollTool::puType
puType
Definition: MergeMcEventCollTool.h:54
HepMC::fillBarcodesAttribute
void fillBarcodesAttribute(GenEvent *)
Definition: GenEvent.h:626
MergeMcEventCollTool::m_startingIndexForBackground
unsigned int m_startingIndexForBackground
Definition: MergeMcEventCollTool.h:113
AthenaPoolTestRead.sc
sc
Definition: AthenaPoolTestRead.py:27
module_driven_slicing.key2
key2
Definition: module_driven_slicing.py:159
PileUpMergeSvc::TimedList::type
std::list< value_t > type
type of the collection of timed data object
Definition: PileUpMergeSvc.h:75
MergeMcEventCollTool::m_absEtaMax
DoubleProperty m_absEtaMax
Definition: MergeMcEventCollTool.h:88
MergeMcEventCollTool::m_pOvrlMcEvColl
McEventCollection * m_pOvrlMcEvColl
Definition: MergeMcEventCollTool.h:84
HepMC::set_signal_process_vertex
void set_signal_process_vertex(GenEvent *e, T v)
Definition: GenEvent.h:650
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
MergeMcEventCollTool::m_doSlimming
BooleanProperty m_doSlimming
Definition: MergeMcEventCollTool.h:109
event
POOL::TEvent event(POOL::TEvent::kClassAccess)
McEventCollection.h
HepMC::newGenVertexPtr
GenVertexPtr newGenVertexPtr(const HepMC::FourVector &pos=HepMC::FourVector(0.0, 0.0, 0.0, 0.0), const int i=0)
Definition: GenVertex.h:64
MergeMcEventCollTool::processAllSubEvents
virtual StatusCode processAllSubEvents(const EventContext &ctx) override final
return false if not interested in certain xing times (in ns) implemented by default in PileUpToolBase...
Definition: MergeMcEventCollTool.cxx:117
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
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
MergeMcEventCollTool::m_nInputMcEventColls
unsigned int m_nInputMcEventColls
Definition: MergeMcEventCollTool.h:117
MergeMcEventCollTool::m_nBkgEventsReadSoFar
unsigned int m_nBkgEventsReadSoFar
Definition: MergeMcEventCollTool.h:119
MergeMcEventCollTool::MergeMcEventCollTool
MergeMcEventCollTool(const std::string &type, const std::string &name, const IInterface *parent)
Definition: MergeMcEventCollTool.cxx:70
MergeMcEventCollTool::saveHeavyIonInfo
StatusCode saveHeavyIonInfo(const McEventCollection *pMcEvtColl)
Definition: MergeMcEventCollTool.cxx:355
test_pyathena.parent
parent
Definition: test_pyathena.py:15
MergeMcEventCollTool::OUTOFTIME
@ OUTOFTIME
Definition: MergeMcEventCollTool.h:54
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
CHECK
#define CHECK(...)
Evaluate an expression and check for errors.
Definition: Control/AthenaKernel/AthenaKernel/errorcheck.h:422
MergeMcEventCollTool::updateClassificationMap
void updateClassificationMap(int signal_process_id, int event_number, int hack, int classification, bool firstUpdateForThisEvent)
Definition: MergeMcEventCollTool.cxx:585
DataVector
Derived DataVector<T>.
Definition: DataVector.h:794
PileUpToolBase
Definition: PileUpToolBase.h:18
MergeMcEventCollTool::m_highTimeToKeep
DoubleProperty m_highTimeToKeep
Definition: MergeMcEventCollTool.h:91
HepMC::ConstGenParticlePtr
const GenParticle * ConstGenParticlePtr
Definition: GenParticle.h:38
MergeMcEventCollTool::m_backgroundClassificationMap
PileUpBackgroundMap m_backgroundClassificationMap
Definition: MergeMcEventCollTool.h:78
MergeMcEventCollTool::mergeEvent
virtual StatusCode mergeEvent(const EventContext &ctx) override final
called at the end of the subevts loop.
Definition: MergeMcEventCollTool.cxx:209
MergeMcEventCollTool::m_addBackgroundCollisionVertices
BooleanProperty m_addBackgroundCollisionVertices
Definition: MergeMcEventCollTool.h:121
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
PileUpTimeEventIndex::time
time_type time() const
bunch xing time in ns
Definition: PileUpTimeEventIndex.cxx:71
errorcheck.h
Helpers for checking error return status codes and reporting errors.
charge
double charge(const T &p)
Definition: AtlasPID.h:756
MergeMcEventCollTool::NOPUTYPE
@ NOPUTYPE
Definition: MergeMcEventCollTool.h:54
MergeMcEventCollTool::m_minKinE
DoubleProperty m_minKinE
Definition: MergeMcEventCollTool.h:99
MergeMcEventCollTool::isInitialCollisionVertex
bool isInitialCollisionVertex(const HepMC::ConstGenVertexPtr &pCurrentVertex) const
Definition: MergeMcEventCollTool.cxx:498
MergeMcEventCollTool::m_saveCavernBackground
BooleanProperty m_saveCavernBackground
Definition: MergeMcEventCollTool.h:107
MergeMcEventCollTool::processBunchXing
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
Definition: MergeMcEventCollTool.cxx:185
MergeMcEventCollTool::isTruthFiltertedMcEventCollection
bool isTruthFiltertedMcEventCollection(const McEventCollection *pMcEvtColl) const
Definition: MergeMcEventCollTool.cxx:308
MergeMcEventCollTool::m_saveRestOfPileup
BooleanProperty m_saveRestOfPileup
Definition: MergeMcEventCollTool.h:105
MergeMcEventCollTool::m_compressOutputCollection
BooleanProperty m_compressOutputCollection
Definition: MergeMcEventCollTool.h:123
MergeMcEventCollTool::m_keepUnstable
BooleanProperty m_keepUnstable
Definition: MergeMcEventCollTool.h:87
MergeMcEventCollTool::RESTOFMB
@ RESTOFMB
Definition: MergeMcEventCollTool.h:54
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
PileUpMergeSvc.h
the preferred mechanism to access information from the different event stores in a pileup job.
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
MC::isBeam
bool isBeam(const T &p)
Identify if the particle is beam particle.
Definition: HepMCHelpers.h:39
DEBUG
#define DEBUG
Definition: page_access.h:11
MergeMcEventCollTool::m_onlySaveSignalTruth
BooleanProperty m_onlySaveSignalTruth
Definition: MergeMcEventCollTool.h:125
MergeMcEventCollTool::m_pMergeSvc
ServiceHandle< PileUpMergeSvc > m_pMergeSvc
Definition: MergeMcEventCollTool.h:82
MergeMcEventCollTool::m_ptMin
DoubleProperty m_ptMin
Definition: MergeMcEventCollTool.h:98
HepMC::mpi
int mpi(const GenEvent &e)
Definition: GenEvent.h:629
SubEventIterator
std::vector< xAOD::EventInfo::SubEvent >::const_iterator SubEventIterator
Definition: IPileUpTool.h:22
HepMC::ConstGenVertexPtr
const HepMC::GenVertex * ConstGenVertexPtr
Definition: GenVertex.h:60
MC::isSimStable
bool isSimStable(const T &p)
Identify if the particle is considered stable at the post-detector-sim stage.
Definition: HepMCHelpers.h:57
MergeMcEventCollTool::m_zRange
DoubleProperty m_zRange
Definition: MergeMcEventCollTool.h:97
MergeMcEventCollTool::compressOutputMcEventCollection
StatusCode compressOutputMcEventCollection()
Definition: MergeMcEventCollTool.cxx:561
HepMC::set_signal_process_id
void set_signal_process_id(GenEvent *e, const int i)
Definition: GenEvent.h:641
PileUpTimeEventIndex
a struct encapsulating the identifier of a pile-up event
Definition: PileUpTimeEventIndex.h:12
MergeMcEventCollTool::processTruthFilteredEvent
StatusCode processTruthFilteredEvent(const McEventCollection *pMcEvtColl, const double currentEventTime, const int currentBkgEventIndex, int pileupType)
Definition: MergeMcEventCollTool.cxx:371
HepMC::set_mpi
void set_mpi(GenEvent *e, const int i)
Definition: GenEvent.h:644
PileUpTimeEventIndex::type
PileUpType type() const
the pileup type - minbias, cavern, beam halo, signal?
Definition: PileUpTimeEventIndex.cxx:81
python.AutoConfigFlags.msg
msg
Definition: AutoConfigFlags.py:7
MergeMcEventCollTool::m_r2Range
double m_r2Range
Definition: MergeMcEventCollTool.h:95
HepMCHelpers.h
GenParticle
@ GenParticle
Definition: TruthClasses.h:30
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37
MergeMcEventCollTool::m_absEtaMax_outOfTime
DoubleProperty m_absEtaMax_outOfTime
Definition: MergeMcEventCollTool.h:89
HepMC::signal_process_vertex
GenVertex * signal_process_vertex(const GenEvent *e)
Definition: GenEvent.h:625
module_driven_slicing.key1
key1
Definition: module_driven_slicing.py:158