ATLAS Offline Software
MultiParticleGunPileup.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 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 
18 MultiParticleGunPileup::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),
24  m_htgPileupProfile(NULL),
25  m_htgPileupMu(NULL),
26  m_htgPileupEvents(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 
36 
37 }
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 
55  m_pileupProfileIntegral.reserve( m_pileupProfile.size() );
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(gp);
135  }
136 //-----------------------------------------
137 
138  // change the process ID to incorporate the BCID * 10000
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 
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 
183 int MultiParticleGunPileup::nPileupEvents(CLHEP::HepRandomEngine* rndmEngine) {
184  // return the instantaneous mu value according to the profile
185  double threshold = rndmEngine->flat() * m_pileupProfileIntegral.back();
187  return std::distance( m_pileupProfileIntegral.begin(), itr );
188 }
HepMC::GenVertexPtr
HepMC::GenVertex * GenVertexPtr
Definition: GenVertex.h:59
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
MultiParticleGunPileup::fillEvt
virtual StatusCode fillEvt(HepMC::GenEvent *event)
For filling the HepMC event object.
Definition: MultiParticleGunPileup.cxx:153
MultiParticleGunPileup::genInitialize
virtual StatusCode genInitialize()
For initializing the generator, if required.
Definition: MultiParticleGunPileup.cxx:39
MultiParticleGunPileup.h
MultiParticleGunPileup::m_filename
std::string m_filename
Definition: MultiParticleGunPileup.h:41
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
MultiParticleGunPileup::callGenerator
virtual StatusCode callGenerator()
For calling the generator on each iteration of the event loop.
Definition: MultiParticleGunPileup.cxx:84
accumulate
bool accumulate(AccumulateMap &map, std::vector< module_t > const &modules, FPGATrackSimMatrixAccumulator const &acc)
Accumulates an accumulator (e.g.
Definition: FPGATrackSimMatrixAccumulator.cxx:22
HepMC::GenParticlePtr
GenParticle * GenParticlePtr
Definition: GenParticle.h:37
MultiParticleGunPileup::m_evts
std::vector< HepMC::GenEvent * > m_evts
Definition: MultiParticleGunPileup.h:47
TH1D
Definition: rootspy.cxx:342
MultiParticleGunPileup::m_htgPileupEvents
TH1D * m_htgPileupEvents
Definition: MultiParticleGunPileup.h:52
MultiParticleGunPileup::m_pileupProfileIntegral
std::vector< double > m_pileupProfileIntegral
Definition: MultiParticleGunPileup.h:49
LArG4FSStartPointFilter.evt
evt
Definition: LArG4FSStartPointFilter.py:42
MultiParticleGunPileup::m_ngen
int m_ngen
Definition: MultiParticleGunPileup.h:43
MultiParticleGunPileup::m_multbcid
std::vector< float > m_multbcid
Definition: MultiParticleGunPileup.h:40
HepMC::fillBarcodesAttribute
void fillBarcodesAttribute(GenEvent *)
Definition: GenEvent.h:504
python.DataFormatRates.events
events
Definition: DataFormatRates.py:105
MultiParticleGunPileup::nPileupEvents
int nPileupEvents(CLHEP::HepRandomEngine *rndmEngine)
Definition: MultiParticleGunPileup.cxx:183
GenModule::getRandomEngine
CLHEP::HepRandomEngine * getRandomEngine(const std::string &streamName, const EventContext &ctx) const
Definition: GenModule.cxx:34
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
GenModule
Base class for common behaviour of generator interfaces.
Definition: GenModule.h:39
MultiParticleGunPileup::MultiParticleGunPileup
MultiParticleGunPileup(const std::string &name, ISvcLocator *pSvcLocator)
Definition: MultiParticleGunPileup.cxx:18
ParticleGun_EoverP_Config.mom
mom
Definition: ParticleGun_EoverP_Config.py:63
ParticleSampler
Definition: Samplers.h:758
MultiParticleGunPileup::m_htgPileupMu
TH1D * m_htgPileupMu
Definition: MultiParticleGunPileup.h:52
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
lumiFormat.i
int i
Definition: lumiFormat.py:92
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
MultiParticleGunPileup::~MultiParticleGunPileup
~MultiParticleGunPileup()
Definition: MultiParticleGunPileup.cxx:35
ParticleGun_EoverP_Config.pid
pid
Definition: ParticleGun_EoverP_Config.py:62
MultiParticleGunPileup::m_ncollevent
int m_ncollevent
Definition: MultiParticleGunPileup.h:38
CyclicSeqSampler
Definition: Samplers.h:217
ParticleSampler::shoot
std::vector< SampledParticle > shoot()
Definition: Samplers.h:785
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
threshold
Definition: chainparser.cxx:74
TH1D::SetBinContent
void SetBinContent(int, double)
Definition: rootspy.cxx:348
MultiParticleGunPileup::genFinalize
virtual StatusCode genFinalize()
For finalising the generator, if required.
Definition: MultiParticleGunPileup.cxx:170
xAOD::bcid
setEventNumber setTimeStamp bcid
Definition: EventInfo_v1.cxx:133
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:18
MultiParticleGunPileup::m_file
TFile * m_file
Definition: MultiParticleGunPileup.h:51
MultiParticleGunPileup::m_pileupProfile
std::vector< int > m_pileupProfile
Definition: MultiParticleGunPileup.h:39
HepMC::newGenParticlePtr
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
MultiParticleGunPileup::m_nbad
int m_nbad
Definition: MultiParticleGunPileup.h:44
LArG4FSStartPointFilter.particles
list particles
Definition: LArG4FSStartPointFilter.py:84
MultiParticleGunPileup::m_htgPileupProfile
TH1D * m_htgPileupProfile
Definition: MultiParticleGunPileup.h:52
PtEtaMPhiSampler
Definition: Samplers.h:566
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
readCCLHist.float
float
Definition: readCCLHist.py:83
MultiParticleGunPileup::m_partSampler
ParticleSampler * m_partSampler
Definition: MultiParticleGunPileup.h:54