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 m_pOvrlMcEvColl->at(0)->add_attribute(HepMCStr::BunchCrossingTime,std::make_shared<HepMC3::IntAttribute>(0));
264 m_pOvrlMcEvColl->at(0)->add_attribute(HepMCStr::PileUpType,std::make_shared<HepMC3::IntAttribute>(0));
265 updateClassificationMap(HepMC::signal_process_id(m_pOvrlMcEvColl->at(0)), m_pOvrlMcEvColl->at(0)->event_number(), 0,- 1, true);
266 m_newevent=false; //Now the McEventCollection and classification map are not empty this should be set to false.
267 ATH_MSG_DEBUG( "execute: copied original event McEventCollection" );
268 const unsigned int nBackgroundMcEventCollections(m_nInputMcEventColls-1); // -1 for original event
269 // -> reserve enough space
270 unsigned int outCollSize(m_pOvrlMcEvColl->size());
271 if(!m_onlySaveSignalTruth) { outCollSize += nBackgroundMcEventCollections; }
272 outCollSize += NOPUTYPE-1; // Adding room for the spacers
273 m_pOvrlMcEvColl->resize(outCollSize);
274 if(!m_onlySaveSignalTruth) { ATH_MSG_DEBUG ( "Number of input SubEvents = " << m_nInputMcEventColls ); }
275 ATH_MSG_DEBUG ( "Total Size of Output McEventCollection = " << outCollSize );
276
277 //now place the "separator" GenEvents. This is a hack used by clients to find/double-check where the GenEvents
278 //of a given type start in the overlay McEventCollection.
279
280 // For example if intime and cavern saving is enabled i.e.
281 // Configurable Variable in code Example Value
282 // SaveInTimeMinBias m_saveType[INTIME] true
283 // SaveOutOfTimeMinBias m_saveType[OUTOFTIME] false
284 // SaveRestOfMinBias m_saveType[RESTOFMB] false
285 // SaveCavernBackground m_saveType[CAVERN] true
286 //If we have two input GenEvents the output collection would look like
287 //SIGNAL, INTIME0, INTIME1, SEPARATOR, SEPARATOR, SEPARATOR, CAVERN0, CAVERN1
288 unsigned int currentMcEventCollectionIndex(1);
289 ATH_MSG_DEBUG ( "Event Type: SIGNAL Starts at Position 0" );
290 for (int type(OUTOFTIME); type<NOPUTYPE; ++type) {
291 //if a type is enabled leave room to insert the events of that type, otherwise place separator immediately after
292 currentMcEventCollectionIndex += 1;
293 m_pOvrlMcEvColl->at(currentMcEventCollectionIndex-1) = HepMC::newGenEvent(0, -1); //pid 0 & event_number -1 flags this GenEvent as SEPARATOR
294 HepMC::set_mpi(m_pOvrlMcEvColl->at(currentMcEventCollectionIndex-1),type);
295 updateClassificationMap(0, -1, type, type, true);
296 ATH_MSG_DEBUG ( "Placing Separator for Type: "<<type<<" at Posistion: " << currentMcEventCollectionIndex-1 );
297 }
298 m_startingIndexForBackground=currentMcEventCollectionIndex;
299 m_nBkgEventsReadSoFar=0; //number of input events/eventcolls read so far. Used to build index of output GenEvent in ovrl McEvColl
300 sc = evtStore()->record(m_pOvrlMcEvColl, m_truthCollOutputKey);//**BIG TEST**//sc=StatusCode::SUCCESS;
301 ATH_MSG_DEBUG( "Starting loop on Background events ... " );
302
303 return sc;
304}
305
307 const HepMC::GenEvent* currentBackgroundEvent = *(pMcEvtColl->begin());
308 if (currentBackgroundEvent->particles().size()!=1) return false;
309 if (currentBackgroundEvent->particles().at(0)->pdg_id()==999) return true;
310 return false;
311}
312
313StatusCode MergeMcEventCollTool::processEvent(const McEventCollection *pMcEvtColl, const double currentEventTime, const int currentBkgEventIndex, int pileupType) {
314 ATH_MSG_VERBOSE ( "processEvent()" );
315 if(m_newevent) return processFirstSubEvent(pMcEvtColl);
316
317 if (pMcEvtColl->empty() || m_onlySaveSignalTruth) {
319 return StatusCode::SUCCESS;
320 }
321 //GenEvt is there
322
323 //Examine the properties of the GenEvent - if it looks like a TruthFiltered background event (contains a Geantino?!)
324 //then save the whole event as below, otherwise do the usual classification.
325 if(isTruthFiltertedMcEventCollection(pMcEvtColl)) {
326 if ( processTruthFilteredEvent(pMcEvtColl, currentEventTime, currentBkgEventIndex, pileupType).isSuccess() ) {
328 return StatusCode::SUCCESS;
329 }
330 else {
331 ATH_MSG_ERROR ("Failed to process a Truth Filtered GenEvent.");
332 }
333 }
334 else {
335 if ( processUnfilteredEvent(pMcEvtColl, currentEventTime, currentBkgEventIndex, pileupType).isSuccess() ) {
337 return StatusCode::SUCCESS;
338 }
339 else {
340 ATH_MSG_ERROR ("Failed to process an Unfiltered GenEvent.");
341 }
342 }
343 //If we make it here something has gone wrong.
345 return StatusCode::FAILURE;
346}
347
349{
350 if (m_pOvrlMcEvColl->at(0)->heavy_ion()) return StatusCode::SUCCESS;
351 if (pMcEvtColl->at(0)->heavy_ion())
352 {
353//It should be clarified if ne wants to get a copy or the content
354 HepMC::GenHeavyIonPtr hinew=std::make_shared<HepMC::GenHeavyIon>(*(pMcEvtColl->at(0)->heavy_ion()));
355 m_pOvrlMcEvColl->at(0)->set_heavy_ion(std::move(hinew));
356 }
357 return StatusCode::SUCCESS;
358}
359
360StatusCode MergeMcEventCollTool::processTruthFilteredEvent(const McEventCollection *pMcEvtColl, const double currentEventTime, const int currentBkgEventIndex, int pileupType) {
361 //insert the GenEvent into the overlay McEventCollection.
362 ATH_MSG_VERBOSE ( "processTruthFilteredEvent(): Event Type: " << pileupType );
363 ATH_CHECK(this->saveHeavyIonInfo(pMcEvtColl));
366 HepMC::fillBarcodesAttribute(&currentBackgroundEvent);
367 const int bunchCrossingTime=static_cast<int>(currentEventTime);
368 currentBackgroundEvent.add_attribute(HepMCStr::BunchCrossingTime,std::make_shared<HepMC3::IntAttribute>(bunchCrossingTime));
369 currentBackgroundEvent.add_attribute(HepMCStr::PileUpType,std::make_shared<HepMC3::IntAttribute>(pileupType));
370
371 currentBackgroundEvent.set_event_number(currentBkgEventIndex);
372 puType currentGenEventClassification(RESTOFMB);
373 if ( std::abs(currentEventTime)<51.0 ) {
374 currentGenEventClassification = ( std::abs(currentEventTime)<1.0 ) ? INTIME : OUTOFTIME;
375 }
377 currentBackgroundEvent.event_number(),
378 0, currentGenEventClassification, true);
379 return StatusCode::SUCCESS;
380}
381
382StatusCode MergeMcEventCollTool::processUnfilteredEvent(const McEventCollection *pMcEvtColl, const double currentEventTime, const int currentBkgEventIndex, int pileupType) {
383 ATH_MSG_VERBOSE ( "processUnfilteredEvent() Event Type: " << pileupType );
384 ATH_CHECK(this->saveHeavyIonInfo(pMcEvtColl));
385 const HepMC::GenEvent& currentBackgroundEvent(**(pMcEvtColl->begin())); //background event
386 //handle the slimming case
387 HepMC::GenVertexPtr pCopyOfGenVertex{nullptr};
388 int spi = HepMC::signal_process_id(currentBackgroundEvent);
389 if ( HepMC::signal_process_vertex(&currentBackgroundEvent) ) pCopyOfGenVertex = std::make_shared<HepMC3::GenVertex> ( HepMC::signal_process_vertex(&currentBackgroundEvent)->data() );
390 //insert the GenEvent into the overlay McEventCollection.
391 //for configs with pile-up truth, also need to propagate barcodes to GenEvent
392 HepMC::GenEvent* evt = m_onlySaveSignalTruth ? new HepMC::GenEvent() : new HepMC::GenEvent(currentBackgroundEvent);
393 const int bunchCrossingTime=static_cast<int>(currentEventTime);
394 evt->add_attribute(HepMCStr::BunchCrossingTime,std::make_shared<HepMC3::IntAttribute>(bunchCrossingTime));
395 evt->add_attribute(HepMCStr::PileUpType,std::make_shared<HepMC3::IntAttribute>(pileupType));
396 //AV Not sure if one should add the vertex here
397 evt->set_event_number(currentBkgEventIndex);
398 evt->add_vertex(pCopyOfGenVertex);
399 HepMC::set_signal_process_vertex(evt,pCopyOfGenVertex);
402 updateClassificationMap(spi, currentBkgEventIndex, 0, RESTOFMB, true);
403
404 unsigned int nCollisionVerticesFound(0);
405 //loop over vertices in Background GenEvent
406 ATH_MSG_VERBOSE( "Starting a vertex loop ... " );
407 auto currentVertexIter = currentBackgroundEvent.vertices().begin();
408 auto endOfCurrentListOfVertices = currentBackgroundEvent.vertices().end();
409 for (; currentVertexIter != endOfCurrentListOfVertices; ++currentVertexIter) {
410 const auto& pCurrentVertex=*currentVertexIter;
411 HepMC::GenVertexPtr pCopyOfVertexForClassification[NOPUTYPE];
412 for (int type(INTIME); type<NOPUTYPE; ++type) pCopyOfVertexForClassification[type]=(HepMC::GenVertexPtr )nullptr;
413
414 //check for collision vertices for in-time events
415 bool isCollisionVertex(false);
416 if(m_addBackgroundCollisionVertices && nCollisionVerticesFound<2 && currentEventTime==0.0) {
417 isCollisionVertex=isInitialCollisionVertex(pCurrentVertex);
418 if(isCollisionVertex) ++nCollisionVerticesFound;
419 }
420
421 //loop over outgoing particles in the current GenVertex keeping those not classified as NOPUTYPE
422 ATH_MSG_VERBOSE( "Starting an outgoing particle loop ... " );
423 for (const HepMC::ConstGenParticlePtr& currentVertexParticle: *pCurrentVertex){
424 ATH_MSG_VERBOSE( "Found a particle at location " << std::hex << currentVertexParticle << std::dec << " with PDG ID = " << currentVertexParticle->pdg_id() );
425 HepMC::ConstGenVertexPtr pCurrentParticleProductionVertex = currentVertexParticle->production_vertex();
426 puType particleClassification(classifyVertex(currentVertexParticle, pCurrentParticleProductionVertex,currentEventTime));
427 //hack to keep the complete vertex information for the interaction vertices of in-time background events
428 if(isCollisionVertex && NOPUTYPE==particleClassification) {
429 particleClassification=INTIME;
430 }
431 //add particle to appropriate vertex
432 if (particleClassification<NOPUTYPE && m_saveType[particleClassification]) {
433 if (!pCopyOfVertexForClassification[particleClassification]) {
434 pCopyOfVertexForClassification[particleClassification] =HepMC::newGenVertexPtr(pCurrentVertex->position());
435 ATH_MSG_VERBOSE( "Added bkg vertex " << pCopyOfVertexForClassification[particleClassification] << " at position " << pCopyOfVertexForClassification[particleClassification] << " for pu type = " << particleClassification );
436 }
437 pCopyOfVertexForClassification[particleClassification]->add_particle_out(std::make_shared<HepMC3::GenParticle>(currentVertexParticle->data()));
438 ATH_MSG_VERBOSE( "Added bkg particle at location " << std::hex << currentVertexParticle << std::dec << " with PDG ID = " << currentVertexParticle->pdg_id() );
439 }
440 } //particle loop
442 if (m_saveType[INTIME] && pCopyOfVertexForClassification[INTIME]) {
443 for (const auto& currentVertexParticle: pCurrentVertex->particles_in()) {
444 pCopyOfVertexForClassification[INTIME]->add_particle_in (std::make_shared<HepMC3::GenParticle>(currentVertexParticle->data()));
445 }
446 }
447 //keep vertices with outgoing particles
448 for (int type(INTIME); type<NOPUTYPE; ++type) {
449 if (!pCopyOfVertexForClassification[type]) continue;
450 int n_particles_out=pCopyOfVertexForClassification[type]->particles_out_size();
451 if (m_saveType[type] && (n_particles_out > 0) ) {
452 updateClassificationMap(spi, currentBkgEventIndex, 0, type, false);
453 }
454 }
455 } //vertex loop
456
457 return StatusCode::SUCCESS;
458}
459
461//AV: The olde version was too generator specific.
462 for (const auto& pCurrentVertexParticle: pCurrentVertex->particles_in()) {
463 if (MC::isBeam(pCurrentVertexParticle)) return true;
464 }
465 return false;
466}
467
468MergeMcEventCollTool::puType MergeMcEventCollTool::classifyVertex(const HepMC::ConstGenParticlePtr& pCurrentVertexParticle, const HepMC::ConstGenVertexPtr& pCurrentParticleProductionVertex, double currentEventTime) {
469 //=======================================================================
470 //handle the slimming case
471 //=======================================================================
472 puType particleClassification(NOPUTYPE);
473 if ( pCurrentParticleProductionVertex ) {
474 //throw away unstable particles and particles outside eta cut
475 if ( m_keepUnstable || MC::isSimStable(pCurrentVertexParticle) ) {
477 if ( std::abs(pCurrentParticleProductionVertex->position().z()) < m_zRange ) {
478 const float xi((pCurrentParticleProductionVertex->position()).x());
479 const float yi((pCurrentParticleProductionVertex->position()).y());
480 if ( !m_doSlimming || ( (xi*xi + yi*yi < m_r2Range) && (pCurrentVertexParticle->momentum().perp() > m_ptMin) ) ) {
481 const double eta(pCurrentVertexParticle->momentum().pseudoRapidity());
482 if ( !m_doSlimming || (std::abs(eta) <= m_absEtaMax) ) {
483 const bool currentEventIsInTime((m_lowTimeToKeep<=currentEventTime) && (currentEventTime<=m_highTimeToKeep));
484 if ( currentEventIsInTime ) {
485 // cout << "the Time is " << currentEventTime << std::endl;
486 if ( 0.0==currentEventTime ) {
487 particleClassification=INTIME;
488 }
489 else if (std::abs(eta) <= m_absEtaMax_outOfTime) {
490 particleClassification=OUTOFTIME;
491 }
492 else {
493 particleClassification=RESTOFMB;
494 }
495 }
496 else {
497 particleClassification=RESTOFMB;
498 }
499 } // r2 && eta cut
500 } // ptmin cut
501 } // zrange cut
502 else {
503 // select cavern events
504 double mass(pCurrentVertexParticle->momentum().m());
505 if ( mass < 0.0 ) { mass = 0.0; }
506 const double kineticEnergy(pCurrentVertexParticle->momentum().e() - mass);
507 if ( !m_doSlimming || ( (kineticEnergy > m_minKinE) && (MC::charge(pCurrentVertexParticle->pdg_id()) != 0) ) ) {
508 particleClassification=CAVERN;
509 }
510 } // zrange cut
511 } // keep unstable
512 } // pCurrentParticleProductionVertex is not NULL
513 return particleClassification;
514}
515
517 int currentClassification=int(INTIME);
518 if (! m_pOvrlMcEvColl->empty()) {
520 while(outputEventItr!=m_pOvrlMcEvColl->end()) { //as end may change
521 const int signal_process_id(HepMC::signal_process_id((*outputEventItr))),event_number((*outputEventItr)->event_number());
522 //Check for separators
523 if(signal_process_id==0 && event_number==-1) {
524 ++outputEventItr;
525 ++currentClassification;
526 continue;
527 }
528 if((*outputEventItr)->vertices_empty()) {
529 //Delete empty GenEvent
530 outputEventItr=m_pOvrlMcEvColl->erase(outputEventItr);
531 ATH_MSG_VERBOSE( "compressOutputMcEventCollection() Removed Empty GenEvent #" << event_number << ", signal_process_id(" << signal_process_id << "), category = " << currentClassification);
532 continue;
533 }
534 ++outputEventItr;
535 }
536 }
537 return StatusCode::SUCCESS;
538}
539
540void MergeMcEventCollTool::updateClassificationMap(int signal_process_id, int event_number, int separator_hack, int classification, bool firstUpdateForThisEvent=false)
541{
543 ATH_MSG_ERROR( "updateClassidificationMap: GenEvent #" << event_number << ", signal_process_id(" << signal_process_id << "), category = " << classification );
544 ATH_MSG_ERROR ("Failed to clear background classification map! Size = "<< m_backgroundClassificationMap.size());
546 }
547 if(-1==classification && !m_newevent) {
548 ATH_MSG_ERROR( "updateClassidificationMap: GenEvent #" << event_number << ", signal_process_id(" << signal_process_id << "), category = " << classification );
549 ATH_MSG_FATAL ("Should only ever be one signal event in the background classification map! Bailing out.");
550 }
551 // Check for separators
552 IndexKey key(makekey(signal_process_id,event_number));
553 //Check for Separator GenEvents
554 if(signal_process_id==0 && event_number==-1) {
555 key=makekey(separator_hack,event_number);
556 }
557 ATH_MSG_VERBOSE( "updateClassidificationMap: GenEvent #" << event_number << ", signal_process_id(" << signal_process_id << "), category = " << classification << ", key = " << key);
558 const PileUpBackgroundMap::iterator event(m_backgroundClassificationMap.find(key));
559 if(event!=m_backgroundClassificationMap.end()) {
560 if(firstUpdateForThisEvent) {
561 ATH_MSG_ERROR( "updateClassidificationMap: Repeated KEY! "<< key <<". Previous category = " << event->second );
562 }
563 else {
564 ATH_MSG_DEBUG( "updateClassidificationMap: Updating category for existing key "<< key <<". Previous category = " << event->second << ", new category = " << classification );
565 }
566 if(int(RESTOFMB)!=event->second) {
567 if(event->second<=classification) return;
568 }
569 }
570 m_backgroundClassificationMap[key]=classification;
571 return;
572}
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.
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.
void operator()(T1)
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)
const std::string BunchCrossingTime
const std::string PileUpType
void set_mpi(GenEvent *e, const int i=0)
Definition GenEvent.h:584
int signal_process_id(const GenEvent &evt)
Definition GenEvent.h:572
HepMC3::GenHeavyIonPtr GenHeavyIonPtr
Definition HeavyIon.h:11
void set_signal_process_vertex(GenEvent *e, T &v)
Definition GenEvent.h:591
void set_signal_process_id(GenEvent *e, const int i=0)
Definition GenEvent.h:580
int mpi(const GenEvent &evt)
Definition GenEvent.h:563
ConstGenVertexPtr signal_process_vertex(const GenEvent *e)
Definition GenEvent.h:597
void fillBarcodesAttribute(GenEvent *e)
Definition GenEvent.h:393
GenVertexPtr newGenVertexPtr(const HepMC3::FourVector &pos=HepMC3::FourVector::ZERO_VECTOR(), const int i=0)
Definition GenVertex.h:25
HepMC3::GenVertexPtr GenVertexPtr
Definition GenVertex.h:23
HepMC3::ConstGenParticlePtr ConstGenParticlePtr
Definition GenParticle.h:20
GenEvent * newGenEvent(const int signal_process_id, const int event_number)
Definition GenEvent.h:360
HepMC3::ConstGenVertexPtr ConstGenVertexPtr
Definition GenVertex.h:24
HepMC3::GenEvent GenEvent
Definition GenEvent.h:39
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