CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
PileUpProducer.cc
Go to the documentation of this file.
7 
9 
11 
18 
19 #include "HepMC/GenEvent.h"
20 #include "TFile.h"
21 #include "TTree.h"
22 #include "TROOT.h"
23 
24 #include <iostream>
25 #include <memory>
26 #include <sys/stat.h>
27 #include <cmath>
28 
29 PileUpProducer::PileUpProducer(edm::ParameterSet const & p) : hprob(0), currentValuesWereSet(false)
30 {
31 
32  // This producer produces an object PileupMixingContent and PileupVertexContent, needed by PileupSummaryInfo
33  produces<PileupMixingContent>();
34  produces<PileupVertexContent>();
35  // This producer produces a HepMCProduct, with all pileup vertices/particles
36  produces<edm::HepMCProduct>("PileUpEvents");
37 
38  // Initialize the random number generator service
40  if ( ! rng.isAvailable() ) {
41  throw cms::Exception("Configuration")
42  << "PileUpProducer requires the RandomGeneratorService\n"
43  "which is not present in the configuration file.\n"
44  "You must add the service in the configuration file\n"
45  "or remove the module that requires it";
46  }
47 
48  // RANDOM_NUMBER_ERROR
49  // Random number should be generated by the engines from the
50  // RandomNumberGeneratorService. This appears to use the global
51  // engine in ROOT. This is not thread safe unless the module using
52  // it is a one module and declares a shared resource and all
53  // other modules using it also declare the same shared resource.
54  // This also breaks replay.
55  gRandom->SetSeed(rng->mySeed());
56 
57  // The pile-up event generation condition
58  const edm::ParameterSet& pu = p.getParameter<edm::ParameterSet>("PileUpSimulator");
59  usePoisson_ = pu.getParameter<bool>("usePoisson");
60  averageNumber_ = 0.;
61  if (usePoisson_) {
62  std::cout << " FastSimulation/PileUpProducer -> poissonian distribution" << std::endl;
63  averageNumber_ = pu.getParameter<double>("averageNumber");
64  } else {//take distribution from configuration
65  dataProbFunctionVar = pu.getParameter<std::vector<int> >("probFunctionVariable");
66  dataProb = pu.getParameter<std::vector<double> >("probValue");
67  varSize = (int) dataProbFunctionVar.size();
68  probSize = (int) dataProb.size();
69  // std::cout << " FastSimulation/PileUpProducer -> varSize = " << varSize << std::endl;
70  // std::cout << " FastSimulation/PileUpProducer -> probSize = " << probSize << std::endl;
71 
72  std::cout << " FastSimulation/PileUpProducer -> distribution from configuration file " << std::endl;
73  if (probSize < varSize){
74  for (int i=0; i<(varSize - probSize); i++) dataProb.push_back(0);
75  edm::LogWarning("") << " The probability function data will be completed with "
76  << (varSize - probSize) <<" values `0';"
77  << " the number of the P(x) data set after adding those 0's is " << dataProb.size();
78  probSize = dataProb.size();
79  }
80  // Create an histogram with the data from the probability function provided by the user
81  int xmin = (int) dataProbFunctionVar[0];
82  int xmax = (int) dataProbFunctionVar[varSize-1]+1; // need upper edge to be one beyond last value
83  int numBins = varSize;
84  std::cout << " FastSimulation/PileUpProducer -> An histogram will be created with " << numBins
85  << " bins in the range ("<< xmin << "," << xmax << ")." << std::endl;
86  hprob = new TH1F("h","Histo from the user's probability function",numBins,xmin,xmax);
87  LogDebug("") << " FastSimulation/PileUpProducer -> Filling histogram with the following data:";
88  for (int j=0; j < numBins ; j++){
89  LogDebug("") << " x = " << dataProbFunctionVar[j ]<< " P(x) = " << dataProb[j];
90  hprob->Fill(dataProbFunctionVar[j]+0.5,dataProb[j]); // assuming integer values for the bins, fill bin centers, not edges
91  }
92 
93  // Check if the histogram is normalized
94  if (((hprob->Integral() - 1) > 1.0e-02) && ((hprob->Integral() - 1) < -1.0e-02)) throw cms::Exception("BadHistoDistribution") << "The histogram should be normalized!" << std::endl;
95 
96  // Get the averageNumber from the histo
97  averageNumber_ = hprob->GetMean();
98  }
99  theFileNames = pu.getUntrackedParameter<std::vector<std::string> >("fileNames");
100  inputFile = pu.getUntrackedParameter<std::string>("inputFile");
102  theFiles.resize(theNumberOfFiles);
103  theTrees.resize(theNumberOfFiles);
104  theBranches.resize(theNumberOfFiles);
105  thePUEvents.resize(theNumberOfFiles);
106  theCurrentEntry.resize(theNumberOfFiles);
107  theCurrentMinBiasEvt.resize(theNumberOfFiles);
108  theNumberOfEntries.resize(theNumberOfFiles);
109  theNumberOfMinBiasEvts.resize(theNumberOfFiles);
110 
111  // Initialize the primary vertex generator
112  const edm::ParameterSet& vtx = p.getParameter<edm::ParameterSet>("VertexGenerator");
113  std::string vtxType = vtx.getParameter<std::string>("type");
114  if ( vtxType == "Gaussian" )
116  else if ( vtxType == "Flat" )
118  else if ( vtxType == "BetaFunc" )
120  else
122 
123 
124 
125  if (averageNumber_ > 0.)
126  {
127  std::cout << " FastSimulation/PileUpProducer -> MinBias events taken from " << theFileNames[0] << " et al., " ;
128  std::cout << " with an average number of events of " << averageNumber_ << std::endl;
129  }
130  else std::cout << " FastSimulation/PileUpProducer -> No pileup " << std::endl;
131 
132 
133 }
134 
136 
137  delete theVertexGenerator;
138  if (hprob) delete hprob;
139 
140 }
141 
143 {
145 
146  // Read the information from a previous run (to keep reproducibility)
148  if ( currentValuesWereSet )
149  std::cout << "***WARNING*** You are reading pile-up information from the file "
150  << inputFile << " created in an earlier run."
151  << std::endl;
152 
153  // Open the file for saving the information of the current run
154  myOutputFile.open ("PileUpOutputFile.txt");
155  myOutputBuffer = 0;
156 
157  // Open the root files
158  for ( unsigned file=0; file<theNumberOfFiles; ++file ) {
159 
160  if (theFileNames[file].find("file:")==0) {
161  fullPath = theFileNames[file].erase(0,5);
162  }
163  else {
164  edm::FileInPath myDataFile("FastSimulation/PileUpProducer/data/"+theFileNames[file]);
165  fullPath = myDataFile.fullPath();
166  }
167  // theFiles[file] = TFile::Open(theFileNames[file].c_str());
168  theFiles[file] = TFile::Open(fullPath.c_str());
169  if ( !theFiles[file] ) throw cms::Exception("FastSimulation/PileUpProducer")
170  << "File " << theFileNames[file] << " " << fullPath << " not found ";
171  //
172  theTrees[file] = (TTree*) theFiles[file]->Get("MinBiasEvents");
173  if ( !theTrees[file] ) throw cms::Exception("FastSimulation/PileUpProducer")
174  << "Tree with name MinBiasEvents not found in " << theFileNames[file];
175  //
176  theBranches[file] = theTrees[file]->GetBranch("puEvent");
177  if ( !theBranches[file] ) throw cms::Exception("FastSimulation/PileUpProducer")
178  << "Branch with name puEvent not found in " << theFileNames[file];
179  //
180  thePUEvents[file] = new PUEvent();
181  theBranches[file]->SetAddress(&thePUEvents[file]);
182  //
183  theNumberOfEntries[file] = theTrees[file]->GetEntries();
184 
185  if ( currentValuesWereSet ) {
186  theTrees[file]->GetEntry(theCurrentEntry[file]);
187  unsigned NMinBias = thePUEvents[file]->nMinBias();
188  theNumberOfMinBiasEvts[file] = NMinBias;
189  }
190  }
191  gROOT->cd();
192 }
193 
195  if ( !currentValuesWereSet ) {
196  currentValuesWereSet = true;
197 
199 
200  for ( unsigned file=0; file < theNumberOfFiles; ++file ) {
202  (unsigned) (theNumberOfEntries[file] * random.flatShoot());
203 
204  theTrees[file]->GetEntry(theCurrentEntry[file]);
205  unsigned NMinBias = thePUEvents[file]->nMinBias();
206  theNumberOfMinBiasEvts[file] = NMinBias;
207 
209  (unsigned) (theNumberOfMinBiasEvts[file] * random.flatShoot());
210  }
211  }
212 }
213 
215 {
216  // Close all local files
217  // Among other things, this allows the TROOT destructor to end up
218  // without crashing, while trying to close these files from outside
219  for ( unsigned file=0; file<theFiles.size(); ++file ) {
220 
221  // std::cout << "Closing " << theFileNames[file] << std::endl;
222  theFiles[file]->Close();
223 
224  }
225 
226  // Close the output file
227  myOutputFile.close();
228 }
229 
231 {
232  // Create the GenEvent and the HepMCProduct
233  std::auto_ptr<edm::HepMCProduct> pu_product(new edm::HepMCProduct());
234  HepMC::GenEvent* evt = new HepMC::GenEvent();
235 
237 
238  // How many pile-up events?
239  int PUevts; float truePUevts;
240  if (usePoisson_) {
241  PUevts = (int) random.poissonShoot(averageNumber_);
242  truePUevts = (float) averageNumber_;
243  }
244  else {
245  // RANDOM_NUMBER_ERROR
246  // Random number should be generated by the engines from the
247  // RandomNumberGeneratorService. This appears to use the global
248  // engine in ROOT. This is not thread safe unless the module using
249  // it is a one module and declares a shared resource and all
250  // other modules using it also declare the same shared resource.
251  // This also breaks replay.
252  float d = (float) hprob->GetRandom();
253  PUevts = (int) random.poissonShoot(d);
254  truePUevts = d;
255  }
256  // std::cout << "PUevts = " << PUevts << std::endl;
257 
258  // Save this information in the PileupMixingContent object
259  // IMPORTANT: the bunch crossing number is always 0 because FastSim has no out-of-time PU
260  std::auto_ptr< PileupMixingContent > PileupMixing_;
261  std::auto_ptr< PileupVertexContent > PileupVertexing_;
262 
263  std::vector<int> bunchCrossingList;
264  bunchCrossingList.push_back(0);
265 
266  std::vector<int> numInteractionList;
267  numInteractionList.push_back(PUevts);
268 
269  std::vector<float> trueInteractionList;
270  trueInteractionList.push_back(truePUevts);
271 
272  std::vector<edm::EventID> eventInfoList;
273 
274  std::vector<float> pThatList;
275  std::vector<float> zposList;
276 
277  // generate fake EventID list to prevent crash in PileupInfo
278 
279  for(uint32_t index=0; index!=uint(PUevts); ++index) {
281  eventInfoList.push_back(Fake);
282  pThatList.push_back(0.);
283  zposList.push_back(0.);
284  }
285 
286  PileupMixing_ = std::auto_ptr< PileupMixingContent >(new PileupMixingContent(bunchCrossingList,numInteractionList,trueInteractionList,eventInfoList,450)); // it shouldn't matter what the assumed bunchspacing is if there is no OOT PU. Add argument for compatibility.
287  iEvent.put(PileupMixing_);
288 
289  PileupVertexing_ = std::auto_ptr< PileupVertexContent >(new PileupVertexContent(pThatList, zposList));
290 
291  iEvent.put(PileupVertexing_);
292 
293  // Get N events from random files
294  for ( int ievt=0; ievt<PUevts; ++ievt ) {
295 
296  // Draw a file in a ramdom manner
297  unsigned file = (unsigned) (theNumberOfFiles * random.flatShoot());
298  /*
299  if ( debug )
300  std::cout << "The file chosen for event " << ievt
301  << " is the file number " << file << std::endl;
302  */
303 
304  // Smear the primary vertex and express it in mm (stupid GenEvent convention...)
306  HepMC::FourVector smearedVertex =
307  HepMC::FourVector(theVertexGenerator->X()*10.,
308  theVertexGenerator->Y()*10.,
309  theVertexGenerator->Z()*10.,
310  0.);
311  HepMC::GenVertex* aVertex = new HepMC::GenVertex(smearedVertex);
312  evt->add_vertex(aVertex);
313 
314  // Some rotation around the z axis, for more randomness
315  double theAngle = random.flatShoot() * 2. * 3.14159265358979323;
316  double cAngle = std::cos(theAngle);
317  double sAngle = std::sin(theAngle);
318 
319  /*
320  if ( debug )
321  std::cout << "File chosen : " << file
322  << " Current entry in this file " << theCurrentEntry[file]
323  << " Current minbias in this chunk= " << theCurrentMinBiasEvt[file]
324  << " Total number of minbias in this chunk = " << theNumberOfMinBiasEvts[file] << std::endl;
325  */
326 
327  // theFiles[file]->cd();
328  // gDirectory->ls();
329  // Check we are not either at the end of a minbias bunch
330  // or at the end of a file
331  if ( theCurrentMinBiasEvt[file] == theNumberOfMinBiasEvts[file] ) {
332  // if ( debug ) std::cout << "End of MinBias bunch ! ";
334  // if ( debug) std::cout << "Read the next entry " << theCurrentEntry[file] << std::endl;
336  if ( theCurrentEntry[file] == theNumberOfEntries[file] ) {
337  theCurrentEntry[file] = 0;
338  // if ( debug ) std::cout << "End of file - Rewind! " << std::endl;
339  }
340  // if ( debug ) std::cout << "The PUEvent is reset ... ";
341  thePUEvents[file]->reset();
342  unsigned myEntry = theCurrentEntry[file];
343  /*
344  if ( debug ) std::cout << "The new entry " << myEntry
345  << " is read ... in TTree " << theTrees[file] << " ";
346  */
347  theTrees[file]->GetEntry(myEntry);
348  /*
349  if ( debug )
350  std::cout << "The number of interactions in the new entry is ... ";
351  */
353  // if ( debug ) std::cout << theNumberOfMinBiasEvts[file] << std::endl;
354  }
355 
356  // Read a minbias event chunk
357  const PUEvent::PUMinBiasEvt& aMinBiasEvt
358  = thePUEvents[file]->thePUMinBiasEvts()[theCurrentMinBiasEvt[file]];
359 
360  // Find corresponding particles
361  unsigned firstTrack = aMinBiasEvt.first;
362  unsigned trackSize = firstTrack + aMinBiasEvt.size;
363  /*
364  if ( debug ) std::cout << "First and last+1 tracks are "
365  << firstTrack << " " << trackSize << std::endl;
366  */
367 
368  // Loop on particles
369  for ( unsigned iTrack=firstTrack; iTrack<trackSize; ++iTrack ) {
370 
371  const PUEvent::PUParticle& aParticle
372  = thePUEvents[file]->thePUParticles()[iTrack];
373  /*
374  if ( debug)
375  std::cout << "Track " << iTrack
376  << " id/px/py/pz/mass "
377  << aParticle.id << " "
378  << aParticle.px << " "
379  << aParticle.py << " "
380  << aParticle.pz << " "
381  << aParticle.mass << " " << std::endl;
382  */
383 
384  // Create a FourVector, with rotation
385  double energy = std::sqrt( aParticle.px*aParticle.px
386  + aParticle.py*aParticle.py
387  + aParticle.pz*aParticle.pz
388  + aParticle.mass*aParticle.mass );
389 
390  HepMC::FourVector myPart(cAngle * aParticle.px + sAngle * aParticle.py,
391  -sAngle * aParticle.px + cAngle * aParticle.py,
392  aParticle.pz, energy);
393 
394  // Add a GenParticle
395  HepMC::GenParticle* aGenParticle = new HepMC::GenParticle(myPart,aParticle.id);
396  aVertex->add_particle_out(aGenParticle);
397 
398  }
399  // End of particle loop
400 
401  // ERROR The way this loops through the pileup events breaks
402  // replay. Which events are retrieved for pileup depends on
403  // which previous events were processed.
404 
405  // Increment for next time
407 
408  }
409  // End of pile-up event loop
410 
411  // evt->print();
412 
413  // Fill the HepMCProduct from the GenEvent
414  if ( evt ) {
415  pu_product->addHepMCData( evt );
416  // Boost in case of beam crossing angle
417  TMatrixD* boost = theVertexGenerator->boost();
418  if ( boost ) pu_product->boostToLab(boost,"momentum");
419  }
420 
421  // Put the HepMCProduct onto the event
422  iEvent.put(pu_product,"PileUpEvents");
423  // delete evt;
424 
425  // Save the current location in each pile-up event files
426  this->save();
427 
428 }
429 
430 void
432 
433  // Size of buffer
434  ++myOutputBuffer;
435 
436  // Periodically close the current file and open a new one
437  if ( myOutputBuffer/1000*1000 == myOutputBuffer ) {
438  myOutputFile.close();
439  myOutputFile.open ("PileUpOutputFile.txt");
440  // myOutputFile.seekp(0); // No need to rewind in that case
441  }
442 
443  // Save the current position to file
444  myOutputFile.write((const char*)(&theCurrentEntry.front()),
445  theCurrentEntry.size()*sizeof(unsigned));
446  myOutputFile.write((const char*)&theCurrentMinBiasEvt.front(),
447  theCurrentMinBiasEvt.size()*sizeof(unsigned));
448  myOutputFile.flush();
449 
450 }
451 
452 bool
454 
455  std::ifstream myInputFile;
456  struct stat results;
457  unsigned size1 = theCurrentEntry.size()*sizeof(unsigned);
458  unsigned size2 = theCurrentMinBiasEvt.size()*sizeof(unsigned);
459  unsigned size = 0;
460 
461 
462  // Open the file (if any)
463  myInputFile.open (inputFile.c_str());
464  if ( myInputFile.is_open() ) {
465 
466  // Get the size of the file
467  if ( stat(inputFile.c_str(), &results) == 0 ) size = results.st_size;
468  else return false; // Something is wrong with that file !
469 
470  // Position the pointer just before the last record
471  myInputFile.seekg(size-size1-size2);
472 
473  // Read the information
474  myInputFile.read((char*)(&theCurrentEntry.front()),size1);
475  myInputFile.read((char*)&theCurrentMinBiasEvt.front(),size2);
476  myInputFile.close();
477 
478  return true;
479 
480  }
481 
482  return false;
483 
484 }
485 
#define LogDebug(id)
PileUpProducer(edm::ParameterSet const &p)
virtual void endRun(edm::Run const &, edm::EventSetup const &) override
T getParameter(std::string const &) const
T getUntrackedParameter(std::string const &, T const &) const
int i
Definition: DBlmapReader.cc:9
std::vector< unsigned > theNumberOfMinBiasEvts
std::vector< std::string > theFileNames
LuminosityBlockIndex index() const
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:17
tuple lumi
Definition: fjr2json.py:35
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
TRandom random
Definition: MVATrainer.cc:138
bool read(std::string inputFile)
Read former minbias configuration (from previous run)
std::vector< int > dataProbFunctionVar
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:7
std::vector< unsigned > theNumberOfEntries
virtual void generate(RandomEngineAndDistribution const *)=0
Generation process (to be implemented)
PrimaryVertexGenerator * theVertexGenerator
std::ofstream myOutputFile
int iEvent
Definition: GenABIO.cc:230
virtual void produce(edm::Event &e, const edm::EventSetup &c) override
OrphanHandle< PROD > put(std::auto_ptr< PROD > product)
Put a new product.
Definition: Event.h:113
T sqrt(T t)
Definition: SSEVec.h:48
bool currentValuesWereSet
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
virtual void beginRun(edm::Run const &, edm::EventSetup const &) override
std::vector< unsigned > theCurrentMinBiasEvt
int j
Definition: DBlmapReader.cc:9
std::vector< PUEvent * > thePUEvents
std::string inputFile
std::vector< double > dataProb
std::vector< unsigned > theCurrentEntry
double averageNumber_
std::vector< TTree * > theTrees
virtual ~PileUpProducer()
StreamID streamID() const
Definition: Event.h:72
Definition: PUEvent.h:6
tuple cout
Definition: gather_cfg.py:121
virtual void beginLuminosityBlock(edm::LuminosityBlock const &, edm::EventSetup const &) override
volatile std::atomic< bool > shutdown_flag false
std::string fullPath() const
Definition: FileInPath.cc:165
unsigned theNumberOfFiles
unsigned myOutputBuffer
tuple size
Write out results.
Definition: Run.h:41
std::vector< TFile * > theFiles
void save()
Save current minbias configuration (for later use)
std::vector< TBranch * > theBranches