CMS 3D CMS Logo

GenXSecAnalyzer.cc
Go to the documentation of this file.
2 #include "TMath.h"
3 #include <iostream>
4 #include <iomanip>
5 
6 // analyzer of a summary information product on filter efficiency for a user specified path
7 // meant for the generator filter efficiency calculation
8 
9 // system include files
10 #include <memory>
11 #include <vector>
12 #include <map>
13 
14 // user include files
17 
28 
30 
31 //
32 // class declaration
33 //
34 namespace gxsec {
35  struct LumiCache {};
36  struct RunCache {
38  : product_(-9999),
39  filterOnlyEffRun_(0, 0, 0, 0, 0., 0., 0., 0.),
40  hepMCFilterEffRun_(0, 0, 0, 0, 0., 0., 0., 0.) {}
41  // for weight before GenFilter and HepMCFilter and before matching
43 
44  // for weight after GenFilter and HepMCFilter and after matching
46 
47  // GenLumiInfo before HepMCFilter and GenFilter, this is used
48  // for computation
50 
51  // statistics from additional generator filter, for computation
52  // reset for each run
54 
55  // statistics from HepMC filter, for computation
57 
58  // the following vectors all have the same size
59  // LHE or Pythia/Herwig cross section of previous luminosity block
60  // vector size = number of processes, used for computation
61  CMS_THREAD_GUARD(GenXSecAnalyzer::mutex_) mutable std::map<int, GenLumiInfoProduct::XSec> previousLumiBlockLHEXSec_;
62 
63  // LHE or Pythia/Herwig combined cross section of current luminosity block
64  // updated for each luminosity block, initialized in every run
65  // used for computation
66  CMS_THREAD_GUARD(GenXSecAnalyzer::mutex_) mutable std::map<int, GenLumiInfoProduct::XSec> currentLumiBlockLHEXSec_;
67  };
68 } // namespace gxsec
69 
71  : public edm::global::EDAnalyzer<edm::RunCache<gxsec::RunCache>, edm::LuminosityBlockCache<gxsec::LumiCache>> {
72 public:
73  explicit GenXSecAnalyzer(const edm::ParameterSet &);
74  ~GenXSecAnalyzer() override;
75 
76 private:
77  void beginJob() final;
78  std::shared_ptr<gxsec::RunCache> globalBeginRun(edm::Run const &, edm::EventSetup const &) const final;
79  std::shared_ptr<gxsec::LumiCache> globalBeginLuminosityBlock(edm::LuminosityBlock const &,
80  edm::EventSetup const &) const final;
81  void analyze(edm::StreamID, const edm::Event &, const edm::EventSetup &) const final;
82  void globalEndLuminosityBlock(edm::LuminosityBlock const &, edm::EventSetup const &) const final;
83  void globalEndRun(edm::Run const &, edm::EventSetup const &) const final;
84  void endJob() final;
85  // computation of cross section after matching and before HepcFilter and GenFilter
87  // combination of cross section from different MCs after matching (could be either before or after HepcFilter and GenFilter)
88  void combine(GenLumiInfoProduct::XSec &, double &, const GenLumiInfoProduct::XSec &, const double &) const;
89  void combine(double &, double &, double &, const double &, const double &, const double &) const;
90 
95 
96  // ----------member data --------------------------
97 
98  mutable std::atomic<int> nMCs_;
99 
100  mutable std::atomic<int> hepidwtup_;
101 
103 
104  // for weight before GenFilter and HepMCFilter and before matching
106 
107  // for weight after GenFilter and HepMCFilter and after matching
109 
110  // combined cross sections before HepMCFilter and GenFilter
112 
113  // final combined cross sections
115 
116  // statistics from additional generator filter, for print-out only
118 
119  // statistics from HepMC filter, for print-out only
121 
122  // the vector/map size is the number of LHE processes + 1
123  // needed only for printouts, not used for computation
124  // only printed out when combining the same physics process
125  // uncertainty-averaged cross sections before matching
126  CMS_THREAD_GUARD(mutex_) mutable std::vector<GenLumiInfoProduct::XSec> xsecBeforeMatching_;
127  // uncertainty-averaged cross sections after matching
128  CMS_THREAD_GUARD(mutex_) mutable std::vector<GenLumiInfoProduct::XSec> xsecAfterMatching_;
129  // statistics from jet matching
130  CMS_THREAD_GUARD(mutex_) mutable std::map<int, GenFilterInfo> jetMatchEffStat_;
131 };
132 
134  : nMCs_(0),
135  hepidwtup_(-9999),
136  totalWeightPre_(0),
137  totalWeight_(0),
138  xsecPreFilter_(-1, -1),
139  xsec_(-1, -1),
140  filterOnlyEffStat_(0, 0, 0, 0, 0., 0., 0., 0.),
141  hepMCFilterEffStat_(0, 0, 0, 0, 0., 0., 0., 0.) {
142  genFilterInfoToken_ = consumes<GenFilterInfo, edm::InLumi>(edm::InputTag("genFilterEfficiencyProducer", ""));
143  hepMCFilterInfoToken_ = consumes<GenFilterInfo, edm::InLumi>(edm::InputTag("generator", ""));
144  genLumiInfoToken_ = consumes<GenLumiInfoProduct, edm::InLumi>(edm::InputTag("generator", ""));
145  lheRunInfoToken_ = consumes<LHERunInfoProduct, edm::InRun>(edm::InputTag("externalLHEProducer", ""));
146 }
147 
149 
151 
152 std::shared_ptr<gxsec::RunCache> GenXSecAnalyzer::globalBeginRun(edm::Run const &iRun, edm::EventSetup const &) const {
153  // initialization for every different physics MC
154 
155  nMCs_++;
156 
157  {
158  std::lock_guard l{mutex_};
159  xsecBeforeMatching_.clear();
160  xsecAfterMatching_.clear();
161  jetMatchEffStat_.clear();
162  }
163  return std::make_shared<gxsec::RunCache>();
164 }
165 
166 std::shared_ptr<gxsec::LumiCache> GenXSecAnalyzer::globalBeginLuminosityBlock(edm::LuminosityBlock const &iLumi,
167  edm::EventSetup const &) const {
168  return std::shared_ptr<gxsec::LumiCache>();
169 }
170 
172 
176  if (!genLumiInfo.isValid())
177  return;
178  hepidwtup_ = genLumiInfo->getHEPIDWTUP();
179 
180  std::vector<GenLumiInfoProduct::ProcessInfo> const &theProcesses = genLumiInfo->getProcessInfos();
181 
182  unsigned int theProcesses_size = theProcesses.size();
183 
184  // if it's a pure parton-shower generator, check there should be only one element in thisProcessInfos
185  // the error of lheXSec is -1
186  if (hepidwtup_ == -1) {
187  if (theProcesses_size != 1) {
188  edm::LogError("GenXSecAnalyzer::endLuminosityBlock") << "Pure parton shower has thisProcessInfos size!=1";
189  return;
190  }
191  }
192 
193  for (unsigned int ip = 0; ip < theProcesses_size; ip++) {
194  if (theProcesses[ip].lheXSec().value() < 0) {
195  edm::LogError("GenXSecAnalyzer::endLuminosityBlock")
196  << "cross section of process " << ip << " value = " << theProcesses[ip].lheXSec().value();
197  return;
198  }
199  }
200 
201  auto runC = runCache(iLumi.getRun().index());
202  {
203  std::lock_guard g{mutex_};
204  runC->product_.mergeProduct(*genLumiInfo);
205  }
206  edm::Handle<GenFilterInfo> genFilter;
207  iLumi.getByToken(genFilterInfoToken_, genFilter);
208 
209  if (genFilter.isValid()) {
210  std::lock_guard g{mutex_};
211  filterOnlyEffStat_.mergeProduct(*genFilter);
212  runC->filterOnlyEffRun_.mergeProduct(*genFilter);
213  runC->thisRunWeight_ += genFilter->sumPassWeights();
214  }
215 
216  edm::Handle<GenFilterInfo> hepMCFilter;
217  iLumi.getByToken(hepMCFilterInfoToken_, hepMCFilter);
218 
219  if (hepMCFilter.isValid()) {
220  std::lock_guard g{mutex_};
221  hepMCFilterEffStat_.mergeProduct(*hepMCFilter);
222  runC->hepMCFilterEffRun_.mergeProduct(*hepMCFilter);
223  }
224 
225  std::lock_guard g{mutex_};
226  // doing generic summing for jet matching statistics
227  // and computation of combined LHE information
228  for (unsigned int ip = 0; ip < theProcesses_size; ip++) {
229  int id = theProcesses[ip].process();
231  GenLumiInfoProduct::XSec &y = runC->currentLumiBlockLHEXSec_[id];
232  GenLumiInfoProduct::FinalStat temp_killed = theProcesses[ip].killed();
233  GenLumiInfoProduct::FinalStat temp_selected = theProcesses[ip].selected();
234  double passw = temp_killed.sum();
235  double passw2 = temp_killed.sum2();
236  double totalw = temp_selected.sum();
237  double totalw2 = temp_selected.sum2();
238  GenFilterInfo tempInfo(theProcesses[ip].nPassPos(),
239  theProcesses[ip].nPassNeg(),
240  theProcesses[ip].nTotalPos(),
241  theProcesses[ip].nTotalNeg(),
242  passw,
243  passw2,
244  totalw,
245  totalw2);
246 
247  // matching statistics for all processes
248  jetMatchEffStat_[10000].mergeProduct(tempInfo);
249  double currentValue = theProcesses[ip].lheXSec().value();
250  double currentError = theProcesses[ip].lheXSec().error();
251 
252  // this process ID has occurred before
253  auto &thisRunWeightPre = runC->thisRunWeightPre_;
254  if (y.value() > 0) {
255  x.mergeProduct(tempInfo);
256  double previousValue = runC->previousLumiBlockLHEXSec_[id].value();
257 
258  if (currentValue != previousValue) // transition of cross section
259  {
260  double xsec = y.value();
261  double err = y.error();
262  combine(xsec, err, thisRunWeightPre, currentValue, currentError, totalw);
263  y = GenLumiInfoProduct::XSec(xsec, err);
264  } else // LHE cross section is the same as previous lumiblock
265  thisRunWeightPre += totalw;
266 
267  }
268  // this process ID has never occurred before
269  else {
270  x = tempInfo;
271  y = theProcesses[ip].lheXSec();
272  thisRunWeightPre += totalw;
273  }
274 
275  runC->previousLumiBlockLHEXSec_[id] = theProcesses[ip].lheXSec();
276  } // end
277 
278  return;
279 }
280 
281 void GenXSecAnalyzer::globalEndRun(edm::Run const &iRun, edm::EventSetup const &) const {
282  //xsection before matching
284 
285  if (iRun.getByToken(lheRunInfoToken_, run)) {
286  const lhef::HEPRUP thisHeprup = run->heprup();
287 
288  for (unsigned int iSize = 0; iSize < thisHeprup.XSECUP.size(); iSize++) {
289  std::cout << std::setw(14) << std::fixed << thisHeprup.XSECUP[iSize] << std::setw(14) << std::fixed
290  << thisHeprup.XERRUP[iSize] << std::setw(14) << std::fixed << thisHeprup.XMAXUP[iSize] << std::setw(14)
291  << std::fixed << thisHeprup.LPRUP[iSize] << std::endl;
292  }
293  std::cout << " " << std::endl;
294  }
295 
296  auto runC = runCache(iRun.index());
297  std::lock_guard l{mutex_};
298 
299  // compute cross section for this run first
300  // set the correct combined LHE+filter cross sections
301  unsigned int i = 0;
302  std::vector<GenLumiInfoProduct::ProcessInfo> newInfos;
303  for (std::map<int, GenLumiInfoProduct::XSec>::const_iterator iter = runC->currentLumiBlockLHEXSec_.begin();
304  iter != runC->currentLumiBlockLHEXSec_.end();
305  ++iter, i++) {
306  GenLumiInfoProduct::ProcessInfo temp = runC->product_.getProcessInfos()[i];
307  temp.setLheXSec(iter->second.value(), iter->second.error());
308  newInfos.push_back(temp);
309  }
310  runC->product_.setProcessInfo(newInfos);
311 
312  const GenLumiInfoProduct::XSec thisRunXSecPre = compute(runC->product_);
313  // xsection after matching before filters
314  combine(xsecPreFilter_, totalWeightPre_, thisRunXSecPre, runC->thisRunWeightPre_);
315 
316  double thisHepFilterEff = 1;
317  double thisHepFilterErr = 0;
318 
319  if (runC->hepMCFilterEffRun_.sumWeights2() > 0) {
320  thisHepFilterEff = runC->hepMCFilterEffRun_.filterEfficiency(hepidwtup_);
321  thisHepFilterErr = runC->hepMCFilterEffRun_.filterEfficiencyError(hepidwtup_);
322  if (thisHepFilterEff < 0) {
323  thisHepFilterEff = 1;
324  thisHepFilterErr = 0;
325  }
326  }
327 
328  double thisGenFilterEff = 1;
329  double thisGenFilterErr = 0;
330 
331  if (runC->filterOnlyEffRun_.sumWeights2() > 0) {
332  thisGenFilterEff = runC->filterOnlyEffRun_.filterEfficiency(hepidwtup_);
333  thisGenFilterErr = runC->filterOnlyEffRun_.filterEfficiencyError(hepidwtup_);
334  if (thisGenFilterEff < 0) {
335  thisGenFilterEff = 1;
336  thisGenFilterErr = 0;
337  }
338  }
339  double thisXsec = thisRunXSecPre.value() > 0 ? thisHepFilterEff * thisGenFilterEff * thisRunXSecPre.value() : 0;
340  double thisErr =
341  thisRunXSecPre.value() > 0
342  ? thisXsec * sqrt(pow(TMath::Max(thisRunXSecPre.error(), (double)0) / thisRunXSecPre.value(), 2) +
343  pow(thisHepFilterErr / thisHepFilterEff, 2) + pow(thisGenFilterErr / thisGenFilterEff, 2))
344  : 0;
345  const GenLumiInfoProduct::XSec thisRunXSec = GenLumiInfoProduct::XSec(thisXsec, thisErr);
346  combine(xsec_, totalWeight_, thisRunXSec, runC->thisRunWeight_);
347 }
348 
349 void GenXSecAnalyzer::combine(double &finalValue,
350  double &finalError,
351  double &finalWeight,
352  const double &currentValue,
353  const double &currentError,
354  const double &currentWeight) const {
355  if (finalValue <= 0) {
356  finalValue = currentValue;
357  finalError = currentError;
358  finalWeight += currentWeight;
359  } else {
360  double wgt1 = (finalError <= 0 || currentError <= 0) ? finalWeight : 1 / (finalError * finalError);
361  double wgt2 = (finalError <= 0 || currentError <= 0) ? currentWeight : 1 / (currentError * currentError);
362  double xsec = (wgt1 * finalValue + wgt2 * currentValue) / (wgt1 + wgt2);
363  double err = (finalError <= 0 || currentError <= 0) ? 0 : 1.0 / std::sqrt(wgt1 + wgt2);
364  finalValue = xsec;
365  finalError = err;
366  finalWeight += currentWeight;
367  }
368  return;
369 }
370 
372  double &totalw,
373  const GenLumiInfoProduct::XSec &thisRunXSec,
374  const double &thisw) const {
375  double value = finalXSec.value();
376  double error = finalXSec.error();
377  double thisValue = thisRunXSec.value();
378  double thisError = thisRunXSec.error();
379  combine(value, error, totalw, thisValue, thisError, thisw);
380  finalXSec = GenLumiInfoProduct::XSec(value, error);
381  return;
382 }
383 
385  // sum of cross sections and errors over different processes
386  double sigSelSum = 0.0;
387  double err2SelSum = 0.0;
388 
389  std::vector<GenLumiInfoProduct::XSec> tempVector_before;
390  std::vector<GenLumiInfoProduct::XSec> tempVector_after;
391 
392  // loop over different processes for each sample
393  unsigned int vectorSize = iLumiInfo.getProcessInfos().size();
394  for (unsigned int ip = 0; ip < vectorSize; ip++) {
396  double hepxsec_value = proc.lheXSec().value();
397  double hepxsec_error = proc.lheXSec().error() <= 0 ? 0 : proc.lheXSec().error();
398  tempVector_before.push_back(GenLumiInfoProduct::XSec(hepxsec_value, hepxsec_error));
399 
400  sigSelSum += hepxsec_value;
401  err2SelSum += hepxsec_error * hepxsec_error;
402 
403  // skips computation if jet matching efficiency=0
404  if (proc.killed().n() < 1) {
405  tempVector_after.push_back(GenLumiInfoProduct::XSec(0.0, 0.0));
406  continue;
407  }
408 
409  // computing jet matching efficiency for this process
410  double fracAcc = 0;
411  double ntotal = proc.nTotalPos() - proc.nTotalNeg();
412  double npass = proc.nPassPos() - proc.nPassNeg();
413  switch (hepidwtup_) {
414  case 3:
415  case -3:
416  fracAcc = ntotal > 0 ? npass / ntotal : -1;
417  break;
418  default:
419  fracAcc = proc.selected().sum() > 0 ? proc.killed().sum() / proc.selected().sum() : -1;
420  break;
421  }
422 
423  if (fracAcc <= 0) {
424  tempVector_after.push_back(GenLumiInfoProduct::XSec(0.0, 0.0));
425  continue;
426  }
427 
428  // cross section after matching for this particular process
429  double sigmaFin = hepxsec_value * fracAcc;
430 
431  // computing error on jet matching efficiency
432  double relErr = 1.0;
433  double efferr2 = 0;
434  switch (hepidwtup_) {
435  case 3:
436  case -3: {
437  double ntotal_pos = proc.nTotalPos();
438  double effp = ntotal_pos > 0 ? (double)proc.nPassPos() / ntotal_pos : 0;
439  double effp_err2 = ntotal_pos > 0 ? (1 - effp) * effp / ntotal_pos : 0;
440 
441  double ntotal_neg = proc.nTotalNeg();
442  double effn = ntotal_neg > 0 ? (double)proc.nPassNeg() / ntotal_neg : 0;
443  double effn_err2 = ntotal_neg > 0 ? (1 - effn) * effn / ntotal_neg : 0;
444 
445  efferr2 = ntotal > 0
446  ? (ntotal_pos * ntotal_pos * effp_err2 + ntotal_neg * ntotal_neg * effn_err2) / ntotal / ntotal
447  : 0;
448  break;
449  }
450  default: {
451  double denominator = pow(proc.selected().sum(), 4);
452  double passw = proc.killed().sum();
453  double passw2 = proc.killed().sum2();
454  double failw = proc.selected().sum() - passw;
455  double failw2 = proc.selected().sum2() - passw2;
456  double numerator = (passw2 * failw * failw + failw2 * passw * passw);
457 
458  efferr2 = denominator > 0 ? numerator / denominator : 0;
459  break;
460  }
461  }
462  double delta2Veto = efferr2 / fracAcc / fracAcc;
463 
464  // computing total error on cross section after matching efficiency
465 
466  double sigma2Sum, sigma2Err;
467  sigma2Sum = hepxsec_value * hepxsec_value;
468  sigma2Err = hepxsec_error * hepxsec_error;
469 
470  double delta2Sum = delta2Veto + sigma2Err / sigma2Sum;
471  relErr = (delta2Sum > 0.0 ? std::sqrt(delta2Sum) : 0.0);
472  double deltaFin = sigmaFin * relErr;
473 
474  tempVector_after.push_back(GenLumiInfoProduct::XSec(sigmaFin, deltaFin));
475 
476  } // end of loop over different processes
477  tempVector_before.push_back(GenLumiInfoProduct::XSec(sigSelSum, sqrt(err2SelSum)));
478 
479  double total_matcheff = jetMatchEffStat_[10000].filterEfficiency(hepidwtup_);
480  double total_matcherr = jetMatchEffStat_[10000].filterEfficiencyError(hepidwtup_);
481 
482  double xsec_after = sigSelSum * total_matcheff;
483  double xsecerr_after = (total_matcheff > 0 && sigSelSum > 0)
484  ? xsec_after * sqrt(err2SelSum / sigSelSum / sigSelSum +
485  total_matcherr * total_matcherr / total_matcheff / total_matcheff)
486  : 0;
487 
488  GenLumiInfoProduct::XSec result(xsec_after, xsecerr_after);
489  tempVector_after.push_back(result);
490 
491  xsecBeforeMatching_ = tempVector_before;
492  xsecAfterMatching_ = tempVector_after;
493 
494  return result;
495 }
496 
498  edm::LogPrint("GenXSecAnalyzer") << "\n"
499  << "------------------------------------"
500  << "\n"
501  << "GenXsecAnalyzer:"
502  << "\n"
503  << "------------------------------------";
504 
505  if (jetMatchEffStat_.empty()) {
506  edm::LogPrint("GenXSecAnalyzer") << "------------------------------------"
507  << "\n"
508  << "Cross-section summary not available"
509  << "\n"
510  << "------------------------------------";
511  return;
512  }
513 
514  // fraction of negative weights
515  double final_fract_neg_w = 0;
516  double final_fract_neg_w_unc = 0;
517 
518  // below print out is only for combination of same physics MC samples and ME+Pythia MCs
519 
520  if (nMCs_ == 1 && hepidwtup_ != -1) {
521  edm::LogPrint("GenXSecAnalyzer")
522  << "-----------------------------------------------------------------------------------------------------------"
523  "--------------------------------------------------------------- \n"
524  << "Overall cross-section summary \n"
525  << "-----------------------------------------------------------------------------------------------------------"
526  "---------------------------------------------------------------";
527  edm::LogPrint("GenXSecAnalyzer") << "Process\t\txsec_before [pb]\t\tpassed\tnposw\tnnegw\ttried\tnposw\tnnegw "
528  "\txsec_match [pb]\t\t\taccepted [%]\t event_eff [%]";
529 
530  const unsigned sizeOfInfos = jetMatchEffStat_.size();
531  const unsigned last = sizeOfInfos - 1;
532  std::string *title = new std::string[sizeOfInfos];
533  unsigned int i = 0;
534  double jetmatch_eff = 0;
535  double jetmatch_err = 0;
536  double matching_eff = 1;
537  double matching_efferr = 1;
538 
539  for (std::map<int, GenFilterInfo>::const_iterator iter = jetMatchEffStat_.begin(); iter != jetMatchEffStat_.end();
540  ++iter, i++) {
541  GenFilterInfo thisJetMatchStat = iter->second;
542  GenFilterInfo thisEventEffStat =
543  GenFilterInfo(thisJetMatchStat.numPassPositiveEvents() + thisJetMatchStat.numPassNegativeEvents(),
544  0,
545  thisJetMatchStat.numTotalPositiveEvents() + thisJetMatchStat.numTotalNegativeEvents(),
546  0,
547  thisJetMatchStat.numPassPositiveEvents() + thisJetMatchStat.numPassNegativeEvents(),
548  thisJetMatchStat.numPassPositiveEvents() + thisJetMatchStat.numPassNegativeEvents(),
549  thisJetMatchStat.numTotalPositiveEvents() + thisJetMatchStat.numTotalNegativeEvents(),
550  thisJetMatchStat.numTotalPositiveEvents() + thisJetMatchStat.numTotalNegativeEvents());
551 
552  jetmatch_eff = thisJetMatchStat.filterEfficiency(hepidwtup_);
553  jetmatch_err = thisJetMatchStat.filterEfficiencyError(hepidwtup_);
554 
555  if (i == last) {
556  title[i] = "Total";
557 
558  edm::LogPrint("GenXSecAnalyzer")
559  << "-------------------------------------------------------------------------------------------------------"
560  "------------------------------------------------------------------- ";
561 
562  // fill negative fraction of negative weights and uncertainty after matching
563  final_fract_neg_w = thisEventEffStat.numEventsPassed() > 0
564  ? thisJetMatchStat.numPassNegativeEvents() / thisEventEffStat.numEventsPassed()
565  : 0;
566  final_fract_neg_w_unc =
567  thisJetMatchStat.numPassNegativeEvents() > 0
568  ? final_fract_neg_w * final_fract_neg_w / thisEventEffStat.numEventsPassed() *
569  sqrt(thisJetMatchStat.numPassPositiveEvents() * thisJetMatchStat.numPassPositiveEvents() /
570  thisJetMatchStat.numPassNegativeEvents() +
571  thisJetMatchStat.numPassPositiveEvents())
572  : 0;
573  } else {
574  title[i] = Form("%d", i);
575  }
576 
577  edm::LogPrint("GenXSecAnalyzer") << title[i] << "\t\t" << std::scientific << std::setprecision(3)
578  << xsecBeforeMatching_[i].value() << " +/- " << xsecBeforeMatching_[i].error()
579  << "\t\t" << thisEventEffStat.numEventsPassed() << "\t"
580  << thisJetMatchStat.numPassPositiveEvents() << "\t"
581  << thisJetMatchStat.numPassNegativeEvents() << "\t"
582  << thisEventEffStat.numEventsTotal() << "\t"
583  << thisJetMatchStat.numTotalPositiveEvents() << "\t"
584  << thisJetMatchStat.numTotalNegativeEvents() << "\t" << std::scientific
585  << std::setprecision(3) << xsecAfterMatching_[i].value() << " +/- "
586  << xsecAfterMatching_[i].error() << "\t\t" << std::fixed << std::setprecision(1)
587  << (jetmatch_eff * 100) << " +/- " << (jetmatch_err * 100) << "\t" << std::fixed
588  << std::setprecision(1) << (thisEventEffStat.filterEfficiency(+3) * 100)
589  << " +/- " << (thisEventEffStat.filterEfficiencyError(+3) * 100);
590 
591  matching_eff = thisEventEffStat.filterEfficiency(+3);
592  matching_efferr = thisEventEffStat.filterEfficiencyError(+3);
593  }
594  delete[] title;
595 
596  edm::LogPrint("GenXSecAnalyzer")
597  << "-----------------------------------------------------------------------------------------------------------"
598  "---------------------------------------------------------------";
599 
600  edm::LogPrint("GenXSecAnalyzer") << "Before matching: total cross section = " << std::scientific
601  << std::setprecision(3) << xsecBeforeMatching_[last].value() << " +- "
602  << xsecBeforeMatching_[last].error() << " pb";
603 
604  edm::LogPrint("GenXSecAnalyzer") << "After matching: total cross section = " << std::scientific
605  << std::setprecision(3) << xsecAfterMatching_[last].value() << " +- "
606  << xsecAfterMatching_[last].error() << " pb";
607 
608  edm::LogPrint("GenXSecAnalyzer") << "Matching efficiency = " << std::fixed << std::setprecision(1) << matching_eff
609  << " +/- " << matching_efferr << " [TO BE USED IN MCM]";
610 
611  } else if (hepidwtup_ == -1)
612  edm::LogPrint("GenXSecAnalyzer") << "Before Filter: total cross section = " << std::scientific
613  << std::setprecision(3) << xsecPreFilter_.value() << " +- "
614  << xsecPreFilter_.error() << " pb";
615 
616  // hepMC filter efficiency
617  double hepMCFilter_eff = 1.0;
618  double hepMCFilter_err = 0.0;
619  if (hepMCFilterEffStat_.sumWeights2() > 0) {
620  hepMCFilter_eff = hepMCFilterEffStat_.filterEfficiency(-1);
621  hepMCFilter_err = hepMCFilterEffStat_.filterEfficiencyError(-1);
622  edm::LogPrint("GenXSecAnalyzer") << "HepMC filter efficiency (taking into account weights)= "
623  << "(" << hepMCFilterEffStat_.sumPassWeights() << ")"
624  << " / "
625  << "(" << hepMCFilterEffStat_.sumWeights() << ")"
626  << " = " << std::scientific << std::setprecision(3) << hepMCFilter_eff << " +- "
627  << hepMCFilter_err;
628 
629  double hepMCFilter_event_total =
631  double hepMCFilter_event_pass =
633  double hepMCFilter_event_eff = hepMCFilter_event_total > 0 ? hepMCFilter_event_pass / hepMCFilter_event_total : 0;
634  double hepMCFilter_event_err =
635  hepMCFilter_event_total > 0
636  ? sqrt((1 - hepMCFilter_event_eff) * hepMCFilter_event_eff / hepMCFilter_event_total)
637  : -1;
638  edm::LogPrint("GenXSecAnalyzer") << "HepMC filter efficiency (event-level)= "
639  << "(" << hepMCFilter_event_pass << ")"
640  << " / "
641  << "(" << hepMCFilter_event_total << ")"
642  << " = " << std::scientific << std::setprecision(3) << hepMCFilter_event_eff
643  << " +- " << hepMCFilter_event_err;
644  }
645 
646  // gen-particle filter efficiency
647  if (filterOnlyEffStat_.sumWeights2() > 0) {
648  double filterOnly_eff = filterOnlyEffStat_.filterEfficiency(-1);
649  double filterOnly_err = filterOnlyEffStat_.filterEfficiencyError(-1);
650 
651  edm::LogPrint("GenXSecAnalyzer") << "Filter efficiency (taking into account weights)= "
652  << "(" << filterOnlyEffStat_.sumPassWeights() << ")"
653  << " / "
654  << "(" << filterOnlyEffStat_.sumWeights() << ")"
655  << " = " << std::scientific << std::setprecision(3) << filterOnly_eff << " +- "
656  << filterOnly_err;
657 
658  double filterOnly_event_total =
660  double filterOnly_event_pass =
662  double filterOnly_event_eff = filterOnly_event_total > 0 ? filterOnly_event_pass / filterOnly_event_total : 0;
663  double filterOnly_event_err = filterOnly_event_total > 0
664  ? sqrt((1 - filterOnly_event_eff) * filterOnly_event_eff / filterOnly_event_total)
665  : -1;
666  edm::LogPrint("GenXSecAnalyzer") << "Filter efficiency (event-level)= "
667  << "(" << filterOnly_event_pass << ")"
668  << " / "
669  << "(" << filterOnly_event_total << ")"
670  << " = " << std::scientific << std::setprecision(3) << filterOnly_event_eff
671  << " +- " << filterOnly_event_err << " [TO BE USED IN MCM]";
672 
673  // fill negative fraction of negative weights and uncertainty after filter
674  final_fract_neg_w =
675  filterOnly_event_pass > 0 ? filterOnlyEffStat_.numPassNegativeEvents() / (filterOnly_event_pass) : 0;
676  final_fract_neg_w_unc =
678  ? final_fract_neg_w * final_fract_neg_w / filterOnly_event_pass *
682  : 0;
683  }
684 
685  edm::LogPrint("GenXSecAnalyzer") << "\nAfter filter: final cross section = " << std::scientific
686  << std::setprecision(3) << xsec_.value() << " +- " << xsec_.error() << " pb";
687 
688  edm::LogPrint("GenXSecAnalyzer") << "After filter: final fraction of events with negative weights = "
689  << std::scientific << std::setprecision(3) << final_fract_neg_w << " +- "
690  << final_fract_neg_w_unc;
691 
692  // L=[N*(1-2f)^2]/s
693  double lumi_1M_evts =
694  xsec_.value() > 0 ? 1e6 * (1 - 2 * final_fract_neg_w) * (1 - 2 * final_fract_neg_w) / xsec_.value() / 1e3 : 0;
695  double lumi_1M_evts_unc =
696  xsec_.value() > 0 ? (1 - 2 * final_fract_neg_w) * lumi_1M_evts *
697  sqrt(1e-6 + 16 * pow(final_fract_neg_w_unc, 2) / pow(1 - 2 * final_fract_neg_w, 2) +
698  pow(xsec_.error() / xsec_.value(), 2))
699  : 0;
700  edm::LogPrint("GenXSecAnalyzer") << "After filter: final equivalent lumi for 1M events (1/fb) = " << std::scientific
701  << std::setprecision(3) << lumi_1M_evts << " +- " << lumi_1M_evts_unc;
702 }
703 
std::vector< GenLumiInfoProduct::XSec > xsecBeforeMatching_
std::shared_ptr< gxsec::LumiCache > globalBeginLuminosityBlock(edm::LuminosityBlock const &, edm::EventSetup const &) const final
std::map< int, GenFilterInfo > jetMatchEffStat_
edm::EDGetTokenT< GenFilterInfo > hepMCFilterInfoToken_
GenLumiInfoProduct product_
Run const & getRun() const
static std::mutex mutex
Definition: Proxy.cc:8
GenFilterInfo filterOnlyEffStat_
edm::EDGetTokenT< GenLumiInfoProduct > genLumiInfoToken_
constexpr int pow(int x)
Definition: conifer.h:24
void combine(GenLumiInfoProduct::XSec &, double &, const GenLumiInfoProduct::XSec &, const double &) const
GenLumiInfoProduct::XSec compute(const GenLumiInfoProduct &) const
GenFilterInfo filterOnlyEffRun_
unsigned int numTotalNegativeEvents() const
Definition: GenFilterInfo.h:29
Log< level::Error, false > LogError
void globalEndRun(edm::Run const &, edm::EventSetup const &) const final
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e g
Definition: Activities.doc:4
std::atomic< int > hepidwtup_
double sumWeights2() const
Definition: GenFilterInfo.h:38
unsigned int numPassNegativeEvents() const
Definition: GenFilterInfo.h:28
GenLumiInfoProduct::XSec xsec_
unsigned int numTotalPositiveEvents() const
Definition: GenFilterInfo.h:26
void globalEndLuminosityBlock(edm::LuminosityBlock const &, edm::EventSetup const &) const final
GenFilterInfo hepMCFilterEffStat_
bool mergeProduct(GenFilterInfo const &other)
void analyze(edm::StreamID, const edm::Event &, const edm::EventSetup &) const final
const std::vector< ProcessInfo > & getProcessInfos() const
T sqrt(T t)
Definition: SSEVec.h:19
void beginJob() final
#define CMS_THREAD_GUARD(_var_)
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
double sumPassWeights() const
Definition: GenFilterInfo.h:31
Definition: value.py:1
Log< level::Warning, true > LogPrint
std::vector< double > XERRUP
Definition: LesHouches.h:118
std::vector< double > XMAXUP
Definition: LesHouches.h:123
double filterEfficiency(int idwtup=+3) const
bool getByToken(EDGetToken token, Handle< PROD > &result) const
double sumWeights() const
Definition: GenFilterInfo.h:37
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Run.h:318
double filterEfficiencyError(int idwtup=+3) const
unsigned int numEventsPassed() const
Definition: GenFilterInfo.h:22
unsigned int numPassPositiveEvents() const
Definition: GenFilterInfo.h:25
bool isValid() const
Definition: HandleBase.h:70
edm::EDGetTokenT< GenFilterInfo > genFilterInfoToken_
RunIndex index() const
Definition: Run.cc:28
GenXSecAnalyzer(const edm::ParameterSet &)
std::vector< GenLumiInfoProduct::XSec > xsecAfterMatching_
~GenXSecAnalyzer() override
edm::EDGetTokenT< LHERunInfoProduct > lheRunInfoToken_
std::vector< double > XSECUP
Definition: LesHouches.h:112
unsigned int numEventsTotal() const
Definition: GenFilterInfo.h:23
std::map< int, GenLumiInfoProduct::XSec > currentLumiBlockLHEXSec_
std::shared_ptr< gxsec::RunCache > globalBeginRun(edm::Run const &, edm::EventSetup const &) const final
GenFilterInfo hepMCFilterEffRun_
GenLumiInfoProduct::XSec xsecPreFilter_
std::atomic< int > nMCs_
void endJob() final
Definition: Run.h:45
std::vector< int > LPRUP
Definition: LesHouches.h:128
std::map< int, GenLumiInfoProduct::XSec > previousLumiBlockLHEXSec_