CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch12/src/FastSimulation/PileUpProducer/plugins/PileUpProducer.cc

Go to the documentation of this file.
00001 #include "FWCore/Framework/interface/Event.h"
00002 #include "FWCore/Framework/interface/MakerMacros.h"
00003 #include "FWCore/ServiceRegistry/interface/Service.h"
00004 #include "FWCore/Utilities/interface/RandomNumberGenerator.h"
00005 
00006 #include "SimDataFormats/GeneratorProducts/interface/HepMCProduct.h"
00007 
00008 #include "FastSimDataFormats/PileUpEvents/interface/PUEvent.h"
00009 
00010 #include "FastSimulation/PileUpProducer/plugins/PileUpProducer.h"
00011 #include "FastSimulation/Event/interface/BetaFuncPrimaryVertexGenerator.h"
00012 #include "FastSimulation/Event/interface/GaussianPrimaryVertexGenerator.h"
00013 #include "FastSimulation/Event/interface/FlatPrimaryVertexGenerator.h"
00014 #include "FastSimulation/Event/interface/NoPrimaryVertexGenerator.h"
00015 #include "FastSimulation/Utilities/interface/RandomEngine.h"
00016 
00017 #include "HepMC/GenEvent.h"
00018 #include "TFile.h"
00019 #include "TTree.h"
00020 #include "TROOT.h"
00021 
00022 #include <iostream>
00023 #include <memory>
00024 #include <sys/stat.h>
00025 #include <cmath>
00026 
00027 PileUpProducer::PileUpProducer(edm::ParameterSet const & p) : hprob(0)
00028 {    
00029 
00030   // This producer produces a HepMCProduct, with all pileup vertices/particles
00031   produces<edm::HepMCProduct>("PileUpEvents");
00032   
00033   // Initialize the random number generator service
00034   edm::Service<edm::RandomNumberGenerator> rng;
00035   if ( ! rng.isAvailable() ) {
00036     throw cms::Exception("Configuration")
00037       << "PileUpProducer requires the RandomGeneratorService\n"
00038          "which is not present in the configuration file.\n"
00039          "You must add the service in the configuration file\n"
00040          "or remove the module that requires it";
00041   }  
00042   random = new RandomEngine(&(*rng));
00043 
00044   // The pile-up event generation condition
00045   const edm::ParameterSet& pu = p.getParameter<edm::ParameterSet>("PileUpSimulator");
00046   usePoisson_ = pu.getParameter<bool>("usePoisson");
00047   if (usePoisson_) {
00048     std::cout << " FastSimulation/PileUpProducer -> poissonian distribution" << std::endl;
00049     averageNumber_ = pu.getParameter<double>("averageNumber");
00050   } else {//take distribution from configuration
00051     dataProbFunctionVar = pu.getParameter<std::vector<int> >("probFunctionVariable");
00052     dataProb = pu.getParameter<std::vector<double> >("probValue");
00053     varSize = (int) dataProbFunctionVar.size();
00054     probSize = (int) dataProb.size();
00055     //    std::cout << " FastSimulation/PileUpProducer -> varSize = " << varSize  << std::endl;
00056     //    std::cout << " FastSimulation/PileUpProducer -> probSize = " << probSize  << std::endl;
00057     
00058     std::cout << " FastSimulation/PileUpProducer -> distribution from configuration file "  << std::endl;
00059     if (probSize < varSize){
00060       for (int i=0; i<(varSize - probSize); i++) dataProb.push_back(0);
00061       edm::LogWarning("") << " The probability function data will be completed with " 
00062                           << (varSize - probSize) <<" values `0';"
00063                           << " the number of the P(x) data set after adding those 0's is " << dataProb.size();
00064       probSize = dataProb.size();
00065     }
00066     // Create an histogram with the data from the probability function provided by the user  
00067     int xmin = (int) dataProbFunctionVar[0];
00068     int xmax = (int) dataProbFunctionVar[varSize-1]+1;  // need upper edge to be one beyond last value
00069     int numBins = varSize;
00070     std::cout << " FastSimulation/PileUpProducer -> An histogram will be created with " << numBins 
00071               << " bins in the range ("<< xmin << "," << xmax << ")." << std::endl;
00072     hprob = new TH1F("h","Histo from the user's probability function",numBins,xmin,xmax); 
00073     LogDebug("") << " FastSimulation/PileUpProducer -> Filling histogram with the following data:";
00074     for (int j=0; j < numBins ; j++){
00075       LogDebug("") << " x = " << dataProbFunctionVar[j ]<< " P(x) = " << dataProb[j];
00076       hprob->Fill(dataProbFunctionVar[j]+0.5,dataProb[j]); // assuming integer values for the bins, fill bin centers, not edges 
00077     }
00078 
00079     // Check if the histogram is normalized
00080     if (((hprob->Integral() - 1) > 1.0e-02) && ((hprob->Integral() - 1) < -1.0e-02)) throw cms::Exception("BadHistoDistribution") << "The histogram should be normalized!" << std::endl;
00081     
00082     // Get the averageNumber from the histo 
00083     averageNumber_ = hprob->GetMean();
00084   }
00085   theFileNames = pu.getUntrackedParameter<std::vector<std::string> >("fileNames");
00086   inputFile = pu.getUntrackedParameter<std::string>("inputFile");
00087   theNumberOfFiles = theFileNames.size();
00088   theFiles.resize(theNumberOfFiles);
00089   theTrees.resize(theNumberOfFiles);
00090   theBranches.resize(theNumberOfFiles);
00091   thePUEvents.resize(theNumberOfFiles);
00092   theCurrentEntry.resize(theNumberOfFiles);
00093   theCurrentMinBiasEvt.resize(theNumberOfFiles);
00094   theNumberOfEntries.resize(theNumberOfFiles);
00095   theNumberOfMinBiasEvts.resize(theNumberOfFiles);
00096 
00097   // Initialize the primary vertex generator
00098   const edm::ParameterSet& vtx = p.getParameter<edm::ParameterSet>("VertexGenerator");
00099   std::string vtxType = vtx.getParameter<std::string>("type");
00100   if ( vtxType == "Gaussian" ) 
00101     theVertexGenerator = new GaussianPrimaryVertexGenerator(vtx,random);
00102   else if ( vtxType == "Flat" ) 
00103     theVertexGenerator = new FlatPrimaryVertexGenerator(vtx,random);
00104   else if ( vtxType == "BetaFunc" )
00105     theVertexGenerator = new BetaFuncPrimaryVertexGenerator(vtx,random);
00106   else
00107     theVertexGenerator = new NoPrimaryVertexGenerator();
00108 
00109 
00110 
00111   if (averageNumber_ > 0.)
00112     {
00113       std::cout << " FastSimulation/PileUpProducer -> MinBias events taken from " << theFileNames[0] << " et al., " ;
00114       std::cout << " with an average number of events of " << averageNumber_ << std::endl;
00115     }
00116   else std::cout << " FastSimulation/PileUpProducer -> No pileup " << std::endl;
00117 
00118 
00119 }
00120 
00121 PileUpProducer::~PileUpProducer() { 
00122 
00123   delete theVertexGenerator;
00124   if (hprob) delete hprob;
00125 
00126 }
00127 
00128 void PileUpProducer::beginRun(edm::Run & run, edm::EventSetup const& es)
00129 {
00130   
00131   gROOT->cd();
00132   
00133   std::string fullPath;
00134   
00135   // Read the information from a previous run (to keep reproducibility)
00136   bool input = this->read(inputFile);
00137   if ( input ) 
00138     std::cout << "***WARNING*** You are reading pile-up information from the file "
00139               << inputFile << " created in an earlier run."
00140               << std::endl;
00141 
00142   // Open the file for saving the information of the current run
00143   myOutputFile.open ("PileUpOutputFile.txt");
00144   myOutputBuffer = 0;
00145 
00146   // Open the root files
00147   for ( unsigned file=0; file<theNumberOfFiles; ++file ) {
00148 
00149     if (theFileNames[file].find("file:")==0) {
00150       fullPath = theFileNames[file].erase(0,5);
00151     }
00152     else {
00153       edm::FileInPath myDataFile("FastSimulation/PileUpProducer/data/"+theFileNames[file]);
00154       fullPath = myDataFile.fullPath();
00155     }
00156     //    theFiles[file] = TFile::Open(theFileNames[file].c_str());
00157     theFiles[file] = TFile::Open(fullPath.c_str());
00158     if ( !theFiles[file] ) throw cms::Exception("FastSimulation/PileUpProducer") 
00159       << "File " << theFileNames[file] << " " << fullPath <<  " not found ";
00160     //
00161     theTrees[file] = (TTree*) theFiles[file]->Get("MinBiasEvents"); 
00162     if ( !theTrees[file] ) throw cms::Exception("FastSimulation/PileUpProducer") 
00163       << "Tree with name MinBiasEvents not found in " << theFileNames[file];
00164     //
00165     theBranches[file] = theTrees[file]->GetBranch("puEvent");
00166     if ( !theBranches[file] ) throw cms::Exception("FastSimulation/PileUpProducer") 
00167       << "Branch with name puEvent not found in " << theFileNames[file];
00168     //
00169     thePUEvents[file] = new PUEvent();
00170     theBranches[file]->SetAddress(&thePUEvents[file]);
00171     //
00172     theNumberOfEntries[file] = theTrees[file]->GetEntries();
00173     // Add some randomness (if there was no input file)
00174     if ( !input ) 
00175       theCurrentEntry[file] 
00176         = (unsigned) (theNumberOfEntries[file] * random->flatShoot());
00177 
00178     theTrees[file]->GetEntry(theCurrentEntry[file]);
00179     unsigned NMinBias = thePUEvents[file]->nMinBias();
00180     theNumberOfMinBiasEvts[file] = NMinBias;
00181     // Add some randomness (if there was no input file)
00182     if ( !input )
00183         theCurrentMinBiasEvt[file] = 
00184           (unsigned) (theNumberOfMinBiasEvts[file] * random->flatShoot());
00185     
00186     /*
00187     std::cout << "File " << theFileNames[file]
00188               << " is opened with " << theNumberOfEntries[file] 
00189               << " entries and will be read from Entry/Event "
00190               << theCurrentEntry[file] << "/" << theCurrentMinBiasEvt[file]
00191               << std::endl;
00192     */
00193   }
00194   
00195   // Return Loot in the same state as it was when entering. 
00196   gROOT->cd();
00197   
00198 }
00199  
00200 void PileUpProducer::endRun()
00201 { 
00202   // Close all local files
00203   // Among other things, this allows the TROOT destructor to end up 
00204   // without crashing, while trying to close these files from outside
00205   for ( unsigned file=0; file<theFiles.size(); ++file ) {
00206     
00207     // std::cout << "Closing " << theFileNames[file] << std::endl;
00208     theFiles[file]->Close();
00209     
00210   }
00211   
00212   // Close the output file
00213   myOutputFile.close();
00214   
00215   // And return Loot in the same state as it was when entering. 
00216   gROOT->cd();
00217   
00218 }
00219  
00220 void PileUpProducer::produce(edm::Event & iEvent, const edm::EventSetup & es)
00221 {
00222 
00223   // Create the GenEvent and the HepMCProduct
00224   std::auto_ptr<edm::HepMCProduct> pu_product(new edm::HepMCProduct());  
00225   HepMC::GenEvent* evt = new HepMC::GenEvent();
00226   
00227   // How many pile-up events?
00228   int PUevts = usePoisson_ ? (int) random->poissonShoot(averageNumber_) : (int) hprob->GetRandom();
00229   //  std::cout << "PUevts = " << PUevts << std::endl;
00230 
00231   // Get N events from random files
00232   for ( int ievt=0; ievt<PUevts; ++ievt ) { 
00233     
00234     // Draw a file in a ramdom manner 
00235     unsigned file = (unsigned) (theNumberOfFiles * random->flatShoot());
00236     /*
00237     if ( debug )  
00238       std::cout << "The file chosen for event " << ievt 
00239                 << " is the file number " << file << std::endl; 
00240     */
00241 
00242     // Smear the primary vertex and express it in mm (stupid GenEvent convention...)
00243     theVertexGenerator->generate();
00244     HepMC::FourVector smearedVertex =  
00245       HepMC::FourVector(theVertexGenerator->X()*10.,
00246                         theVertexGenerator->Y()*10.,
00247                         theVertexGenerator->Z()*10.,
00248                         0.);
00249     HepMC::GenVertex* aVertex = new HepMC::GenVertex(smearedVertex);
00250     evt->add_vertex(aVertex);
00251 
00252     // Some rotation around the z axis, for more randomness
00253     double theAngle = random->flatShoot() * 2. * 3.14159265358979323;
00254     double cAngle = std::cos(theAngle);
00255     double sAngle = std::sin(theAngle);
00256 
00257     /*
00258     if ( debug ) 
00259       std::cout << "File chosen : " << file 
00260                 << " Current entry in this file " << theCurrentEntry[file] 
00261                 << " Current minbias in this chunk= " << theCurrentMinBiasEvt[file] 
00262                 << " Total number of minbias in this chunk = " << theNumberOfMinBiasEvts[file] << std::endl;
00263     */
00264 
00265     //      theFiles[file]->cd();
00266     //      gDirectory->ls();
00267     // Check we are not either at the end of a minbias bunch 
00268     // or at the end of a file
00269     if ( theCurrentMinBiasEvt[file] == theNumberOfMinBiasEvts[file] ) {
00270       // if ( debug ) std::cout << "End of MinBias bunch ! ";
00271       ++theCurrentEntry[file];
00272       // if ( debug) std::cout << "Read the next entry " << theCurrentEntry[file] << std::endl;
00273       theCurrentMinBiasEvt[file] = 0;
00274       if ( theCurrentEntry[file] == theNumberOfEntries[file] ) { 
00275         theCurrentEntry[file] = 0;
00276         // if ( debug ) std::cout << "End of file - Rewind! " << std::endl;
00277       }
00278       // if ( debug ) std::cout << "The PUEvent is reset ... "; 
00279       thePUEvents[file]->reset();
00280       unsigned myEntry = theCurrentEntry[file];
00281       /* 
00282       if ( debug ) std::cout << "The new entry " << myEntry 
00283                              << " is read ... in TTree " << theTrees[file] << " "; 
00284       */
00285       theTrees[file]->GetEntry(myEntry);
00286       /*
00287       if ( debug ) 
00288         std::cout << "The number of interactions in the new entry is ... ";     
00289       */
00290       theNumberOfMinBiasEvts[file] = thePUEvents[file]->nMinBias();
00291       // if ( debug ) std::cout << theNumberOfMinBiasEvts[file] << std::endl;
00292   }
00293   
00294     // Read a minbias event chunk
00295     const PUEvent::PUMinBiasEvt& aMinBiasEvt 
00296       = thePUEvents[file]->thePUMinBiasEvts()[theCurrentMinBiasEvt[file]];
00297   
00298     // Find corresponding particles
00299     unsigned firstTrack = aMinBiasEvt.first; 
00300     unsigned trackSize = firstTrack + aMinBiasEvt.size;
00301     /*
00302     if ( debug ) std::cout << "First and last+1 tracks are " 
00303                            << firstTrack << " " << trackSize << std::endl;
00304     */
00305 
00306     // Loop on particles
00307     for ( unsigned iTrack=firstTrack; iTrack<trackSize; ++iTrack ) {
00308       
00309       const PUEvent::PUParticle& aParticle 
00310         = thePUEvents[file]->thePUParticles()[iTrack];
00311       /*
00312       if ( debug) 
00313         std::cout << "Track " << iTrack 
00314                   << " id/px/py/pz/mass "
00315                   << aParticle.id << " " 
00316                   << aParticle.px << " " 
00317                   << aParticle.py << " " 
00318                   << aParticle.pz << " " 
00319                   << aParticle.mass << " " << std::endl; 
00320       */
00321       
00322       // Create a FourVector, with rotation 
00323       double energy = std::sqrt( aParticle.px*aParticle.px
00324                                + aParticle.py*aParticle.py
00325                                + aParticle.pz*aParticle.pz
00326                                + aParticle.mass*aParticle.mass );
00327 
00328       HepMC::FourVector myPart(cAngle * aParticle.px + sAngle * aParticle.py,
00329                               -sAngle * aParticle.px + cAngle * aParticle.py,
00330                                aParticle.pz, energy);
00331 
00332       // Add a GenParticle
00333       HepMC::GenParticle* aGenParticle = new HepMC::GenParticle(myPart,aParticle.id);
00334       aVertex->add_particle_out(aGenParticle);
00335 
00336     }
00337     // End of particle loop
00338     
00339     // Increment for next time
00340     ++theCurrentMinBiasEvt[file];
00341     
00342   }
00343   // End of pile-up event loop
00344 
00345   // evt->print();
00346 
00347   // Fill the HepMCProduct from the GenEvent
00348   if ( evt )  { 
00349     pu_product->addHepMCData( evt );
00350     // Boost in case of beam crossing angle
00351     TMatrixD* boost = theVertexGenerator->boost();
00352     if ( boost ) pu_product->boostToLab(boost,"momentum");
00353   }
00354 
00355   // Put the HepMCProduct onto the event
00356   iEvent.put(pu_product,"PileUpEvents");
00357   // delete evt;
00358 
00359   // Save the current location in each pile-up event files
00360   this->save();
00361 
00362 }
00363 
00364 void
00365 PileUpProducer::save() {
00366 
00367   // Size of buffer
00368   ++myOutputBuffer;
00369 
00370   // Periodically close the current file and open a new one
00371   if ( myOutputBuffer/1000*1000 == myOutputBuffer ) { 
00372     myOutputFile.close();
00373     myOutputFile.open ("PileUpOutputFile.txt");
00374     //    myOutputFile.seekp(0); // No need to rewind in that case
00375   }
00376 
00377   // Save the current position to file
00378   myOutputFile.write((const char*)(&theCurrentEntry.front()),
00379                      theCurrentEntry.size()*sizeof(unsigned));
00380   myOutputFile.write((const char*)&theCurrentMinBiasEvt.front(),
00381                      theCurrentMinBiasEvt.size()*sizeof(unsigned));
00382   myOutputFile.flush();
00383 
00384 }
00385 
00386 bool
00387 PileUpProducer::read(std::string inputFile) {
00388 
00389   ifstream myInputFile;
00390   struct stat results;
00391   unsigned size1 = theCurrentEntry.size()*sizeof(unsigned);
00392   unsigned size2 = theCurrentMinBiasEvt.size()*sizeof(unsigned);
00393   unsigned size = 0;
00394 
00395 
00396   // Open the file (if any)
00397   myInputFile.open (inputFile.c_str());
00398   if ( myInputFile.is_open() ) { 
00399 
00400     // Get the size of the file
00401     if ( stat(inputFile.c_str(), &results) == 0 ) size = results.st_size;
00402     else return false; // Something is wrong with that file !
00403   
00404     // Position the pointer just before the last record
00405     myInputFile.seekg(size-size1-size2);
00406 
00407     // Read the information
00408     myInputFile.read((char*)(&theCurrentEntry.front()),size1);
00409     myInputFile.read((char*)&theCurrentMinBiasEvt.front(),size2);
00410     myInputFile.close();
00411 
00412     return true;
00413 
00414   } 
00415 
00416   return false;
00417 
00418 }
00419 
00420 DEFINE_FWK_MODULE(PileUpProducer);