Rivet analyses

Measurement of the differential Drell-Yan cross section in proton-proton collisions at $\sqrt{s} = 13\,TeV$

Experiment: CMS (LHC)

Inspire ID: 1711625

Status: VALIDATED

Authors: - cms-pag-conveners-smp@cern.ch - Kyeongpil Lee

References: - arXiv: 1812.10529 - SMP-17-001 - JHEP 1912 (2019) 059

Beams: p+ p+

Beam energies: (6500.0, 6500.0)GeV

Run details: - pp to Z interactions at $\sqrt{s} = 13$ TeV. Data collected by CMS during the year 2015.

Differential Drell-Yan cross sections dσ/dm are presented. The cross section measurement is reported in the dilepton invariant mass range from 15 to 3000 GeV. The results within detector acceptance are provided in muon and electron channel respectively. In addition, the results in muon channel are also obtained with the correction to the full phase space and the other correction for the effects of final state radiation.

Source code:CMS_2018_I1711625.cc

// -*- C++ -*-
#include "Rivet/Analysis.hh"
#include "Rivet/Projections/FinalState.hh"
#include "Rivet/Projections/PromptFinalState.hh"
#include "Rivet/Projections/LeptonFinder.hh"

namespace Rivet {


  /// Drell-Yan differential cross section measurement @ 13 TeV
  class CMS_2018_I1711625 : public Analysis {
  public:

    /// Constructor
    RIVET_DEFAULT_ANALYSIS_CTOR(CMS_2018_I1711625);


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

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

      // prompt final state electrons
      const PromptFinalState el_pfs = PromptFinalState(Cuts::abspid == PID::ELECTRON);
      declare(el_pfs, "PromptFinalStateElectrons");

      // prompt final state muons
      const PromptFinalState mu_pfs = PromptFinalState(Cuts::abspid == PID::MUON);
      declare(mu_pfs, "PromptFinalStateMuons");

      // dressed leptons
      const FinalState photon_fs = FinalState(Cuts::abspid == PID::PHOTON);

      const LeptonFinder mu_dressed(mu_pfs, photon_fs, 0.1, Cuts::open());
      declare(mu_dressed, "DressedMuons");

      book(_h_massMuMu, 3, 1, 1); /// muon channel result in full-phase space @ dressed level
      book(_h_massMuMuFiducial, 5, 1, 1); /// muon channel result in fiducial region @ post-FSR level
      book(_h_massEEFiducial, 6, 1, 1); /// electron channel result in fiducial region @ post-FSR level
    }


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

