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
00031 produces<edm::HepMCProduct>("PileUpEvents");
00032
00033
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
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 {
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
00056
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
00067 int xmin = (int) dataProbFunctionVar[0];
00068 int xmax = (int) dataProbFunctionVar[varSize-1]+1;
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]);
00077 }
00078
00079
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
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
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
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
00143 myOutputFile.open ("PileUpOutputFile.txt");
00144 myOutputBuffer = 0;
00145
00146
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
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
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
00182 if ( !input )
00183 theCurrentMinBiasEvt[file] =
00184 (unsigned) (theNumberOfMinBiasEvts[file] * random->flatShoot());
00185
00186
00187
00188
00189
00190
00191
00192
00193 }
00194
00195
00196 gROOT->cd();
00197
00198 }
00199
00200 void PileUpProducer::endRun()
00201 {
00202
00203
00204
00205 for ( unsigned file=0; file<theFiles.size(); ++file ) {
00206
00207
00208 theFiles[file]->Close();
00209
00210 }
00211
00212
00213 myOutputFile.close();
00214
00215
00216 gROOT->cd();
00217
00218 }
00219
00220 void PileUpProducer::produce(edm::Event & iEvent, const edm::EventSetup & es)
00221 {
00222
00223
00224 std::auto_ptr<edm::HepMCProduct> pu_product(new edm::HepMCProduct());
00225 HepMC::GenEvent* evt = new HepMC::GenEvent();
00226
00227
00228 int PUevts = usePoisson_ ? (int) random->poissonShoot(averageNumber_) : (int) hprob->GetRandom();
00229
00230
00231
00232 for ( int ievt=0; ievt<PUevts; ++ievt ) {
00233
00234
00235 unsigned file = (unsigned) (theNumberOfFiles * random->flatShoot());
00236
00237
00238
00239
00240
00241
00242
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
00253 double theAngle = random->flatShoot() * 2. * 3.14159265358979323;
00254 double cAngle = std::cos(theAngle);
00255 double sAngle = std::sin(theAngle);
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269 if ( theCurrentMinBiasEvt[file] == theNumberOfMinBiasEvts[file] ) {
00270
00271 ++theCurrentEntry[file];
00272
00273 theCurrentMinBiasEvt[file] = 0;
00274 if ( theCurrentEntry[file] == theNumberOfEntries[file] ) {
00275 theCurrentEntry[file] = 0;
00276
00277 }
00278
00279 thePUEvents[file]->reset();
00280 unsigned myEntry = theCurrentEntry[file];
00281
00282
00283
00284
00285 theTrees[file]->GetEntry(myEntry);
00286
00287
00288
00289
00290 theNumberOfMinBiasEvts[file] = thePUEvents[file]->nMinBias();
00291
00292 }
00293
00294
00295 const PUEvent::PUMinBiasEvt& aMinBiasEvt
00296 = thePUEvents[file]->thePUMinBiasEvts()[theCurrentMinBiasEvt[file]];
00297
00298
00299 unsigned firstTrack = aMinBiasEvt.first;
00300 unsigned trackSize = firstTrack + aMinBiasEvt.size;
00301
00302
00303
00304
00305
00306
00307 for ( unsigned iTrack=firstTrack; iTrack<trackSize; ++iTrack ) {
00308
00309 const PUEvent::PUParticle& aParticle
00310 = thePUEvents[file]->thePUParticles()[iTrack];
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
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
00333 HepMC::GenParticle* aGenParticle = new HepMC::GenParticle(myPart,aParticle.id);
00334 aVertex->add_particle_out(aGenParticle);
00335
00336 }
00337
00338
00339
00340 ++theCurrentMinBiasEvt[file];
00341
00342 }
00343
00344
00345
00346
00347
00348 if ( evt ) {
00349 pu_product->addHepMCData( evt );
00350
00351 TMatrixD* boost = theVertexGenerator->boost();
00352 if ( boost ) pu_product->boostToLab(boost,"momentum");
00353 }
00354
00355
00356 iEvent.put(pu_product,"PileUpEvents");
00357
00358
00359
00360 this->save();
00361
00362 }
00363
00364 void
00365 PileUpProducer::save() {
00366
00367
00368 ++myOutputBuffer;
00369
00370
00371 if ( myOutputBuffer/1000*1000 == myOutputBuffer ) {
00372 myOutputFile.close();
00373 myOutputFile.open ("PileUpOutputFile.txt");
00374
00375 }
00376
00377
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
00397 myInputFile.open (inputFile.c_str());
00398 if ( myInputFile.is_open() ) {
00399
00400
00401 if ( stat(inputFile.c_str(), &results) == 0 ) size = results.st_size;
00402 else return false;
00403
00404
00405 myInputFile.seekg(size-size1-size2);
00406
00407
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);