ATLAS Offline Software
Loading...
Searching...
No Matches
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
17MultiPy8Pileup::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),
24 m_htgPileupMu(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
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
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
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);
99 StatusCode sc=Pythia8_i::callGenerator();
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
104 int pid=HepMC::signal_process_id(evt);
105 HepMC::set_signal_process_id(evt,pid+10000*bcid);
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
126StatusCode MultiPy8Pileup::fillEvt(HepMC::GenEvent* evt) {
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
156int MultiPy8Pileup::nPileupEvents(CLHEP::HepRandomEngine* rndmEngine) {
157 // return the instantaneous mu value according to the profile
158 double threshold = rndmEngine->flat() * m_pileupProfileIntegral.back();
159 std::vector< double >::iterator itr = std::lower_bound( m_pileupProfileIntegral.begin(), m_pileupProfileIntegral.end(), threshold );
160 return std::distance( m_pileupProfileIntegral.begin(), itr );
161}
#define ATH_MSG_INFO(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
static Double_t sc
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
CLHEP::HepRandomEngine * getRandomEngine(const std::string &streamName, const EventContext &ctx) const
Definition GenModule.cxx:34
std::vector< int > m_pileupProfile
virtual StatusCode callGenerator()
For calling the generator on each iteration of the event loop.
TH1D * m_htgPileupEvents
std::vector< float > m_multbcid
MultiPy8Pileup(const std::string &name, ISvcLocator *pSvcLocator)
std::vector< double > m_pileupProfileIntegral
virtual StatusCode genFinalize()
For finalising the generator, if required.
virtual StatusCode fillEvt(HepMC::GenEvent *event)
For filling the HepMC event object.
std::string m_filename
int nPileupEvents(CLHEP::HepRandomEngine *rndmEngine)
TH1D * m_htgPileupProfile
std::vector< HepMC::GenEvent * > m_evts
virtual StatusCode genInitialize()
For initializing the generator, if required.
virtual StatusCode genInitialize()
For initializing the generator, if required.
Definition Pythia8_i.cxx:98
virtual StatusCode fillEvt(HepMC::GenEvent *evt)
For filling the HepMC event object.
virtual StatusCode callGenerator()
For calling the generator on each iteration of the event loop.
virtual StatusCode genFinalize()
For finalising the generator, if required.
Pythia8_i(const std::string &name, ISvcLocator *pSvcLocator)
Definition Pythia8_i.cxx:68
int signal_process_id(const GenEvent &e)
Definition GenEvent.h:637
void set_signal_process_id(GenEvent *e, const int i)
Definition GenEvent.h:643
void fillBarcodesAttribute(GenEvent *)
Definition GenEvent.h:628