Rivet analyses

MC analysis for distributions of event weights

Experiment: ()

Status: VALIDATED

Authors: - Frank Siegert - Christian Gutschow

References: none listed

Beams: * *

Beam energies: ANY

Run details: - Suitable for any process.

Analysis for studying event weight distributions and fraction of events with negative weights. This analysis will not produce sensible distributions in case of correlated NLO sub-events.

Source code:MC_WEIGHTS.cc

// -*- C++ -*-
#include "Rivet/Analysis.hh"
#include "Rivet/AnalysisHandler.hh"
#include "Rivet/Projections/DirectFinalState.hh"
#include "Rivet/Projections/FastJets.hh"
#include "Rivet/Projections/VetoedFinalState.hh"

namespace Rivet {


  /// Analysis of the generated event-weight distributions
  class MC_WEIGHTS : public Analysis {
  public:

    RIVET_DEFAULT_ANALYSIS_CTOR(MC_WEIGHTS);


    /// @name Analysis methods
    /// @{

    /// Book histograms and initialise projections before the run
    void init() {

      DirectFinalState leps(Cuts::abspid == PID::ELECTRON || Cuts::abspid == PID::MUON, TauDecaysAs::PROMPT);
      VetoedFinalState vfs;
      vfs.vetoFinalState(leps);
      declare(FastJets(vfs, JetAlg::ANTIKT, 0.4, JetMuons::DECAY, JetInvisibles::DECAY), "jets");

      book(_n["weight_10+7"], "weight_10+7", 200, -1e+03, 1e+03);
      book(_n["weight_10+6"], "weight_10+6", 200, -1e+02, 1e+02);
      book(_n["weight_10+5"], "weight_10+5", 200, -1e+01, 1e+01);
      book(_n["weight_10+4"], "weight_10+4", 200, -1e+04, 1e+04);
      book(_n["weight_10+3"], "weight_10+3", 200, -1e+03, 1e+03);
      book(_n["weight_10+2"], "weight_10+2", 200, -1e+02, 1e+02);
      book(_n["weight_10"],   "weight_10",   200, -1e+01, 1e+01);
      book(_n["weight_1"],    "weight_1",    200, -1e+00, 1e+00);

      book(_n["logweight_pos"], "logweight_pos", logspace(100, 1e-5, 1e5));
      book(_n["logweight_neg"], "logweight_neg", logspace(100, 1e-5, 1e5));

      book(_h["xs_10+7"], "xs_10+7", 200, -1e+03, 1e+03);
      book(_h["xs_10+6"], "xs_10+6", 200, -1e+02, 1e+02);
      book(_h["xs_10+5"], "xs_10+5", 200, -1e+01, 1e+01);
      book(_h["xs_10+4"], "xs_10+4", 200, -1e+04, 1e+04);
      book(_h["xs_10+3"], "xs_10+3", 200, -1e+03, 1e+03);
      book(_h["xs_10+2"], "xs_10+2", 200, -1e+02, 1e+02);
      book(_h["xs_10"],   "xs_10",   200, -1e+01, 1e+01);
      book(_h["xs_1"],    "xs_1",    200, -1e+00, 1e+00);

      tripleBook("Njets",    7, -0.5,   6.5);
      tripleBook("Nbjets",   5, -0.5,   4.5);
      tripleBook("HT",      50,   0., 1500.);
      tripleBook("jet1pT", 100,  20., 1000.);
      tripleBook("bjet1pT", 50,  20.,  500.);

      book(_e_xsfraction_neg, "xsfraction_neg");
      book(_e_fracneff, "neff_frac");
      book(_e_neff, "neff");
    }

    void tripleBook(const string& name, size_t nbins, double xmin, double xmax) {
      book(_h[name+"_neg"], name+"_neg", nbins, xmin, xmax);
      book(_h[name+"_pos"], name+"_pos", nbins, xmin, xmax);
      book(_e[name], name, nbins, xmin, xmax);
    }

