ATLAS Offline Software
MultiPy8Pileup.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // MultiPY8Pileup.cxx - extension of Pythia8_i to generate multiple pileup
6 // events in one go for fast simulation chain
7 // Richard Hawkings, started 20/2/15, + contributions from Vladimir Lyubushkin
8 
9 #include <algorithm>
10 #include <numeric>
11 #include <functional>
12 #include <iterator>
13 
14 #include "CLHEP/Random/RandPoisson.h"
16 
17 MultiPy8Pileup::MultiPy8Pileup(const std::string& name, ISvcLocator* pSvcLocator) :
18  Pythia8_i::Pythia8_i( name, pSvcLocator ),
19  m_ngen(0),
20  m_nbad(0),
21  // m_evnumber(1),
22  m_file(NULL),
23  m_htgPileupProfile(NULL),
24  m_htgPileupMu(NULL),
25  m_htgPileupEvents(NULL)
26 {
27  declareProperty("NCollPerEvent",m_ncollevent=20,"Collisons per event (-1 to use profile)");
28  declareProperty("PileupProfile",m_pileupProfile,"Pileup profile array");
29  declareProperty("MultBCID",m_multbcid,"Pileup multiplier per BCID array");
30  declareProperty("HistFile",m_filename="","Filename for histograms");
31 }
32 
34 
35 }
36 
38  ATH_MSG_INFO( "In MultiPy8Pileup::genInitialize" );
39 
40  // if filename set, initialise histograms for mu/nevt profiles
41  if (m_filename!="") {
42  m_file = new TFile( m_filename.c_str(), "recreate" );
43  m_file->cd();
44  m_htgPileupProfile = new TH1D( "pileupProfile", "input pileupProfile", 100, 0., 100. );
45  m_htgPileupMu = new TH1D( "generatedMu", "generated pileup mu", 100, 0., 100. );
46  m_htgPileupEvents = new TH1D( "generatedEvents", "generated pileup events", 100, 0., 100. );
47  }
48 
50  m_pileupProfileIntegral.reserve( m_pileupProfile.size() );
51  for ( std::vector< int >::iterator itr = m_pileupProfile.begin(); itr != m_pileupProfile.end(); ++itr ) {
52  m_pileupProfileIntegral.push_back( std::accumulate( m_pileupProfile.begin(), itr + 1, 0. ) );
53  if (m_file)
54  m_htgPileupProfile->SetBinContent( std::distance( m_pileupProfile.begin(), itr ) + 1, *itr );
55  }
56 
57  if ( m_ncollevent > 0 ) {
58  ATH_MSG_INFO("Generate fixed number of " << m_ncollevent << " minbias collisions per bunch crossing");
59  }
60  else {
61  ATH_MSG_INFO("Generate varying minbias collisions per event according to given pileup profile");
62  }
63  m_evts.reserve( 50 );
64 
65  ATH_MSG_INFO("Simulate " << m_multbcid.size() << " bunch crossings per event");
66  int ibc=1;
67  for (std::vector<float>::const_iterator itr=m_multbcid.begin();
68  itr!=m_multbcid.end();++itr,++ibc) {
69  ATH_MSG_INFO("Bunch crossing BCID " << ibc << " mu multiplier " << *itr);
70  }
71 
72  // exit via the base class initialisation
73  return Pythia8_i::genInitialize();
74 }
75 
77  // initialise random generators the first time - delayed after Pythia init
78  const EventContext& ctx = Gaudi::Hive::currentContext();
79  CLHEP::HepRandomEngine* rndmEngine = this->getRandomEngine("MultiPy8Pileup", ctx);
80  // decide how many events to generate
81 
82  int muval = ( m_ncollevent > 0 ? m_ncollevent : nPileupEvents(rndmEngine) );
83  if (m_file) m_htgPileupMu->Fill(muval+0.1);
84  m_evts.clear();
85 
86  // loop over all BCID - starting from 1 for in-time pileup
87  int bcid=1;
88  for (std::vector<float>::const_iterator bcitr=m_multbcid.begin();
89  bcitr!=m_multbcid.end();++bcitr,++bcid) {
90  // actual number of minbias in this BCID
91  // Poisson around instantaneous_mu * multiplier value
92  const int nevtraw=CLHEP::RandPoisson::shoot(muval);
93  if (m_file) m_htgPileupEvents->Fill(nevtraw+0.1);
94  const int nevt=(float)nevtraw*(*bcitr);
95 
96  for (int ievt=0;ievt<nevt;++ievt) {
97  ATH_MSG_DEBUG("Request generation of event " << ievt << " of " << nevt
98  << " for BCID " << bcid);
100  if (sc==StatusCode::SUCCESS) {
101  HepMC::GenEvent* evt=new HepMC::GenEvent();
102  if (Pythia8_i::fillEvt(evt)==StatusCode::SUCCESS) {
103  // change the process ID to incorporate the BCID * 10000
106  ATH_MSG_DEBUG("Signal process ID " << pid << " set to " <<
107  HepMC::signal_process_id(evt) << " for BCID " << bcid);
109  m_evts.push_back(evt);
110  ++m_ngen;
111  } else {
112  ATH_MSG_WARNING("Failed to fillEvt for event seq " << ievt);
113  ++m_nbad;
114  }
115  } else {
116  ++m_nbad;
117  ATH_MSG_WARNING("Failed to generate event seq " << ievt);
118  }
119  }
120  }
121  ATH_MSG_DEBUG("callGenerator finished with " << m_evts.size() <<
122  " pileup events in buffer");
123  return StatusCode::SUCCESS;
124 }
125 
127  int nbuf=m_evts.size();
128  if (nbuf>1) {
129  // send extra events into McEventCollection via backdoor
130  for (int i=1;i<nbuf;++i) {
131  events()->push_back(m_evts[i]);
132  }
133  }
134  // send first event back via usual method
135  // have to copy it to the passed in GenEvent
136  if (nbuf>0) {
137  *evt=*m_evts[0];
138  delete m_evts[0];
139  }
140  return StatusCode::SUCCESS;
141 }
142 
144  ATH_MSG_INFO("MultiPy8Pileup finished with " << m_ngen << " good events and " << m_nbad << " failures" );
145 
146  if (m_file) {
147  m_file->cd();
148  m_file->Write();
149  m_file->Close();
150  }
151 
152  return Pythia8_i::genFinalize();
153 }
154 
155 
156 int MultiPy8Pileup::nPileupEvents(CLHEP::HepRandomEngine* rndmEngine) {
157  // return the instantaneous mu value according to the profile
158  double threshold = rndmEngine->flat() * m_pileupProfileIntegral.back();
160  return std::distance( m_pileupProfileIntegral.begin(), itr );
161 }
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
MultiPy8Pileup::m_pileupProfileIntegral
std::vector< double > m_pileupProfileIntegral
Definition: MultiPy8Pileup.h:49
MultiPy8Pileup::m_multbcid
std::vector< float > m_multbcid
Definition: MultiPy8Pileup.h:40
AthCommonDataStore< AthCommonMsg< Algorithm > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
HepMC::signal_process_id
int signal_process_id(const GenEvent &e)
Definition: GenEvent.h:513
accumulate
bool accumulate(AccumulateMap &map, std::vector< module_t > const &modules, FPGATrackSimMatrixAccumulator const &acc)
Accumulates an accumulator (e.g.
Definition: FPGATrackSimMatrixAccumulator.cxx:22
MultiPy8Pileup::m_evts
std::vector< HepMC::GenEvent * > m_evts
Definition: MultiPy8Pileup.h:47
TH1D
Definition: rootspy.cxx:342
LArG4FSStartPointFilter.evt
evt
Definition: LArG4FSStartPointFilter.py:42
MultiPy8Pileup::m_file
TFile * m_file
Definition: MultiPy8Pileup.h:51
MultiPy8Pileup::genFinalize
virtual StatusCode genFinalize()
For finalising the generator, if required.
Definition: MultiPy8Pileup.cxx:143
HepMC::fillBarcodesAttribute
void fillBarcodesAttribute(GenEvent *)
Definition: GenEvent.h:504
MultiPy8Pileup::genInitialize
virtual StatusCode genInitialize()
For initializing the generator, if required.
Definition: MultiPy8Pileup.cxx:37
python.DataFormatRates.events
events
Definition: DataFormatRates.py:105
MultiPy8Pileup::m_filename
std::string m_filename
Definition: MultiPy8Pileup.h:41
MultiPy8Pileup::m_htgPileupProfile
TH1D * m_htgPileupProfile
Definition: MultiPy8Pileup.h:52
GenModule::getRandomEngine
CLHEP::HepRandomEngine * getRandomEngine(const std::string &streamName, const EventContext &ctx) const
Definition: GenModule.cxx:34
AthenaPoolTestRead.sc
sc
Definition: AthenaPoolTestRead.py:27
m_file
std::unique_ptr< TFile > m_file
description: this is a custom writer for the old-school drivers that don't use an actual writer
Definition: OutputStreamData.cxx:52
MultiPy8Pileup::callGenerator
virtual StatusCode callGenerator()
For calling the generator on each iteration of the event loop.
Definition: MultiPy8Pileup.cxx:76
MultiPy8Pileup::MultiPy8Pileup
MultiPy8Pileup(const std::string &name, ISvcLocator *pSvcLocator)
Definition: MultiPy8Pileup.cxx:17
Pythia8_i::fillEvt
virtual StatusCode fillEvt(HepMC::GenEvent *evt)
For filling the HepMC event object.
Definition: Pythia8_i.cxx:422
Pythia8_i
Definition: Pythia8_i.h:59
lumiFormat.i
int i
Definition: lumiFormat.py:92
MultiPy8Pileup::~MultiPy8Pileup
~MultiPy8Pileup()
Definition: MultiPy8Pileup.cxx:33
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
Pythia8_i::callGenerator
virtual StatusCode callGenerator()
For calling the generator on each iteration of the event loop.
Definition: Pythia8_i.cxx:356
ParticleGun_EoverP_Config.pid
pid
Definition: ParticleGun_EoverP_Config.py:62
Pythia8_i::genFinalize
virtual StatusCode genFinalize()
For finalising the generator, if required.
Definition: Pythia8_i.cxx:637
MultiPy8Pileup::m_nbad
int m_nbad
Definition: MultiPy8Pileup.h:44
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
MultiPy8Pileup::m_ngen
int m_ngen
Definition: MultiPy8Pileup.h:43
MultiPy8Pileup::fillEvt
virtual StatusCode fillEvt(HepMC::GenEvent *event)
For filling the HepMC event object.
Definition: MultiPy8Pileup.cxx:126
MultiPy8Pileup::m_pileupProfile
std::vector< int > m_pileupProfile
Definition: MultiPy8Pileup.h:39
threshold
Definition: chainparser.cxx:74
TH1D::SetBinContent
void SetBinContent(int, double)
Definition: rootspy.cxx:348
xAOD::bcid
setEventNumber setTimeStamp bcid
Definition: EventInfo_v1.cxx:133
MultiPy8Pileup::m_htgPileupEvents
TH1D * m_htgPileupEvents
Definition: MultiPy8Pileup.h:52
MultiPy8Pileup::m_htgPileupMu
TH1D * m_htgPileupMu
Definition: MultiPy8Pileup.h:52
MultiPy8Pileup::m_ncollevent
int m_ncollevent
Definition: MultiPy8Pileup.h:38
MultiPy8Pileup::nPileupEvents
int nPileupEvents(CLHEP::HepRandomEngine *rndmEngine)
Definition: MultiPy8Pileup.cxx:156
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
HepMC::set_signal_process_id
void set_signal_process_id(GenEvent *e, const int i)
Definition: GenEvent.h:519
Amg::distance
float distance(const Amg::Vector3D &p1, const Amg::Vector3D &p2)
calculates the distance between two point in 3D space
Definition: GeoPrimitivesHelpers.h:54
Pythia8_i::genInitialize
virtual StatusCode genInitialize()
For initializing the generator, if required.
Definition: Pythia8_i.cxx:96
readCCLHist.float
float
Definition: readCCLHist.py:83
MultiPy8Pileup.h