CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_0/src/Mixing/Base/src/PileUp.cc

Go to the documentation of this file.
00001 #include "Mixing/Base/interface/PileUp.h"
00002 #include "FWCore/Framework/interface/EventPrincipal.h"
00003 #include "FWCore/Framework/interface/InputSourceDescription.h"
00004 #include "FWCore/Sources/interface/VectorInputSourceFactory.h"
00005 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00006 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00007 #include "FWCore/Utilities/interface/Exception.h"
00008 
00009 #include "FWCore/ServiceRegistry/interface/Service.h"
00010 #include "FWCore/Utilities/interface/RandomNumberGenerator.h"
00011 
00012 #include "FWCore/Framework/interface/ESHandle.h"
00013 #include "FWCore/Framework/interface/EventSetup.h"
00014 #include "CondFormats/DataRecord/interface/MixingRcd.h"
00015 #include "CondFormats/RunInfo/interface/MixingModuleConfig.h"
00016 
00017 #include <algorithm>
00018 
00019 namespace edm {
00020   PileUp::PileUp(ParameterSet const& pset, double averageNumber, TH1F * const histo, const bool playback) :
00021     type_(pset.getParameter<std::string>("type")),
00022     averageNumber_(averageNumber),
00023     intAverage_(static_cast<int>(averageNumber)),
00024     histo_(histo),
00025     histoDistribution_(type_ == "histo"),
00026     probFunctionDistribution_(type_ == "probFunction"),
00027     poisson_(type_ == "poisson"),
00028     fixed_(type_ == "fixed"),
00029     none_(type_ == "none"),
00030     input_(VectorInputSourceFactory::get()->makeVectorInputSource(pset, InputSourceDescription()).release()),
00031     poissonDistribution_(0),
00032     poissonDistr_OOT_(0),
00033     playback_(playback),
00034     sequential_(pset.getUntrackedParameter<bool>("sequential", false)),
00035     samelumi_(pset.getUntrackedParameter<bool>("sameLumiBlock", false)),
00036     seed_(0)
00037    {
00038      if (pset.exists("nbPileupEvents"))
00039        seed_=pset.getParameter<edm::ParameterSet>("nbPileupEvents").getUntrackedParameter<int>("seed",0);
00040 
00041     bool DB=type_=="readDB";
00042 
00043     edm::Service<edm::RandomNumberGenerator> rng;
00044     if (!rng.isAvailable()) {
00045       throw cms::Exception("Configuration")
00046         << "PileUp requires the RandomNumberGeneratorService\n"
00047         "which is not present in the configuration file.  You must add the service\n"
00048         "in the configuration file or remove the modules that require it.";
00049     }
00050     
00051     CLHEP::HepRandomEngine& engine = rng->getEngine();
00052     poissonDistribution_ = new CLHEP::RandPoissonQ(engine, averageNumber_);
00053     
00054     // Get seed for the case when using user histogram or probability function
00055     if (histoDistribution_ || probFunctionDistribution_ || DB){ 
00056       if(seed_ !=0) {
00057         gRandom->SetSeed(seed_);
00058         LogInfo("MixingModule") << " Change seed for " << type_ << " mode. The seed is set to " << seed_;
00059       }
00060       else {
00061         gRandom->SetSeed(engine.getSeed());
00062       }
00063     } 
00064      
00065         
00066     if (!(histoDistribution_ || probFunctionDistribution_ || poisson_ || fixed_ || none_) && !DB) {
00067       throw cms::Exception("Illegal parameter value","PileUp::PileUp(ParameterSet const& pset)")
00068         << "'type' parameter (a string) has a value of '" << type_ << "'.\n"
00069         << "Legal values are 'poisson', 'fixed', or 'none'\n";
00070     }
00071 
00072     if (!DB){
00073     manage_OOT_ = pset.getUntrackedParameter<bool>("manage_OOT", false);
00074 
00075     if(manage_OOT_) { // figure out what the parameters are
00076 
00077       //      if (playback_) throw cms::Exception("Illegal parameter clash","PileUp::PileUp(ParameterSet const& pset)")
00078       // << " manage_OOT option not allowed with playback ";
00079 
00080       std::string OOT_type = pset.getUntrackedParameter<std::string>("OOT_type");
00081 
00082       if(OOT_type == "Poisson" || OOT_type == "poisson") {
00083         poisson_OOT_ = true;
00084         poissonDistr_OOT_ = new CLHEP::RandPoisson(engine);
00085       }
00086       else if(OOT_type == "Fixed" || OOT_type == "fixed") {
00087         fixed_OOT_ = true;
00088         // read back the fixed number requested out-of-time
00089         intFixed_OOT_ = pset.getUntrackedParameter<int>("intFixed_OOT", -1);
00090         if(intFixed_OOT_ < 0) {
00091           throw cms::Exception("Illegal parameter value","PileUp::PileUp(ParameterSet const& pset)") 
00092             << " Fixed out-of-time pileup requested, but no fixed value given ";
00093         }
00094       }
00095       else {
00096         throw cms::Exception("Illegal parameter value","PileUp::PileUp(ParameterSet const& pset)")
00097           << "'OOT_type' parameter (a string) has a value of '" << OOT_type << "'.\n"
00098           << "Legal values are 'poisson' or 'fixed'\n";
00099       }
00100       edm::LogInfo("MixingModule") <<" Out-of-time pileup will be generated with a " << OOT_type << " distribution. " ;
00101     }
00102     }
00103     
00104   }
00105 
00106   void PileUp::reload(const edm::EventSetup & setup){
00107     //get the required parameters from DB.
00108     edm::ESHandle<MixingModuleConfig> configM;
00109     setup.get<MixingRcd>().get(configM);
00110 
00111     const MixingInputConfig & config=configM->config(inputType_);
00112 
00113     //get the type
00114     type_=config.type();
00115     //set booleans
00116     histoDistribution_=type_ == "histo";
00117     probFunctionDistribution_=type_ == "probFunction";
00118     poisson_=type_ == "poisson";
00119     fixed_=type_ == "fixed";
00120     none_=type_ == "none";
00121     
00122     if (histoDistribution_) edm::LogError("MisConfiguration")<<"type histo cannot be reloaded from DB, yet";
00123     
00124     if (fixed_){
00125       averageNumber_=averageNumber();
00126     }
00127     else if (poisson_)
00128       {
00129         averageNumber_=config.averageNumber();
00130         edm::Service<edm::RandomNumberGenerator> rng; 
00131         CLHEP::HepRandomEngine& engine = rng->getEngine();            
00132         delete poissonDistribution_;
00133         poissonDistribution_ = new CLHEP::RandPoissonQ(engine, averageNumber_);  
00134       }
00135     else if (probFunctionDistribution_)
00136       {
00137         //need to reload the histogram from DB
00138         const std::vector<int> & dataProbFunctionVar = config.probFunctionVariable();
00139         std::vector<double> dataProb = config.probValue();
00140         
00141         int varSize = (int) dataProbFunctionVar.size();
00142         int probSize = (int) dataProb.size();
00143                 
00144         if ((dataProbFunctionVar[0] != 0) || (dataProbFunctionVar[varSize - 1] != (varSize - 1))) 
00145           throw cms::Exception("BadProbFunction") << "Please, check the variables of the probability function! The first variable should be 0 and the difference between two variables should be 1." << std::endl;
00146                 
00147         // Complete the vector containing the probability  function data
00148         // with the values "0"
00149         if (probSize < varSize){
00150           edm::LogWarning("MixingModule") << " The probability function data will be completed with " <<(varSize - probSize)  <<" values 0.";
00151           
00152           for (int i=0; i<(varSize - probSize); i++) dataProb.push_back(0);
00153           
00154           probSize = dataProb.size();
00155           edm::LogInfo("MixingModule") << " The number of the P(x) data set after adding the values 0 is " << probSize;
00156         }
00157         
00158         // Create an histogram with the data from the probability function provided by the user           
00159         int xmin = (int) dataProbFunctionVar[0];
00160         int xmax = (int) dataProbFunctionVar[varSize-1]+1;  // need upper edge to be one beyond last value
00161         int numBins = varSize;
00162         
00163         edm::LogInfo("MixingModule") << "An histogram will be created with " << numBins << " bins in the range ("<< xmin << "," << xmax << ")." << std::endl;
00164 
00165         if (histo_) delete histo_;
00166         histo_ = new TH1F("h","Histo from the user's probability function",numBins,xmin,xmax); 
00167         
00168         LogDebug("MixingModule") << "Filling histogram with the following data:" << std::endl;
00169         
00170         for (int j=0; j < numBins ; j++){
00171           LogDebug("MixingModule") << " x = " << dataProbFunctionVar[j ]<< " P(x) = " << dataProb[j];
00172           histo_->Fill(dataProbFunctionVar[j]+0.5,dataProb[j]); // assuming integer values for the bins, fill bin centers, not edges 
00173         }
00174         
00175         // Check if the histogram is normalized
00176         if ( ((histo_->Integral() - 1) > 1.0e-02) && ((histo_->Integral() - 1) < -1.0e-02)){ 
00177           throw cms::Exception("BadProbFunction") << "The probability function should be normalized!!! " << std::endl;
00178         }
00179         averageNumber_=histo_->GetMean();
00180       }
00181 
00182     int oot=config.outOfTime();
00183     manage_OOT_=false;
00184     if (oot==1)
00185       {
00186         manage_OOT_=true;
00187         poisson_OOT_ = false;
00188         if (poissonDistr_OOT_){delete poissonDistr_OOT_; poissonDistr_OOT_=0; }
00189         fixed_OOT_ = true;
00190         intFixed_OOT_=config.fixedOutOfTime();
00191       }
00192     else if (oot==2)
00193       {
00194         manage_OOT_=true;
00195         poisson_OOT_ = true;
00196         fixed_OOT_ = false;
00197         if (!poissonDistr_OOT_) {
00198           //no need to trash the previous one if already there
00199           edm::Service<edm::RandomNumberGenerator> rng; 
00200           CLHEP::HepRandomEngine& engine = rng->getEngine();                      
00201           poissonDistr_OOT_ = new CLHEP::RandPoisson(engine);
00202         }
00203       }
00204 
00205     
00206   }
00207   PileUp::~PileUp() {
00208     delete poissonDistribution_;
00209     delete poissonDistr_OOT_ ;
00210   }
00211 
00212   void PileUp::CalculatePileup(int MinBunch, int MaxBunch, std::vector<int>& PileupSelection, std::vector<float>& TrueNumInteractions) {
00213 
00214     // if we are managing the distribution of out-of-time pileup separately, select the distribution for bunch
00215     // crossing zero first, save it for later.
00216 
00217     int nzero_crossing = -1;
00218     double Fnzero_crossing = -1;
00219 
00220     if(manage_OOT_) {
00221       if (none_){
00222         nzero_crossing = 0;
00223       }else if (poisson_){
00224         nzero_crossing =  poissonDistribution_->fire() ;
00225       }else if (fixed_){
00226         nzero_crossing =  intAverage_ ;
00227       }else if (histoDistribution_ || probFunctionDistribution_){
00228         double d = histo_->GetRandom();
00229         //n = (int) floor(d + 0.5);  // incorrect for bins with integer edges
00230         Fnzero_crossing =  d;
00231       }
00232 
00233     }
00234 
00235     for(int bx = MinBunch; bx < MaxBunch+1; ++bx) {
00236 
00237       if(manage_OOT_) {
00238         if(bx==0 && !poisson_OOT_) { 
00239           PileupSelection.push_back(nzero_crossing) ;
00240           TrueNumInteractions.push_back( nzero_crossing );
00241         }
00242         else{
00243           if(poisson_OOT_) {
00244             PileupSelection.push_back(poissonDistr_OOT_->fire(Fnzero_crossing)) ;
00245             TrueNumInteractions.push_back( Fnzero_crossing );
00246           }
00247           else {
00248             PileupSelection.push_back(intFixed_OOT_) ;
00249             TrueNumInteractions.push_back( intFixed_OOT_ );
00250           }  
00251         }
00252       }
00253       else {
00254         if (none_){
00255           PileupSelection.push_back(0);
00256           TrueNumInteractions.push_back( 0. );
00257         }else if (poisson_){
00258           PileupSelection.push_back(poissonDistribution_->fire());
00259           TrueNumInteractions.push_back( averageNumber_ );
00260         }else if (fixed_){
00261           PileupSelection.push_back(intAverage_);
00262           TrueNumInteractions.push_back( intAverage_ );
00263         }else if (histoDistribution_ || probFunctionDistribution_){
00264           double d = histo_->GetRandom();
00265           PileupSelection.push_back(int(d));
00266           TrueNumInteractions.push_back( d );
00267         }
00268       }
00269     
00270     }
00271   }
00272 
00273 
00274 } //namespace edm