CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
PileUp.cc
Go to the documentation of this file.
16 
19 
25 
26 #include "CLHEP/Random/RandPoissonQ.h"
27 #include "CLHEP/Random/RandPoisson.h"
28 
29 #include <algorithm>
30 #include <memory>
31 #include "TMath.h"
32 
37 /*************************************************************************
38  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
39  * All rights reserved. *
40  * *
41  * For the licensing terms see $ROOTSYS/LICENSE. *
42  * For the list of contributors see $ROOTSYS/README/CREDITS. *
43  *************************************************************************/
44 
45 static Double_t GetRandom(TH1* th1, CLHEP::HepRandomEngine* rng)
46 {
47  Int_t nbinsx = th1->GetNbinsX();
48  Double_t* fIntegral = th1->GetIntegral();
49  Double_t integral = fIntegral[nbinsx];
50 
51  if (integral == 0) return 0;
52 
53  Double_t r1 = rng->flat();
54  Int_t ibin = TMath::BinarySearch(nbinsx,fIntegral,r1);
55  Double_t x = th1->GetBinLowEdge(ibin+1);
56  if (r1 > fIntegral[ibin])
57  x += th1->GetBinWidth(ibin+1)*(r1-fIntegral[ibin])/(fIntegral[ibin+1] - fIntegral[ibin]);
58  return x;
59 }
61 
62 
63 namespace edm {
64  PileUp::PileUp(ParameterSet const& pset, std::string sourcename, double averageNumber, TH1F * const histo, const bool playback) :
65  type_(pset.getParameter<std::string>("type")),
66  Source_type_(sourcename),
67  averageNumber_(averageNumber),
68  intAverage_(static_cast<int>(averageNumber)),
69  histo_(histo),
70  histoDistribution_(type_ == "histo"),
71  probFunctionDistribution_(type_ == "probFunction"),
72  poisson_(type_ == "poisson"),
73  fixed_(type_ == "fixed"),
74  none_(type_ == "none"),
75  fileNameHash_(0U),
76  productRegistry_(new SignallingProductRegistry),
77  input_(VectorInputSourceFactory::get()->makeVectorInputSource(pset, VectorInputSourceDescription(
78  productRegistry_, edm::PreallocationConfiguration())).release()),
79  processConfiguration_(new ProcessConfiguration(std::string("@MIXING"), getReleaseVersion(), getPassID())),
80  eventPrincipal_(),
81  lumiPrincipal_(),
82  runPrincipal_(),
83  provider_(),
84  vPoissonDistribution_(),
85  vPoissonDistr_OOT_(),
86  randomEngines_(),
87  playback_(playback),
88  sequential_(pset.getUntrackedParameter<bool>("sequential", false)) {
89 
90  // Use the empty parameter set for the parameter set ID of our "@MIXING" process.
92 
93  if(pset.existsAs<std::vector<ParameterSet> >("producers", true)) {
94  std::vector<ParameterSet> producers = pset.getParameter<std::vector<ParameterSet> >("producers");
96  }
97 
98  productRegistry_->setFrozen();
99 
100  // A modified HistoryAppender must be used for unscheduled processing.
101  eventPrincipal_.reset(new EventPrincipal(input_->productRegistry(),
102  std::make_shared<BranchIDListHelper>(),
103  std::make_shared<ThinnedAssociationsHelper>(),
105  nullptr));
106 
107  bool DB=type_=="readDB";
108 
109  if (pset.exists("nbPileupEvents")) {
110  if (0 != pset.getParameter<edm::ParameterSet>("nbPileupEvents").getUntrackedParameter<int>("seed",0)) {
111  edm::LogWarning("MixingModule") << "Parameter nbPileupEvents.seed is not supported";
112  }
113  }
114 
116  if (!rng.isAvailable()) {
117  throw cms::Exception("Configuration")
118  << "PileUp requires the RandomNumberGeneratorService\n"
119  "which is not present in the configuration file. You must add the service\n"
120  "in the configuration file or remove the modules that require it.";
121  }
122 
124  throw cms::Exception("Illegal parameter value","PileUp::PileUp(ParameterSet const& pset)")
125  << "'type' parameter (a string) has a value of '" << type_ << "'.\n"
126  << "Legal values are 'poisson', 'fixed', or 'none'\n";
127  }
128 
129  if (!DB){
130  manage_OOT_ = pset.getUntrackedParameter<bool>("manage_OOT", false);
131 
132  // Check for string describing special processing. Add these here for individual cases
133 
134  PU_Study_ = false;
135  Study_type_ = "";
136 
137  Study_type_ = pset.getUntrackedParameter<std::string>("Special_Pileup_Studies", "");
138 
139  if(Study_type_ == "Fixed_ITPU_Vary_OOTPU") {
140 
141  PU_Study_ = true;
142  intFixed_ITPU_ = pset.getUntrackedParameter<int>("intFixed_ITPU", 0);
143 
144  }
145 
146  if(manage_OOT_) { // figure out what the parameters are
147 
148  // if (playback_) throw cms::Exception("Illegal parameter clash","PileUp::PileUp(ParameterSet const& pset)")
149  // << " manage_OOT option not allowed with playback ";
150 
151  std::string OOT_type = pset.getUntrackedParameter<std::string>("OOT_type");
152 
153  if(OOT_type == "Poisson" || OOT_type == "poisson") {
154  poisson_OOT_ = true;
155  }
156  else if(OOT_type == "Fixed" || OOT_type == "fixed") {
157  fixed_OOT_ = true;
158  // read back the fixed number requested out-of-time
159  intFixed_OOT_ = pset.getUntrackedParameter<int>("intFixed_OOT", -1);
160  if(intFixed_OOT_ < 0) {
161  throw cms::Exception("Illegal parameter value","PileUp::PileUp(ParameterSet const& pset)")
162  << " Fixed out-of-time pileup requested, but no fixed value given ";
163  }
164  }
165  else {
166  throw cms::Exception("Illegal parameter value","PileUp::PileUp(ParameterSet const& pset)")
167  << "'OOT_type' parameter (a string) has a value of '" << OOT_type << "'.\n"
168  << "Legal values are 'poisson' or 'fixed'\n";
169  }
170  edm::LogInfo("MixingModule") <<" Out-of-time pileup will be generated with a " << OOT_type << " distribution. " ;
171  }
172  }
173 
174  if(Source_type_ == "cosmics") { // allow for some extra flexibility for mixing
175  minBunch_cosmics_ = pset.getUntrackedParameter<int>("minBunch_cosmics", -1000);
176  maxBunch_cosmics_ = pset.getUntrackedParameter<int>("maxBunch_cosmics", 1000);
177  }
178 
179 
180 
181  } // end of constructor
182 
183 
184 
185 
186 
188  input_->doBeginJob();
189  if (provider_.get() != nullptr) {
190  provider_->beginJob(*productRegistry_);
191  }
192  }
193 
194  void PileUp::endJob () {
195  if (provider_.get() != nullptr) {
196  provider_->endJob();
197  }
198  input_->doEndJob();
199  }
200 
202  if (provider_.get() != nullptr) {
203  auto aux = std::make_shared<RunAuxiliary>(run.runAuxiliary());
205  provider_->beginRun(*runPrincipal_, setup, run.moduleCallingContext());
206  }
207  }
209  if (provider_.get() != nullptr) {
210  auto aux = std::make_shared<LuminosityBlockAuxiliary>(lumi.luminosityBlockAuxiliary());
212  lumiPrincipal_->setRunPrincipal(runPrincipal_);
213  provider_->beginLuminosityBlock(*lumiPrincipal_, setup, lumi.moduleCallingContext());
214  }
215  }
216 
218  if (provider_.get() != nullptr) {
219  provider_->endRun(*runPrincipal_, setup, run.moduleCallingContext());
220  }
221  }
223  if (provider_.get() != nullptr) {
224  provider_->endLuminosityBlock(*lumiPrincipal_, setup, lumi.moduleCallingContext());
225  }
226  }
227 
229  if (provider_.get() != nullptr) {
230  // note: run and lumi numbers must be modified to match lumiPrincipal_
231  eventPrincipal_->setLuminosityBlockPrincipal(lumiPrincipal_);
232  eventPrincipal_->setRunAndLumiNumber(lumiPrincipal_->run(), lumiPrincipal_->luminosityBlock());
233  provider_->setupPileUpEvent(*eventPrincipal_, setup);
234  }
235  }
236 
238  //get the required parameters from DB.
240  setup.get<MixingRcd>().get(configM);
241 
242  const MixingInputConfig & config=configM->config(inputType_);
243 
244  //get the type
245  type_=config.type();
246  //set booleans
247  histoDistribution_=type_ == "histo";
248  probFunctionDistribution_=type_ == "probFunction";
249  poisson_=type_ == "poisson";
250  fixed_=type_ == "fixed";
251  none_=type_ == "none";
252 
253  if (histoDistribution_) edm::LogError("MisConfiguration")<<"type histo cannot be reloaded from DB, yet";
254 
255  if (fixed_){
257  }
258  else if (poisson_)
259  {
260  averageNumber_=config.averageNumber();
261  for(auto & distribution : vPoissonDistribution_) {
262  if(distribution) {
263  distribution.reset(new CLHEP::RandPoissonQ(distribution->engine(), averageNumber_));
264  }
265  }
266  }
267  else if (probFunctionDistribution_)
268  {
269  //need to reload the histogram from DB
270  const std::vector<int> & dataProbFunctionVar = config.probFunctionVariable();
271  std::vector<double> dataProb = config.probValue();
272 
273  int varSize = (int) dataProbFunctionVar.size();
274  int probSize = (int) dataProb.size();
275 
276  if ((dataProbFunctionVar[0] != 0) || (dataProbFunctionVar[varSize - 1] != (varSize - 1)))
277  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;
278 
279  // Complete the vector containing the probability function data
280  // with the values "0"
281  if (probSize < varSize){
282  edm::LogWarning("MixingModule") << " The probability function data will be completed with " <<(varSize - probSize) <<" values 0.";
283 
284  for (int i=0; i<(varSize - probSize); i++) dataProb.push_back(0);
285 
286  probSize = dataProb.size();
287  edm::LogInfo("MixingModule") << " The number of the P(x) data set after adding the values 0 is " << probSize;
288  }
289 
290  // Create an histogram with the data from the probability function provided by the user
291  int xmin = (int) dataProbFunctionVar[0];
292  int xmax = (int) dataProbFunctionVar[varSize-1]+1; // need upper edge to be one beyond last value
293  int numBins = varSize;
294 
295  edm::LogInfo("MixingModule") << "An histogram will be created with " << numBins << " bins in the range ("<< xmin << "," << xmax << ")." << std::endl;
296 
297  if (histo_) delete histo_;
298  histo_ = new TH1F("h","Histo from the user's probability function",numBins,xmin,xmax);
299 
300  LogDebug("MixingModule") << "Filling histogram with the following data:" << std::endl;
301 
302  for (int j=0; j < numBins ; j++){
303  LogDebug("MixingModule") << " x = " << dataProbFunctionVar[j ]<< " P(x) = " << dataProb[j];
304  histo_->Fill(dataProbFunctionVar[j]+0.5,dataProb[j]); // assuming integer values for the bins, fill bin centers, not edges
305  }
306 
307  // Check if the histogram is normalized
308  if (std::abs(histo_->Integral() - 1) > 1.0e-02){
309  throw cms::Exception("BadProbFunction") << "The probability function should be normalized!!! " << std::endl;
310  }
311  averageNumber_=histo_->GetMean();
312  }
313 
314  int oot=config.outOfTime();
315  manage_OOT_=false;
316  if (oot==1)
317  {
318  manage_OOT_=true;
319  poisson_OOT_ = false;
320  fixed_OOT_ = true;
321  intFixed_OOT_=config.fixedOutOfTime();
322  }
323  else if (oot==2)
324  {
325  manage_OOT_=true;
326  poisson_OOT_ = true;
327  fixed_OOT_ = false;
328  }
329 
330 
331  }
333  }
334 
335  std::unique_ptr<CLHEP::RandPoissonQ> const& PileUp::poissonDistribution(StreamID const& streamID) {
336  unsigned int index = streamID.value();
337  if(index >= vPoissonDistribution_.size()) {
338  // This resizing is not thread safe and only works because
339  // this is used by a "one" type module
340  vPoissonDistribution_.resize(index + 1);
341  }
342  std::unique_ptr<CLHEP::RandPoissonQ>& ptr = vPoissonDistribution_[index];
343  if(!ptr) {
344  CLHEP::HepRandomEngine& engine = *randomEngine(streamID);
345  ptr.reset(new CLHEP::RandPoissonQ(engine, averageNumber_));
346  }
347  return ptr;
348  }
349 
350  std::unique_ptr<CLHEP::RandPoisson> const& PileUp::poissonDistr_OOT(StreamID const& streamID) {
351  unsigned int index = streamID.value();
352  if(index >= vPoissonDistr_OOT_.size()) {
353  // This resizing is not thread safe and only works because
354  // this is used by a "one" type module
355  vPoissonDistr_OOT_.resize(index + 1);
356  }
357  std::unique_ptr<CLHEP::RandPoisson>& ptr = vPoissonDistr_OOT_[index];
358  if(!ptr) {
359  CLHEP::HepRandomEngine& engine = *randomEngine(streamID);
360  ptr.reset(new CLHEP::RandPoisson(engine));
361  }
362  return ptr;
363  }
364 
365  CLHEP::HepRandomEngine* PileUp::randomEngine(StreamID const& streamID) {
366  unsigned int index = streamID.value();
367  if(index >= randomEngines_.size()) {
368  // This resizing is not thread safe and only works because
369  // this is used by a "one" type module
370  randomEngines_.resize(index + 1, nullptr);
371  }
372  CLHEP::HepRandomEngine* ptr = randomEngines_[index];
373  if(!ptr) {
375  ptr = &rng->getEngine(streamID);
376  randomEngines_[index] = ptr;
377  }
378  return ptr;
379  }
380 
381  void PileUp::CalculatePileup(int MinBunch, int MaxBunch, std::vector<int>& PileupSelection, std::vector<float>& TrueNumInteractions, StreamID const& streamID) {
382 
383  // if we are managing the distribution of out-of-time pileup separately, select the distribution for bunch
384  // crossing zero first, save it for later.
385 
386  int nzero_crossing = -1;
387  double Fnzero_crossing = -1;
388 
389  if(manage_OOT_) {
390  if (none_){
391  nzero_crossing = 0;
392  }else if (poisson_){
393  nzero_crossing = poissonDistribution(streamID)->fire() ;
394  }else if (fixed_){
395  nzero_crossing = intAverage_ ;
397  // RANDOM_NUMBER_ERROR
398  // Random number should be generated by the engines from the
399  // RandomNumberGeneratorService. This appears to use the global
400  // engine in ROOT. This is not thread safe unless the module using
401  // it is a one module and declares a shared resource and all
402  // other modules using it also declare the same shared resource.
403  // This also breaks replay.
404  double d = GetRandom(histo_, randomEngine(streamID));
405  //n = (int) floor(d + 0.5); // incorrect for bins with integer edges
406  Fnzero_crossing = d;
407  nzero_crossing = int(d);
408  }
409 
410  }
411 
412  for(int bx = MinBunch; bx < MaxBunch+1; ++bx) {
413 
414  if(manage_OOT_) {
415  if(bx==0 && !poisson_OOT_) {
416  PileupSelection.push_back(nzero_crossing) ;
417  TrueNumInteractions.push_back( nzero_crossing );
418  }
419  else{
420  if(poisson_OOT_) {
421  if(PU_Study_ && (Study_type_ == "Fixed_ITPU_Vary_OOTPU" ) && bx==0 ) {
422  PileupSelection.push_back(intFixed_ITPU_) ;
423  }
424  else{
425  PileupSelection.push_back(poissonDistr_OOT(streamID)->fire(Fnzero_crossing)) ;
426  }
427  TrueNumInteractions.push_back( Fnzero_crossing );
428  }
429  else {
430  PileupSelection.push_back(intFixed_OOT_) ;
431  TrueNumInteractions.push_back( intFixed_OOT_ );
432  }
433  }
434  }
435  else {
436  if (none_){
437  PileupSelection.push_back(0);
438  TrueNumInteractions.push_back( 0. );
439  }else if (poisson_){
440  PileupSelection.push_back(poissonDistribution(streamID)->fire());
441  TrueNumInteractions.push_back( averageNumber_ );
442  }else if (fixed_){
443  PileupSelection.push_back(intAverage_);
444  TrueNumInteractions.push_back( intAverage_ );
446  // RANDOM_NUMBER_ERROR
447  // Random number should be generated by the engines from the
448  // RandomNumberGeneratorService. This appears to use the global
449  // engine in ROOT. This is not thread safe unless the module using
450  // it is a one module and declares a shared resource and all
451  // other modules using it also declare the same shared resource.
452  // This also breaks replay.
453  double d = GetRandom(histo_, randomEngine(streamID));
454  PileupSelection.push_back(int(d));
455  TrueNumInteractions.push_back( d );
456  }
457  }
458 
459  }
460  }
461 
462 
463 } //namespace edm
#define LogDebug(id)
bool manage_OOT_
Definition: PileUp.h:96
T getParameter(std::string const &) const
T getUntrackedParameter(std::string const &, T const &) const
std::string getPassID()
Definition: GetPassID.h:8
int i
Definition: DBlmapReader.cc:9
std::unique_ptr< SecondaryEventProvider > provider_
Definition: PileUp.h:117
bool existsAs(std::string const &parameterName, bool trackiness=true) const
checks if a parameter exists as a given type
Definition: ParameterSet.h:186
std::shared_ptr< ProcessConfiguration > processConfiguration_
Definition: PileUp.h:113
unsigned int inputType_
Definition: PileUp.h:85
const int fixedOutOfTime() const
tuple lumi
Definition: fjr2json.py:35
bool exists(std::string const &parameterName) const
checks if a parameter exists
static Double_t GetRandom(TH1 *th1, CLHEP::HepRandomEngine *rng)
Definition: PileUp.cc:45
void endJob()
Definition: PileUp.cc:194
TH1F * histo_
Definition: PileUp.h:90
bool fixed_
Definition: PileUp.h:94
const std::vector< double > & probValue() const
PileUp(ParameterSet const &pset, std::string sourcename, double averageNumber, TH1F *const histo, const bool playback)
Definition: PileUp.cc:64
const double averageNumber() const
ModuleCallingContext const * moduleCallingContext() const
std::vector< CLHEP::HepRandomEngine * > randomEngines_
Definition: PileUp.h:120
int const intAverage_
Definition: PileUp.h:89
bool probFunctionDistribution_
Definition: PileUp.h:92
int maxBunch_cosmics_
Definition: PileUp.h:108
std::string Study_type_
Definition: PileUp.h:101
tuple d
Definition: ztail.py:151
bool histoDistribution_
Definition: PileUp.h:91
bool poisson_
Definition: PileUp.h:93
void endLuminosityBlock(const edm::LuminosityBlock &lumi, const edm::EventSetup &setup)
Definition: PileUp.cc:222
T x() const
Cartesian x coordinate.
double averageNumber() const
Definition: PileUp.h:44
const int outOfTime() const
std::vector< std::unique_ptr< CLHEP::RandPoissonQ > > vPoissonDistribution_
Definition: PileUp.h:118
std::unique_ptr< VectorInputSource > const input_
Definition: PileUp.h:112
bool poisson_OOT_
Definition: PileUp.h:97
void beginJob()
Definition: PileUp.cc:187
tuple averageNumber
set the number of pileup
bool isAvailable() const
Definition: Service.h:46
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
int j
Definition: DBlmapReader.cc:9
int intFixed_ITPU_
Definition: PileUp.h:105
void beginRun(const edm::Run &run, const edm::EventSetup &setup)
Definition: PileUp.cc:201
std::unique_ptr< CLHEP::RandPoissonQ > const & poissonDistribution(StreamID const &streamID)
Definition: PileUp.cc:335
void CalculatePileup(int MinBunch, int MaxBunch, std::vector< int > &PileupSelection, std::vector< float > &TrueNumInteractions, StreamID const &)
Definition: PileUp.cc:381
bool PU_Study_
Definition: PileUp.h:100
void beginLuminosityBlock(const edm::LuminosityBlock &lumi, const edm::EventSetup &setup)
Definition: PileUp.cc:208
bool fixed_OOT_
Definition: PileUp.h:98
int minBunch_cosmics_
Definition: PileUp.h:107
Integral< F, X >::type integral(const F &f)
Definition: Integral.h:69
std::string getReleaseVersion()
void setupPileUpEvent(const edm::EventSetup &setup)
Definition: PileUp.cc:228
unsigned int value() const
Definition: StreamID.h:46
std::shared_ptr< LuminosityBlockPrincipal > lumiPrincipal_
Definition: PileUp.h:115
std::string type_
Definition: PileUp.h:86
LuminosityBlockAuxiliary const & luminosityBlockAuxiliary() const
const T & get() const
Definition: EventSetup.h:56
void endRun(const edm::Run &run, const edm::EventSetup &setup)
Definition: PileUp.cc:217
const std::vector< int > & probFunctionVariable() const
RunAuxiliary const & runAuxiliary() const
Definition: Run.h:60
std::shared_ptr< ProductRegistry > productRegistry_
Definition: PileUp.h:111
std::string Source_type_
Definition: PileUp.h:87
std::unique_ptr< CLHEP::RandPoisson > const & poissonDistr_OOT(StreamID const &streamID)
Definition: PileUp.cc:350
void reload(const edm::EventSetup &setup)
Definition: PileUp.cc:237
ModuleCallingContext const * moduleCallingContext() const
Definition: Run.h:148
bool none_
Definition: PileUp.h:95
CLHEP::HepRandomEngine * randomEngine(StreamID const &streamID)
Definition: PileUp.cc:365
std::vector< std::unique_ptr< CLHEP::RandPoisson > > vPoissonDistr_OOT_
Definition: PileUp.h:119
int intFixed_OOT_
Definition: PileUp.h:104
volatile std::atomic< bool > shutdown_flag false
std::unique_ptr< EventPrincipal > eventPrincipal_
Definition: PileUp.h:114
std::string type() const
std::shared_ptr< RunPrincipal > runPrincipal_
Definition: PileUp.h:116
static ParameterSetID emptyParameterSetID()
void setup(std::vector< TH2F > &depth, std::string name, std::string units="")
T get(const Candidate &c)
Definition: component.h:55
double averageNumber_
Definition: PileUp.h:88
Definition: Run.h:43