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