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.
5 
7 
9 
16 
17 #include "HepMC/GenEvent.h"
18 #include "TFile.h"
19 #include "TTree.h"
20 #include "TROOT.h"
21 
22 #include <iostream>
23 #include <memory>
24 #include <sys/stat.h>
25 #include <cmath>
26 
28 {
29 
30  // This producer produces an object PileupMixingContent, needed by PileupSummaryInfo
31  produces<PileupMixingContent>();
32  // This producer produces a HepMCProduct, with all pileup vertices/particles
33  produces<edm::HepMCProduct>("PileUpEvents");
34 
35  // Initialize the random number generator service
37  if ( ! rng.isAvailable() ) {
38  throw cms::Exception("Configuration")
39  << "PileUpProducer requires the RandomGeneratorService\n"
40  "which is not present in the configuration file.\n"
41  "You must add the service in the configuration file\n"
42  "or remove the module that requires it";
43  }
44 
45  // RANDOM_NUMBER_ERROR
46  // Random number should be generated by the engines from the
47  // RandomNumberGeneratorService. This appears to use the global
48  // engine in ROOT. This is not thread safe unless the module using
49  // it is a one module and declares a shared resource and all
50  // other modules using it also declare the same shared resource.
51  // This also breaks replay.
52  gRandom->SetSeed(rng->mySeed());
53 
54  // The pile-up event generation condition
55  const edm::ParameterSet& pu = p.getParameter<edm::ParameterSet>("PileUpSimulator");
56  usePoisson_ = pu.getParameter<bool>("usePoisson");
57  averageNumber_ = 0.;
58  if (usePoisson_) {
59  std::cout << " FastSimulation/PileUpProducer -> poissonian distribution" << std::endl;
60  averageNumber_ = pu.getParameter<double>("averageNumber");
61  } else {//take distribution from configuration
62  dataProbFunctionVar = pu.getParameter<std::vector<int> >("probFunctionVariable");
63  dataProb = pu.getParameter<std::vector<double> >("probValue");
64  varSize = (int) dataProbFunctionVar.size();
65  probSize = (int) dataProb.size();
66  // std::cout << " FastSimulation/PileUpProducer -> varSize = " << varSize << std::endl;
67  // std::cout << " FastSimulation/PileUpProducer -> probSize = " << probSize << std::endl;
68 
69  std::cout << " FastSimulation/PileUpProducer -> distribution from configuration file " << std::endl;
70  if (probSize < varSize){
71  for (int i=0; i<(varSize - probSize); i++) dataProb.push_back(0);
72  edm::LogWarning("") << " The probability function data will be completed with "
73  << (varSize - probSize) <<" values `0';"
74  << " the number of the P(x) data set after adding those 0's is " << dataProb.size();
75  probSize = dataProb.size();
76  }
77  // Create an histogram with the data from the probability function provided by the user
78  int xmin = (int) dataProbFunctionVar[0];
79  int xmax = (int) dataProbFunctionVar[varSize-1]+1; // need upper edge to be one beyond last value
80  int numBins = varSize;
81  std::cout << " FastSimulation/PileUpProducer -> An histogram will be created with " << numBins
82  << " bins in the range ("<< xmin << "," << xmax << ")." << std::endl;
83  hprob = new TH1F("h","Histo from the user's probability function",numBins,xmin,xmax);
84  LogDebug("") << " FastSimulation/PileUpProducer -> Filling histogram with the following data:";
85  for (int j=0; j < numBins ; j++){
86  LogDebug("") << " x = " << dataProbFunctionVar[j ]<< " P(x) = " << dataProb[j];
87  hprob->Fill(dataProbFunctionVar[j]+0.5,dataProb[j]); // assuming integer values for the bins, fill bin centers, not edges
88  }
89 
90  // Check if the histogram is normalized
91  if (((hprob->Integral() - 1) > 1.0e-02) && ((hprob->Integral() - 1) < -1.0e-02)) throw cms::Exception("BadHistoDistribution") << "The histogram should be normalized!" << std::endl;
92 
93  // Get the averageNumber from the histo
94  averageNumber_ = hprob->GetMean();
95  }
96  theFileNames = pu.getUntrackedParameter<std::vector<std::string> >("fileNames");
97  inputFile = pu.getUntrackedParameter<std::string>("inputFile");
99  theFiles.resize(theNumberOfFiles);
100  theTrees.resize(theNumberOfFiles);
101  theBranches.resize(theNumberOfFiles);
102  thePUEvents.resize(theNumberOfFiles);
103  theCurrentEntry.resize(theNumberOfFiles);
104  theCurrentMinBiasEvt.resize(theNumberOfFiles);
105  theNumberOfEntries.resize(theNumberOfFiles);
106  theNumberOfMinBiasEvts.resize(theNumberOfFiles);
107 
108  // Initialize the primary vertex generator
109  const edm::ParameterSet& vtx = p.getParameter<edm::ParameterSet>("VertexGenerator");
110  std::string vtxType = vtx.getParameter<std::string>("type");
111  if ( vtxType == "Gaussian" )
113  else if ( vtxType == "Flat" )
115  else if ( vtxType == "BetaFunc" )
117  else
119 
120 
121 
122  if (averageNumber_ > 0.)
123  {
124  std::cout << " FastSimulation/PileUpProducer -> MinBias events taken from " << theFileNames[0] << " et al., " ;
125  std::cout << " with an average number of events of " << averageNumber_ << std::endl;
126  }
127  else std::cout << " FastSimulation/PileUpProducer -> No pileup " << std::endl;
128 
129 
130 }
131 
133 
134  delete theVertexGenerator;
135  if (hprob) delete hprob;
136 
137 }
138 
140 {
141 
142  gROOT->cd();
143 
144  std::string fullPath;
145 
146  // Read the information from a previous run (to keep reproducibility)
147  bool input = this->read(inputFile);
148  if ( input )
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  // RANDOM_NUMBER_ERROR
185  // Random numbers should only be generated in the beginLuminosityBlock method
186  // or event methods of a module
188  // Add some randomness (if there was no input file)
189  if ( !input )
191  = (unsigned) (theNumberOfEntries[file] * random.flatShoot());
192 
193  theTrees[file]->GetEntry(theCurrentEntry[file]);
194  unsigned NMinBias = thePUEvents[file]->nMinBias();
195  theNumberOfMinBiasEvts[file] = NMinBias;
196  // Add some randomness (if there was no input file)
197  if ( !input )
199  (unsigned) (theNumberOfMinBiasEvts[file] * random.flatShoot());
200 
201  /*
202  std::cout << "File " << theFileNames[file]
203  << " is opened with " << theNumberOfEntries[file]
204  << " entries and will be read from Entry/Event "
205  << theCurrentEntry[file] << "/" << theCurrentMinBiasEvt[file]
206  << std::endl;
207  */
208  }
209 
210  // Return Loot in the same state as it was when entering.
211  gROOT->cd();
212 
213 }
214 
216 {
217  // Close all local files
218  // Among other things, this allows the TROOT destructor to end up
219  // without crashing, while trying to close these files from outside
220  for ( unsigned file=0; file<theFiles.size(); ++file ) {
221 
222  // std::cout << "Closing " << theFileNames[file] << std::endl;
223  theFiles[file]->Close();
224 
225  }
226 
227  // Close the output file
228  myOutputFile.close();
229 
230  // And return Loot in the same state as it was when entering.
231  gROOT->cd();
232 
233 }
234 
236 {
237  // Create the GenEvent and the HepMCProduct
238  std::auto_ptr<edm::HepMCProduct> pu_product(new edm::HepMCProduct());
239  HepMC::GenEvent* evt = new HepMC::GenEvent();
240 
242 
243  // How many pile-up events?
244  int PUevts; float truePUevts;
245  if (usePoisson_) {
246  PUevts = (int) random.poissonShoot(averageNumber_);
247  truePUevts = (float) averageNumber_;
248  }
249  else {
250  // RANDOM_NUMBER_ERROR
251  // Random number should be generated by the engines from the
252  // RandomNumberGeneratorService. This appears to use the global
253  // engine in ROOT. This is not thread safe unless the module using
254  // it is a one module and declares a shared resource and all
255  // other modules using it also declare the same shared resource.
256  // This also breaks replay.
257  float d = (float) hprob->GetRandom();
258  PUevts = (int) d;
259  truePUevts = d;
260  }
261  // std::cout << "PUevts = " << PUevts << std::endl;
262 
263  // Save this information in the PileupMixingContent object
264  // IMPORTANT: the bunch crossing number is always 0 because FastSim has no out-of-time PU
265  std::auto_ptr< PileupMixingContent > PileupMixing_;
266 
267  std::vector<int> bunchCrossingList;
268  bunchCrossingList.push_back(0);
269 
270  std::vector<int> numInteractionList;
271  numInteractionList.push_back(PUevts);
272 
273  std::vector<float> trueInteractionList;
274  trueInteractionList.push_back(truePUevts);
275 
276  PileupMixing_ = std::auto_ptr< PileupMixingContent >(new PileupMixingContent(bunchCrossingList,numInteractionList,trueInteractionList));
277  iEvent.put(PileupMixing_);
278 
279  // Get N events from random files
280  for ( int ievt=0; ievt<PUevts; ++ievt ) {
281 
282  // Draw a file in a ramdom manner
283  unsigned file = (unsigned) (theNumberOfFiles * random.flatShoot());
284  /*
285  if ( debug )
286  std::cout << "The file chosen for event " << ievt
287  << " is the file number " << file << std::endl;
288  */
289 
290  // Smear the primary vertex and express it in mm (stupid GenEvent convention...)
292  HepMC::FourVector smearedVertex =
293  HepMC::FourVector(theVertexGenerator->X()*10.,
294  theVertexGenerator->Y()*10.,
295  theVertexGenerator->Z()*10.,
296  0.);
297  HepMC::GenVertex* aVertex = new HepMC::GenVertex(smearedVertex);
298  evt->add_vertex(aVertex);
299 
300  // Some rotation around the z axis, for more randomness
301  double theAngle = random.flatShoot() * 2. * 3.14159265358979323;
302  double cAngle = std::cos(theAngle);
303  double sAngle = std::sin(theAngle);
304 
305  /*
306  if ( debug )
307  std::cout << "File chosen : " << file
308  << " Current entry in this file " << theCurrentEntry[file]
309  << " Current minbias in this chunk= " << theCurrentMinBiasEvt[file]
310  << " Total number of minbias in this chunk = " << theNumberOfMinBiasEvts[file] << std::endl;
311  */
312 
313  // theFiles[file]->cd();
314  // gDirectory->ls();
315  // Check we are not either at the end of a minbias bunch
316  // or at the end of a file
317  if ( theCurrentMinBiasEvt[file] == theNumberOfMinBiasEvts[file] ) {
318  // if ( debug ) std::cout << "End of MinBias bunch ! ";
320  // if ( debug) std::cout << "Read the next entry " << theCurrentEntry[file] << std::endl;
322  if ( theCurrentEntry[file] == theNumberOfEntries[file] ) {
323  theCurrentEntry[file] = 0;
324  // if ( debug ) std::cout << "End of file - Rewind! " << std::endl;
325  }
326  // if ( debug ) std::cout << "The PUEvent is reset ... ";
327  thePUEvents[file]->reset();
328  unsigned myEntry = theCurrentEntry[file];
329  /*
330  if ( debug ) std::cout << "The new entry " << myEntry
331  << " is read ... in TTree " << theTrees[file] << " ";
332  */
333  theTrees[file]->GetEntry(myEntry);
334  /*
335  if ( debug )
336  std::cout << "The number of interactions in the new entry is ... ";
337  */
339  // if ( debug ) std::cout << theNumberOfMinBiasEvts[file] << std::endl;
340  }
341 
342  // Read a minbias event chunk
343  const PUEvent::PUMinBiasEvt& aMinBiasEvt
344  = thePUEvents[file]->thePUMinBiasEvts()[theCurrentMinBiasEvt[file]];
345 
346  // Find corresponding particles
347  unsigned firstTrack = aMinBiasEvt.first;
348  unsigned trackSize = firstTrack + aMinBiasEvt.size;
349  /*
350  if ( debug ) std::cout << "First and last+1 tracks are "
351  << firstTrack << " " << trackSize << std::endl;
352  */
353 
354  // Loop on particles
355  for ( unsigned iTrack=firstTrack; iTrack<trackSize; ++iTrack ) {
356 
357  const PUEvent::PUParticle& aParticle
358  = thePUEvents[file]->thePUParticles()[iTrack];
359  /*
360  if ( debug)
361  std::cout << "Track " << iTrack
362  << " id/px/py/pz/mass "
363  << aParticle.id << " "
364  << aParticle.px << " "
365  << aParticle.py << " "
366  << aParticle.pz << " "
367  << aParticle.mass << " " << std::endl;
368  */
369 
370  // Create a FourVector, with rotation
371  double energy = std::sqrt( aParticle.px*aParticle.px
372  + aParticle.py*aParticle.py
373  + aParticle.pz*aParticle.pz
374  + aParticle.mass*aParticle.mass );
375 
376  HepMC::FourVector myPart(cAngle * aParticle.px + sAngle * aParticle.py,
377  -sAngle * aParticle.px + cAngle * aParticle.py,
378  aParticle.pz, energy);
379 
380  // Add a GenParticle
381  HepMC::GenParticle* aGenParticle = new HepMC::GenParticle(myPart,aParticle.id);
382  aVertex->add_particle_out(aGenParticle);
383 
384  }
385  // End of particle loop
386 
387  // Increment for next time
389 
390  }
391  // End of pile-up event loop
392 
393  // evt->print();
394 
395  // Fill the HepMCProduct from the GenEvent
396  if ( evt ) {
397  pu_product->addHepMCData( evt );
398  // Boost in case of beam crossing angle
399  TMatrixD* boost = theVertexGenerator->boost();
400  if ( boost ) pu_product->boostToLab(boost,"momentum");
401  }
402 
403  // Put the HepMCProduct onto the event
404  iEvent.put(pu_product,"PileUpEvents");
405  // delete evt;
406 
407  // Save the current location in each pile-up event files
408  this->save();
409 
410 }
411 
412 void
414 
415  // Size of buffer
416  ++myOutputBuffer;
417 
418  // Periodically close the current file and open a new one
419  if ( myOutputBuffer/1000*1000 == myOutputBuffer ) {
420  myOutputFile.close();
421  myOutputFile.open ("PileUpOutputFile.txt");
422  // myOutputFile.seekp(0); // No need to rewind in that case
423  }
424 
425  // Save the current position to file
426  myOutputFile.write((const char*)(&theCurrentEntry.front()),
427  theCurrentEntry.size()*sizeof(unsigned));
428  myOutputFile.write((const char*)&theCurrentMinBiasEvt.front(),
429  theCurrentMinBiasEvt.size()*sizeof(unsigned));
430  myOutputFile.flush();
431 
432 }
433 
434 bool
436 
437  std::ifstream myInputFile;
438  struct stat results;
439  unsigned size1 = theCurrentEntry.size()*sizeof(unsigned);
440  unsigned size2 = theCurrentMinBiasEvt.size()*sizeof(unsigned);
441  unsigned size = 0;
442 
443 
444  // Open the file (if any)
445  myInputFile.open (inputFile.c_str());
446  if ( myInputFile.is_open() ) {
447 
448  // Get the size of the file
449  if ( stat(inputFile.c_str(), &results) == 0 ) size = results.st_size;
450  else return false; // Something is wrong with that file !
451 
452  // Position the pointer just before the last record
453  myInputFile.seekg(size-size1-size2);
454 
455  // Read the information
456  myInputFile.read((char*)(&theCurrentEntry.front()),size1);
457  myInputFile.read((char*)&theCurrentMinBiasEvt.front(),size2);
458  myInputFile.close();
459 
460  return true;
461 
462  }
463 
464  return false;
465 
466 }
467 
#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
double flatShoot(double xmin=0.0, double xmax=1.0) const
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:17
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
static std::string const input
Definition: EdmProvDump.cc:44
std::ofstream myOutputFile
int iEvent
Definition: GenABIO.cc:243
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:116
T sqrt(T t)
Definition: SSEVec.h:48
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:75
Definition: PUEvent.h:6
tuple cout
Definition: gather_cfg.py:121
std::string fullPath() const
Definition: FileInPath.cc:171
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