Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:09:58

0001 #include "FWCore/Framework/interface/Frameworkfwd.h"
0002 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0003 #include "FWCore/Framework/interface/MakerMacros.h"
0004 #include "DQMServices/Core/interface/DQMEDAnalyzer.h"
0005 #include "DQMServices/Core/interface/DQMStore.h"
0006 #include "DQMOffline/Trigger/plugins/TriggerDQMBase.h"
0007 #include "CommonTools/TriggerUtils/interface/GenericTriggerEventFlag.h"
0008 
0009 #include "DataFormats/METReco/interface/PFMET.h"
0010 #include "DataFormats/METReco/interface/PFMETCollection.h"
0011 #include "DataFormats/METReco/interface/MET.h"
0012 #include "DataFormats/METReco/interface/METCollection.h"
0013 #include "DataFormats/JetReco/interface/PFJet.h"
0014 #include "DataFormats/BTauReco/interface/JetTag.h"
0015 #include "DataFormats/Common/interface/TriggerResults.h"
0016 #include "DataFormats/HLTReco/interface/TriggerObject.h"
0017 #include "DataFormats/HLTReco/interface/TriggerEvent.h"
0018 #include "DataFormats/HLTReco/interface/TriggerEventWithRefs.h"
0019 #include "DataFormats/HLTReco/interface/TriggerEventWithRefs.h"
0020 #include "DataFormats/VertexReco/interface/VertexFwd.h"
0021 #include "DataFormats/VertexReco/interface/Vertex.h"
0022 #include "DataFormats/BeamSpot/interface/BeamSpot.h"
0023 #include "DataFormats/Common/interface/ValueMap.h"
0024 #include "DataFormats/MuonReco/interface/MuonFwd.h"
0025 #include "DataFormats/MuonReco/interface/Muon.h"
0026 #include "DataFormats/MuonReco/interface/MuonSelectors.h"
0027 #include "DataFormats/EgammaCandidates/interface/Electron.h"
0028 #include "DataFormats/EgammaCandidates/interface/GsfElectron.h"
0029 #include "DataFormats/EgammaCandidates/interface/Conversion.h"
0030 #include "CommonTools/Egamma/interface/ConversionTools.h"
0031 
0032 #include <limits>
0033 #include <algorithm>
0034 
0035 class LepHTMonitor : public DQMEDAnalyzer, public TriggerDQMBase {
0036 public:
0037   typedef dqm::reco::MonitorElement MonitorElement;
0038   typedef dqm::reco::DQMStore DQMStore;
0039 
0040   LepHTMonitor(const edm::ParameterSet &ps);
0041   ~LepHTMonitor() throw() override;
0042 
0043 protected:
0044   void bookHistograms(DQMStore::IBooker &ibooker, const edm::Run &, const edm::EventSetup &) override;
0045   void analyze(const edm::Event &e, const edm::EventSetup &eSetup) override;
0046 
0047 private:
0048   edm::InputTag theElectronTag_;
0049   edm::EDGetTokenT<edm::View<reco::GsfElectron> > theElectronCollection_;
0050   edm::InputTag theElectronVIDTag_;
0051   edm::EDGetTokenT<edm::ValueMap<bool> > theElectronVIDMap_;
0052   edm::InputTag theMuonTag_;
0053   edm::EDGetTokenT<reco::MuonCollection> theMuonCollection_;
0054   edm::InputTag thePfMETTag_;
0055   edm::EDGetTokenT<reco::PFMETCollection> thePfMETCollection_;
0056   edm::InputTag thePfJetTag_;
0057   edm::EDGetTokenT<reco::PFJetCollection> thePfJetCollection_;
0058   edm::InputTag theJetTagTag_;
0059   edm::EDGetTokenT<reco::JetTagCollection> theJetTagCollection_;
0060   edm::InputTag theVertexCollectionTag_;
0061   edm::EDGetTokenT<reco::VertexCollection> theVertexCollection_;
0062   edm::InputTag theConversionCollectionTag_;
0063   edm::EDGetTokenT<reco::ConversionCollection> theConversionCollection_;
0064   edm::InputTag theBeamSpotTag_;
0065   edm::EDGetTokenT<reco::BeamSpot> theBeamSpot_;
0066 
0067   std::unique_ptr<GenericTriggerEventFlag> num_genTriggerEventFlag_;
0068   std::unique_ptr<GenericTriggerEventFlag> den_lep_genTriggerEventFlag_;
0069   std::unique_ptr<GenericTriggerEventFlag> den_HT_genTriggerEventFlag_;
0070 
0071   const std::string folderName_;
0072 
0073   const bool requireValidHLTPaths_;
0074   bool hltPathsAreValid_;
0075 
0076   int muonIDlevel_;
0077 
0078   double jetPtCut_;
0079   double jetEtaCut_;
0080   double metCut_;
0081   double htCut_;
0082   double nmusCut_;
0083   double nelsCut_;
0084   double lep_pt_plateau_;
0085   double lep_counting_threshold_;
0086   double lep_iso_cut_;
0087   double lep_eta_cut_;
0088   double lep_d0_cut_b_;
0089   double lep_dz_cut_b_;
0090   double lep_d0_cut_e_;
0091   double lep_dz_cut_e_;
0092 
0093   std::vector<double> ptbins_;
0094   std::vector<double> htbins_;
0095   int nbins_eta_;
0096   int nbins_phi_;
0097   int nbins_npv_;
0098   float etabins_min_;
0099   float etabins_max_;
0100   float phibins_min_;
0101   float phibins_max_;
0102   float npvbins_min_;
0103   float npvbins_max_;
0104 
0105   // Histograms
0106   MonitorElement *h_pfHTTurnOn_num_;
0107   MonitorElement *h_pfHTTurnOn_den_;
0108   MonitorElement *h_lepPtTurnOn_num_;
0109   MonitorElement *h_lepPtTurnOn_den_;
0110   MonitorElement *h_lepEtaTurnOn_num_;
0111   MonitorElement *h_lepEtaTurnOn_den_;
0112   MonitorElement *h_lepPhiTurnOn_num_;
0113   MonitorElement *h_lepPhiTurnOn_den_;
0114   MonitorElement *h_lepEtaPhiTurnOn_num_;
0115   MonitorElement *h_lepEtaPhiTurnOn_den_;
0116   MonitorElement *h_NPVTurnOn_num_;
0117   MonitorElement *h_NPVTurnOn_den_;
0118 };
0119 
0120 namespace {
0121 
0122   //Offline electron definition
0123   bool isGood(const reco::GsfElectron &el,
0124               const reco::Vertex::Point &pv_position,
0125               const reco::BeamSpot::Point &bs_position,
0126               const edm::Handle<reco::ConversionCollection> &convs,
0127               bool pass_id,
0128               const double lep_counting_threshold,
0129               const double lep_iso_cut,
0130               const double lep_eta_cut,
0131               const double d0_cut_b,
0132               const double dz_cut_b,
0133               const double d0_cut_e,
0134               const double dz_cut_e) {
0135     //Electron ID
0136     if (!pass_id)
0137       return false;
0138 
0139     //pT
0140     if (el.pt() < lep_counting_threshold || std::abs(el.superCluster()->eta()) > lep_eta_cut)
0141       return false;
0142 
0143     //Isolation
0144     auto const &iso = el.pfIsolationVariables();
0145     const float absiso =
0146         iso.sumChargedHadronPt + std::max(0.0, iso.sumNeutralHadronEt + iso.sumPhotonEt - 0.5 * iso.sumPUPt);
0147     const float relisowithdb = absiso / el.pt();
0148     if (relisowithdb > lep_iso_cut)
0149       return false;
0150 
0151     //Conversion matching
0152     bool pass_conversion = false;
0153     if (convs.isValid()) {
0154       pass_conversion = !ConversionTools::hasMatchedConversion(el, *convs, bs_position);
0155     } else {
0156       edm::LogError("LepHTMonitor") << "Electron conversion matching failed.\n";
0157     }
0158     if (!pass_conversion)
0159       return false;
0160 
0161     //Impact parameter
0162     float d0 = 999., dz = 999.;
0163     if (el.gsfTrack().isNonnull()) {
0164       d0 = -(el.gsfTrack()->dxy(pv_position));
0165       dz = el.gsfTrack()->dz(pv_position);
0166     } else {
0167       edm::LogError("LepHTMonitor") << "Could not read electron.gsfTrack().\n";
0168       return false;
0169     }
0170     float etasc = el.superCluster()->eta();
0171     if (std::abs(etasc) > 1.479) {  //Endcap
0172       if (std::abs(d0) > d0_cut_e || std::abs(dz) > dz_cut_e)
0173         return false;
0174 
0175     } else {  //Barrel
0176       if (std::abs(d0) > d0_cut_b || std::abs(dz) > dz_cut_b)
0177         return false;
0178     }
0179 
0180     return true;
0181   }
0182 
0183   //Offline muon definition
0184   bool isGood(const reco::Muon &mu,
0185               const reco::Vertex &pv,
0186               const double lep_counting_threshold,
0187               const double lep_iso_cut,
0188               const double lep_eta_cut,
0189               const double d0_cut,
0190               const double dz_cut,
0191               int muonIDlevel) {
0192     const reco::Vertex::Point &pv_position = pv.position();
0193 
0194     // Muon pt and eta acceptance
0195     if (mu.pt() < lep_counting_threshold || std::abs(mu.eta()) > lep_eta_cut)
0196       return false;
0197 
0198     // Muon isolation
0199     auto const &iso = mu.pfIsolationR04();
0200     const float absiso =
0201         iso.sumChargedHadronPt + std::max(0.0, iso.sumNeutralHadronEt + iso.sumPhotonEt - 0.5 * iso.sumPUPt);
0202     const float relisowithdb = absiso / mu.pt();
0203     if (relisowithdb > lep_iso_cut)
0204       return false;
0205 
0206     // Muon ID
0207     bool pass_id = false;
0208     if (muonIDlevel == 1)
0209       pass_id = muon::isLooseMuon(mu);
0210     else if (muonIDlevel == 3)
0211       pass_id = muon::isTightMuon(mu, pv);
0212     else
0213       pass_id = muon::isMediumMuon(mu);
0214 
0215     if (!pass_id)
0216       return false;
0217 
0218     // Muon impact parameter
0219     float d0 = std::abs(mu.muonBestTrack()->dxy(pv_position));
0220     float dz = std::abs(mu.muonBestTrack()->dz(pv_position));
0221     if (d0 > d0_cut || dz > dz_cut)
0222       return false;
0223 
0224     return true;
0225   }
0226 }  // namespace
0227 
0228 LepHTMonitor::LepHTMonitor(const edm::ParameterSet &ps)
0229     : theElectronTag_(ps.getParameter<edm::InputTag>("electronCollection")),
0230       theElectronCollection_(consumes<edm::View<reco::GsfElectron> >(theElectronTag_)),
0231       theElectronVIDTag_(ps.getParameter<edm::InputTag>("electronVID")),
0232       theElectronVIDMap_(consumes<edm::ValueMap<bool> >(theElectronVIDTag_)),
0233       theMuonTag_(ps.getParameter<edm::InputTag>("muonCollection")),
0234       theMuonCollection_(consumes<reco::MuonCollection>(theMuonTag_)),
0235       thePfMETTag_(ps.getParameter<edm::InputTag>("pfMetCollection")),
0236       thePfMETCollection_(consumes<reco::PFMETCollection>(thePfMETTag_)),
0237       thePfJetTag_(ps.getParameter<edm::InputTag>("pfJetCollection")),
0238       thePfJetCollection_(consumes<reco::PFJetCollection>(thePfJetTag_)),
0239       theJetTagTag_(ps.getParameter<edm::InputTag>("jetTagCollection")),
0240       theJetTagCollection_(consumes<reco::JetTagCollection>(theJetTagTag_)),
0241       theVertexCollectionTag_(ps.getParameter<edm::InputTag>("vertexCollection")),
0242       theVertexCollection_(consumes<reco::VertexCollection>(theVertexCollectionTag_)),
0243       theConversionCollectionTag_(ps.getParameter<edm::InputTag>("conversionCollection")),
0244       theConversionCollection_(consumes<reco::ConversionCollection>(theConversionCollectionTag_)),
0245       theBeamSpotTag_(ps.getParameter<edm::InputTag>("beamSpot")),
0246       theBeamSpot_(consumes<reco::BeamSpot>(theBeamSpotTag_)),
0247 
0248       num_genTriggerEventFlag_(new GenericTriggerEventFlag(
0249           ps.getParameter<edm::ParameterSet>("numGenericTriggerEventPSet"), consumesCollector(), *this)),
0250       den_lep_genTriggerEventFlag_(new GenericTriggerEventFlag(
0251           ps.getParameter<edm::ParameterSet>("den_lep_GenericTriggerEventPSet"), consumesCollector(), *this)),
0252       den_HT_genTriggerEventFlag_(new GenericTriggerEventFlag(
0253           ps.getParameter<edm::ParameterSet>("den_HT_GenericTriggerEventPSet"), consumesCollector(), *this)),
0254 
0255       folderName_(ps.getParameter<std::string>("folderName")),
0256       requireValidHLTPaths_(ps.getParameter<bool>("requireValidHLTPaths")),
0257       hltPathsAreValid_(false),
0258 
0259       muonIDlevel_(ps.getUntrackedParameter<int>("muonIDlevel")),
0260       jetPtCut_(ps.getUntrackedParameter<double>("jetPtCut")),
0261       jetEtaCut_(ps.getUntrackedParameter<double>("jetEtaCut")),
0262       metCut_(ps.getUntrackedParameter<double>("metCut")),
0263       htCut_(ps.getUntrackedParameter<double>("htCut")),
0264 
0265       nmusCut_(ps.getUntrackedParameter<double>("nmus")),
0266       nelsCut_(ps.getUntrackedParameter<double>("nels")),
0267       lep_pt_plateau_(ps.getUntrackedParameter<double>("leptonPtPlateau")),
0268       lep_counting_threshold_(ps.getUntrackedParameter<double>("leptonCountingThreshold")),
0269       lep_iso_cut_(ps.getUntrackedParameter<double>("lepIsoCut")),
0270       lep_eta_cut_(ps.getUntrackedParameter<double>("lepEtaCut")),
0271       lep_d0_cut_b_(ps.getUntrackedParameter<double>("lep_d0_cut_b")),
0272       lep_dz_cut_b_(ps.getUntrackedParameter<double>("lep_dz_cut_b")),
0273       lep_d0_cut_e_(ps.getUntrackedParameter<double>("lep_d0_cut_e")),
0274       lep_dz_cut_e_(ps.getUntrackedParameter<double>("lep_dz_cut_e")),
0275       ptbins_(ps.getParameter<std::vector<double> >("ptbins")),
0276       htbins_(ps.getParameter<std::vector<double> >("htbins")),
0277 
0278       nbins_eta_(ps.getUntrackedParameter<int>("nbins_eta")),
0279       nbins_phi_(ps.getUntrackedParameter<int>("nbins_phi")),
0280       nbins_npv_(ps.getUntrackedParameter<int>("nbins_npv")),
0281       etabins_min_(ps.getUntrackedParameter<double>("etabins_min")),
0282       etabins_max_(ps.getUntrackedParameter<double>("etabins_max")),
0283       phibins_min_(ps.getUntrackedParameter<double>("phibins_min")),
0284       phibins_max_(ps.getUntrackedParameter<double>("phibins_max")),
0285       npvbins_min_(ps.getUntrackedParameter<double>("npvbins_min")),
0286       npvbins_max_(ps.getUntrackedParameter<double>("npvbins_max")),
0287 
0288       h_pfHTTurnOn_num_(nullptr),
0289       h_pfHTTurnOn_den_(nullptr),
0290       h_lepPtTurnOn_num_(nullptr),
0291       h_lepPtTurnOn_den_(nullptr),
0292       h_lepEtaTurnOn_num_(nullptr),
0293       h_lepEtaTurnOn_den_(nullptr),
0294       h_lepPhiTurnOn_num_(nullptr),
0295       h_lepPhiTurnOn_den_(nullptr),
0296       h_NPVTurnOn_num_(nullptr),
0297       h_NPVTurnOn_den_(nullptr) {
0298   edm::LogInfo("LepHTMonitor") << "Constructor LepHTMonitor::LepHTMonitor\n";
0299 }
0300 
0301 LepHTMonitor::~LepHTMonitor() throw() {
0302   if (num_genTriggerEventFlag_) {
0303     num_genTriggerEventFlag_.reset();
0304   }
0305   if (den_lep_genTriggerEventFlag_) {
0306     den_lep_genTriggerEventFlag_.reset();
0307   }
0308   if (den_HT_genTriggerEventFlag_) {
0309     den_HT_genTriggerEventFlag_.reset();
0310   }
0311 }
0312 
0313 void LepHTMonitor::bookHistograms(DQMStore::IBooker &ibooker, const edm::Run &iRun, const edm::EventSetup &iSetup) {
0314   // Initialize trigger flags
0315   if (num_genTriggerEventFlag_ && num_genTriggerEventFlag_->on()) {
0316     num_genTriggerEventFlag_->initRun(iRun, iSetup);
0317   }
0318   if (den_lep_genTriggerEventFlag_ && den_lep_genTriggerEventFlag_->on()) {
0319     den_lep_genTriggerEventFlag_->initRun(iRun, iSetup);
0320   }
0321   if (den_HT_genTriggerEventFlag_ && den_HT_genTriggerEventFlag_->on()) {
0322     den_HT_genTriggerEventFlag_->initRun(iRun, iSetup);
0323   }
0324 
0325   // check if every HLT path specified in numerator and denominator has a valid match in the HLT Menu
0326   hltPathsAreValid_ = ((num_genTriggerEventFlag_ && num_genTriggerEventFlag_->on() &&
0327                         num_genTriggerEventFlag_->allHLTPathsAreValid()) &&
0328                        ((den_lep_genTriggerEventFlag_ && den_lep_genTriggerEventFlag_->on() &&
0329                          den_lep_genTriggerEventFlag_->allHLTPathsAreValid()) ||
0330                         (den_HT_genTriggerEventFlag_ && den_HT_genTriggerEventFlag_->on() &&
0331                          den_HT_genTriggerEventFlag_->allHLTPathsAreValid())));
0332 
0333   // if valid HLT paths are required,
0334   // create DQM outputs only if all paths are valid
0335   if (requireValidHLTPaths_ and (not hltPathsAreValid_)) {
0336     return;
0337   }
0338 
0339   // book at beginRun
0340   ibooker.cd();
0341   ibooker.setCurrentFolder("HLT/SUSY/LepHT/" + folderName_);
0342 
0343   bool is_mu = false;
0344   bool is_ele = false;
0345   if (theElectronTag_.label().empty() and not theMuonTag_.label().empty()) {
0346     is_mu = true;
0347   } else if (not theElectronTag_.label().empty() and theMuonTag_.label().empty()) {
0348     is_ele = true;
0349   }
0350 
0351   // Cosmetic axis names
0352   std::string lepton = "lepton", Lepton = "Lepton";
0353   if (is_mu && !is_ele) {
0354     lepton = "muon";
0355     Lepton = "Muon";
0356   } else if (is_ele && !is_mu) {
0357     lepton = "electron";
0358     Lepton = "Electron";
0359   }
0360 
0361   //Convert to vfloat for picky TH1F constructor
0362   vector<float> f_ptbins;
0363   f_ptbins.reserve(ptbins_.size());
0364   for (double ptbin : ptbins_)
0365     f_ptbins.push_back(static_cast<float>(ptbin));
0366   vector<float> f_htbins;
0367   f_htbins.reserve(htbins_.size());
0368   for (double htbin : htbins_)
0369     f_htbins.push_back(static_cast<float>(htbin));
0370 
0371   //num and den hists to be divided in harvesting step to make turn on curves
0372   h_pfHTTurnOn_num_ =
0373       ibooker.book1D("pfHTTurnOn_num", "Numerator;Offline H_{T} [GeV];", f_htbins.size() - 1, f_htbins.data());
0374   h_pfHTTurnOn_den_ =
0375       ibooker.book1D("pfHTTurnOn_den", "Denominator;Offline H_{T} [GeV];", f_htbins.size() - 1, f_htbins.data());
0376 
0377   h_lepPtTurnOn_num_ = ibooker.book1D("lepPtTurnOn_num",
0378                                       ("Numerator;Offline " + lepton + " p_{T} [GeV];").c_str(),
0379                                       f_ptbins.size() - 1,
0380                                       f_ptbins.data());
0381   h_lepPtTurnOn_den_ = ibooker.book1D("lepPtTurnOn_den",
0382                                       ("Denominator;Offline " + lepton + " p_{T} [GeV];").c_str(),
0383                                       f_ptbins.size() - 1,
0384                                       f_ptbins.data());
0385   h_lepEtaTurnOn_num_ =
0386       ibooker.book1D("lepEtaTurnOn_num", "Numerator;Offline lepton #eta;", nbins_eta_, etabins_min_, etabins_max_);
0387   h_lepEtaTurnOn_den_ =
0388       ibooker.book1D("lepEtaTurnOn_den", "Denominator;Offline lepton #eta;", nbins_eta_, etabins_min_, etabins_max_);
0389   h_lepPhiTurnOn_num_ =
0390       ibooker.book1D("lepPhiTurnOn_num", "Numerator;Offline lepton #phi;", nbins_phi_, phibins_min_, phibins_max_);
0391   h_lepPhiTurnOn_den_ =
0392       ibooker.book1D("lepPhiTurnOn_den", "Denominator;Offline lepton #phi;", nbins_phi_, phibins_min_, phibins_max_);
0393 
0394   h_lepEtaPhiTurnOn_num_ = ibooker.book2D("lepEtaPhiTurnOn_num",
0395                                           "Numerator;Offline lepton #eta;Offline lepton #phi;",
0396                                           nbins_eta_ / 2,
0397                                           etabins_min_,
0398                                           etabins_max_,
0399                                           nbins_phi_ / 2,
0400                                           phibins_min_,
0401                                           phibins_max_);
0402   h_lepEtaPhiTurnOn_den_ = ibooker.book2D("lepEtaPhiTurnOn_den",
0403                                           "Denominator;Offline lepton #eta;Offline lepton #phi;",
0404                                           nbins_eta_ / 2,
0405                                           etabins_min_,
0406                                           etabins_max_,
0407                                           nbins_phi_ / 2,
0408                                           phibins_min_,
0409                                           phibins_max_);
0410 
0411   h_NPVTurnOn_num_ = ibooker.book1D("NPVTurnOn_num", "Numerator;N_{PV};", nbins_npv_, npvbins_min_, npvbins_max_);
0412   h_NPVTurnOn_den_ = ibooker.book1D("NPVTurnOn_den", "Denominator;N_{PV};", nbins_npv_, npvbins_min_, npvbins_max_);
0413 
0414   ibooker.cd();
0415 }
0416 
0417 void LepHTMonitor::analyze(const edm::Event &e, const edm::EventSetup &eSetup) {
0418   // if valid HLT paths are required,
0419   // analyze event only if all paths are valid
0420   if (requireValidHLTPaths_ and (not hltPathsAreValid_)) {
0421     return;
0422   }
0423 
0424   // Find whether main and auxilliary triggers fired
0425   bool hasFired = false;
0426   bool hasFiredAuxiliary = false;
0427   bool hasFiredLeptonAuxiliary = false;
0428   if (den_lep_genTriggerEventFlag_->on() && den_lep_genTriggerEventFlag_->accept(e, eSetup))
0429     hasFiredLeptonAuxiliary = true;
0430   if (den_HT_genTriggerEventFlag_->on() && den_HT_genTriggerEventFlag_->accept(e, eSetup))
0431     hasFiredAuxiliary = true;
0432   if (num_genTriggerEventFlag_->on() && num_genTriggerEventFlag_->accept(e, eSetup))
0433     hasFired = true;
0434 
0435   if (!(hasFiredAuxiliary || hasFiredLeptonAuxiliary))
0436     return;
0437   int npv = 0;
0438   //Vertex
0439   edm::Handle<reco::VertexCollection> VertexCollection;
0440   if (not theVertexCollectionTag_.label().empty()) {
0441     e.getByToken(theVertexCollection_, VertexCollection);
0442     if (!VertexCollection.isValid()) {
0443       edm::LogWarning("LepHTMonitor") << "Invalid VertexCollection: " << theVertexCollectionTag_.label() << '\n';
0444     } else
0445       npv = VertexCollection->size();
0446   }
0447 
0448   //Get electron ID map
0449   edm::Handle<edm::ValueMap<bool> > ele_id_decisions;
0450   if (not theElectronVIDTag_.label().empty()) {
0451     e.getByToken(theElectronVIDMap_, ele_id_decisions);
0452     if (!ele_id_decisions.isValid()) {
0453       edm::LogWarning("LepHTMonitor") << "Invalid Electron VID map: " << theElectronVIDTag_.label() << '\n';
0454     }
0455   }
0456 
0457   //Conversions
0458   edm::Handle<reco::ConversionCollection> ConversionCollection;
0459   if (not theConversionCollectionTag_.label().empty()) {
0460     e.getByToken(theConversionCollection_, ConversionCollection);
0461     if (!ConversionCollection.isValid()) {
0462       edm::LogWarning("LepHTMonitor") << "Invalid ConversionCollection: " << theConversionCollectionTag_.label()
0463                                       << '\n';
0464     }
0465   }
0466 
0467   //Beam Spot
0468   edm::Handle<reco::BeamSpot> BeamSpot;
0469   if (not theBeamSpotTag_.label().empty()) {
0470     e.getByToken(theBeamSpot_, BeamSpot);
0471     if (!BeamSpot.isValid()) {
0472       edm::LogWarning("LepHTMonitor") << "Invalid BeamSpot: " << theBeamSpotTag_.label() << '\n';
0473     }
0474   }
0475 
0476   //MET
0477   edm::Handle<reco::PFMETCollection> pfMETCollection;
0478   if (not thePfMETTag_.label().empty()) {
0479     e.getByToken(thePfMETCollection_, pfMETCollection);
0480     if (!pfMETCollection.isValid()) {
0481       edm::LogWarning("LepHTMonitor") << "Invalid PFMETCollection: " << thePfMETTag_.label() << '\n';
0482     }
0483   }
0484 
0485   //Jets
0486   edm::Handle<reco::PFJetCollection> pfJetCollection;
0487   if (not thePfJetTag_.label().empty()) {
0488     e.getByToken(thePfJetCollection_, pfJetCollection);
0489     if (!pfJetCollection.isValid()) {
0490       edm::LogWarning("LepHTMonitor") << "Invalid PFJetCollection: " << thePfJetTag_.label() << '\n';
0491     }
0492   }
0493 
0494   //Electron
0495   edm::Handle<edm::View<reco::GsfElectron> > ElectronCollection;
0496   if (not theElectronTag_.label().empty()) {
0497     e.getByToken(theElectronCollection_, ElectronCollection);
0498     if (!ElectronCollection.isValid()) {
0499       edm::LogWarning("LepHTMonitor") << "Invalid GsfElectronCollection: " << theElectronTag_.label() << '\n';
0500     }
0501   }
0502 
0503   //Muon
0504   edm::Handle<reco::MuonCollection> MuonCollection;
0505   if (not theMuonTag_.label().empty()) {
0506     e.getByToken(theMuonCollection_, MuonCollection);
0507     if (!MuonCollection.isValid()) {
0508       edm::LogWarning("LepHTMonitor") << "Invalid MuonCollection: " << theMuonTag_.label() << '\n';
0509     }
0510   }
0511 
0512   //Get offline HT
0513   double pfHT = -1.0;
0514   if (pfJetCollection.isValid()) {
0515     pfHT = 0.0;
0516     for (auto const &pfjet : *pfJetCollection) {
0517       if (pfjet.pt() < jetPtCut_)
0518         continue;
0519       if (std::abs(pfjet.eta()) > jetEtaCut_)
0520         continue;
0521       pfHT += pfjet.pt();
0522     }
0523   }
0524 
0525   //Get offline MET
0526   double pfMET = -1.0;
0527   if (pfMETCollection.isValid() && !pfMETCollection->empty()) {
0528     pfMET = pfMETCollection->front().et();
0529   }
0530 
0531   //Find offline leptons and keep track of pt,eta of leading and trailing leptons
0532   double lep_max_pt = -1.0;
0533   double lep_eta = 0;
0534   double lep_phi = 0;
0535   double trailing_ele_eta = 0;
0536   double trailing_ele_phi = 0;
0537   double trailing_mu_eta = 0;
0538   double trailing_mu_phi = 0;
0539   double min_ele_pt = -1.0;
0540   double min_mu_pt = -1.0;
0541   int nels = 0;
0542   int nmus = 0;
0543   if (VertexCollection.isValid() && !VertexCollection->empty()) {  //for quality checks
0544     //Try to find a reco electron
0545     if (ElectronCollection.isValid() && ConversionCollection.isValid() && BeamSpot.isValid() &&
0546         ele_id_decisions.isValid()) {
0547       size_t index = 0;
0548       for (auto const &electron : *ElectronCollection) {
0549         const auto el = ElectronCollection->ptrAt(index);
0550         bool pass_id = (*ele_id_decisions)[el];
0551         if (isGood(electron,
0552                    VertexCollection->front().position(),
0553                    BeamSpot->position(),
0554                    ConversionCollection,
0555                    pass_id,
0556                    lep_counting_threshold_,
0557                    lep_iso_cut_,
0558                    lep_eta_cut_,
0559                    lep_d0_cut_b_,
0560                    lep_dz_cut_b_,
0561                    lep_d0_cut_e_,
0562                    lep_dz_cut_e_)) {
0563           if (electron.pt() > lep_max_pt) {
0564             lep_max_pt = electron.pt();
0565             lep_eta = electron.eta();
0566             lep_phi = electron.phi();
0567           }
0568           if (electron.pt() < min_ele_pt || min_ele_pt < 0) {
0569             min_ele_pt = electron.pt();
0570             trailing_ele_eta = electron.eta();
0571             trailing_ele_phi = electron.phi();
0572           }
0573           nels++;
0574         }
0575         index++;
0576       }
0577     }
0578 
0579     //Try to find a reco muon
0580     if (MuonCollection.isValid()) {
0581       for (auto const &muon : *MuonCollection) {
0582         if (isGood(muon,
0583                    VertexCollection->front(),
0584                    lep_counting_threshold_,
0585                    lep_iso_cut_,
0586                    lep_eta_cut_,
0587                    lep_d0_cut_b_,
0588                    lep_dz_cut_b_,
0589                    muonIDlevel_)) {
0590           if (muon.pt() > lep_max_pt) {
0591             lep_max_pt = muon.pt();
0592             lep_eta = muon.eta();
0593             lep_phi = muon.phi();
0594           }
0595           if (muon.pt() < min_mu_pt || min_mu_pt < 0) {
0596             min_mu_pt = muon.pt();
0597             trailing_mu_eta = muon.eta();
0598             trailing_mu_phi = muon.phi();
0599           }
0600           nmus++;
0601         }
0602       }
0603     }
0604   }
0605 
0606   //Fill single lepton triggers with leading lepton pT
0607   float lep_pt = lep_max_pt;
0608 
0609   //For dilepton triggers, use trailing rather than leading lepton
0610   if (nmusCut_ >= 2) {
0611     lep_pt = min_mu_pt;
0612     lep_eta = trailing_mu_eta;
0613     lep_phi = trailing_mu_phi;
0614   }
0615   if (nelsCut_ >= 2) {
0616     lep_pt = min_ele_pt;
0617     lep_eta = trailing_ele_eta;
0618     lep_phi = trailing_ele_phi;
0619   }
0620   if (nelsCut_ >= 1 && nmusCut_ >= 1) {
0621     if (min_ele_pt < min_mu_pt) {
0622       lep_pt = min_ele_pt;
0623       lep_eta = trailing_ele_eta;
0624       lep_phi = trailing_ele_phi;
0625     } else {
0626       lep_pt = min_mu_pt;
0627       lep_eta = trailing_mu_eta;
0628       lep_phi = trailing_mu_phi;
0629     }
0630   }
0631 
0632   const bool nleps_cut = nels >= nelsCut_ && nmus >= nmusCut_;
0633   bool lep_plateau = lep_pt > lep_pt_plateau_ || lep_pt_plateau_ < 0.0;
0634 
0635   //Fill lepton pT and eta histograms
0636   if (hasFiredLeptonAuxiliary || !e.isRealData()) {
0637     if (nleps_cut && (pfMET > metCut_ || metCut_ < 0.0) && (pfHT > htCut_ || htCut_ < 0.0)) {
0638       if (h_lepPtTurnOn_den_) {
0639         if (lep_pt > ptbins_.back())
0640           lep_pt = ptbins_.back() - 1;  //Overflow protection
0641         h_lepPtTurnOn_den_->Fill(lep_pt);
0642       }
0643       if (h_lepPtTurnOn_num_ && hasFired)
0644         h_lepPtTurnOn_num_->Fill(lep_pt);
0645 
0646       if (lep_plateau) {
0647         //Fill Eta and Phi histograms for leptons above pT threshold
0648         if (h_lepEtaTurnOn_den_)
0649           h_lepEtaTurnOn_den_->Fill(lep_eta);
0650         if (h_lepEtaTurnOn_num_ && hasFired)
0651           h_lepEtaTurnOn_num_->Fill(lep_eta);
0652         if (h_lepPhiTurnOn_den_)
0653           h_lepPhiTurnOn_den_->Fill(lep_phi);
0654         if (h_lepPhiTurnOn_num_ && hasFired)
0655           h_lepPhiTurnOn_num_->Fill(lep_phi);
0656         if (h_lepEtaPhiTurnOn_den_)
0657           h_lepEtaPhiTurnOn_den_->Fill(lep_eta, lep_phi);
0658         if (h_lepEtaPhiTurnOn_num_ && hasFired)
0659           h_lepEtaPhiTurnOn_num_->Fill(lep_eta, lep_phi);
0660 
0661         //Fill NPV histograms
0662         if (h_NPVTurnOn_den_)
0663           h_NPVTurnOn_den_->Fill(npv);
0664         if (h_NPVTurnOn_num_ && hasFired)
0665           h_NPVTurnOn_num_->Fill(npv);
0666       }
0667     }
0668   }
0669 
0670   //Fill HT turn-on histograms
0671   if (hasFiredAuxiliary || !e.isRealData()) {
0672     if (nleps_cut && lep_plateau) {
0673       if (h_pfHTTurnOn_den_) {
0674         if (pfHT > htbins_.back())
0675           pfHT = htbins_.back() - 1;  //Overflow protection
0676         h_pfHTTurnOn_den_->Fill(pfHT);
0677       }
0678       if (h_pfHTTurnOn_num_ && hasFired)
0679         h_pfHTTurnOn_num_->Fill(pfHT);
0680     }
0681   }
0682 }
0683 
0684 DEFINE_FWK_MODULE(LepHTMonitor);