CMS 3D CMS Logo

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