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 
261 
262 
263  std::auto_ptr< PileupMixingContent > PileupMixing_;
264  std::auto_ptr< PileupVertexContent > PileupVertexing_;
265 
266  std::vector<int> bunchCrossingList;
267  bunchCrossingList.push_back(0);
268 
269  std::vector<int> numInteractionList;
270  numInteractionList.push_back(PUevts);
271 
272  std::vector<float> trueInteractionList;
273  trueInteractionList.push_back(truePUevts);
274 
275  std::vector<edm::EventID> eventInfoList;
276 
277  std::vector<float> pThatList;
278  std::vector<float> zposList;
279  // generate fake EventID list to prevent crash in PileupInfo
280  for(uint32_t index=0; index!=uint(PUevts); ++index) {
282  eventInfoList.push_back(Fake);
283  pThatList.push_back(0.);
284  zposList.push_back(0.);
285  }
286 
287  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.
288  iEvent.put(PileupMixing_);
289 
290  PileupVertexing_ = std::auto_ptr< PileupVertexContent >(new PileupVertexContent(pThatList, zposList));
291 
292  iEvent.put(PileupVertexing_);
293 
294 
295  // Get N events from random files
296  for ( int ievt=0; ievt<PUevts; ++ievt ) {
297 
298  // Draw a file in a ramdom manner
299  unsigned file = (unsigned) (theNumberOfFiles * random.flatShoot());
300  /*
301  if ( debug )
302  std::cout << "The file chosen for event " << ievt
303  << " is the file number " << file << std::endl;
304  */
305 
306  // Smear the primary vertex and express it in mm (stupid GenEvent convention...)
308  HepMC::FourVector smearedVertex =
309  HepMC::FourVector(theVertexGenerator->X()*10.,
310  theVertexGenerator->Y()*10.,
311  theVertexGenerator->Z()*10.,
312  0.);
313  HepMC::GenVertex* aVertex = new HepMC::GenVertex(smearedVertex);
314  evt->add_vertex(aVertex);
315 
316  // Some rotation around the z axis, for more randomness
317  double theAngle = random.flatShoot() * 2. * 3.14159265358979323;
318  double cAngle = std::cos(theAngle);
319  double sAngle = std::sin(theAngle);
320 
321  /*
322  if ( debug )
323  std::cout << "File chosen : " << file
324  << " Current entry in this file " << theCurrentEntry[file]
325  << " Current minbias in this chunk= " << theCurrentMinBiasEvt[file]
326  << " Total number of minbias in this chunk = " << theNumberOfMinBiasEvts[file] << std::endl;
327  */
328 
329  // theFiles[file]->cd();
330  // gDirectory->ls();
331  // Check we are not either at the end of a minbias bunch
332  // or at the end of a file
333  if ( theCurrentMinBiasEvt[file] == theNumberOfMinBiasEvts[file] ) {
334  // if ( debug ) std::cout << "End of MinBias bunch ! ";
336  // if ( debug) std::cout << "Read the next entry " << theCurrentEntry[file] << std::endl;
338  if ( theCurrentEntry[file] == theNumberOfEntries[file] ) {
339  theCurrentEntry[file] = 0;
340  // if ( debug ) std::cout << "End of file - Rewind! " << std::endl;
341  }
342  // if ( debug ) std::cout << "The PUEvent is reset ... ";
343  thePUEvents[file]->reset();
344  unsigned myEntry = theCurrentEntry[file];
345  /*
346  if ( debug ) std::cout << "The new entry " << myEntry
347  << " is read ... in TTree " << theTrees[file] << " ";
348  */
349  theTrees[file]->GetEntry(myEntry);
350  /*
351  if ( debug )
352  std::cout << "The number of interactions in the new entry is ... ";
353  */
355  // if ( debug ) std::cout << theNumberOfMinBiasEvts[file] << std::endl;
356  }
357 
358  // Read a minbias event chunk
359  const PUEvent::PUMinBiasEvt& aMinBiasEvt
360  = thePUEvents[file]->thePUMinBiasEvts()[theCurrentMinBiasEvt[file]];
361 
362  // Find corresponding particles
363  unsigned firstTrack = aMinBiasEvt.first;
364  unsigned trackSize = firstTrack + aMinBiasEvt.size;
365  /*
366  if ( debug ) std::cout << "First and last+1 tracks are "
367  << firstTrack << " " << trackSize << std::endl;
368  */
369 
370  // Loop on particles
371  for ( unsigned iTrack=firstTrack; iTrack<trackSize; ++iTrack ) {
372 
373  const PUEvent::PUParticle& aParticle
374  = thePUEvents[file]->thePUParticles()[iTrack];
375  /*
376  if ( debug)
377  std::cout << "Track " << iTrack
378  << " id/px/py/pz/mass "
379  << aParticle.id << " "
380  << aParticle.px << " "
381  << aParticle.py << " "
382  << aParticle.pz << " "
383  << aParticle.mass << " " << std::endl;
384  */
385 
386  // Create a FourVector, with rotation
387  double energy = std::sqrt( aParticle.px*aParticle.px
388  + aParticle.py*aParticle.py
389  + aParticle.pz*aParticle.pz
390  + aParticle.mass*aParticle.mass );
391 
392  HepMC::FourVector myPart(cAngle * aParticle.px + sAngle * aParticle.py,
393  -sAngle * aParticle.px + cAngle * aParticle.py,
394  aParticle.pz, energy);
395 
396  // Add a GenParticle
397  HepMC::GenParticle* aGenParticle = new HepMC::GenParticle(myPart,aParticle.id);
398  aVertex->add_particle_out(aGenParticle);
399 
400  }
401  // End of particle loop
402 
403  // ERROR The way this loops through the pileup events breaks
404  // replay. Which events are retrieved for pileup depends on
405  // which previous events were processed.
406 
407  // Increment for next time
409 
410  }
411  // End of pile-up event loop
412 
413  // evt->print();
414 
415  // Fill the HepMCProduct from the GenEvent
416  if ( evt ) {
417  pu_product->addHepMCData( evt );
418  // Boost in case of beam crossing angle
419  TMatrixD* boost = theVertexGenerator->boost();
420  if ( boost ) pu_product->boostToLab(boost,"momentum");
421  }
422 
423  // Put the HepMCProduct onto the event
424  iEvent.put(pu_product,"PileUpEvents");
425  // delete evt;
426 
427  // Save the current location in each pile-up event files
428  this->save();
429 
430 }
431 
432 void
434 
435  // Size of buffer
436  ++myOutputBuffer;
437 
438  // Periodically close the current file and open a new one
439  if ( myOutputBuffer/1000*1000 == myOutputBuffer ) {
440  myOutputFile.close();
441  myOutputFile.open ("PileUpOutputFile.txt");
442  // myOutputFile.seekp(0); // No need to rewind in that case
443  }
444 
445  // Save the current position to file
446  myOutputFile.write((const char*)(&theCurrentEntry.front()),
447  theCurrentEntry.size()*sizeof(unsigned));
448  myOutputFile.write((const char*)&theCurrentMinBiasEvt.front(),
449  theCurrentMinBiasEvt.size()*sizeof(unsigned));
450  myOutputFile.flush();
451 
452 }
453 
454 bool
456 
457  std::ifstream myInputFile;
458  struct stat results;
459  unsigned size1 = theCurrentEntry.size()*sizeof(unsigned);
460  unsigned size2 = theCurrentMinBiasEvt.size()*sizeof(unsigned);
461  unsigned size = 0;
462 
463 
464  // Open the file (if any)
465  myInputFile.open (inputFile.c_str());
466  if ( myInputFile.is_open() ) {
467 
468  // Get the size of the file
469  if ( stat(inputFile.c_str(), &results) == 0 ) size = results.st_size;
470  else return false; // Something is wrong with that file !
471 
472  // Position the pointer just before the last record
473  myInputFile.seekg(size-size1-size2);
474 
475  // Read the information
476  myInputFile.read((char*)(&theCurrentEntry.front()),size1);
477  myInputFile.read((char*)&theCurrentMinBiasEvt.front(),size2);
478  myInputFile.close();
479 
480  return true;
481 
482  }
483 
484  return false;
485 
486 }
487 
#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