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 
32 namespace edm {
33  PileUp::PileUp(ParameterSet const& pset, std::string sourcename, double averageNumber, TH1F * const histo, const bool playback) :
34  type_(pset.getParameter<std::string>("type")),
35  Source_type_(sourcename),
36  averageNumber_(averageNumber),
37  intAverage_(static_cast<int>(averageNumber)),
38  histo_(histo),
39  histoDistribution_(type_ == "histo"),
40  probFunctionDistribution_(type_ == "probFunction"),
41  poisson_(type_ == "poisson"),
42  fixed_(type_ == "fixed"),
43  none_(type_ == "none"),
44  productRegistry_(new SignallingProductRegistry),
45  input_(VectorInputSourceFactory::get()->makeVectorInputSource(pset, InputSourceDescription(
47  *productRegistry_,
48  std::make_shared<BranchIDListHelper>(),
49  std::make_shared<ThinnedAssociationsHelper>(),
50  std::make_shared<ActivityRegistry>(),
51  -1, -1, -1,
53  )).release()),
54  processConfiguration_(new ProcessConfiguration(std::string("@MIXING"), getReleaseVersion(), getPassID())),
55  eventPrincipal_(),
56  lumiPrincipal_(),
57  runPrincipal_(),
58  provider_(),
59  vPoissonDistribution_(),
60  vPoissonDistr_OOT_(),
61  randomEngines_(),
62  playback_(playback),
63  sequential_(pset.getUntrackedParameter<bool>("sequential", false)),
64  samelumi_(pset.getUntrackedParameter<bool>("sameLumiBlock", false)),
65  seed_(0) {
66 
67  // Use the empty parameter set for the parameter set ID of our "@MIXING" process.
69 
70  if(pset.existsAs<std::vector<ParameterSet> >("producers", true)) {
71  std::vector<ParameterSet> producers = pset.getParameter<std::vector<ParameterSet> >("producers");
73  }
74 
75  productRegistry_->setFrozen();
76 
77  // A modified HistoryAppender must be used for unscheduled processing.
78  eventPrincipal_.reset(new EventPrincipal(input_->productRegistry(),
79  input_->branchIDListHelper(),
80  input_->thinnedAssociationsHelper(),
82  nullptr));
83 
84  if (pset.exists("nbPileupEvents")) {
85  seed_=pset.getParameter<edm::ParameterSet>("nbPileupEvents").getUntrackedParameter<int>("seed",0);
86  }
87 
88  bool DB=type_=="readDB";
89 
91  if (!rng.isAvailable()) {
92  throw cms::Exception("Configuration")
93  << "PileUp requires the RandomNumberGeneratorService\n"
94  "which is not present in the configuration file. You must add the service\n"
95  "in the configuration file or remove the modules that require it.";
96  }
97 
98  // Get seed for the case when using user histogram or probability function
99  // RANDOM_NUMBER_ERROR
100  // Random number should be generated by the engines from the
101  // RandomNumberGeneratorService. This appears to use the global
102  // engine in ROOT. This is not thread safe unless the module using
103  // it is a one module and declares a shared resource and all
104  // other modules using it also declare the same shared resource.
105  // This also breaks replay.
107  if(seed_ !=0) {
108  gRandom->SetSeed(seed_);
109  LogInfo("MixingModule") << " Change seed for " << type_ << " mode. The seed is set to " << seed_;
110  }
111  else {
112  gRandom->SetSeed(rng->mySeed());
113  }
114  }
115 
117  throw cms::Exception("Illegal parameter value","PileUp::PileUp(ParameterSet const& pset)")
118  << "'type' parameter (a string) has a value of '" << type_ << "'.\n"
119  << "Legal values are 'poisson', 'fixed', or 'none'\n";
120  }
121 
122  if (!DB){
123  manage_OOT_ = pset.getUntrackedParameter<bool>("manage_OOT", false);
124 
125  // Check for string describing special processing. Add these here for individual cases
126 
127  PU_Study_ = false;
128  Study_type_ = "";
129 
130  Study_type_ = pset.getUntrackedParameter<std::string>("Special_Pileup_Studies", "");
131 
132  if(Study_type_ == "Fixed_ITPU_Vary_OOTPU") {
133 
134  PU_Study_ = true;
135  intFixed_ITPU_ = pset.getUntrackedParameter<int>("intFixed_ITPU", 0);
136 
137  }
138 
139  if(manage_OOT_) { // figure out what the parameters are
140 
141  // if (playback_) throw cms::Exception("Illegal parameter clash","PileUp::PileUp(ParameterSet const& pset)")
142  // << " manage_OOT option not allowed with playback ";
143 
144  std::string OOT_type = pset.getUntrackedParameter<std::string>("OOT_type");
145 
146  if(OOT_type == "Poisson" || OOT_type == "poisson") {
147  poisson_OOT_ = true;
148  }
149  else if(OOT_type == "Fixed" || OOT_type == "fixed") {
150  fixed_OOT_ = true;
151  // read back the fixed number requested out-of-time
152  intFixed_OOT_ = pset.getUntrackedParameter<int>("intFixed_OOT", -1);
153  if(intFixed_OOT_ < 0) {
154  throw cms::Exception("Illegal parameter value","PileUp::PileUp(ParameterSet const& pset)")
155  << " Fixed out-of-time pileup requested, but no fixed value given ";
156  }
157  }
158  else {
159  throw cms::Exception("Illegal parameter value","PileUp::PileUp(ParameterSet const& pset)")
160  << "'OOT_type' parameter (a string) has a value of '" << OOT_type << "'.\n"
161  << "Legal values are 'poisson' or 'fixed'\n";
162  }
163  edm::LogInfo("MixingModule") <<" Out-of-time pileup will be generated with a " << OOT_type << " distribution. " ;
164  }
165  }
166 
167  if(Source_type_ == "cosmics") { // allow for some extra flexibility for mixing
168  minBunch_cosmics_ = pset.getUntrackedParameter<int>("minBunch_cosmics", -1000);
169  maxBunch_cosmics_ = pset.getUntrackedParameter<int>("maxBunch_cosmics", 1000);
170  }
171 
172 
173 
174  } // end of constructor
175 
176 
177 
178 
179 
181  input_->doBeginJob();
182  if (provider_.get() != nullptr) {
183  provider_->beginJob(*productRegistry_);
184  }
185  }
186 
187  void PileUp::endJob () {
188  if (provider_.get() != nullptr) {
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());
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());
207  }
208  }
209 
211  if (provider_.get() != nullptr) {
212  provider_->endRun(*runPrincipal_, setup, run.moduleCallingContext());
213  }
214  }
216  if (provider_.get() != nullptr) {
217  provider_->endLuminosityBlock(*lumiPrincipal_, setup, lumi.moduleCallingContext());
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);
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();
254  for(auto & distribution : vPoissonDistribution_) {
255  if(distribution) {
256  distribution.reset(new CLHEP::RandPoissonQ(distribution->engine(), averageNumber_));
257  }
258  }
259  }
260  else if (probFunctionDistribution_)
261  {
262  //need to reload the histogram from DB
263  const std::vector<int> & dataProbFunctionVar = config.probFunctionVariable();
264  std::vector<double> dataProb = config.probValue();
265 
266  int varSize = (int) dataProbFunctionVar.size();
267  int probSize = (int) dataProb.size();
268 
269  if ((dataProbFunctionVar[0] != 0) || (dataProbFunctionVar[varSize - 1] != (varSize - 1)))
270  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;
271 
272  // Complete the vector containing the probability function data
273  // with the values "0"
274  if (probSize < varSize){
275  edm::LogWarning("MixingModule") << " The probability function data will be completed with " <<(varSize - probSize) <<" values 0.";
276 
277  for (int i=0; i<(varSize - probSize); i++) dataProb.push_back(0);
278 
279  probSize = dataProb.size();
280  edm::LogInfo("MixingModule") << " The number of the P(x) data set after adding the values 0 is " << probSize;
281  }
282 
283  // Create an histogram with the data from the probability function provided by the user
284  int xmin = (int) dataProbFunctionVar[0];
285  int xmax = (int) dataProbFunctionVar[varSize-1]+1; // need upper edge to be one beyond last value
286  int numBins = varSize;
287 
288  edm::LogInfo("MixingModule") << "An histogram will be created with " << numBins << " bins in the range ("<< xmin << "," << xmax << ")." << std::endl;
289 
290  if (histo_) delete histo_;
291  histo_ = new TH1F("h","Histo from the user's probability function",numBins,xmin,xmax);
292 
293  LogDebug("MixingModule") << "Filling histogram with the following data:" << std::endl;
294 
295  for (int j=0; j < numBins ; j++){
296  LogDebug("MixingModule") << " x = " << dataProbFunctionVar[j ]<< " P(x) = " << dataProb[j];
297  histo_->Fill(dataProbFunctionVar[j]+0.5,dataProb[j]); // assuming integer values for the bins, fill bin centers, not edges
298  }
299 
300  // Check if the histogram is normalized
301  if ( ((histo_->Integral() - 1) > 1.0e-02) && ((histo_->Integral() - 1) < -1.0e-02)){
302  throw cms::Exception("BadProbFunction") << "The probability function should be normalized!!! " << std::endl;
303  }
304  averageNumber_=histo_->GetMean();
305  }
306 
307  int oot=config.outOfTime();
308  manage_OOT_=false;
309  if (oot==1)
310  {
311  manage_OOT_=true;
312  poisson_OOT_ = false;
313  fixed_OOT_ = true;
314  intFixed_OOT_=config.fixedOutOfTime();
315  }
316  else if (oot==2)
317  {
318  manage_OOT_=true;
319  poisson_OOT_ = true;
320  fixed_OOT_ = false;
321  }
322 
323 
324  }
326  }
327 
328  std::unique_ptr<CLHEP::RandPoissonQ> const& PileUp::poissonDistribution(StreamID const& streamID) {
329  unsigned int index = streamID.value();
330  if(index >= vPoissonDistribution_.size()) {
331  // This resizing is not thread safe and only works because
332  // this is used by a "one" type module
333  vPoissonDistribution_.resize(index + 1);
334  }
335  std::unique_ptr<CLHEP::RandPoissonQ>& ptr = vPoissonDistribution_[index];
336  if(!ptr) {
337  CLHEP::HepRandomEngine& engine = *randomEngine(streamID);
338  ptr.reset(new CLHEP::RandPoissonQ(engine, averageNumber_));
339  }
340  return ptr;
341  }
342 
343  std::unique_ptr<CLHEP::RandPoisson> const& PileUp::poissonDistr_OOT(StreamID const& streamID) {
344  unsigned int index = streamID.value();
345  if(index >= vPoissonDistr_OOT_.size()) {
346  // This resizing is not thread safe and only works because
347  // this is used by a "one" type module
348  vPoissonDistr_OOT_.resize(index + 1);
349  }
350  std::unique_ptr<CLHEP::RandPoisson>& ptr = vPoissonDistr_OOT_[index];
351  if(!ptr) {
352  CLHEP::HepRandomEngine& engine = *randomEngine(streamID);
353  ptr.reset(new CLHEP::RandPoisson(engine));
354  }
355  return ptr;
356  }
357 
358  CLHEP::HepRandomEngine* PileUp::randomEngine(StreamID const& streamID) {
359  unsigned int index = streamID.value();
360  if(index >= randomEngines_.size()) {
361  // This resizing is not thread safe and only works because
362  // this is used by a "one" type module
363  randomEngines_.resize(index + 1, nullptr);
364  }
365  CLHEP::HepRandomEngine* ptr = randomEngines_[index];
366  if(!ptr) {
368  ptr = &rng->getEngine(streamID);
369  randomEngines_[index] = ptr;
370  }
371  return ptr;
372  }
373 
374  void PileUp::CalculatePileup(int MinBunch, int MaxBunch, std::vector<int>& PileupSelection, std::vector<float>& TrueNumInteractions, StreamID const& streamID) {
375 
376  // if we are managing the distribution of out-of-time pileup separately, select the distribution for bunch
377  // crossing zero first, save it for later.
378 
379  int nzero_crossing = -1;
380  double Fnzero_crossing = -1;
381 
382  if(manage_OOT_) {
383  if (none_){
384  nzero_crossing = 0;
385  }else if (poisson_){
386  nzero_crossing = poissonDistribution(streamID)->fire() ;
387  }else if (fixed_){
388  nzero_crossing = intAverage_ ;
390  // RANDOM_NUMBER_ERROR
391  // Random number should be generated by the engines from the
392  // RandomNumberGeneratorService. This appears to use the global
393  // engine in ROOT. This is not thread safe unless the module using
394  // it is a one module and declares a shared resource and all
395  // other modules using it also declare the same shared resource.
396  // This also breaks replay.
397  double d = histo_->GetRandom();
398  //n = (int) floor(d + 0.5); // incorrect for bins with integer edges
399  Fnzero_crossing = d;
400  nzero_crossing = int(d);
401  }
402 
403  }
404 
405  for(int bx = MinBunch; bx < MaxBunch+1; ++bx) {
406 
407  if(manage_OOT_) {
408  if(bx==0 && !poisson_OOT_) {
409  PileupSelection.push_back(nzero_crossing) ;
410  TrueNumInteractions.push_back( nzero_crossing );
411  }
412  else{
413  if(poisson_OOT_) {
414  if(PU_Study_ && (Study_type_ == "Fixed_ITPU_Vary_OOTPU" ) && bx==0 ) {
415  PileupSelection.push_back(intFixed_ITPU_) ;
416  }
417  else{
418  PileupSelection.push_back(poissonDistr_OOT(streamID)->fire(Fnzero_crossing)) ;
419  }
420  TrueNumInteractions.push_back( Fnzero_crossing );
421  }
422  else {
423  PileupSelection.push_back(intFixed_OOT_) ;
424  TrueNumInteractions.push_back( intFixed_OOT_ );
425  }
426  }
427  }
428  else {
429  if (none_){
430  PileupSelection.push_back(0);
431  TrueNumInteractions.push_back( 0. );
432  }else if (poisson_){
433  PileupSelection.push_back(poissonDistribution(streamID)->fire());
434  TrueNumInteractions.push_back( averageNumber_ );
435  }else if (fixed_){
436  PileupSelection.push_back(intAverage_);
437  TrueNumInteractions.push_back( intAverage_ );
439  // RANDOM_NUMBER_ERROR
440  // Random number should be generated by the engines from the
441  // RandomNumberGeneratorService. This appears to use the global
442  // engine in ROOT. This is not thread safe unless the module using
443  // it is a one module and declares a shared resource and all
444  // other modules using it also declare the same shared resource.
445  // This also breaks replay.
446  double d = histo_->GetRandom();
447  PileupSelection.push_back(int(d));
448  TrueNumInteractions.push_back( d );
449  }
450  }
451 
452  }
453  }
454 
455 
456 } //namespace edm
#define LogDebug(id)
bool manage_OOT_
Definition: PileUp.h:93
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:113
bool existsAs(std::string const &parameterName, bool trackiness=true) const
checks if a parameter exists as a given type
Definition: ParameterSet.h:184
std::shared_ptr< ProcessConfiguration > processConfiguration_
Definition: PileUp.h:109
unsigned int inputType_
Definition: PileUp.h:82
const int fixedOutOfTime() const
tuple lumi
Definition: fjr2json.py:35
bool exists(std::string const &parameterName) const
checks if a parameter exists
void endJob()
Definition: PileUp.cc:187
TH1F * histo_
Definition: PileUp.h:87
bool fixed_
Definition: PileUp.h:91
const std::vector< double > & probValue() const
PileUp(ParameterSet const &pset, std::string sourcename, double averageNumber, TH1F *const histo, const bool playback)
Definition: PileUp.cc:33
const double averageNumber() const
ModuleCallingContext const * moduleCallingContext() const
std::vector< CLHEP::HepRandomEngine * > randomEngines_
Definition: PileUp.h:116
int const intAverage_
Definition: PileUp.h:86
bool probFunctionDistribution_
Definition: PileUp.h:89
int maxBunch_cosmics_
Definition: PileUp.h:105
std::string Study_type_
Definition: PileUp.h:98
bool histoDistribution_
Definition: PileUp.h:88
bool poisson_
Definition: PileUp.h:90
void endLuminosityBlock(const edm::LuminosityBlock &lumi, const edm::EventSetup &setup)
Definition: PileUp.cc:215
double averageNumber() const
Definition: PileUp.h:41
const int outOfTime() const
virtual std::uint32_t mySeed() const =0
std::vector< std::unique_ptr< CLHEP::RandPoissonQ > > vPoissonDistribution_
Definition: PileUp.h:114
std::unique_ptr< VectorInputSource > const input_
Definition: PileUp.h:108
bool poisson_OOT_
Definition: PileUp.h:94
void beginJob()
Definition: PileUp.cc:180
tuple averageNumber
set the number of pileup
bool isAvailable() const
Definition: Service.h:46
int j
Definition: DBlmapReader.cc:9
int intFixed_ITPU_
Definition: PileUp.h:102
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:328
void CalculatePileup(int MinBunch, int MaxBunch, std::vector< int > &PileupSelection, std::vector< float > &TrueNumInteractions, StreamID const &)
Definition: PileUp.cc:374
bool PU_Study_
Definition: PileUp.h:97
void beginLuminosityBlock(const edm::LuminosityBlock &lumi, const edm::EventSetup &setup)
Definition: PileUp.cc:201
bool fixed_OOT_
Definition: PileUp.h:95
int minBunch_cosmics_
Definition: PileUp.h:104
std::string getReleaseVersion()
void setupPileUpEvent(const edm::EventSetup &setup)
Definition: PileUp.cc:221
unsigned int value() const
Definition: StreamID.h:46
std::shared_ptr< LuminosityBlockPrincipal > lumiPrincipal_
Definition: PileUp.h:111
std::string type_
Definition: PileUp.h:83
LuminosityBlockAuxiliary const & luminosityBlockAuxiliary() const
const T & get() const
Definition: EventSetup.h:55
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:55
std::shared_ptr< ProductRegistry > productRegistry_
Definition: PileUp.h:107
std::string Source_type_
Definition: PileUp.h:84
std::unique_ptr< CLHEP::RandPoisson > const & poissonDistr_OOT(StreamID const &streamID)
Definition: PileUp.cc:343
void reload(const edm::EventSetup &setup)
Definition: PileUp.cc:230
int seed_
Definition: PileUp.h:132
ModuleCallingContext const * moduleCallingContext() const
Definition: Run.h:143
bool none_
Definition: PileUp.h:92
CLHEP::HepRandomEngine * randomEngine(StreamID const &streamID)
Definition: PileUp.cc:358
tuple playback
Definition: Playback_cff.py:20
std::vector< std::unique_ptr< CLHEP::RandPoisson > > vPoissonDistr_OOT_
Definition: PileUp.h:115
int intFixed_OOT_
Definition: PileUp.h:101
volatile std::atomic< bool > shutdown_flag false
std::unique_ptr< EventPrincipal > eventPrincipal_
Definition: PileUp.h:110
std::string type() const
std::shared_ptr< RunPrincipal > runPrincipal_
Definition: PileUp.h:112
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:85
Definition: Run.h:41