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