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 
167  edm::EventSetup const &) const {
168  return std::shared_ptr<gxsec::LumiCache>();
169 }
170 
172 
175  iLumi.getByToken(genLumiInfoToken_, genLumiInfo);
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  if (nullptr == runC)
298  return;
299 
300  std::lock_guard l{mutex_};
301 
302  // compute cross section for this run first
303  // set the correct combined LHE+filter cross sections
304  unsigned int i = 0;
305  std::vector<GenLumiInfoProduct::ProcessInfo> newInfos;
306  for (std::map<int, GenLumiInfoProduct::XSec>::const_iterator iter = runC->currentLumiBlockLHEXSec_.begin();
307  iter != runC->currentLumiBlockLHEXSec_.end();
308  ++iter, i++) {
309  GenLumiInfoProduct::ProcessInfo temp = runC->product_.getProcessInfos()[i];
310  temp.setLheXSec(iter->second.value(), iter->second.error());
311  newInfos.push_back(temp);
312  }
313  runC->product_.setProcessInfo(newInfos);
314 
315  const GenLumiInfoProduct::XSec thisRunXSecPre = compute(runC->product_);
316  // xsection after matching before filters
317  combine(xsecPreFilter_, totalWeightPre_, thisRunXSecPre, runC->thisRunWeightPre_);
318 
319  double thisHepFilterEff = 1;
320  double thisHepFilterErr = 0;
321 
322  if (runC->hepMCFilterEffRun_.sumWeights2() > 0) {
323  thisHepFilterEff = runC->hepMCFilterEffRun_.filterEfficiency(hepidwtup_);
324  thisHepFilterErr = runC->hepMCFilterEffRun_.filterEfficiencyError(hepidwtup_);
325  if (thisHepFilterEff < 0) {
326  thisHepFilterEff = 1;
327  thisHepFilterErr = 0;
328  }
329  }
330 
331  double thisGenFilterEff = 1;
332  double thisGenFilterErr = 0;
333 
334  if (runC->filterOnlyEffRun_.sumWeights2() > 0) {
335  thisGenFilterEff = runC->filterOnlyEffRun_.filterEfficiency(hepidwtup_);
336  thisGenFilterErr = runC->filterOnlyEffRun_.filterEfficiencyError(hepidwtup_);
337  if (thisGenFilterEff < 0) {
338  thisGenFilterEff = 1;
339  thisGenFilterErr = 0;
340  }
341  }
342  double thisXsec = thisRunXSecPre.value() > 0 ? thisHepFilterEff * thisGenFilterEff * thisRunXSecPre.value() : 0;
343  double thisErr =
344  thisRunXSecPre.value() > 0
345  ? thisXsec * sqrt(pow(TMath::Max(thisRunXSecPre.error(), (double)0) / thisRunXSecPre.value(), 2) +
346  pow(thisHepFilterErr / thisHepFilterEff, 2) + pow(thisGenFilterErr / thisGenFilterEff, 2))
347  : 0;
348  const GenLumiInfoProduct::XSec thisRunXSec = GenLumiInfoProduct::XSec(thisXsec, thisErr);
349  combine(xsec_, totalWeight_, thisRunXSec, runC->thisRunWeight_);
350 }
351 
352 void GenXSecAnalyzer::combine(double &finalValue,
353  double &finalError,
354  double &finalWeight,
355  const double &currentValue,
356  const double &currentError,
357  const double &currentWeight) const {
358  if (finalValue <= 0) {
359  finalValue = currentValue;
360  finalError = currentError;
361  finalWeight += currentWeight;
362  } else {
363  double wgt1 = (finalError <= 0 || currentError <= 0) ? finalWeight : 1 / (finalError * finalError);
364  double wgt2 = (finalError <= 0 || currentError <= 0) ? currentWeight : 1 / (currentError * currentError);
365  double xsec = (wgt1 * finalValue + wgt2 * currentValue) / (wgt1 + wgt2);
366  double err = (finalError <= 0 || currentError <= 0) ? 0 : 1.0 / std::sqrt(wgt1 + wgt2);
367  finalValue = xsec;
368  finalError = err;
369  finalWeight += currentWeight;
370  }
371  return;
372 }
373 
375  double &totalw,
376  const GenLumiInfoProduct::XSec &thisRunXSec,
377  const double &thisw) const {
378  double value = finalXSec.value();
379  double error = finalXSec.error();
380  double thisValue = thisRunXSec.value();
381  double thisError = thisRunXSec.error();
382  combine(value, error, totalw, thisValue, thisError, thisw);
383  finalXSec = GenLumiInfoProduct::XSec(value, error);
384  return;
385 }
386 
388  // sum of cross sections and errors over different processes
389  double sigSelSum = 0.0;
390  double err2SelSum = 0.0;
391 
392  std::vector<GenLumiInfoProduct::XSec> tempVector_before;
393  std::vector<GenLumiInfoProduct::XSec> tempVector_after;
394 
395  // loop over different processes for each sample
396  unsigned int vectorSize = iLumiInfo.getProcessInfos().size();
397  for (unsigned int ip = 0; ip < vectorSize; ip++) {
399  double hepxsec_value = proc.lheXSec().value();
400  double hepxsec_error = proc.lheXSec().error() <= 0 ? 0 : proc.lheXSec().error();
401  tempVector_before.push_back(GenLumiInfoProduct::XSec(hepxsec_value, hepxsec_error));
402 
403  sigSelSum += hepxsec_value;
404  err2SelSum += hepxsec_error * hepxsec_error;
405 
406  // skips computation if jet matching efficiency=0
407  if (proc.killed().n() < 1) {
408  tempVector_after.push_back(GenLumiInfoProduct::XSec(0.0, 0.0));
409  continue;
410  }
411 
412  // computing jet matching efficiency for this process
413  double fracAcc = 0;
414  double ntotal = proc.nTotalPos() - proc.nTotalNeg();
415  double npass = proc.nPassPos() - proc.nPassNeg();
416  switch (hepidwtup_) {
417  case 3:
418  case -3:
419  fracAcc = ntotal > 0 ? npass / ntotal : -1;
420  break;
421  default:
422  fracAcc = proc.selected().sum() > 0 ? proc.killed().sum() / proc.selected().sum() : -1;
423  break;
424  }
425 
426  if (fracAcc <= 0) {
427  tempVector_after.push_back(GenLumiInfoProduct::XSec(0.0, 0.0));
428  continue;
429  }
430 
431  // cross section after matching for this particular process
432  double sigmaFin = hepxsec_value * fracAcc;
433 
434  // computing error on jet matching efficiency
435  double relErr = 1.0;
436  double efferr2 = 0;
437  switch (hepidwtup_) {
438  case 3:
439  case -3: {
440  double ntotal_pos = proc.nTotalPos();
441  double effp = ntotal_pos > 0 ? (double)proc.nPassPos() / ntotal_pos : 0;
442  double effp_err2 = ntotal_pos > 0 ? (1 - effp) * effp / ntotal_pos : 0;
443 
444  double ntotal_neg = proc.nTotalNeg();
445  double effn = ntotal_neg > 0 ? (double)proc.nPassNeg() / ntotal_neg : 0;
446  double effn_err2 = ntotal_neg > 0 ? (1 - effn) * effn / ntotal_neg : 0;
447 
448  efferr2 = ntotal > 0
449  ? (ntotal_pos * ntotal_pos * effp_err2 + ntotal_neg * ntotal_neg * effn_err2) / ntotal / ntotal
450  : 0;
451  break;
452  }
453  default: {
454  double denominator = pow(proc.selected().sum(), 4);
455  double passw = proc.killed().sum();
456  double passw2 = proc.killed().sum2();
457  double failw = proc.selected().sum() - passw;
458  double failw2 = proc.selected().sum2() - passw2;
459  double numerator = (passw2 * failw * failw + failw2 * passw * passw);
460 
461  efferr2 = denominator > 0 ? numerator / denominator : 0;
462  break;
463  }
464  }
465  double delta2Veto = efferr2 / fracAcc / fracAcc;
466 
467  // computing total error on cross section after matching efficiency
468 
469  double sigma2Sum, sigma2Err;
470  sigma2Sum = hepxsec_value * hepxsec_value;
471  sigma2Err = hepxsec_error * hepxsec_error;
472 
473  double delta2Sum = delta2Veto + sigma2Err / sigma2Sum;
474  relErr = (delta2Sum > 0.0 ? std::sqrt(delta2Sum) : 0.0);
475  double deltaFin = sigmaFin * relErr;
476 
477  tempVector_after.push_back(GenLumiInfoProduct::XSec(sigmaFin, deltaFin));
478 
479  } // end of loop over different processes
480  tempVector_before.push_back(GenLumiInfoProduct::XSec(sigSelSum, sqrt(err2SelSum)));
481 
482  double total_matcheff = jetMatchEffStat_[10000].filterEfficiency(hepidwtup_);
483  double total_matcherr = jetMatchEffStat_[10000].filterEfficiencyError(hepidwtup_);
484 
485  double xsec_after = sigSelSum * total_matcheff;
486  double xsecerr_after = (total_matcheff > 0 && sigSelSum > 0)
487  ? xsec_after * sqrt(err2SelSum / sigSelSum / sigSelSum +
488  total_matcherr * total_matcherr / total_matcheff / total_matcheff)
489  : 0;
490 
491  GenLumiInfoProduct::XSec result(xsec_after, xsecerr_after);
492  tempVector_after.push_back(result);
493 
494  xsecBeforeMatching_ = tempVector_before;
495  xsecAfterMatching_ = tempVector_after;
496 
497  return result;
498 }
499 
501  edm::LogPrint("GenXSecAnalyzer") << "\n"
502  << "------------------------------------"
503  << "\n"
504  << "GenXsecAnalyzer:"
505  << "\n"
506  << "------------------------------------";
507 
508  if (jetMatchEffStat_.empty()) {
509  edm::LogPrint("GenXSecAnalyzer") << "------------------------------------"
510  << "\n"
511  << "Cross-section summary not available"
512  << "\n"
513  << "------------------------------------";
514  return;
515  }
516 
517  // fraction of negative weights
518  double final_fract_neg_w = 0;
519  double final_fract_neg_w_unc = 0;
520 
521  // below print out is only for combination of same physics MC samples and ME+Pythia MCs
522 
523  if (nMCs_ == 1 && hepidwtup_ != -1) {
524  edm::LogPrint("GenXSecAnalyzer")
525  << "-----------------------------------------------------------------------------------------------------------"
526  "--------------------------------------------------------------- \n"
527  << "Overall cross-section summary \n"
528  << "-----------------------------------------------------------------------------------------------------------"
529  "---------------------------------------------------------------";
530  edm::LogPrint("GenXSecAnalyzer") << "Process\t\txsec_before [pb]\t\tpassed\tnposw\tnnegw\ttried\tnposw\tnnegw "
531  "\txsec_match [pb]\t\t\taccepted [%]\t event_eff [%]";
532 
533  const unsigned sizeOfInfos = jetMatchEffStat_.size();
534  const unsigned last = sizeOfInfos - 1;
535  std::string *title = new std::string[sizeOfInfos];
536  unsigned int i = 0;
537  double jetmatch_eff = 0;
538  double jetmatch_err = 0;
539  double matching_eff = 1;
540  double matching_efferr = 1;
541 
542  for (std::map<int, GenFilterInfo>::const_iterator iter = jetMatchEffStat_.begin(); iter != jetMatchEffStat_.end();
543  ++iter, i++) {
544  GenFilterInfo thisJetMatchStat = iter->second;
545  GenFilterInfo thisEventEffStat =
546  GenFilterInfo(thisJetMatchStat.numPassPositiveEvents() + thisJetMatchStat.numPassNegativeEvents(),
547  0,
548  thisJetMatchStat.numTotalPositiveEvents() + thisJetMatchStat.numTotalNegativeEvents(),
549  0,
550  thisJetMatchStat.numPassPositiveEvents() + thisJetMatchStat.numPassNegativeEvents(),
551  thisJetMatchStat.numPassPositiveEvents() + thisJetMatchStat.numPassNegativeEvents(),
552  thisJetMatchStat.numTotalPositiveEvents() + thisJetMatchStat.numTotalNegativeEvents(),
553  thisJetMatchStat.numTotalPositiveEvents() + thisJetMatchStat.numTotalNegativeEvents());
554 
555  jetmatch_eff = thisJetMatchStat.filterEfficiency(hepidwtup_);
556  jetmatch_err = thisJetMatchStat.filterEfficiencyError(hepidwtup_);
557 
558  if (i == last) {
559  title[i] = "Total";
560 
561  edm::LogPrint("GenXSecAnalyzer")
562  << "-------------------------------------------------------------------------------------------------------"
563  "------------------------------------------------------------------- ";
564 
565  // fill negative fraction of negative weights and uncertainty after matching
566  final_fract_neg_w = thisEventEffStat.numEventsPassed() > 0
567  ? thisJetMatchStat.numPassNegativeEvents() / thisEventEffStat.numEventsPassed()
568  : 0;
569  final_fract_neg_w_unc =
570  thisJetMatchStat.numPassNegativeEvents() > 0
571  ? final_fract_neg_w * final_fract_neg_w / thisEventEffStat.numEventsPassed() *
572  sqrt(thisJetMatchStat.numPassPositiveEvents() * thisJetMatchStat.numPassPositiveEvents() /
573  thisJetMatchStat.numPassNegativeEvents() +
574  thisJetMatchStat.numPassPositiveEvents())
575  : 0;
576  } else {
577  title[i] = Form("%d", i);
578  }
579 
580  edm::LogPrint("GenXSecAnalyzer") << title[i] << "\t\t" << std::scientific << std::setprecision(3)
581  << xsecBeforeMatching_[i].value() << " +/- " << xsecBeforeMatching_[i].error()
582  << "\t\t" << thisEventEffStat.numEventsPassed() << "\t"
583  << thisJetMatchStat.numPassPositiveEvents() << "\t"
584  << thisJetMatchStat.numPassNegativeEvents() << "\t"
585  << thisEventEffStat.numEventsTotal() << "\t"
586  << thisJetMatchStat.numTotalPositiveEvents() << "\t"
587  << thisJetMatchStat.numTotalNegativeEvents() << "\t" << std::scientific
588  << std::setprecision(3) << xsecAfterMatching_[i].value() << " +/- "
589  << xsecAfterMatching_[i].error() << "\t\t" << std::fixed << std::setprecision(1)
590  << (jetmatch_eff * 100) << " +/- " << (jetmatch_err * 100) << "\t" << std::fixed
591  << std::setprecision(1) << (thisEventEffStat.filterEfficiency(+3) * 100)
592  << " +/- " << (thisEventEffStat.filterEfficiencyError(+3) * 100);
593 
594  matching_eff = thisEventEffStat.filterEfficiency(+3);
595  matching_efferr = thisEventEffStat.filterEfficiencyError(+3);
596  }
597  delete[] title;
598 
599  edm::LogPrint("GenXSecAnalyzer")
600  << "-----------------------------------------------------------------------------------------------------------"
601  "---------------------------------------------------------------";
602 
603  edm::LogPrint("GenXSecAnalyzer") << "Before matching: total cross section = " << std::scientific
604  << std::setprecision(3) << xsecBeforeMatching_[last].value() << " +- "
605  << xsecBeforeMatching_[last].error() << " pb";
606 
607  edm::LogPrint("GenXSecAnalyzer") << "After matching: total cross section = " << std::scientific
608  << std::setprecision(3) << xsecAfterMatching_[last].value() << " +- "
609  << xsecAfterMatching_[last].error() << " pb";
610 
611  edm::LogPrint("GenXSecAnalyzer") << "Matching efficiency = " << std::fixed << std::setprecision(1) << matching_eff
612  << " +/- " << matching_efferr << " [TO BE USED IN MCM]";
613 
614  } else if (hepidwtup_ == -1)
615  edm::LogPrint("GenXSecAnalyzer") << "Before Filter: total cross section = " << std::scientific
616  << std::setprecision(3) << xsecPreFilter_.value() << " +- "
617  << xsecPreFilter_.error() << " pb";
618 
619  // hepMC filter efficiency
620  double hepMCFilter_eff = 1.0;
621  double hepMCFilter_err = 0.0;
622  if (hepMCFilterEffStat_.sumWeights2() > 0) {
623  hepMCFilter_eff = hepMCFilterEffStat_.filterEfficiency(-1);
624  hepMCFilter_err = hepMCFilterEffStat_.filterEfficiencyError(-1);
625  edm::LogPrint("GenXSecAnalyzer") << "HepMC filter efficiency (taking into account weights)= "
626  << "(" << hepMCFilterEffStat_.sumPassWeights() << ")"
627  << " / "
628  << "(" << hepMCFilterEffStat_.sumWeights() << ")"
629  << " = " << std::scientific << std::setprecision(3) << hepMCFilter_eff << " +- "
630  << hepMCFilter_err;
631 
632  double hepMCFilter_event_total =
634  double hepMCFilter_event_pass =
636  double hepMCFilter_event_eff = hepMCFilter_event_total > 0 ? hepMCFilter_event_pass / hepMCFilter_event_total : 0;
637  double hepMCFilter_event_err =
638  hepMCFilter_event_total > 0
639  ? sqrt((1 - hepMCFilter_event_eff) * hepMCFilter_event_eff / hepMCFilter_event_total)
640  : -1;
641  edm::LogPrint("GenXSecAnalyzer") << "HepMC filter efficiency (event-level)= "
642  << "(" << hepMCFilter_event_pass << ")"
643  << " / "
644  << "(" << hepMCFilter_event_total << ")"
645  << " = " << std::scientific << std::setprecision(3) << hepMCFilter_event_eff
646  << " +- " << hepMCFilter_event_err;
647  }
648 
649  // gen-particle filter efficiency
650  if (filterOnlyEffStat_.sumWeights2() > 0) {
651  double filterOnly_eff = filterOnlyEffStat_.filterEfficiency(-1);
652  double filterOnly_err = filterOnlyEffStat_.filterEfficiencyError(-1);
653 
654  edm::LogPrint("GenXSecAnalyzer") << "Filter efficiency (taking into account weights)= "
655  << "(" << filterOnlyEffStat_.sumPassWeights() << ")"
656  << " / "
657  << "(" << filterOnlyEffStat_.sumWeights() << ")"
658  << " = " << std::scientific << std::setprecision(3) << filterOnly_eff << " +- "
659  << filterOnly_err;
660 
661  double filterOnly_event_total =
663  double filterOnly_event_pass =
665  double filterOnly_event_eff = filterOnly_event_total > 0 ? filterOnly_event_pass / filterOnly_event_total : 0;
666  double filterOnly_event_err = filterOnly_event_total > 0
667  ? sqrt((1 - filterOnly_event_eff) * filterOnly_event_eff / filterOnly_event_total)
668  : -1;
669  edm::LogPrint("GenXSecAnalyzer") << "Filter efficiency (event-level)= "
670  << "(" << filterOnly_event_pass << ")"
671  << " / "
672  << "(" << filterOnly_event_total << ")"
673  << " = " << std::scientific << std::setprecision(3) << filterOnly_event_eff
674  << " +- " << filterOnly_event_err << " [TO BE USED IN MCM]";
675 
676  // fill negative fraction of negative weights and uncertainty after filter
677  final_fract_neg_w =
678  filterOnly_event_pass > 0 ? filterOnlyEffStat_.numPassNegativeEvents() / (filterOnly_event_pass) : 0;
679  final_fract_neg_w_unc =
681  ? final_fract_neg_w * final_fract_neg_w / filterOnly_event_pass *
685  : 0;
686  }
687 
688  edm::LogPrint("GenXSecAnalyzer") << "\nAfter filter: final cross section = " << std::scientific
689  << std::setprecision(3) << xsec_.value() << " +- " << xsec_.error() << " pb";
690 
691  edm::LogPrint("GenXSecAnalyzer") << "After filter: final fraction of events with negative weights = "
692  << std::scientific << std::setprecision(3) << final_fract_neg_w << " +- "
693  << final_fract_neg_w_unc;
694 
695  // L=[N*(1-2f)^2]/s
696  double lumi_1M_evts =
697  xsec_.value() > 0 ? 1e6 * (1 - 2 * final_fract_neg_w) * (1 - 2 * final_fract_neg_w) / xsec_.value() / 1e3 : 0;
698  double lumi_1M_evts_unc =
699  xsec_.value() > 0 ? (1 - 2 * final_fract_neg_w) * lumi_1M_evts *
700  sqrt(1e-6 + 16 * pow(final_fract_neg_w_unc, 2) / pow(1 - 2 * final_fract_neg_w, 2) +
701  pow(xsec_.error() / xsec_.value(), 2))
702  : 0;
703  edm::LogPrint("GenXSecAnalyzer") << "After filter: final equivalent lumi for 1M events (1/fb) = " << std::scientific
704  << std::setprecision(3) << lumi_1M_evts << " +- " << lumi_1M_evts_unc;
705 }
706 
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_
static std::mutex mutex
Definition: Proxy.cc:8
GenFilterInfo filterOnlyEffStat_
edm::EDGetTokenT< GenLumiInfoProduct > genLumiInfoToken_
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:28
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:37
unsigned int numPassNegativeEvents() const
Definition: GenFilterInfo.h:27
GenLumiInfoProduct::XSec xsec_
unsigned int numTotalPositiveEvents() const
Definition: GenFilterInfo.h:25
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:23
void beginJob() final
#define CMS_THREAD_GUARD(_var_)
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
double sumPassWeights() const
Definition: GenFilterInfo.h:30
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
double sumWeights() const
Definition: GenFilterInfo.h:36
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Run.h:313
double filterEfficiencyError(int idwtup=+3) const
unsigned int numEventsPassed() const
Definition: GenFilterInfo.h:21
unsigned int numPassPositiveEvents() const
Definition: GenFilterInfo.h:24
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:22
std::map< int, GenLumiInfoProduct::XSec > currentLumiBlockLHEXSec_
std::shared_ptr< gxsec::RunCache > globalBeginRun(edm::Run const &, edm::EventSetup const &) const final
GenFilterInfo hepMCFilterEffRun_
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:29
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_