00001 #include "Mixing/Base/interface/PileUp.h"
00002 #include "DataFormats/Provenance/interface/BranchIDListHelper.h"
00003 #include "DataFormats/Provenance/interface/ModuleDescription.h"
00004 #include "FWCore/Framework/interface/EventPrincipal.h"
00005 #include "FWCore/Framework/interface/InputSourceDescription.h"
00006 #include "FWCore/Framework/src/SignallingProductRegistry.h"
00007 #include "FWCore/ServiceRegistry/interface/ActivityRegistry.h"
00008 #include "FWCore/Sources/interface/VectorInputSourceFactory.h"
00009 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00010 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00011 #include "FWCore/Utilities/interface/Exception.h"
00012 #include "FWCore/Utilities/interface/GetPassID.h"
00013 #include "FWCore/Version/interface/GetReleaseVersion.h"
00014
00015 #include "FWCore/ServiceRegistry/interface/Service.h"
00016 #include "FWCore/Utilities/interface/RandomNumberGenerator.h"
00017
00018 #include "FWCore/Framework/interface/ESHandle.h"
00019 #include "FWCore/Framework/interface/EventSetup.h"
00020 #include "CondFormats/DataRecord/interface/MixingRcd.h"
00021 #include "CondFormats/RunInfo/interface/MixingModuleConfig.h"
00022
00023 #include "boost/shared_ptr.hpp"
00024
00025 #include <algorithm>
00026
00027 namespace edm {
00028 PileUp::PileUp(ParameterSet const& pset, double averageNumber, TH1F * const histo, const bool playback) :
00029 type_(pset.getParameter<std::string>("type")),
00030 averageNumber_(averageNumber),
00031 intAverage_(static_cast<int>(averageNumber)),
00032 histo_(histo),
00033 histoDistribution_(type_ == "histo"),
00034 probFunctionDistribution_(type_ == "probFunction"),
00035 poisson_(type_ == "poisson"),
00036 fixed_(type_ == "fixed"),
00037 none_(type_ == "none"),
00038 productRegistry_(new SignallingProductRegistry),
00039 input_(VectorInputSourceFactory::get()->makeVectorInputSource(pset, InputSourceDescription(
00040 ModuleDescription(),
00041 *productRegistry_,
00042 boost::shared_ptr<BranchIDListHelper>(new BranchIDListHelper),
00043 boost::shared_ptr<ActivityRegistry>(new ActivityRegistry),
00044 -1, -1
00045 )).release()),
00046 processConfiguration_(new ProcessConfiguration(std::string("@MIXING"), getReleaseVersion(), getPassID())),
00047 eventPrincipal_(),
00048 poissonDistribution_(),
00049 poissonDistr_OOT_(),
00050 playback_(playback),
00051 sequential_(pset.getUntrackedParameter<bool>("sequential", false)),
00052 samelumi_(pset.getUntrackedParameter<bool>("sameLumiBlock", false)),
00053 seed_(0) {
00054
00055
00056 ParameterSet emptyPSet;
00057 emptyPSet.registerIt();
00058 processConfiguration_->setParameterSetID(emptyPSet.id());
00059
00060 input_->productRegistry()->setFrozen();
00061
00062
00063 eventPrincipal_.reset(new EventPrincipal(input_->productRegistry(),
00064 input_->branchIDListHelper(),
00065 *processConfiguration_,
00066 nullptr));
00067
00068 if (pset.exists("nbPileupEvents")) {
00069 seed_=pset.getParameter<edm::ParameterSet>("nbPileupEvents").getUntrackedParameter<int>("seed",0);
00070 }
00071
00072 bool DB=type_=="readDB";
00073
00074 edm::Service<edm::RandomNumberGenerator> rng;
00075 if (!rng.isAvailable()) {
00076 throw cms::Exception("Configuration")
00077 << "PileUp requires the RandomNumberGeneratorService\n"
00078 "which is not present in the configuration file. You must add the service\n"
00079 "in the configuration file or remove the modules that require it.";
00080 }
00081
00082 CLHEP::HepRandomEngine& engine = rng->getEngine();
00083 poissonDistribution_.reset(new CLHEP::RandPoissonQ(engine, averageNumber_));
00084
00085
00086 if (histoDistribution_ || probFunctionDistribution_ || DB){
00087 if(seed_ !=0) {
00088 gRandom->SetSeed(seed_);
00089 LogInfo("MixingModule") << " Change seed for " << type_ << " mode. The seed is set to " << seed_;
00090 }
00091 else {
00092 gRandom->SetSeed(engine.getSeed());
00093 }
00094 }
00095
00096
00097 if (!(histoDistribution_ || probFunctionDistribution_ || poisson_ || fixed_ || none_) && !DB) {
00098 throw cms::Exception("Illegal parameter value","PileUp::PileUp(ParameterSet const& pset)")
00099 << "'type' parameter (a string) has a value of '" << type_ << "'.\n"
00100 << "Legal values are 'poisson', 'fixed', or 'none'\n";
00101 }
00102
00103 if (!DB){
00104 manage_OOT_ = pset.getUntrackedParameter<bool>("manage_OOT", false);
00105
00106
00107
00108 PU_Study_ = false;
00109 Study_type_ = "";
00110
00111 Study_type_ = pset.getUntrackedParameter<std::string>("Special_Pileup_Studies", "");
00112
00113 if(Study_type_ == "Fixed_ITPU_Vary_OOTPU") {
00114
00115 PU_Study_ = true;
00116 intFixed_ITPU_ = pset.getUntrackedParameter<int>("intFixed_ITPU", 0);
00117
00118 }
00119
00120 if(manage_OOT_) {
00121
00122
00123
00124
00125 std::string OOT_type = pset.getUntrackedParameter<std::string>("OOT_type");
00126
00127 if(OOT_type == "Poisson" || OOT_type == "poisson") {
00128 poisson_OOT_ = true;
00129 poissonDistr_OOT_.reset(new CLHEP::RandPoisson(engine));
00130 }
00131 else if(OOT_type == "Fixed" || OOT_type == "fixed") {
00132 fixed_OOT_ = true;
00133
00134 intFixed_OOT_ = pset.getUntrackedParameter<int>("intFixed_OOT", -1);
00135 if(intFixed_OOT_ < 0) {
00136 throw cms::Exception("Illegal parameter value","PileUp::PileUp(ParameterSet const& pset)")
00137 << " Fixed out-of-time pileup requested, but no fixed value given ";
00138 }
00139 }
00140 else {
00141 throw cms::Exception("Illegal parameter value","PileUp::PileUp(ParameterSet const& pset)")
00142 << "'OOT_type' parameter (a string) has a value of '" << OOT_type << "'.\n"
00143 << "Legal values are 'poisson' or 'fixed'\n";
00144 }
00145 edm::LogInfo("MixingModule") <<" Out-of-time pileup will be generated with a " << OOT_type << " distribution. " ;
00146 }
00147 }
00148
00149 }
00150
00151 void PileUp::reload(const edm::EventSetup & setup){
00152
00153 edm::ESHandle<MixingModuleConfig> configM;
00154 setup.get<MixingRcd>().get(configM);
00155
00156 const MixingInputConfig & config=configM->config(inputType_);
00157
00158
00159 type_=config.type();
00160
00161 histoDistribution_=type_ == "histo";
00162 probFunctionDistribution_=type_ == "probFunction";
00163 poisson_=type_ == "poisson";
00164 fixed_=type_ == "fixed";
00165 none_=type_ == "none";
00166
00167 if (histoDistribution_) edm::LogError("MisConfiguration")<<"type histo cannot be reloaded from DB, yet";
00168
00169 if (fixed_){
00170 averageNumber_=averageNumber();
00171 }
00172 else if (poisson_)
00173 {
00174 averageNumber_=config.averageNumber();
00175 edm::Service<edm::RandomNumberGenerator> rng;
00176 CLHEP::HepRandomEngine& engine = rng->getEngine();
00177 poissonDistribution_.reset(new CLHEP::RandPoissonQ(engine, averageNumber_));
00178 }
00179 else if (probFunctionDistribution_)
00180 {
00181
00182 const std::vector<int> & dataProbFunctionVar = config.probFunctionVariable();
00183 std::vector<double> dataProb = config.probValue();
00184
00185 int varSize = (int) dataProbFunctionVar.size();
00186 int probSize = (int) dataProb.size();
00187
00188 if ((dataProbFunctionVar[0] != 0) || (dataProbFunctionVar[varSize - 1] != (varSize - 1)))
00189 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;
00190
00191
00192
00193 if (probSize < varSize){
00194 edm::LogWarning("MixingModule") << " The probability function data will be completed with " <<(varSize - probSize) <<" values 0.";
00195
00196 for (int i=0; i<(varSize - probSize); i++) dataProb.push_back(0);
00197
00198 probSize = dataProb.size();
00199 edm::LogInfo("MixingModule") << " The number of the P(x) data set after adding the values 0 is " << probSize;
00200 }
00201
00202
00203 int xmin = (int) dataProbFunctionVar[0];
00204 int xmax = (int) dataProbFunctionVar[varSize-1]+1;
00205 int numBins = varSize;
00206
00207 edm::LogInfo("MixingModule") << "An histogram will be created with " << numBins << " bins in the range ("<< xmin << "," << xmax << ")." << std::endl;
00208
00209 if (histo_) delete histo_;
00210 histo_ = new TH1F("h","Histo from the user's probability function",numBins,xmin,xmax);
00211
00212 LogDebug("MixingModule") << "Filling histogram with the following data:" << std::endl;
00213
00214 for (int j=0; j < numBins ; j++){
00215 LogDebug("MixingModule") << " x = " << dataProbFunctionVar[j ]<< " P(x) = " << dataProb[j];
00216 histo_->Fill(dataProbFunctionVar[j]+0.5,dataProb[j]);
00217 }
00218
00219
00220 if ( ((histo_->Integral() - 1) > 1.0e-02) && ((histo_->Integral() - 1) < -1.0e-02)){
00221 throw cms::Exception("BadProbFunction") << "The probability function should be normalized!!! " << std::endl;
00222 }
00223 averageNumber_=histo_->GetMean();
00224 }
00225
00226 int oot=config.outOfTime();
00227 manage_OOT_=false;
00228 if (oot==1)
00229 {
00230 manage_OOT_=true;
00231 poisson_OOT_ = false;
00232 if (poissonDistr_OOT_){poissonDistr_OOT_.reset(); }
00233 fixed_OOT_ = true;
00234 intFixed_OOT_=config.fixedOutOfTime();
00235 }
00236 else if (oot==2)
00237 {
00238 manage_OOT_=true;
00239 poisson_OOT_ = true;
00240 fixed_OOT_ = false;
00241 if (!poissonDistr_OOT_) {
00242
00243 edm::Service<edm::RandomNumberGenerator> rng;
00244 CLHEP::HepRandomEngine& engine = rng->getEngine();
00245 poissonDistr_OOT_.reset(new CLHEP::RandPoisson(engine));
00246 }
00247 }
00248
00249
00250 }
00251 PileUp::~PileUp() {
00252 }
00253
00254 void PileUp::CalculatePileup(int MinBunch, int MaxBunch, std::vector<int>& PileupSelection, std::vector<float>& TrueNumInteractions) {
00255
00256
00257
00258
00259 int nzero_crossing = -1;
00260 double Fnzero_crossing = -1;
00261
00262 if(manage_OOT_) {
00263 if (none_){
00264 nzero_crossing = 0;
00265 }else if (poisson_){
00266 nzero_crossing = poissonDistribution_->fire() ;
00267 }else if (fixed_){
00268 nzero_crossing = intAverage_ ;
00269 }else if (histoDistribution_ || probFunctionDistribution_){
00270 double d = histo_->GetRandom();
00271
00272 Fnzero_crossing = d;
00273 nzero_crossing = int(d);
00274 }
00275
00276 }
00277
00278 for(int bx = MinBunch; bx < MaxBunch+1; ++bx) {
00279
00280 if(manage_OOT_) {
00281 if(bx==0 && !poisson_OOT_) {
00282 PileupSelection.push_back(nzero_crossing) ;
00283 TrueNumInteractions.push_back( nzero_crossing );
00284 }
00285 else{
00286 if(poisson_OOT_) {
00287 if(PU_Study_ && (Study_type_ == "Fixed_ITPU_Vary_OOTPU" ) && bx==0 ) {
00288 PileupSelection.push_back(intFixed_ITPU_) ;
00289 }
00290 else{
00291 PileupSelection.push_back(poissonDistr_OOT_->fire(Fnzero_crossing)) ;
00292 }
00293 TrueNumInteractions.push_back( Fnzero_crossing );
00294 }
00295 else {
00296 PileupSelection.push_back(intFixed_OOT_) ;
00297 TrueNumInteractions.push_back( intFixed_OOT_ );
00298 }
00299 }
00300 }
00301 else {
00302 if (none_){
00303 PileupSelection.push_back(0);
00304 TrueNumInteractions.push_back( 0. );
00305 }else if (poisson_){
00306 PileupSelection.push_back(poissonDistribution_->fire());
00307 TrueNumInteractions.push_back( averageNumber_ );
00308 }else if (fixed_){
00309 PileupSelection.push_back(intAverage_);
00310 TrueNumInteractions.push_back( intAverage_ );
00311 }else if (histoDistribution_ || probFunctionDistribution_){
00312 double d = histo_->GetRandom();
00313 PileupSelection.push_back(int(d));
00314 TrueNumInteractions.push_back( d );
00315 }
00316 }
00317
00318 }
00319 }
00320
00321
00322 }