ATLAS Offline Software
Loading...
Searching...
No Matches
MultiParticleGunPileup.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5// MultiPY8Pileup.cxx - extension of GenModule_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
15#include "CLHEP/Random/RandPoisson.h"
17
18MultiParticleGunPileup::MultiParticleGunPileup(const std::string& name, ISvcLocator* pSvcLocator) :
19 GenModule( name, pSvcLocator ),
20 m_ngen(0),
21 m_nbad(0),
22 // m_evnumber(1),
23 m_file(NULL),
25 m_htgPileupMu(NULL),
27 m_partSampler(NULL)
28{
29 declareProperty("NCollPerEvent",m_ncollevent=20,"Collisons per event (-1 to use profile)");
30 declareProperty("PileupProfile",m_pileupProfile,"Pileup profile array");
31 declareProperty("MultBCID",m_multbcid,"Pileup multiplier per BCID array");
32 declareProperty("HistFile",m_filename="","Filename for histograms");
33}
34
38
40 ATH_MSG_INFO( "In MultiParticleGunPileup::genInitialize" );
41
42 // should be initialized after Pythia8_i::genInitialize() ???
43 // m_randomEngine = atRndmGenSvc().GetEngine( Pythia8_i::pythia_stream );
44
45 // if filename set, initialise histograms for mu/nevt profiles
46 if (m_filename!="") {
47 m_file = new TFile( m_filename.c_str(), "recreate" );
48 m_file->cd();
49 m_htgPileupProfile = new TH1D( "pileupProfile", "input pileupProfile", 100, 0., 100. );
50 m_htgPileupMu = new TH1D( "generatedMu", "generated pileup mu", 100, 0., 100. );
51 m_htgPileupEvents = new TH1D( "generatedEvents", "generated pileup events", 100, 0., 100. );
52 }
53
56 for ( std::vector< int >::iterator itr = m_pileupProfile.begin(); itr != m_pileupProfile.end(); ++itr ) {
57 m_pileupProfileIntegral.push_back( std::accumulate( m_pileupProfile.begin(), itr + 1, 0. ) );
58 if (m_file)
59 m_htgPileupProfile->SetBinContent( std::distance( m_pileupProfile.begin(), itr ) + 1, *itr );
60 }
61
62 if ( m_ncollevent > 0 ) {
63 ATH_MSG_INFO("Generate fixed number of " << m_ncollevent << " minbias collisions per bunch crossing");
64 }
65 else {
66 ATH_MSG_INFO("Generate varying minbias collisions per event according to given pileup profile");
67 }
68 m_evts.reserve( 50 );
69
70 ATH_MSG_INFO("Simulate " << m_multbcid.size() << " bunch crossings per event");
71 int ibc=1;
72 for (std::vector<float>::const_iterator itr=m_multbcid.begin();
73 itr!=m_multbcid.end();++itr,++ibc) {
74 ATH_MSG_INFO("Bunch crossing BCID " << ibc << " mu multiplier " << *itr);
75 }
76
77 //Initialize the ParticleGun generator
78 m_partSampler = new ParticleSampler(new CyclicSeqSampler("-11,11,"), new PtEtaMPhiSampler(10000.,10000.,-3,3),1);
79
80 // exit via the base class initialisation
81 return StatusCode::SUCCESS;
82}
83
85 // initialise random generators the first time - delayed after Pythia init
86 const EventContext& ctx = Gaudi::Hive::currentContext();
87 CLHEP::HepRandomEngine* rndmEngine = this->getRandomEngine("ParticleGun", ctx);
88
89 // decide how many events to generate
90
91 int muval = ( m_ncollevent > 0 ? m_ncollevent : nPileupEvents(rndmEngine) );
92 if (m_file) m_htgPileupMu->Fill(muval+0.1);
93 m_evts.clear();
94
95 // loop over all BCID - starting from 1 for in-time pileup
96 int bcid=1;
97 for (std::vector<float>::const_iterator bcitr=m_multbcid.begin();
98 bcitr!=m_multbcid.end();++bcitr,++bcid) {
99 // actual number of minbias in this BCID
100 // Poisson around instantaneous_mu * multiplier value
101 const int nevtraw=CLHEP::RandPoisson::shoot(muval);
102 if (m_file) m_htgPileupEvents->Fill(nevtraw+0.1);
103 const int nevt=(float)nevtraw*(*bcitr);
104
105 for (int ievt=0;ievt<nevt;++ievt) {
106 ATH_MSG_DEBUG("Request generation of event " << ievt << " of " << nevt
107 << " for BCID " << bcid);
108
109//--------------------------- CALL GUN HERE
110 HepMC::GenEvent* evt=new HepMC::GenEvent();
111 evt->weights().push_back(1.0);
112 //evt->set_event_number(ievt); //Maybe dangerous to do this since the first event gets stacked last
113 // Make and fill particles
114 std::vector<SampledParticle> particles = m_partSampler->shoot();
115 for (const auto& p : particles){
116 // Debug printout of particle properties
117 std::cout << ievt << " DEBUG0," << p.m_pid << ", " << p.m_mom.E()<< ", " << p.m_mom.Pt()<< ", " << p.m_mom.M() << std::endl;
118 std::cout << ievt << " DEBUG1 (px,py,pz,E) = (" << p.m_mom.Px()<< ", " << p.m_mom.Py()<< ", " << p.m_mom.Pz()<< ", " << p.m_mom.E() <<")" << std::endl;
119 std::cout << ievt << " DEBUG2 (eta,phi,pt,m) = ()" << p.m_mom.Eta()<< ", " << p.m_mom.Phi()<< ", " << p.m_mom.Pt()<< ", " << p.m_mom.M() <<")" << std::endl;
120 std::cout << ievt << " DEBUG3 (x,y,z,t) = ()" << p.m_pos.X()<< ", " << p.m_pos.Y()<< ", " << p.m_pos.Z()<< ", " << p.m_pos.T() << ")" << std::endl;
121 // Make particle-creation vertex
122 // TODO: do something cleverer than one vertex per particle?
123 HepMC::FourVector pos(p.m_pos.X(), p.m_pos.Y(), p.m_pos.Z(), p.m_pos.T());
125 evt->add_vertex(gv);
126 // Make particle with status == 1
127 HepMC::FourVector mom(p.m_mom.Px(), p.m_mom.Py(), p.m_mom.Pz(), p.m_mom.E());
129 gp->set_status(1);
130 gp->set_pdg_id(p.m_pid);
131 gp->set_momentum(mom);
132 if (p.m_mass)
133 gp->set_generated_mass(p.m_mass);
134 gv->add_particle_out(std::move(gp));
135 }
136//-----------------------------------------
137
138 // change the process ID to incorporate the BCID * 10000
139 int pid=HepMC::signal_process_id(evt);
140 HepMC::set_signal_process_id(evt,pid+10000*bcid);
141 ATH_MSG_DEBUG("Signal process ID " << pid << " set to " <<
142 HepMC::signal_process_id(evt) << " for BCID " << bcid);
144 m_evts.push_back(evt);
145 ++m_ngen;
146 }
147 }
148 ATH_MSG_DEBUG("callGenerator finished with " << m_evts.size() <<
149 " pileup events in buffer");
150 return StatusCode::SUCCESS;
151}
152
153StatusCode MultiParticleGunPileup::fillEvt(HepMC::GenEvent* evt) {
154 int nbuf=m_evts.size();
155 if (nbuf>1) {
156 // send extra events into McEventCollection via backdoor
157 for (int i=1;i<nbuf;++i) {
158 events()->push_back(m_evts[i]);
159 }
160 }
161 // send first event back via usual method
162 // have to copy it to the passed in GenEvent
163 if (nbuf>0) {
164 *evt=*m_evts[0];
165 delete m_evts[0];
166 }
167 return StatusCode::SUCCESS;
168}
169
171 ATH_MSG_INFO("MultiParticleGunPileup finished with " << m_ngen << " good events and " << m_nbad << " failures" );
172
173 if (m_file) {
174 m_file->cd();
175 m_file->Write();
176 m_file->Close();
177 }
178
179 return StatusCode::SUCCESS;
180}
181
182
183int MultiParticleGunPileup::nPileupEvents(CLHEP::HepRandomEngine* rndmEngine) {
184 // return the instantaneous mu value according to the profile
185 double threshold = rndmEngine->flat() * m_pileupProfileIntegral.back();
186 std::vector< double >::iterator itr = std::lower_bound( m_pileupProfileIntegral.begin(), m_pileupProfileIntegral.end(), threshold );
187 return std::distance( m_pileupProfileIntegral.begin(), itr );
188}
#define ATH_MSG_INFO(x)
#define ATH_MSG_DEBUG(x)
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
GenModule(const std::string &name, ISvcLocator *pSvcLocator)
Constructor.
Definition GenModule.cxx:14
CLHEP::HepRandomEngine * getRandomEngine(const std::string &streamName, const EventContext &ctx) const
Definition GenModule.cxx:34
virtual StatusCode genFinalize()
For finalising the generator, if required.
virtual StatusCode genInitialize()
For initializing the generator, if required.
virtual StatusCode callGenerator()
For calling the generator on each iteration of the event loop.
std::vector< double > m_pileupProfileIntegral
std::vector< HepMC::GenEvent * > m_evts
std::vector< float > m_multbcid
int nPileupEvents(CLHEP::HepRandomEngine *rndmEngine)
MultiParticleGunPileup(const std::string &name, ISvcLocator *pSvcLocator)
virtual StatusCode fillEvt(HepMC::GenEvent *event)
For filling the HepMC event object.
std::vector< int > m_pileupProfile
int signal_process_id(const GenEvent &e)
Definition GenEvent.h:637
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
GenParticlePtr newGenParticlePtr(const HepMC::FourVector &mom=HepMC::FourVector(0.0, 0.0, 0.0, 0.0), int pid=0, int status=0)
Definition GenParticle.h:39
void set_signal_process_id(GenEvent *e, const int i)
Definition GenEvent.h:643
void fillBarcodesAttribute(GenEvent *)
Definition GenEvent.h:628
GenParticle * GenParticlePtr
Definition GenParticle.h:37