    /// Perform the per-event analysis
    void analyze(const Event& event) {

      Jets jets = apply<FastJets>(event, "jets").jetsByPt(Cuts::pT > 20*GeV);
      Jets bjets = select(jets, hasBTag(Cuts::pT > 5*GeV));

      const size_t numWeights = event.weights().size();
      for (size_t m = 0; m < numWeights; ++m) {
        const double weight = event.weights()[m];
        _n["weight_10+7"].get()->persistent(m)->fill(weight/1e4, 1.0);
        _n["weight_10+6"].get()->persistent(m)->fill(weight/1e4, 1.0);
        _n["weight_10+5"].get()->persistent(m)->fill(weight/1e4, 1.0);
        _n["weight_10+4"].get()->persistent(m)->fill(weight, 1.0);
        _n["weight_10+3"].get()->persistent(m)->fill(weight, 1.0);
        _n["weight_10+2"].get()->persistent(m)->fill(weight, 1.0);
        _n["weight_10"].get()->persistent(m)->fill(weight, 1.0);
        _n["weight_1"].get()->persistent(m)->fill(weight, 1.0);

        _h["xs_10+7"].get()->persistent(m)->fill(weight/1e4, fabs(weight));
        _h["xs_10+6"].get()->persistent(m)->fill(weight/1e4, fabs(weight));
        _h["xs_10+5"].get()->persistent(m)->fill(weight/1e4, fabs(weight));
        _h["xs_10+4"].get()->persistent(m)->fill(weight, fabs(weight));
        _h["xs_10+3"].get()->persistent(m)->fill(weight, fabs(weight));
        _h["xs_10+2"].get()->persistent(m)->fill(weight, fabs(weight));
        _h["xs_10"].get()->persistent(m)->fill(weight, fabs(weight));
        _h["xs_1"].get()->persistent(m)->fill(weight, fabs(weight));

        if (weight < 0.) {
          _n["logweight_neg"].get()->persistent(m)->fill(fabs(weight), 1.0);
          _h["Njets_neg"].get()->persistent(m)->fill(jets.size(), fabs(weight));
          _h["Nbjets_neg"].get()->persistent(m)->fill(bjets.size(), fabs(weight));
          _h["HT_neg"].get()->persistent(m)->fill(sum(jets, Kin::pT, 0.0)/GeV, fabs(weight));
          if (jets.size()) {
            _h["jet1pT_neg"].get()->persistent(m)->fill(jets[0].pT()/GeV, fabs(weight));
          }
          if (bjets.size()) {
            _h["bjet1pT_neg"].get()->persistent(m)->fill(bjets[0].pT()/GeV, fabs(weight));
          }
        } else {
          _n["logweight_pos"].get()->persistent(m)->fill(weight, 1.0);
          _h["Njets_pos"].get()->persistent(m)->fill(jets.size(), weight);
          _h["Nbjets_pos"].get()->persistent(m)->fill(bjets.size(), weight);
          _h["HT_pos"].get()->persistent(m)->fill(sum(jets, Kin::pT, 0.0)/GeV, weight);
          if (jets.size()) {
            _h["jet1pT_pos"].get()->persistent(m)->fill(jets[0].pT()/GeV, weight);
          }
          if (bjets.size()) {
            _h["bjet1pT_pos"].get()->persistent(m)->fill(bjets[0].pT()/GeV, weight);
          }
        }
      }
    }


    /// Normalise histograms etc., after the run
    void finalize() {

      scale(_n, 1.0 / numEvents());
      scale(_h, crossSection() / picobarn / sumOfWeights());

      const double totalSumW  = _n["logweight_neg"]->sumW()  + _n["logweight_pos"]->sumW();
      const double totalSumW2 = _n["logweight_neg"]->sumW2() + _n["logweight_pos"]->sumW2();
      const double negFrac    = _n["logweight_neg"]->sumW() / totalSumW;
      const double negFracErr = negFrac * totalSumW / sqrt(totalSumW2);

      for (auto& item : _e) {
        const string& aop = item.second->path();
        *item.second = *_h[item.first+"_neg"] / (*_h[item.first+"_neg"] + *_h[item.first+"_pos"]);
        item.second->setPath(aop);
      }

      _e_xsfraction_neg->set(negFrac, negFracErr);
      _e_neff->setVal(effNumEvents());
      _e_fracneff->setVal(effNumEvents()/numEvents());
    }

    /// @}


    /// @name Histograms
    /// @{
    map<string,Histo1DPtr> _h, _n;
    map<string,Estimate1DPtr> _e;
    Estimate0DPtr _e_xsfraction_neg, _e_neff, _e_fracneff;
    /// @}

  };



  RIVET_DECLARE_PLUGIN(MC_WEIGHTS);

}