      const LeptonFinder muons_dressed = apply<LeptonFinder>(event, "DressedMuons");
      bool filled_mu = FillHistogram_DressedLepton(muons_dressed, 13);
      if ( filled_mu ) {

        const PromptFinalState muons_PFS = apply<PromptFinalState>(event, "PromptFinalStateMuons");
        FillHistogram_PFSLepton(muons_PFS, 13);
      }
      else { // electron channel

        const PromptFinalState electrons_PFS = apply<PromptFinalState>(event, "PromptFinalStateElectrons");
        FillHistogram_PFSLepton(electrons_PFS, 11);
      }
    }


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

      scale(_h_massMuMu, crossSection()/picobarn/sumOfWeights()); /// norm to cross section
      scale(_h_massMuMuFiducial, crossSection()/picobarn/sumOfWeights()); /// norm to cross section
      scale(_h_massEEFiducial, crossSection()/picobarn/sumOfWeights()); /// norm to cross section

    }

    /// @}


  private:


    /// @name Histograms
    /// @{
    Histo1DPtr _h_massMuMu;
    Histo1DPtr _h_massMuMuFiducial;
    Histo1DPtr _h_massEEFiducial;
    /// @}


    // select two opposite sign leptons with highest pT & fill the histogram for full-phase space diff. x-section
    bool FillHistogram_DressedLepton(LeptonFinder leptons_dressed, int leptonID) {
      bool filled = false;

      vector< DressedLepton > vec_dressedLepByPt = leptons_dressed.dressedLeptons();

      int nLepton_dressed = (int)vec_dressedLepByPt.size();
      if ( nLepton_dressed >= 2 ) {
        int index_lepton1 = -1;
        int index_lepton2 = -1;
        FindDressedLeptonPair_HighestPt(vec_dressedLepByPt, index_lepton1, index_lepton2);

        if ( index_lepton1 != -1 && index_lepton2 != -1 ) {
          DressedLepton lepton1_dressed = vec_dressedLepByPt[index_lepton1];
          DressedLepton lepton2_dressed = vec_dressedLepByPt[index_lepton2];

          const FourMomentum pVec_diLep = lepton1_dressed.mom() + lepton2_dressed.mom();
          double mass = pVec_diLep.mass();

          // // fill histograms
          if ( leptonID == 13 ) _h_massMuMu->fill(mass/GeV);

          filled = true;
        }
      } // end of if( nLepton_dressed >= 2 )

      return filled;
    }


    void FindDressedLeptonPair_HighestPt(DressedLeptons& vec_dressedLepByPt, int& index_lepton1, int& index_lepton2) {
      // 1st lepton: lepton with highest pT
      int nLepton_dressed = int(vec_dressedLepByPt.size());
      for (int i=0; i<nLepton_dressed; ++i) {
        auto& lepton = vec_dressedLepByPt[i]; // decreasing order of pT
        if ( lepton.isLepton() ) {
          index_lepton1 = i;
          break;
        }
      }

      // if no lepton is found in the leptons_dressed
      if ( index_lepton1 < 0 ) {
        index_lepton1 = -1;
        index_lepton2 = -1;
        return;
      }

      // 2nd lepton: lepton with highest-pT among the leptons with the opposite sign with 1st lepton
      int pdgID_lepton1 = vec_dressedLepByPt[index_lepton1].pid();
      for (int i=index_lepton1+1; i<nLepton_dressed; ++i) { // starting after lepton1
        auto& lepton = vec_dressedLepByPt[i];
        if ( lepton.isLepton() && lepton.pid() == (-1)*pdgID_lepton1 ) {
          index_lepton2 = i;
          break;
        }
      }
    }


    // select two opposite sign leptons with highest pT & fill the histogram for the fiducial diff. x-section
    void FillHistogram_PFSLepton(PromptFinalState leptons_PFS, int leptonID) {
      vector< Particle > vec_PFSLepByPt = leptons_PFS.particlesByPt();

      int nLepton_PFS = int(vec_PFSLepByPt.size());
      if ( nLepton_PFS >= 2 ) {
        int index_lepton1 = -1;
        int index_lepton2 = -1;
        FindPFSLeptonPair_HighestPtWithinAcc(vec_PFSLepByPt, leptonID, index_lepton1, index_lepton2);
        if ( index_lepton1 != -1 && index_lepton2 != -1 ) {
          Particle lepton1_PFS = leptons_PFS.particlesByPt()[index_lepton1];
          Particle lepton2_PFS = leptons_PFS.particlesByPt()[index_lepton2];

          const FourMomentum pVec_diLep = lepton1_PFS.mom() + lepton2_PFS.mom();
          double mass = pVec_diLep.mass();

          if      ( leptonID == 11 ) _h_massEEFiducial->fill(mass/GeV);
          else if ( leptonID == 13 ) _h_massMuMuFiducial->fill(mass/GeV);
        }
      } // end of if ( nLepton_PFS >= 2 )
    }


    void FindPFSLeptonPair_HighestPtWithinAcc(vector<Particle>& vec_PFSLepByPt, int pdgID, int& index_lepton1, int& index_lepton2) {
      double pTCut_lead = 0;
      if ( pdgID == 11 ) pTCut_lead = 30.0;
      if ( pdgID == 13 ) pTCut_lead = 22.0;
      double pTCut_sub = 10.0; // same for both channel

      double etaCut_lead = 0;
      if ( pdgID == 11 ) etaCut_lead = 2.5;
      if ( pdgID == 13 ) etaCut_lead = 2.4;
      double etaCut_sub = etaCut_lead;

      int nLepton = int(vec_PFSLepByPt.size());
      for (int i=0; i<nLepton; ++i) {
        auto& lepton = vec_PFSLepByPt[i];
        if ( lepton.isLepton() && lepton.pT() > pTCut_lead && lepton.abseta() < etaCut_lead ) {
          if ( pdgID == 11 ) { // electron channel: check ECAL gap
            if ( !(lepton.abseta() > 1.4442 && lepton.abseta() < 1.566) ) {
              index_lepton1 = i;
              break;
            }
          }
          else { // muon channel
            index_lepton1 = i;
            break;
          }
        }
      } // end of lepton iteration

      // if no lepton is found in the leptons_PFS
      if ( index_lepton1 < 0 ) {
        index_lepton1 = -1;
        index_lepton2 = -1;
        return;
      }

      // 2nd lepton: lepton with highest-pT among the leptons with the opposite sign with 1st lepton
      int pdgID_lepton1 = vec_PFSLepByPt[index_lepton1].pid();
      for (int i=index_lepton1+1; i<nLepton; ++i) { // starting after lepton1
        auto& lepton = vec_PFSLepByPt[i];
        if ( lepton.isLepton() && lepton.pid() == (-1)*pdgID_lepton1 &&
             lepton.pT() > pTCut_sub && lepton.abseta() < etaCut_sub ) {
          if ( pdgID == 11 ) { // electron channel: check ECAL gap
            if ( !(lepton.abseta() > 1.4442 && lepton.abseta() < 1.566) ) {
              index_lepton2 = i;
              break;
            }
          }
          else { // muon channel
            index_lepton2 = i;
            break;
          }
        }
      } // end of lepton iteration
    }
  };


  RIVET_DECLARE_PLUGIN(CMS_2018_I1711625);


}