From 47631d50a3a3b698576ef05a0a658bab14068a19 Mon Sep 17 00:00:00 2001 From: David Walter Date: Mon, 19 Feb 2018 10:10:40 +0100 Subject: [PATCH 01/17] DeepNtuplizer can now run on Data and MC, DeepNtuplizer_tt_dilep.py makes a preselection for ttbar events; Add branches isRealData and event_weight; Add small programs PupMCHistProd.py, PupWeightMaker.py and LHEcounter.py for computation of pileup weights and the effective event number for events with lhe weights --- .idea/webServers.xml | 15 + DeepNtuplizer/interface/ntuple_JetInfo.h | 26 +- DeepNtuplizer/plots/plot_features.py | 201 +++++++++ DeepNtuplizer/plugins/DeepNtuplizer.cc | 39 +- DeepNtuplizer/plugins/ElectronIdAdder.cc | 86 ++++ DeepNtuplizer/plugins/MuonIdAdder.cc | 50 +++ DeepNtuplizer/plugins/lheAnalyzer.cc | 141 +++++++ DeepNtuplizer/plugins/puAnalyzer.cc | 146 +++++++ .../production/DeepNtuplizer_tt_dilep.py | 397 ++++++++++++++++++ DeepNtuplizer/python/DeepNtuplizer_cfi.py | 10 +- DeepNtuplizer/python/LHEcounter.py | 93 ++++ DeepNtuplizer/python/PupMCHistProd.py | 88 ++++ DeepNtuplizer/python/PupWeightMaker.py | 28 ++ DeepNtuplizer/src/ntuple_JetInfo.cc | 219 ++++++---- 14 files changed, 1436 insertions(+), 103 deletions(-) create mode 100644 .idea/webServers.xml create mode 100644 DeepNtuplizer/plots/plot_features.py create mode 100644 DeepNtuplizer/plugins/ElectronIdAdder.cc create mode 100644 DeepNtuplizer/plugins/MuonIdAdder.cc create mode 100644 DeepNtuplizer/plugins/lheAnalyzer.cc create mode 100644 DeepNtuplizer/plugins/puAnalyzer.cc create mode 100644 DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py create mode 100644 DeepNtuplizer/python/LHEcounter.py create mode 100644 DeepNtuplizer/python/PupMCHistProd.py create mode 100644 DeepNtuplizer/python/PupWeightMaker.py diff --git a/.idea/webServers.xml b/.idea/webServers.xml new file mode 100644 index 00000000000..e2a1442af4f --- /dev/null +++ b/.idea/webServers.xml @@ -0,0 +1,15 @@ + + + + + + \ No newline at end of file diff --git a/DeepNtuplizer/interface/ntuple_JetInfo.h b/DeepNtuplizer/interface/ntuple_JetInfo.h index c99a0b7117d..6cea78b8742 100644 --- a/DeepNtuplizer/interface/ntuple_JetInfo.h +++ b/DeepNtuplizer/interface/ntuple_JetInfo.h @@ -13,6 +13,8 @@ #include #include +#include "SimDataFormats/GeneratorProducts/interface/LHEEventProduct.h" + /* * For global jet info such as eta, pt, gen info */ @@ -21,7 +23,8 @@ class ntuple_JetInfo: public ntuple_content{ ntuple_JetInfo():ntuple_content(), gluonReduction_(0), useherwcompat_matching_(false), - isherwig_(false) + isherwig_(false), + isData_(false) {} void getInput(const edm::ParameterSet& iConfig); @@ -70,12 +73,19 @@ class ntuple_JetInfo: public ntuple_content{ electronsToken_ = electronsToken; } + void setLHEToken(edm::EDGetTokenT lheToken) { + lheToken_ = lheToken; + } + void setUseHerwigCompatibleMatching(const bool use){ useherwcompat_matching_=use; } void setIsHerwig(const bool use){ isherwig_=use; } + void setIsData(const bool use){ + isData_=use; + } //private: @@ -104,6 +114,8 @@ class ntuple_JetInfo: public ntuple_content{ edm::EDGetTokenT muonsToken_; edm::EDGetTokenT electronsToken_; + edm::EDGetTokenT lheToken_; + edm::Handle > genJetMatchRecluster; edm::Handle > genJetMatchWithNu; @@ -112,6 +124,8 @@ class ntuple_JetInfo: public ntuple_content{ edm::Handle muonsHandle; edm::Handle electronsHandle; + edm::Handle lheInfo; + TRandom3 TRandom_; float gluonReduction_; @@ -130,6 +144,7 @@ class ntuple_JetInfo: public ntuple_content{ bool useherwcompat_matching_; bool isherwig_; + bool isData_; /////////branches @@ -167,6 +182,7 @@ class ntuple_JetInfo: public ntuple_content{ int isPhysLeptonicB_; int isPhysLeptonicB_C_; int isPhysTau_; + int isRealData_; // global variables float npv_; @@ -183,6 +199,14 @@ class ntuple_JetInfo: public ntuple_content{ float jet_mass_; float jet_energy_; + // variables for event weights + bool useLHEWeights_; + std::vector pupWeights = {0., 0.9059208563049067, 0.4689946658078284, 0.4646384395209148, 0.35969952879169353, 0.20581098696265324, 0.1272975292012222, 0.11484070280016173, 0.18997631713506571, 0.2134442228038988, 0.2643260644534947, 0.38290419689123334, 0.5233231080095909, 0.6531355038202962, 0.7413472652417477, 0.8226986246368242, 0.909166618129074, 0.9754246515040906, 1.0116680456990728, 1.0419003275306946, 1.0762295787102802, 1.1034517536607453, 1.1240057591005752, 1.1262609366258989, 1.1198925605086503, 1.1078563848872773, 1.083911370342871, 1.0496801331833463, 1.0169474777740053, 0.9813073284102061, 0.9426647112682524, 0.9233559974737714, 0.894377685151131, 0.884518640484559, 0.8804996845439541, 0.888865624721422, 0.9107720191678217, 0.953824079957025, 1.0112115792549745, 1.0947266350670766, 1.1906625100966544, 1.3370686699103784, 1.510754710039529, 1.7098870624229212, 1.9391935863130325, 2.1529480239752585, 2.396292845558282, 2.7067102383965915, 2.9081731387455574, 3.126536829527805, 3.263323444233829, 3.3766746819738014, 3.3825183331846596, 3.332122539734733, 3.309580249670872, 2.962530063365449, 2.609107759179973, 2.4216997456337266, 2.228050917243899, 1.963846134469284, 1.844961576497657, 1.431817556288543, 1.5742387193813208, 1.731514171818786, 2.21989485741883, 2.8198818386713915, 3.8909891214054464, 5.4911613943458395, 8.610687700958811, 12.634799153629881, 20.32733145948569}; + float crossSection_; + float luminosity_; + float efficiency_; + float event_weight_; + float jet_looseId_; // quark/gluon diff --git a/DeepNtuplizer/plots/plot_features.py b/DeepNtuplizer/plots/plot_features.py new file mode 100644 index 00000000000..eb28364ce05 --- /dev/null +++ b/DeepNtuplizer/plots/plot_features.py @@ -0,0 +1,201 @@ +####### +# plot distributions of different featues of deepntuples root tree +# add root files with ntuples to files_mc or files_data +# itinitialize feature to plot and bin range +# for twodimensional features you have to choose 'all' if you want to plot all flattened or 'max' to plot the maximum value of each tuple +# +####### + +import pdb +import ROOT +import os +from array import array + +import matplotlib.pyplot as plt +import root_numpy as rn +import numpy as np + +ROOT.gROOT.SetBatch() # don't pop up canvases +ROOT.gROOT.SetStyle('Plain') # white background +ROOT.gStyle.SetFillStyle(0) + +def hist_bin_uncertainty(data, weights, bin_edges): + """ + The statistical uncertainity per bin of the binned data. + If there are weights then the uncertainity will be the root of the + sum of the weights squared. + If there are no weights (weights = 1) this reduces to the root of + the number of events. + Args: + data: `array`, the data being histogrammed. + weights: `array`, the associated weights of the `data`. + bin_edges: `array`, the edges of the bins of the histogram. + Returns: + bin_uncertainties: `array`, the statistical uncertainity on the bins. + """ + # Bound the data and weights to be within the bin edges + in_range_index = [idx for idx in range(len(data)) + if data[idx] > min(bin_edges) and data[idx] < max(bin_edges)] + in_range_data = np.asarray([data[idx] for idx in in_range_index]) + + if weights is None or np.array_equal(weights, np.ones(len(weights))): + # Default to weights of 1 and thus uncertainty = sqrt(N) + in_range_weights = np.ones(len(in_range_data)) + else: + in_range_weights = np.asarray([weights[idx] for idx in in_range_index]) + + # Bin the weights with the same binning as the data + bin_index = np.digitize(in_range_data, bin_edges) + # N.B.: range(1, bin_edges.size) is used instead of set(bin_index) as if + # there is a gap in the data such that a bin is skipped no index would appear + # for it in the set + binned_weights = np.asarray( + [in_range_weights[np.where(bin_index == idx)[0]] for idx in range(1, len(bin_edges))]) + bin_uncertainties = np.asarray( + [np.sqrt(np.sum(np.square(w))) for w in binned_weights]) + return bin_uncertainties + + + +class datacollection: + """ DOC """ + + + def __init__(self, filenames_mc, filenames_data = None): + + self.features = [] + self.bins_list = [] + self.fillopt_list = [] + self.freqs_list = [] + self.scalefactor_data = 1. + self.filenames_mc = filenames_mc + self.filenames_data = filenames_data + + + #pdb.set_trace() + + + def fill(self): + + print 'load samples' + self.collection_mc = rn.root2array(self.filenames_mc, "deepntuplizer/tree", list(set(self.features))) + self.weight_mc = rn.root2array(self.filenames_mc, "deepntuplizer/tree", "event_weight") + if self.filenames_data != None: + self.collection_data = rn.root2array(self.filenames_data, "deepntuplizer/tree", list(set(self.features))) + self.weight_data = rn.root2array(self.filenames_data, "deepntuplizer/tree", "event_weight") + + #pdb.set_trace() + + + def add_feature(self,feature, bins, fillopt=''): + self.features.append(feature) + self.bins_list.append(bins) + self.fillopt_list.append(fillopt) + + + + def scale_data(self,sf): + self.scalefactor_data *= sf + + + def plot_features(self): + #pdb.set_trace() + for i, var in enumerate(self.features): + print 'make plot for feature '+var + + if 'all' in self.fillopt_list[i]: + flat_col_mc = np.concatenate(self.collection_mc[var], axis=-1) + freqlist = [len(j) for j in self.collection_mc[var]] + flat_weight_mc = np.repeat(self.weight_mc, freqlist) + + flat_col_data = np.concatenate(self.collection_data[var], axis=-1) + freqlist = [len(j) for j in self.collection_data[var]] + flat_weight_data = np.repeat(self.weight_data, freqlist) + + entries_mc, binEdges = np.histogram(flat_col_mc, self.bins_list[i], weights=flat_weight_mc) + entries_data, _ = np.histogram(flat_col_data, self.bins_list[i], weights=flat_weight_data) + err_mc = hist_bin_uncertainty(flat_col_mc, flat_weight_mc, binEdges) + err_data = hist_bin_uncertainty(flat_col_data, flat_weight_data, binEdges) + + if 'max' in self.fillopt_list[i]: + max_col_mc = np.empty((self.collection_mc[var].shape)) + max_col_data = np.empty((self.collection_data[var].shape)) + for j,arr in enumerate(self.collection_mc[var]): + if len(arr) > 0: + max_col_mc[j] = np.amax(arr) + + for j, arr in enumerate(self.collection_data[var]): + if len(arr) > 0: + max_col_data[j] = np.amax(arr) + entries_mc, binEdges = np.histogram(max_col_mc, self.bins_list[i], weights=self.weight_mc) + entries_data, _ = np.histogram(max_col_data, self.bins_list[i], weights=self.weight_data) + err_mc = hist_bin_uncertainty(max_col_mc, self.weight_mc, binEdges) + err_data = hist_bin_uncertainty(max_col_data, self.weight_data, binEdges) + + if self.fillopt_list[i] == '': + entries_mc, binEdges = np.histogram(self.collection_mc[var], self.bins_list[i], weights=self.weight_mc) + entries_data, _ = np.histogram(self.collection_data[var], self.bins_list[i], weights=self.weight_data) + err_mc = hist_bin_uncertainty(self.collection_mc[var],self.weight_mc,binEdges) + err_data = hist_bin_uncertainty(self.collection_data[var], self.weight_data, binEdges) + + plt.cla() + fig, ax = plt.subplots() + + bincenters = 0.5 * (binEdges[1:] + binEdges[:-1]) + binWidth = binEdges[1:] - binEdges[:-1] + plt.bar(bincenters, entries_mc, yerr = err_mc, width = binWidth, align='center', color='w') + plt.errorbar(bincenters,entries_data*self.scalefactor_data, yerr=err_data*self.scalefactor_data, fmt='k.',ecolor='k') + ax.set_xlim(binEdges[0], binEdges[-1]) + ax.set_ylabel('weighted frequency') + ax.set_xlabel(var) + ax.set_title(self.fillopt_list[i]+' entries of '+var+' in GoodJets') + ax.set_ylim(bottom=0) + + plt.savefig(var+"_"+self.fillopt_list[i]+".png") + + + + + + +files_mc = ["tt_1_0.root","tt_2_0.root","tt_3_0.root","tt_4_0.root","tt_5_0.root", + "dy50_1_0.root","dy10to50_1_0.root","wantit_1_0.root","wt_1_0.root", + "ww_1_0.root","wz_1_0.root","zz_1_0.root","wjets_1_0.root"] +files_data = "muonEG_H_0.root" + +dc = datacollection(files_mc,files_data) +dc.add_feature("nCpfcand", np.arange(0,30,1)) +dc.add_feature("nNpfcand", np.arange(0,30,1)) +dc.add_feature("jet_pt", np.arange(0,320,20)) +dc.add_feature("jet_eta", np.arange(-2.4,2.8,0.4)) +dc.add_feature("npv", np.arange(0,50,1)) +dc.add_feature("nsv", np.arange(0,10,1)) + +dc.add_feature("Cpfcan_pt", np.arange(0,105,5),fillopt='max') +dc.add_feature("Npfcan_pt", np.arange(0,105,5),fillopt='max') +dc.add_feature("sv_pt", np.arange(0,110,10),fillopt='max') + +dc.add_feature("Cpfcan_pt", np.arange(0,55,2.5),fillopt='all') +dc.add_feature("Npfcan_pt", np.arange(0,55,2.5),fillopt='all') +dc.add_feature("sv_pt", np.arange(0,110,10),fillopt='all') +dc.add_feature("sv_deltaR", np.arange(0,110,10),fillopt='all') + + + + + +dc.fill() + + +dc.scale_data(1./0.8701594758966494)#*35.9/8.651) + + +title='features' + +directory = os.path.dirname('./plots_'+title+'/') +# make a canvas, draw, and save it +if not os.path.exists(directory): + os.makedirs(directory) +os.chdir(directory) + +dc.plot_features() \ No newline at end of file diff --git a/DeepNtuplizer/plugins/DeepNtuplizer.cc b/DeepNtuplizer/plugins/DeepNtuplizer.cc index 0b1c4296688..a57c64876f0 100644 --- a/DeepNtuplizer/plugins/DeepNtuplizer.cc +++ b/DeepNtuplizer/plugins/DeepNtuplizer.cc @@ -52,7 +52,7 @@ #include "TrackingTools/IPTools/interface/IPTools.h" #include "DataFormats/GeometryCommonDetAlgo/interface/Measurement1D.h" - +#include "SimDataFormats/GeneratorProducts/interface/LHEEventProduct.h" #if defined( __GXX_EXPERIMENTAL_CXX0X__) #include "TrackingTools/TransientTrack/interface/TransientTrack.h" @@ -108,10 +108,10 @@ DeepNtuplizer::DeepNtuplizer(const edm::ParameterSet& iConfig): vtxToken_(consumes(iConfig.getParameter("vertices"))), svToken_(consumes( iConfig.getParameter("secVertices"))), - jetToken_(consumes >(iConfig.getParameter("jets"))), - puToken_(consumes>(iConfig.getParameter("pupInfo"))), - rhoToken_(consumes(iConfig.getParameter("rhoInfo"))), - t_qgtagger(iConfig.getParameter("qgtagger")) + jetToken_(consumes >(iConfig.getParameter("jets"))), + puToken_(consumes>(iConfig.getParameter("pupInfo"))), + rhoToken_(consumes(iConfig.getParameter("rhoInfo"))), + t_qgtagger(iConfig.getParameter("qgtagger")) { /* * Initialise the modules here @@ -126,11 +126,13 @@ DeepNtuplizer::DeepNtuplizer(const edm::ParameterSet& iConfig): //not implemented yet const bool useHerwigCompatibleMatching=iConfig.getParameter("useHerwigCompatible"); const bool isHerwig=iConfig.getParameter("isHerwig"); + const bool isData=iConfig.getParameter("isData"); ntuple_content::useoffsets = iConfig.getParameter("useOffsets"); applySelection_=iConfig.getParameter("applySelection"); + ntuple_SV* svmodule=new ntuple_SV("", jetR); addModule(svmodule); @@ -155,13 +157,22 @@ DeepNtuplizer::DeepNtuplizer(const edm::ParameterSet& iConfig): jetinfo->setUseHerwigCompatibleMatching(useHerwigCompatibleMatching); jetinfo->setIsHerwig(isHerwig); + jetinfo->setIsData(isData); + + if(!isData){ + jetinfo->setGenJetMatchReclusterToken( + consumes >( + iConfig.getParameter( "genJetMatchRecluster" ))); + jetinfo->setGenJetMatchWithNuToken( + consumes >( + iConfig.getParameter( "genJetMatchWithNu" ))); + + + } + jetinfo->setLHEToken( + consumes( + iConfig.getParameter("lheInfo"))); - jetinfo->setGenJetMatchReclusterToken( - consumes >( - iConfig.getParameter( "genJetMatchRecluster" ))); - jetinfo->setGenJetMatchWithNuToken( - consumes >( - iConfig.getParameter( "genJetMatchWithNu" ))); jetinfo->setGenParticlesToken( consumes( @@ -225,7 +236,8 @@ DeepNtuplizer::analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) iEvent.getByToken(svToken_, secvertices); edm::Handle > pupInfo; - iEvent.getByToken(puToken_, pupInfo); + if(!iEvent.isRealData()) + iEvent.getByToken(puToken_, pupInfo); edm::Handle rhoInfo; iEvent.getByToken(rhoToken_,rhoInfo); @@ -236,7 +248,8 @@ DeepNtuplizer::analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) for(auto& m:modules_){ m->setPrimaryVertices(vertices.product()); m->setSecVertices(secvertices.product()); - m->setPuInfo(pupInfo.product()); + if(!iEvent.isRealData()) + m->setPuInfo(pupInfo.product()); m->setRhoInfo(rhoInfo.product()); m->readSetup(iSetup); m->readEvent(iEvent); diff --git a/DeepNtuplizer/plugins/ElectronIdAdder.cc b/DeepNtuplizer/plugins/ElectronIdAdder.cc new file mode 100644 index 00000000000..54b19e804d2 --- /dev/null +++ b/DeepNtuplizer/plugins/ElectronIdAdder.cc @@ -0,0 +1,86 @@ +#include + +#include "FWCore/Framework/interface/EDProducer.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/Framework/interface/Frameworkfwd.h" + +#include "DataFormats/PatCandidates/interface/Electron.h" +#include "DataFormats/VertexReco/interface/Vertex.h" + + + +class ElectronIdAdder : public edm::EDProducer { + public: + explicit ElectronIdAdder(const edm::ParameterSet& iConfig): + src_(consumes >(iConfig.getParameter("src"))), + idMap_(consumes >(iConfig.getParameter("idMap"))), + vSrc_(consumes > (iConfig.getParameter("vSrc"))){ + produces >(); + } + ~ElectronIdAdder(){} + void produce(edm::Event & iEvent, const edm::EventSetup& iSetup) override; + + private: + edm::EDGetTokenT > src_; + edm::EDGetTokenT > idMap_; + edm::EDGetTokenT > vSrc_; +}; + +void ElectronIdAdder::produce(edm::Event & iEvent, const edm::EventSetup & es) { + edm::Handle > electrons; + edm::Handle > map; + edm::Handle > vertex; + + iEvent.getByToken(src_, electrons); + iEvent.getByToken(idMap_, map); + iEvent.getByToken(vSrc_, vertex); + + std::vector * out = new std::vector; out->reserve(electrons->size()); + + for (size_t i = 0; i < electrons->size(); ++i){ + const auto iElectron = electrons->ptrAt(i); + bool idresult = (*map)[iElectron]; + bool notInCrack = false; + double absd0 = 1.; + double absdz = 1.; + bool inAbsD0 = false; + bool inAbsDz = false; + double global_default_value = 1.5; + double SCeta = (iElectron->superCluster().isAvailable()) ? iElectron->superCluster()->position().eta() : global_default_value; + double absSCeta = fabs(SCeta); + + + if( iElectron->superCluster().isAvailable() ){ + notInCrack = ( absSCeta<1.4442 || absSCeta>1.5660 ); + } + if( iElectron->gsfTrack().isAvailable() ){ + absd0 = fabs(iElectron->gsfTrack()->dxy(vertex->ptrAt(0)->position())); + absdz = fabs(iElectron->gsfTrack()->dz(vertex->ptrAt(0)->position())); + } + if( iElectron->superCluster().isAvailable() ){ + if( absSCeta < 1.4442){ + inAbsD0 = absd0 < 0.05; + inAbsDz = absdz < 0.1; + } + if( absSCeta > 1.5660){ + inAbsD0 = absd0 < 0.1; + inAbsDz = absdz < 0.2; + } + } + + pat::Electron newele(*iElectron); + newele.addUserFloat("tightcutbased",(float)idresult); + newele.addUserFloat("notInEtaVetoRegion", (float)notInCrack); + newele.addUserFloat("inAbsD0",(float)inAbsD0); + newele.addUserFloat("inAbsDz",(float)inAbsDz); + out->push_back(newele); + } + std::unique_ptr > ptr(out); + iEvent.put(std::move(ptr)); + +} + +//define this as a plug-in +DEFINE_FWK_MODULE(ElectronIdAdder); \ No newline at end of file diff --git a/DeepNtuplizer/plugins/MuonIdAdder.cc b/DeepNtuplizer/plugins/MuonIdAdder.cc new file mode 100644 index 00000000000..be75a97c05b --- /dev/null +++ b/DeepNtuplizer/plugins/MuonIdAdder.cc @@ -0,0 +1,50 @@ +#include + +#include "FWCore/Framework/interface/EDProducer.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/Framework/interface/Frameworkfwd.h" + +#include "DataFormats/PatCandidates/interface/Muon.h" +#include "DataFormats/VertexReco/interface/Vertex.h" + +class MuonIdAdder : public edm::EDProducer { + public: + explicit MuonIdAdder(const edm::ParameterSet& iConfig): + src_(consumes > (iConfig.getParameter("src"))), + vSrc_(consumes > (iConfig.getParameter("vSrc"))){ + produces >(); + } + ~MuonIdAdder(){} + void produce(edm::Event & iEvent, const edm::EventSetup& iSetup) override; + + private: + edm::EDGetTokenT > src_; + edm::EDGetTokenT > vSrc_; +}; + +void MuonIdAdder::produce(edm::Event & iEvent, const edm::EventSetup & iSetup) { + edm::Handle > muons; + edm::Handle > vertex; + + iEvent.getByToken(src_, muons); + iEvent.getByToken(vSrc_, vertex); + + std::vector * out = new std::vector; out->reserve(muons->size()); + + for (size_t i = 0; i < muons->size(); ++i){ + const auto muon = muons->ptrAt(i); + bool idresult = muon->isTightMuon(*(vertex->ptrAt(0))); + + pat::Muon newmuon(*muon); + newmuon.addUserFloat("tightcutbased",(float)idresult); + out->push_back(newmuon); + } + std::unique_ptr > ptr(out); + iEvent.put(std::move(ptr)); + +} + +//define this as a plug-in +DEFINE_FWK_MODULE(MuonIdAdder); \ No newline at end of file diff --git a/DeepNtuplizer/plugins/lheAnalyzer.cc b/DeepNtuplizer/plugins/lheAnalyzer.cc new file mode 100644 index 00000000000..83c17970604 --- /dev/null +++ b/DeepNtuplizer/plugins/lheAnalyzer.cc @@ -0,0 +1,141 @@ +// -*- C++ -*- +// +// Package: DeepNTuples/DeepNtuplizer +// Class: puAnalyzer +// +/**\class lheAnalyzer lheAnalyzer.cc DeepNTuples/DeepNtuplizer/plugins/lheAnalyzer.cc + Description: This analyzer is used in LHEcounter.py to produce a histogram with the lhe weights of the input files. + This is needed to calculate the effective event number of mc events which is the total number of events minus the once with negative lhe weights + Implementation: + [Notes on implementation] +*/ +// +// Original Author: David Walter +// Created: Wed, 22 Nov 2017 09:40:19 GMT +// +// + + +// system include files +#include +#include + +// user include files +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/Framework/interface/one/EDAnalyzer.h" + +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" + +#include "FWCore/ParameterSet/interface/ParameterSet.h" + +#include "FWCore/ServiceRegistry/interface/Service.h" +#include "CommonTools/UtilAlgos/interface/TFileService.h" + +#include "SimDataFormats/GeneratorProducts/interface/LHEEventProduct.h" +// +// class declaration +// + +// If the analyzer does not use TFileService, please remove +// the template argument to the base class so the class inherits +// from edm::one::EDAnalyzer<> and also remove the line from +// constructor "usesResource("TFileService");" +// This will improve performance in multithreaded jobs. + +class lheAnalyzer : public edm::one::EDAnalyzer { + public: + lheAnalyzer(const edm::ParameterSet&); + + ~lheAnalyzer(); + + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); + + + private: + virtual void beginJob() override; + virtual void analyze(const edm::Event&, const edm::EventSetup&) override; + virtual void endJob() override; + + // ----------member data --------------------------- + edm::EDGetTokenT t_LHEInfo; + TH1F * hist_lheWeight_0; +}; + +// +// constants, enums and typedefs +// + +// +// static data member definitions +// + +// +// constructors and destructor +// +lheAnalyzer::lheAnalyzer(const edm::ParameterSet& iConfig): + t_LHEInfo(consumes (iConfig.getParameter("lheInfo"))){ + + edm::Service fs; + hist_lheWeight_0 = fs->make( "lheweight" , "lhe weight [0]", 10, -2., 2. ); + +} + + +lheAnalyzer::~lheAnalyzer() +{ + + // do anything here that needs to be done at desctruction time + // (e.g. close files, deallocate resources etc.) + +} + + +// +// member functions +// + +// ------------ method called for each event ------------ +void +lheAnalyzer::analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) +{ + + edm::Handle h_LHEWeights; + + iEvent.getByToken(t_LHEInfo, h_LHEWeights); + + double theWeight; + + theWeight = h_LHEWeights->weights()[0].wgt/std::abs(h_LHEWeights->weights()[0].wgt); + + + + hist_lheWeight_0->Fill(theWeight); + +} + + +// ------------ method called once each job just before starting event loop ------------ +void +lheAnalyzer::beginJob() +{ +} + +// ------------ method called once each job just after ending the event loop ------------ +void +lheAnalyzer::endJob() +{ +} + +// ------------ method fills 'descriptions' with the allowed parameters for the module ------------ +void +lheAnalyzer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + //The following says we do not know what parameters are allowed so do no validation + // Please change this to state exactly what you do use, even if it is no parameters + edm::ParameterSetDescription desc; + desc.setUnknown(); + descriptions.addDefault(desc); +} + +//define this as a plug-in +DEFINE_FWK_MODULE(lheAnalyzer); \ No newline at end of file diff --git a/DeepNtuplizer/plugins/puAnalyzer.cc b/DeepNtuplizer/plugins/puAnalyzer.cc new file mode 100644 index 00000000000..19969030fe0 --- /dev/null +++ b/DeepNtuplizer/plugins/puAnalyzer.cc @@ -0,0 +1,146 @@ +// -*- C++ -*- +// +// Package: DeepNTuples/DeepNtuplizer +// Class: puAnalyzer +// +/**\class puAnalyzer puAnalyzer.cc DeepNTuples/DeepNtuplizer/plugins/puAnalyzer.cc + Description: This analyzer is used in pupMCHistProd.py to calculate the pileup from the number of interactions per bunch crossing + Implementation: + [Notes on implementation] +*/ +// +// Original Author: David Walter +// Created: Mon, 20 Nov 2017 18:49:19 GMT +// +// + + +// system include files +#include +#include + +// user include files +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/Framework/interface/one/EDAnalyzer.h" + +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" + +#include "FWCore/ParameterSet/interface/ParameterSet.h" + +#include "SimDataFormats/PileupSummaryInfo/interface/PileupSummaryInfo.h" + +#include "FWCore/ServiceRegistry/interface/Service.h" +#include "CommonTools/UtilAlgos/interface/TFileService.h" +// +// class declaration +// + +// If the analyzer does not use TFileService, please remove +// the template argument to the base class so the class inherits +// from edm::one::EDAnalyzer<> and also remove the line from +// constructor "usesResource("TFileService");" +// This will improve performance in multithreaded jobs. + +class puAnalyzer : public edm::one::EDAnalyzer { + public: + puAnalyzer(const edm::ParameterSet&); + + ~puAnalyzer(); + + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); + + + private: + virtual void beginJob() override; + virtual void analyze(const edm::Event&, const edm::EventSetup&) override; + virtual void endJob() override; + + // ----------member data --------------------------- + edm::EDGetTokenT< std::vector > EDMPUInfoToken; + TH1F * h_pileup; +}; + +// +// constants, enums and typedefs +// + +// +// static data member definitions +// + +// +// constructors and destructor +// +puAnalyzer::puAnalyzer(const edm::ParameterSet& iConfig): + EDMPUInfoToken(consumes > (iConfig.getParameter("pileupInfo"))){ + + edm::Service fs; + h_pileup = fs->make( "pileup" , "Number of interactions per bunch crossing", 70, 0., 70 ); + +} + + +puAnalyzer::~puAnalyzer() +{ + + // do anything here that needs to be done at desctruction time + // (e.g. close files, deallocate resources etc.) + +} + + +// +// member functions +// + +// ------------ method called for each event ------------ +void +puAnalyzer::analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) +{ + //using namespace edm; + + edm::Handle< std::vector > PupInfo; + iEvent.getByToken(EDMPUInfoToken, PupInfo); + + + std::vector::const_iterator PVI; + float Tnpv = -1; + for(PVI = PupInfo->begin(); PVI != PupInfo->end(); ++PVI) { + + int BX = PVI->getBunchCrossing(); + + if(BX == 0) { + Tnpv = PVI->getTrueNumInteractions(); + continue; + } + } + h_pileup->Fill(Tnpv); + +} + + +// ------------ method called once each job just before starting event loop ------------ +void +puAnalyzer::beginJob() +{ +} + +// ------------ method called once each job just after ending the event loop ------------ +void +puAnalyzer::endJob() +{ +} + +// ------------ method fills 'descriptions' with the allowed parameters for the module ------------ +void +puAnalyzer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + //The following says we do not know what parameters are allowed so do no validation + // Please change this to state exactly what you do use, even if it is no parameters + edm::ParameterSetDescription desc; + desc.setUnknown(); + descriptions.addDefault(desc); +} + +//define this as a plug-in +DEFINE_FWK_MODULE(puAnalyzer); \ No newline at end of file diff --git a/DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py b/DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py new file mode 100644 index 00000000000..c999f61607f --- /dev/null +++ b/DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py @@ -0,0 +1,397 @@ +# this can be run with CMSSW 8_2_29; in CMSSW 8_2_25 the module 'cutBasedElectronID_Summer16_80X_V1_cff' is missing + +import FWCore.ParameterSet.Config as cms + +import FWCore.ParameterSet.VarParsing as VarParsing +### parsing job options +import sys + +options = VarParsing.VarParsing() + +options.register('inputScript', '', VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.string,"input Script") +options.register('outputFile', 'output', VarParsing.VarParsing.multiplicity.singleton,VarParsing.VarParsing.varType.string, "output File (w/o .root)") +options.register('maxEvents', -1, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int,"maximum events") +options.register('skipEvents', 0, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int, "skip N events") +options.register('job', 0, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int,"job number") +options.register('nJobs', 1, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int, "total jobs") +options.register('gluonReduction', 0.0, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.float, "gluon reduction") +options.register('selectJets', True, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.bool,"select jets with good gen match") +options.register('isData', False, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.bool, "switch off generator jets") +options.register('deepNtuplizer',True, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.bool, "run deepNtuplizer or just the ttbar selection") + +import os + +release = os.environ['CMSSW_VERSION'][6:12] +print("Using release " + release) + +options.register( + 'inputFiles', '', + VarParsing.VarParsing.multiplicity.list, + VarParsing.VarParsing.varType.string, + "input files (default is the tt RelVal)" +) + +if hasattr(sys, "argv"): + options.parseArguments() + +process = cms.Process("ttbarSelectedDNNFiller") + +process.load("FWCore.MessageService.MessageLogger_cfi") +process.load("Configuration.EventContent.EventContent_cff") +process.load('Configuration.StandardSequences.Services_cff') +process.load('Configuration.StandardSequences.GeometryRecoDB_cff') +process.load('Configuration.StandardSequences.MagneticField_cff') +process.load('Configuration.StandardSequences.FrontierConditions_GlobalTag_cff') + +if options.isData == False: + process.GlobalTag.globaltag = '80X_mcRun2_asymptotic_2016_TrancheIV_v8' # For MC Jet Energy correction +if options.isData == True: + process.GlobalTag.globaltag = '80X_dataRun2_2016SeptRepro_v7' # For Data Jet Energy correction + +process.maxEvents = cms.untracked.PSet(input=cms.untracked.int32(-1)) + +process.load('FWCore.MessageService.MessageLogger_cfi') +process.MessageLogger.cerr.FwkReport.reportEvery = 10 +if options.inputScript == '': # this is probably for testing + process.MessageLogger.cerr.FwkReport.reportEvery = 100 + +process.options = cms.untracked.PSet( + allowUnscheduled=cms.untracked.bool(True), + wantSummary=cms.untracked.bool(False) +) + + +process.load('DeepNTuples.DeepNtuplizer.samples.TTJetsPhase1_cfg') # default input + +if options.inputFiles: + process.source.fileNames = options.inputFiles + +if options.inputScript != '' and options.inputScript != 'DeepNTuples.DeepNtuplizer.samples.TTJetsPhase1_cfg': + process.load(options.inputScript) + + +#process.source.fileNames=['file:./00E02A09-853C-E711-93FF-3417EBE644A7.root'] #store/data/Run2016H/SingleMuon/MINIAOD/18Apr2017-v1/00000/00E02A09-853C-E711-93FF-3417EBE644A7.root +#process.source.fileNames=['file:./000C6E52-8BEC-E611-B3FF-0025905C42FE.root'] #isData=True +process.source.fileNames=['file:./0693E0E7-97BE-E611-B32F-0CC47A78A3D8.root'] #isData=False + +numberOfFiles = len(process.source.fileNames) +numberOfJobs = options.nJobs +jobNumber = options.job + +process.source.fileNames = process.source.fileNames[jobNumber:numberOfFiles:numberOfJobs] +if options.nJobs > 1: + print ("running over these files:") + print (process.source.fileNames) + +process.source.skipEvents = cms.untracked.uint32(options.skipEvents) +process.maxEvents = cms.untracked.PSet( + input=cms.untracked.int32(options.maxEvents) +) + +if int(release.replace("_", "")) >= 8400 or int(release.replace("_", "")) == 8029: + bTagInfos = [ + 'pfImpactParameterTagInfos', + 'pfInclusiveSecondaryVertexFinderTagInfos', + 'pfDeepCSVTagInfos'] +else: + bTagInfos = [ + 'pfImpactParameterTagInfos', + 'pfInclusiveSecondaryVertexFinderTagInfos', + 'deepNNTagInfos', + ] + +if int(release.replace("_", "")) >= 8400 or int(release.replace("_", "")) == 8029: + bTagDiscriminators = [ + 'softPFMuonBJetTags', + 'softPFElectronBJetTags', + 'pfJetBProbabilityBJetTags', + 'pfJetProbabilityBJetTags', + 'pfCombinedInclusiveSecondaryVertexV2BJetTags', + 'pfDeepCSVJetTags:probudsg', # to be fixed with new names + 'pfDeepCSVJetTags:probb', + 'pfDeepCSVJetTags:probc', + 'pfDeepCSVJetTags:probbb', + 'pfDeepCSVJetTags:probcc', + ] +else: + bTagDiscriminators = [ + 'softPFMuonBJetTags', + 'softPFElectronBJetTags', + 'pfJetBProbabilityBJetTags', + 'pfJetProbabilityBJetTags', + 'pfCombinedInclusiveSecondaryVertexV2BJetTags', + 'deepFlavourJetTags:probudsg', # to be fixed with new names + 'deepFlavourJetTags:probb', + 'deepFlavourJetTags:probc', + 'deepFlavourJetTags:probbb', + 'deepFlavourJetTags:probcc', + ] + +###### ttbar selection +outFileName = options.outputFile + '_' + str(options.job) + '.root' +print ('Using output file ' + outFileName) + +if options.deepNtuplizer: + process.TFileService = cms.Service("TFileService", + fileName=cms.string(outFileName)) +else: + process.MINIAODSIMEventContent.outputCommands.extend([ + 'keep *_GoodElectron_*_*', + 'keep *_GoodMuon_*_*', + 'keep *_GoodJets_*_*', + 'keep *_GoodOFLeptonPair_*_*' + ]) + + process.outmod = cms.OutputModule("PoolOutputModule", + process.MINIAODSIMEventContent, + SelectEvents = cms.untracked.PSet( + SelectEvents = cms.vstring('ttbaremupath') + ), + fileName = cms.untracked.string(outFileName) + ) + +from PhysicsTools.SelectorUtils.tools.vid_id_tools import * +dataFormat = DataFormat.MiniAOD +switchOnVIDElectronIdProducer(process, dataFormat) +my_id_modules = [ + 'RecoEgamma.ElectronIdentification.Identification.cutBasedElectronID_Summer16_80X_V1_cff' +] +for idmod in my_id_modules: + setupAllVIDIdsInModule(process,idmod,setupVIDElectronSelection) + + +#HighLevelTrigger +HLTlistSM = cms.vstring(#"HLT_Mu23_TrkIsoVVL_Ele12_CaloIdL_TrackIdL_IsoVL_v*", #Run B-G + #"HLT_Mu8_TrkIsoVVL_Ele23_CaloIdL_TrackIdL_IsoVL_v*", #Run B-G + #"HLT_Mu23_TrkIsoVVL_Ele12_CaloIdL_TrackIdL_IsoVL_DZ_v*", #Run H + #"HLT_Mu8_TrkIsoVVL_Ele23_CaloIdL_TrackIdL_IsoVL_DZ_v*", #Run H + "HLT_Ele27_WPTight_Gsf_v*", #Run B-H + "HLT_IsoTkMu24_v*", #Run B-H + "HLT_IsoMu24_v*" #Run B-H + ) +process.TriggerSel = cms.EDFilter("HLTHighLevel", + TriggerResultsTag = cms.InputTag("TriggerResults","","HLT"), + HLTPaths = cms.vstring(HLTlistSM), + eventSetupPathsKey = cms.string(''), # not empty => use read paths from AlCaRecoTriggerBitsRcd via this key + andOr = cms.bool(True), # how to deal with multiple triggers: True (OR) accept if ANY is true, False (AND) accept if ALL are true + throw = cms.bool(True) # throw exception on unknown path names +) +# Electron Selection +process.EleIdEmbed = cms.EDProducer("ElectronIdAdder", + src=cms.InputTag("slimmedElectrons"), + vSrc=cms.InputTag("offlineSlimmedPrimaryVertices"), + idMap=cms.InputTag("egmGsfElectronIDs:cutBasedElectronID-Summer16-80X-V1-tight") + ) + +process.GoodElectron = cms.EDFilter("CandViewSelector", + src = cms.InputTag("EleIdEmbed"), + cut = cms.string("pt > 20.0 && abs(eta)<2.4 " + "&& userFloat('tightcutbased')" + "&& userFloat('notInEtaVetoRegion')" + "&& userFloat('inAbsD0')" + "&& userFloat('inAbsDz')" + ) + ) + +### Muon Selection +process.MuonIdEmbed = cms.EDProducer("MuonIdAdder", + src=cms.InputTag("slimmedMuons"), + vSrc=cms.InputTag("offlineSlimmedPrimaryVertices") + ) + +process.GoodMuon = cms.EDFilter("CandViewSelector", + src = cms.InputTag("MuonIdEmbed"), + cut = cms.string("pt > 20.0 && abs(eta)<2.4 " + "&& userFloat('tightcutbased')" + "&& (pfIsolationR04().sumChargedHadronPt + max(0.0, (pfIsolationR04().sumNeutralHadronEt + pfIsolationR04().sumPhotonEt -0.5*pfIsolationR04().sumPUPt)))/pt < 0.15" + ) +) +### Jets + +# Jet Energy Corrections +if options.isData: + jetCorrections = cms.vstring(['L1FastJet', 'L2Relative', 'L3Absolute', 'L2L3Residual']) +else: + jetCorrections = cms.vstring(['L1FastJet', 'L2Relative', 'L3Absolute']) + +from PhysicsTools.PatAlgos.tools.jetTools import updateJetCollection + +updateJetCollection( + process, + jetSource = cms.InputTag('slimmedJets'), + labelName = 'UpdatedJEC', + jetCorrections = ('AK4PFchs', jetCorrections, 'None') +) + +process.GoodJets = cms.EDProducer("PATJetCleaner", + src = cms.InputTag("updatedPatJetsUpdatedJEC"), + preselection = cms.string("pt>30 && abs(eta) < 2.4 && neutralHadronEnergyFraction < 0.99 " + "&& neutralEmEnergyFraction < 0.99 && (chargedMultiplicity+neutralMultiplicity) > 1 " + "&& chargedHadronEnergyFraction > 0.0 " + "&& chargedMultiplicity > 0.0 && chargedEmEnergyFraction < 0.99 "), + checkOverlaps = cms.PSet( + muons = cms.PSet( + src = cms.InputTag("GoodMuon"), + algorithm = cms.string("byDeltaR"), + preselection = cms.string(""), + deltaR = cms.double(0.4), + checkRecoComponents = cms.bool(False), # don't check if they share some AOD object ref + pairCut = cms.string(""), + requireNoOverlaps = cms.bool(True), # overlaps cause the jet to be discarded + ), + electrons = cms.PSet( + src = cms.InputTag("GoodElectron"), + algorithm = cms.string("byDeltaR"), + preselection = cms.string(""), + deltaR = cms.double(0.4), + checkRecoComponents = cms.bool(False), # don't check if they share some AOD object ref + pairCut = cms.string(""), + requireNoOverlaps = cms.bool(True), # overlaps cause the jet to be discarded + ) + ), + finalCut = cms.string('') + ) + +process.GoodOFLeptonPair = cms.EDProducer("CandViewShallowCloneCombiner", + decay = cms.string("GoodMuon@+ GoodElectron@-"), + cut = cms.string("20.0 < mass" + "&& (daughter(0).pt > 25 || daughter(1).pt > 25)") + ) + + +process.FinalSel = cms.EDFilter("CandViewCountFilter", + src = cms.InputTag("GoodOFLeptonPair"), + minNumber = cms.uint32(1), + ) +### end selection + + +from PhysicsTools.PatAlgos.tools.jetTools import updateJetCollection +updateJetCollection( + process, + labelName="DeepFlavour", + # jetSource=cms.InputTag('slimmedJetsAK8PFPuppiSoftDropPacked', 'SubJets'), # 'subjets from AK8' + jetSource=cms.InputTag('GoodJets'), # 'ak4Jets' + jetCorrections=('AK4PFchs', jetCorrections, 'None'), + pfCandidates=cms.InputTag('packedPFCandidates'), + pvSource=cms.InputTag("offlineSlimmedPrimaryVertices"), + svSource=cms.InputTag('slimmedSecondaryVertices'), + muSource=cms.InputTag('slimmedMuons'), + elSource=cms.InputTag('slimmedElectrons'), + btagInfos=bTagInfos, + btagDiscriminators=bTagDiscriminators, + explicitJTA=False +) + +if hasattr(process, 'updatedPatJetsTransientCorrectedDeepFlavour'): + process.updatedPatJetsTransientCorrectedDeepFlavour.addTagInfos = cms.bool(True) + process.updatedPatJetsTransientCorrectedDeepFlavour.addBTagInfo = cms.bool(True) +else: + raise ValueError( + 'I could not find updatedPatJetsTransientCorrectedDeepFlavour to embed the tagInfos, please check the cfg') + +# QGLikelihood +process.load("DeepNTuples.DeepNtuplizer.QGLikelihood_cfi") +process.es_prefer_jec = cms.ESPrefer("PoolDBESSource", "QGPoolDBESSource") +process.load('RecoJets.JetProducers.QGTagger_cfi') +process.QGTagger.srcJets = cms.InputTag("selectedUpdatedPatJetsDeepFlavour") +process.QGTagger.jetsLabel = cms.string('QGL_AK4PFchs') + +from RecoJets.JetProducers.ak4GenJets_cfi import ak4GenJets + +process.ak4GenJetsWithNu = ak4GenJets.clone(src='packedGenParticles') + +## Filter out neutrinos from packed GenParticles +process.packedGenParticlesForJetsNoNu = cms.EDFilter("CandPtrSelector", src=cms.InputTag("packedGenParticles"), + cut=cms.string( + "abs(pdgId) != 12 && abs(pdgId) != 14 && abs(pdgId) != 16")) +## Define GenJets +process.ak4GenJetsRecluster = ak4GenJets.clone(src='packedGenParticlesForJetsNoNu') + +process.patGenJetMatchWithNu = cms.EDProducer("GenJetMatcher", # cut on deltaR; pick best by deltaR + src=cms.InputTag("selectedUpdatedPatJetsDeepFlavour"), + # RECO jets (any View is ok) + matched=cms.InputTag("ak4GenJetsWithNu"), + # GEN jets (must be GenJetCollection) + mcPdgId=cms.vint32(), # n/a + mcStatus=cms.vint32(), # n/a + checkCharge=cms.bool(False), # n/a + maxDeltaR=cms.double(0.4), # Minimum deltaR for the match + # maxDPtRel = cms.double(3.0), # Minimum deltaPt/Pt for the match (not used in GenJetMatcher) + resolveAmbiguities=cms.bool(True), + # Forbid two RECO objects to match to the same GEN object + resolveByMatchQuality=cms.bool(False), + # False = just match input in order; True = pick lowest deltaR pair first + ) + +process.patGenJetMatchRecluster = cms.EDProducer("GenJetMatcher", # cut on deltaR; pick best by deltaR + src=cms.InputTag("selectedUpdatedPatJetsDeepFlavour"), + # RECO jets (any View is ok) + matched=cms.InputTag("ak4GenJetsRecluster"), + # GEN jets (must be GenJetCollection) + mcPdgId=cms.vint32(), # n/a + mcStatus=cms.vint32(), # n/a + checkCharge=cms.bool(False), # n/a + maxDeltaR=cms.double(0.4), # Minimum deltaR for the match + # maxDPtRel = cms.double(3.0), # Minimum deltaPt/Pt for the match (not used in GenJetMatcher) + resolveAmbiguities=cms.bool(True), + # Forbid two RECO objects to match to the same GEN object + resolveByMatchQuality=cms.bool(False), + # False = just match input in order; True = pick lowest deltaR pair first + ) + +process.genJetSequence = cms.Sequence(process.packedGenParticlesForJetsNoNu + * process.ak4GenJetsWithNu + * process.ak4GenJetsRecluster + * process.patGenJetMatchWithNu + * process.patGenJetMatchRecluster) + +# Very Loose IVF SV collection +from PhysicsTools.PatAlgos.tools.helpers import loadWithPrefix + +loadWithPrefix(process, 'RecoVertex.AdaptiveVertexFinder.inclusiveVertexing_cff', "looseIVF") +process.looseIVFinclusiveCandidateVertexFinder.primaryVertices = cms.InputTag("offlineSlimmedPrimaryVertices") +process.looseIVFinclusiveCandidateVertexFinder.tracks = cms.InputTag("packedPFCandidates") +process.looseIVFinclusiveCandidateVertexFinder.vertexMinDLen2DSig = cms.double(0.) +process.looseIVFinclusiveCandidateVertexFinder.vertexMinDLenSig = cms.double(0.) +process.looseIVFinclusiveCandidateVertexFinder.fitterSigmacut = 20 + +process.looseIVFcandidateVertexArbitrator.primaryVertices = cms.InputTag("offlineSlimmedPrimaryVertices") +process.looseIVFcandidateVertexArbitrator.tracks = cms.InputTag("packedPFCandidates") +process.looseIVFcandidateVertexArbitrator.secondaryVertices = cms.InputTag("looseIVFcandidateVertexMerger") +process.looseIVFcandidateVertexArbitrator.fitterSigmacut = 20 + + + +# DeepNtuplizer +process.load("DeepNTuples.DeepNtuplizer.DeepNtuplizer_cfi") +process.deepntuplizer.jets = cms.InputTag('selectedUpdatedPatJetsDeepFlavour') +process.deepntuplizer.bDiscriminators = bTagDiscriminators +process.deepntuplizer.bDiscriminators.append('pfCombinedMVAV2BJetTags') +process.deepntuplizer.LooseSVs = cms.InputTag("looseIVFinclusiveCandidateSecondaryVertices") + +process.deepntuplizer.applySelection = cms.bool(options.selectJets) + +if int(release.replace("_", "")) >= 840: + process.deepntuplizer.tagInfoName = cms.string('pfDeepCSV') + +process.deepntuplizer.gluonReduction = cms.double(options.gluonReduction) + +# 1631 +process.ProfilerService = cms.Service( + "ProfilerService", + firstEvent=cms.untracked.int32(1631), + lastEvent=cms.untracked.int32(1641), + paths=cms.untracked.vstring('p') +) + +if options.isData: + if options.deepNtuplizer: + process.p = cms.Path(process.TriggerSel + process.FinalSel + process.QGTagger + process.deepntuplizer) + else: + process.p = cms.Path(process.TriggerSel + process.FinalSel + process.QGTagger) +else: + if options.deepNtuplizer: + process.p = cms.Path(process.TriggerSel + process.FinalSel + process.QGTagger + process.genJetSequence * process.deepntuplizer) + else: + process.p = cms.Path(process.TriggerSel + process.FinalSel + process.QGTagger + process.genJetSequence) diff --git a/DeepNtuplizer/python/DeepNtuplizer_cfi.py b/DeepNtuplizer/python/DeepNtuplizer_cfi.py index 7994705291b..ed196255e99 100644 --- a/DeepNtuplizer/python/DeepNtuplizer_cfi.py +++ b/DeepNtuplizer/python/DeepNtuplizer_cfi.py @@ -7,6 +7,7 @@ jetR = cms.double(0.4), runFatJet = cms.bool(False), pupInfo = cms.InputTag("slimmedAddPileupInfo"), + lheInfo = cms.InputTag("externalLHEProducer"), rhoInfo = cms.InputTag("fixedGridRhoFastjetAll"), SVs = cms.InputTag("slimmedSecondaryVertices"), LooseSVs = cms.InputTag("inclusiveCandidateSecondaryVertices"), @@ -31,5 +32,12 @@ useHerwigCompatible=cms.bool(False), isHerwig=cms.bool(False), useOffsets=cms.bool(True), - applySelection=cms.bool(True) + applySelection=cms.bool(True), + + isData=cms.bool(False), + useLHEWeights=cms.bool(False), + + crossSection=cms.double(1.0), + luminosity = cms.double(42.0), + efficiency = cms.double(1.0) #1/((effective) number of events ) diff --git a/DeepNtuplizer/python/LHEcounter.py b/DeepNtuplizer/python/LHEcounter.py new file mode 100644 index 00000000000..5aabb11fa17 --- /dev/null +++ b/DeepNtuplizer/python/LHEcounter.py @@ -0,0 +1,93 @@ +### +# Program to produce a histogram of the lhe weights to compute the effective event number of a sample with lhe weights +### +import FWCore.ParameterSet.Config as cms + +import FWCore.ParameterSet.VarParsing as VarParsing +### parsing job options +import sys + + +options = VarParsing.VarParsing() + +options.register('inputScript','',VarParsing.VarParsing.multiplicity.singleton,VarParsing.VarParsing.varType.string,"input Script") +options.register('outputFile','output',VarParsing.VarParsing.multiplicity.singleton,VarParsing.VarParsing.varType.string,"output File (w/o .root)") +options.register('maxEvents',-1,VarParsing.VarParsing.multiplicity.singleton,VarParsing.VarParsing.varType.int,"maximum events") +options.register('skipEvents', 0, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int, "skip N events") +options.register('job', 0, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int, "job number") +options.register('nJobs', 1, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int, "total jobs") + + +import os +release=os.environ['CMSSW_VERSION'][6:11] +print("Using release "+release) + +options.register( + 'inputFiles','', + VarParsing.VarParsing.multiplicity.list, + VarParsing.VarParsing.varType.string, + "input files " + ) + +if hasattr(sys, "argv"): + options.parseArguments() + + +process = cms.Process("lheWeightCounter") + +process.maxEvents = cms.untracked.PSet( input = cms.untracked.int32(-1) ) + +process.load('FWCore.MessageService.MessageLogger_cfi') +process.MessageLogger.cerr.FwkReport.reportEvery = 10 +if options.inputScript == '': #this is probably for testing + process.MessageLogger.cerr.FwkReport.reportEvery = 100 + +process.options = cms.untracked.PSet( + allowUnscheduled = cms.untracked.bool(True), + wantSummary=cms.untracked.bool(True) +) + + +sampleListFile = 'DeepNTuples.DeepNtuplizer.samples.singleMuon_2016_cfg' +process.load(sampleListFile) #default input + +if options.inputFiles: + process.source.fileNames = options.inputFiles + +if options.inputScript != '' and options.inputScript != sampleListFile: + process.load(options.inputScript) + +#process.source.fileNames=['file:/afs/cern.ch/work/d/dwalter/data/ttbar/data.root'] #store/data/Run2016H/SingleMuon/MINIAOD/18Apr2017-v1/00000/00E02A09-853C-E711-93FF-3417EBE644A7.root + + + +numberOfFiles = len(process.source.fileNames) +numberOfJobs = options.nJobs +jobNumber = options.job + +process.source.fileNames = process.source.fileNames[jobNumber:numberOfFiles:numberOfJobs] +if options.nJobs > 1: + print ("running over these files:") + print (process.source.fileNames) + +process.source.skipEvents = cms.untracked.uint32(options.skipEvents) +process.maxEvents = cms.untracked.PSet( + input = cms.untracked.int32 (options.maxEvents) +) + +process.options = cms.untracked.PSet( + SkipEvent = cms.untracked.vstring('ProductNotFound') +) + + +process.TFileService = cms.Service("TFileService", + fileName=cms.string("lheWeights_"+str(options.job) +".root"), + closeFileFast=cms.untracked.bool(True) + ) + +process.lheAnalyzer = cms.EDAnalyzer('lheAnalyzer', + lheInfo = cms.InputTag("externalLHEProducer") + ) + + +process.endp = cms.EndPath(process.lheAnalyzer) \ No newline at end of file diff --git a/DeepNtuplizer/python/PupMCHistProd.py b/DeepNtuplizer/python/PupMCHistProd.py new file mode 100644 index 00000000000..5b86114116b --- /dev/null +++ b/DeepNtuplizer/python/PupMCHistProd.py @@ -0,0 +1,88 @@ +### +# Program to produce a histogram of the number of interactions per bunch crossing of a monte carlo sample, uses puAnalyzer.cc +# This histogram is needed to calculate the pileup reweighting +### +import FWCore.ParameterSet.Config as cms + +import FWCore.ParameterSet.VarParsing as VarParsing +### parsing job options +import sys + + +options = VarParsing.VarParsing() + +options.register('inputScript','',VarParsing.VarParsing.multiplicity.singleton,VarParsing.VarParsing.varType.string,"input Script") +options.register('outputFile','output',VarParsing.VarParsing.multiplicity.singleton,VarParsing.VarParsing.varType.string,"output File (w/o .root)") +options.register('maxEvents',-1,VarParsing.VarParsing.multiplicity.singleton,VarParsing.VarParsing.varType.int,"maximum events") +options.register('skipEvents', 0, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int, "skip N events") +options.register('job', 0, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int, "job number") +options.register('nJobs', 1, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int, "total jobs") +options.register('isData', True, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.bool, "switch off generator jets") + +import os +release=os.environ['CMSSW_VERSION'][6:11] +print("Using release "+release) + +options.register( + 'inputFiles','', + VarParsing.VarParsing.multiplicity.list, + VarParsing.VarParsing.varType.string, + "input files (default is the tt RelVal)" + ) + +if hasattr(sys, "argv"): + options.parseArguments() + + +process = cms.Process("pupMCHistProd") + + +process.maxEvents = cms.untracked.PSet( input = cms.untracked.int32(-1) ) + +process.load('FWCore.MessageService.MessageLogger_cfi') +process.MessageLogger.cerr.FwkReport.reportEvery = 10 +if options.inputScript == '': #this is probably for testing + process.MessageLogger.cerr.FwkReport.reportEvery = 100 + +process.options = cms.untracked.PSet( + allowUnscheduled = cms.untracked.bool(True), + wantSummary=cms.untracked.bool(True) +) + + +sampleListFile = 'DeepNTuples.DeepNtuplizer.samples.singleMuon_2016_cfg' +process.load(sampleListFile) #default input + +if options.inputFiles: + process.source.fileNames = options.inputFiles + +if options.inputScript != '' and options.inputScript != sampleListFile: + process.load(options.inputScript) + +process.source.fileNames=['file:/afs/cern.ch/work/d/dwalter/data/ttbar/TT/output_0_1.root'] #store/data/Run2016H/SingleMuon/MINIAOD/18Apr2017-v1/00000/00E02A09-853C-E711-93FF-3417EBE644A7.root + +numberOfFiles = len(process.source.fileNames) +numberOfJobs = options.nJobs +jobNumber = options.job + +process.source.fileNames = process.source.fileNames[jobNumber:numberOfFiles:numberOfJobs] +if options.nJobs > 1: + print ("running over these files:") + print (process.source.fileNames) + + +process.maxEvents = cms.untracked.PSet( + input = cms.untracked.int32 (options.maxEvents) +) + + +process.TFileService = cms.Service("TFileService", + fileName=cms.string("MyMCPileupHistogram_"+str(options.job) +".root"), + closeFileFast=cms.untracked.bool(True) + ) +process.puAnalyzer = cms.EDAnalyzer("puAnalyzer", + pileupInfo=cms.InputTag("slimmedAddPileupInfo") + ) + + +process.endp = cms.EndPath( process.puAnalyzer) \ No newline at end of file diff --git a/DeepNtuplizer/python/PupWeightMaker.py b/DeepNtuplizer/python/PupWeightMaker.py new file mode 100644 index 00000000000..b25be612e1b --- /dev/null +++ b/DeepNtuplizer/python/PupWeightMaker.py @@ -0,0 +1,28 @@ +###### +# takes data and MC histograms of pileup distribution and computes the pileup weights +###### + +import ROOT +import pdb + +file_pileup_MC = ROOT.TFile( + "/afs/cern.ch/work/d/dwalter/DeepNTuples/CMSSW_8_0_29/src/DeepNTuples/DeepNtuplizer/data/MyMCPileupHist.root") +file_pileup_Data = ROOT.TFile( + "/afs/cern.ch/work/d/dwalter/DeepNTuples/CMSSW_8_0_29/src/DeepNTuples//DeepNtuplizer/data/MyDataPileupHist.root") + +hist_pileup_MC = file_pileup_MC.Get("pileup") +hist_pileup_Data = file_pileup_Data.Get("pileup") + +def makePileupWeights(hist_data, hist_mc): + pupWeights = [1.0] + hist_mc.Scale(1. / hist_mc.Integral()) + hist_data.Scale(1. / hist_data.Integral()) + for bin in range(1,hist_data.GetNbinsX()+2): + if hist_mc.GetBinContent(bin) != 0: + w = hist_data.GetBinContent(bin)/hist_mc.GetBinContent(bin) + pupWeights.append(w) + else: + pupWeights.append(1) + return pupWeights + +print makePileupWeights(hist_pileup_Data,hist_pileup_MC) \ No newline at end of file diff --git a/DeepNtuplizer/src/ntuple_JetInfo.cc b/DeepNtuplizer/src/ntuple_JetInfo.cc index 97e70cedcc4..6df19343f37 100644 --- a/DeepNtuplizer/src/ntuple_JetInfo.cc +++ b/DeepNtuplizer/src/ntuple_JetInfo.cc @@ -15,6 +15,9 @@ #include #include "DataFormats/Math/interface/deltaR.h" +#include +#include + using namespace std; void ntuple_JetInfo::getInput(const edm::ParameterSet& iConfig){ @@ -25,10 +28,16 @@ void ntuple_JetInfo::getInput(const edm::ParameterSet& iConfig){ jetAbsEtaMin_=(iConfig.getParameter("jetAbsEtaMin")); jetAbsEtaMax_=(iConfig.getParameter("jetAbsEtaMax")); + useLHEWeights_ = (iConfig.getParameter("useLHEWeights")); + crossSection_ = (iConfig.getParameter("crossSection")); + luminosity_ = (iConfig.getParameter("luminosity")); + efficiency_ = (iConfig.getParameter("efficiency")); + vector disc_names = iConfig.getParameter >("bDiscriminators"); for(auto& name : disc_names) { discriminators_[name] = 0.; } + } void ntuple_JetInfo::initBranches(TTree* tree){ @@ -57,6 +66,7 @@ void ntuple_JetInfo::initBranches(TTree* tree){ addBranch(tree,"isG",&isG_, "isG_/i"); addBranch(tree,"isUndefined",&isUndefined_, "isUndefined_/i"); addBranch(tree,"genDecay",&genDecay_, "genDecay_/f"); + addBranch(tree,"isRealData",&isRealData_, "isRealData_/i"); //truth labeling with fallback to physics definition for light/gluon/undefined of standard flavor definition addBranch(tree,"isPhysB",&isPhysB_, "isPhysB_/i"); @@ -82,7 +92,7 @@ void ntuple_JetInfo::initBranches(TTree* tree){ addBranch(tree,"jet_mass", &jet_mass_); addBranch(tree,"jet_energy", &jet_energy_); - + addBranch(tree,"event_weight", &event_weight_); //jet id addBranch(tree,"jet_looseId", &jet_looseId_); @@ -142,10 +152,14 @@ void ntuple_JetInfo::readEvent(const edm::Event& iEvent){ iEvent.getByToken(axis2Token_, axis2Handle); iEvent.getByToken(multToken_, multHandle); - iEvent.getByToken(genJetMatchReclusterToken_, genJetMatchRecluster); - iEvent.getByToken(genJetMatchWithNuToken_, genJetMatchWithNu); + if(!iEvent.isRealData()){ + iEvent.getByToken(genJetMatchReclusterToken_, genJetMatchRecluster); + iEvent.getByToken(genJetMatchWithNuToken_, genJetMatchWithNu); + + iEvent.getByToken(genParticlesToken_, genParticlesHandle); - iEvent.getByToken(genParticlesToken_, genParticlesHandle); + iEvent.getByToken(lheToken_, lheInfo); + } iEvent.getByToken(muonsToken_, muonsHandle); @@ -165,88 +179,91 @@ void ntuple_JetInfo::readEvent(const edm::Event& iEvent){ Bhadron_daughter_.clear(); //std::cout << " start search for a b in this event "<(genC); - - if((abs(gen.pdgId())>500&&abs(gen.pdgId())<600)||(abs(gen.pdgId())>5000&&abs(gen.pdgId())<6000)) { - - //std::cout<0){ - - if( (abs(gen.daughter(0)->pdgId())>500&&abs(gen.daughter(0)->pdgId())<600)||(abs(gen.daughter(0)->pdgId())>5000&&abs(gen.daughter(0)->pdgId())<6000)) - { - if(gen.daughter(0)->numberOfDaughters()>0) - { - - const reco::GenParticle &daughter_ = static_cast< const reco::GenParticle &>(*(gen.daughter(0)->daughter(0))); - - if(daughter_.vx()!=gen.vx()) - { - Bhadron_daughter_.push_back(daughter_); - } - // else { - // std::cout << "only b daughters " << endl; - // } - } - else Bhadron_daughter_.push_back(gen); - - } - else{ - // std::cout<vx()<< " oh " <pdgId() <(*gen.daughter(0)); - Bhadron_daughter_.push_back(daughter_); - } - - }// if daughter is there - else { - - //std::cout << " lonly B hadron, has NO daughter??? "<(genC); - if(abs(gen.pdgId())==12||abs(gen.pdgId())==14||abs(gen.pdgId())==16) { - const reco::GenParticle* mother = static_cast< const reco::GenParticle*> (gen.mother()); - if(mother!=NULL) { - if((abs(mother->pdgId())>500&&abs(mother->pdgId())<600)||(abs(mother->pdgId())>5000&&abs(mother->pdgId())<6000)) { - neutrinosLepB.emplace_back(gen); + if(!iEvent.isRealData()){ + for (const reco::Candidate &genC : *genParticlesHandle){ + + const reco::GenParticle &gen = static_cast< const reco::GenParticle &>(genC); + + if((abs(gen.pdgId())>500&&abs(gen.pdgId())<600)||(abs(gen.pdgId())>5000&&abs(gen.pdgId())<6000)) { + + //std::cout<0){ + + if( (abs(gen.daughter(0)->pdgId())>500&&abs(gen.daughter(0)->pdgId())<600)||(abs(gen.daughter(0)->pdgId())>5000&&abs(gen.daughter(0)->pdgId())<6000)) + { + if(gen.daughter(0)->numberOfDaughters()>0) + { + + const reco::GenParticle &daughter_ = static_cast< const reco::GenParticle &>(*(gen.daughter(0)->daughter(0))); + + if(daughter_.vx()!=gen.vx()) + { + Bhadron_daughter_.push_back(daughter_); + } + // else { + // std::cout << "only b daughters " << endl; + // } + } + else Bhadron_daughter_.push_back(gen); + + } + else{ + // std::cout<vx()<< " oh " <pdgId() <(*gen.daughter(0)); + Bhadron_daughter_.push_back(daughter_); + } + + }// if daughter is there + else { + + //std::cout << " lonly B hadron, has NO daughter??? "<pdgId())>400&&abs(mother->pdgId())<500)||(abs(mother->pdgId())>4000&&abs(mother->pdgId())<5000)) { - neutrinosLepB_C.emplace_back(gen); + } + } + + + for (const reco::Candidate &genC : *genParticlesHandle) { + const reco::GenParticle &gen = static_cast< const reco::GenParticle &>(genC); + if(abs(gen.pdgId())==12||abs(gen.pdgId())==14||abs(gen.pdgId())==16) { + const reco::GenParticle* mother = static_cast< const reco::GenParticle*> (gen.mother()); + if(mother!=NULL) { + if((abs(mother->pdgId())>500&&abs(mother->pdgId())<600)||(abs(mother->pdgId())>5000&&abs(mother->pdgId())<6000)) { + neutrinosLepB.emplace_back(gen); + } + if((abs(mother->pdgId())>400&&abs(mother->pdgId())<500)||(abs(mother->pdgId())>4000&&abs(mother->pdgId())<5000)) { + neutrinosLepB_C.emplace_back(gen); + } + } + else { + std::cout << "No mother" << std::endl; } } - else { - std::cout << "No mother" << std::endl; + + int id(std::abs(gen.pdgId())); + int status(gen.status()); + + if (id == 21 && status >= 21 && status <= 59) { //// Pythia8 hard scatter, ISR, or FSR + if ( gen.numberOfDaughters() == 2 ) { + const reco::Candidate* d0 = gen.daughter(0); + const reco::Candidate* d1 = gen.daughter(1); + if ( std::abs(d0->pdgId()) == 5 && std::abs(d1->pdgId()) == 5 + && d0->pdgId()*d1->pdgId() < 0 && reco::deltaR(*d0, *d1) < 0.4) gToBB.push_back(gen) ; + if ( std::abs(d0->pdgId()) == 4 && std::abs(d1->pdgId()) == 4 + && d0->pdgId()*d1->pdgId() < 0 && reco::deltaR(*d0, *d1) < 0.4) gToCC.push_back(gen) ; + } } - } - int id(std::abs(gen.pdgId())); - int status(gen.status()); - - if (id == 21 && status >= 21 && status <= 59) { //// Pythia8 hard scatter, ISR, or FSR - if ( gen.numberOfDaughters() == 2 ) { - const reco::Candidate* d0 = gen.daughter(0); - const reco::Candidate* d1 = gen.daughter(1); - if ( std::abs(d0->pdgId()) == 5 && std::abs(d1->pdgId()) == 5 - && d0->pdgId()*d1->pdgId() < 0 && reco::deltaR(*d0, *d1) < 0.4) gToBB.push_back(gen) ; - if ( std::abs(d0->pdgId()) == 4 && std::abs(d1->pdgId()) == 4 - && d0->pdgId()*d1->pdgId() < 0 && reco::deltaR(*d0, *d1) < 0.4) gToCC.push_back(gen) ; + if(id == 15 && false){ + alltaus_.push_back(gen); } - } - if(id == 15 && false){ - alltaus_.push_back(gen); } - + //technically a branch fill but per event, therefore here } - //technically a branch fill but per event, therefore here } //use either of these functions @@ -263,11 +280,14 @@ bool ntuple_JetInfo::fillBranches(const pat::Jet & jet, const size_t& jetidx, co if ( fabs(jet.eta()) < jetAbsEtaMin_ || fabs(jet.eta()) > jetAbsEtaMax_ ) returnval=false; // apply jet eta cut - // often we have way to many gluons that we do not need. This randomply reduces the gluons - if (gluonReduction_>0 && jet.partonFlavour()==21) - if(TRandom_.Uniform()>gluonReduction_) returnval=false; + if(!isData_){ + // often we have way to many gluons that we do not need. This randomply reduces the gluons + if (gluonReduction_>0 && jet.partonFlavour()==21) + if(TRandom_.Uniform()>gluonReduction_) returnval=false; + + if(jet.genJet()==NULL)returnval=false; + } - if(jet.genJet()==NULL)returnval=false; //branch fills @@ -277,12 +297,31 @@ bool ntuple_JetInfo::fillBranches(const pat::Jet & jet, const size_t& jetidx, co npv_ = vertices()->size(); - for (auto const& v : *pupInfo()) { - int bx = v.getBunchCrossing(); - if (bx == 0) { - ntrueInt_ = v.getTrueNumInteractions(); + if(!isData_){ + for (auto const& v : *pupInfo()) { + int bx = v.getBunchCrossing(); + if (bx == 0) { + ntrueInt_ = v.getTrueNumInteractions(); + } + } + double lheWeight = 1.; + + if(useLHEWeights_){ + lheWeight = lheInfo->weights()[0].wgt/std::abs(lheInfo->weights()[0].wgt); + } + + double pupWeight = 0; + if(ntrueInt_ < pupWeights.size()){ + pupWeight = pupWeights.at(ntrueInt_); } + + event_weight_ = luminosity_ * crossSection_ * efficiency_ * lheWeight * pupWeight; + } + else{ + event_weight_ = luminosity_; } + + rho_ = rhoInfo()[0]; @@ -299,7 +338,7 @@ bool ntuple_JetInfo::fillBranches(const pat::Jet & jet, const size_t& jetidx, co //std::vector > p= coll->ptrs(); isB_=0; isGBB_=0; isBB_=0; isC_=0; isGCC_=0; isCC_=0; isUD_=0;isTau_=0; - isS_=0; isG_=0, isLeptonicB_=0, isLeptonicB_C_=0, isUndefined_=0; + isS_=0; isG_=0, isLeptonicB_=0, isLeptonicB_C_=0, isUndefined_=0, isRealData_=0; auto muIds = deep_ntuples::jet_muonsIds(jet,*muonsHandle); auto elecIds = deep_ntuples::jet_electronsIds(jet,*electronsHandle); @@ -376,8 +415,12 @@ bool ntuple_JetInfo::fillBranches(const pat::Jet & jet, const size_t& jetidx, co isUndefined_=1;isPhysUndefined_=1; } - if(isUndefined_ && isPhysUndefined_) returnval=false; //skip event, if neither standard flavor definition nor physics definition fallback define a "proper flavor" - + if(isData_){ + isRealData_=1; + } + else{ + if(isUndefined_ && isPhysUndefined_) returnval=false; //skip event, if neither standard flavor definition nor physics definition fallback define a "proper flavor" + } pat::JetCollection h; jet_pt_ = jet.correctedJet("Uncorrected").pt(); From 8b45f0617a14b7fb74cb00c89da521a9204f20c6 Mon Sep 17 00:00:00 2001 From: David Walter Date: Mon, 19 Feb 2018 17:35:25 +0100 Subject: [PATCH 02/17] some minor changes for better usage --- .../production/DeepNtuplizer_tt_dilep.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py b/DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py index c999f61607f..b364165df61 100644 --- a/DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py +++ b/DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py @@ -18,6 +18,12 @@ options.register('selectJets', True, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.bool,"select jets with good gen match") options.register('isData', False, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.bool, "switch off generator jets") options.register('deepNtuplizer',True, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.bool, "run deepNtuplizer or just the ttbar selection") +options.register('lheWeights',False, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.bool, "use LHE weights") +options.register('crossSection', 1.0, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.float, "cross section") +options.register('luminosity', 1.0, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.float, "luminosity") +options.register('nEvents', 1.0, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.float, "total number of the events for this process (to compute efficiency)") + + import os @@ -72,7 +78,7 @@ #process.source.fileNames=['file:./00E02A09-853C-E711-93FF-3417EBE644A7.root'] #store/data/Run2016H/SingleMuon/MINIAOD/18Apr2017-v1/00000/00E02A09-853C-E711-93FF-3417EBE644A7.root #process.source.fileNames=['file:./000C6E52-8BEC-E611-B3FF-0025905C42FE.root'] #isData=True -process.source.fileNames=['file:./0693E0E7-97BE-E611-B32F-0CC47A78A3D8.root'] #isData=False +#process.source.fileNames=['file:./0693E0E7-97BE-E611-B32F-0CC47A78A3D8.root'] #isData=False numberOfFiles = len(process.source.fileNames) numberOfJobs = options.nJobs @@ -372,6 +378,13 @@ process.deepntuplizer.applySelection = cms.bool(options.selectJets) +process.deepntuplizer.isData = cms.bool(options.isData) +process.deepntuplizer.useLHEWeights = cms.bool(options.lheWeights) +process.deepntuplizer.crossSection = cms.double(options.crossSection) +process.deepntuplizer.luminosity = cms.double(options.luminosity) +process.deepntuplizer.efficiency = cms.double(1./options.nEvents) + + if int(release.replace("_", "")) >= 840: process.deepntuplizer.tagInfoName = cms.string('pfDeepCSV') From 28dbcb9950ffcce9fad54f502037a9f0c74998b1 Mon Sep 17 00:00:00 2001 From: davidwalter2 <31730764+davidwalter2@users.noreply.github.com> Date: Mon, 19 Feb 2018 17:38:54 +0100 Subject: [PATCH 03/17] Delete webServers.xml --- .idea/webServers.xml | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 .idea/webServers.xml diff --git a/.idea/webServers.xml b/.idea/webServers.xml deleted file mode 100644 index e2a1442af4f..00000000000 --- a/.idea/webServers.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - \ No newline at end of file From aa6f17c7adb952ec535df438fcc9d0538bc5e8a3 Mon Sep 17 00:00:00 2001 From: David Walter Date: Tue, 20 Feb 2018 12:52:06 +0100 Subject: [PATCH 04/17] New module ntuple_eventInfo.cc --- DeepNtuplizer/interface/ntuple_JetInfo.h | 21 ------ DeepNtuplizer/interface/ntuple_eventInfo.h | 63 ++++++++++++++++++ DeepNtuplizer/plugins/DeepNtuplizer.cc | 16 +++-- .../production/DeepNtuplizer_tt_dilep.py | 10 +-- DeepNtuplizer/python/DeepNtuplizer_cfi.py | 5 +- DeepNtuplizer/src/ntuple_JetInfo.cc | 52 ++++----------- DeepNtuplizer/src/ntuple_eventInfo.cc | 64 +++++++++++++++++++ 7 files changed, 154 insertions(+), 77 deletions(-) create mode 100644 DeepNtuplizer/interface/ntuple_eventInfo.h create mode 100644 DeepNtuplizer/src/ntuple_eventInfo.cc diff --git a/DeepNtuplizer/interface/ntuple_JetInfo.h b/DeepNtuplizer/interface/ntuple_JetInfo.h index 6cea78b8742..215bc148bb1 100644 --- a/DeepNtuplizer/interface/ntuple_JetInfo.h +++ b/DeepNtuplizer/interface/ntuple_JetInfo.h @@ -13,8 +13,6 @@ #include #include -#include "SimDataFormats/GeneratorProducts/interface/LHEEventProduct.h" - /* * For global jet info such as eta, pt, gen info */ @@ -73,19 +71,12 @@ class ntuple_JetInfo: public ntuple_content{ electronsToken_ = electronsToken; } - void setLHEToken(edm::EDGetTokenT lheToken) { - lheToken_ = lheToken; - } - void setUseHerwigCompatibleMatching(const bool use){ useherwcompat_matching_=use; } void setIsHerwig(const bool use){ isherwig_=use; } - void setIsData(const bool use){ - isData_=use; - } //private: @@ -114,8 +105,6 @@ class ntuple_JetInfo: public ntuple_content{ edm::EDGetTokenT muonsToken_; edm::EDGetTokenT electronsToken_; - edm::EDGetTokenT lheToken_; - edm::Handle > genJetMatchRecluster; edm::Handle > genJetMatchWithNu; @@ -124,8 +113,6 @@ class ntuple_JetInfo: public ntuple_content{ edm::Handle muonsHandle; edm::Handle electronsHandle; - edm::Handle lheInfo; - TRandom3 TRandom_; float gluonReduction_; @@ -199,14 +186,6 @@ class ntuple_JetInfo: public ntuple_content{ float jet_mass_; float jet_energy_; - // variables for event weights - bool useLHEWeights_; - std::vector pupWeights = {0., 0.9059208563049067, 0.4689946658078284, 0.4646384395209148, 0.35969952879169353, 0.20581098696265324, 0.1272975292012222, 0.11484070280016173, 0.18997631713506571, 0.2134442228038988, 0.2643260644534947, 0.38290419689123334, 0.5233231080095909, 0.6531355038202962, 0.7413472652417477, 0.8226986246368242, 0.909166618129074, 0.9754246515040906, 1.0116680456990728, 1.0419003275306946, 1.0762295787102802, 1.1034517536607453, 1.1240057591005752, 1.1262609366258989, 1.1198925605086503, 1.1078563848872773, 1.083911370342871, 1.0496801331833463, 1.0169474777740053, 0.9813073284102061, 0.9426647112682524, 0.9233559974737714, 0.894377685151131, 0.884518640484559, 0.8804996845439541, 0.888865624721422, 0.9107720191678217, 0.953824079957025, 1.0112115792549745, 1.0947266350670766, 1.1906625100966544, 1.3370686699103784, 1.510754710039529, 1.7098870624229212, 1.9391935863130325, 2.1529480239752585, 2.396292845558282, 2.7067102383965915, 2.9081731387455574, 3.126536829527805, 3.263323444233829, 3.3766746819738014, 3.3825183331846596, 3.332122539734733, 3.309580249670872, 2.962530063365449, 2.609107759179973, 2.4216997456337266, 2.228050917243899, 1.963846134469284, 1.844961576497657, 1.431817556288543, 1.5742387193813208, 1.731514171818786, 2.21989485741883, 2.8198818386713915, 3.8909891214054464, 5.4911613943458395, 8.610687700958811, 12.634799153629881, 20.32733145948569}; - float crossSection_; - float luminosity_; - float efficiency_; - float event_weight_; - float jet_looseId_; // quark/gluon diff --git a/DeepNtuplizer/interface/ntuple_eventInfo.h b/DeepNtuplizer/interface/ntuple_eventInfo.h new file mode 100644 index 00000000000..095e0b2b830 --- /dev/null +++ b/DeepNtuplizer/interface/ntuple_eventInfo.h @@ -0,0 +1,63 @@ +/* + * ntuple_eventInfo.h + * + * Created on: 20 Feb 2018 + * Author: dwalter + */ + +#ifndef DEEPNTUPLES_DEEPNTUPLIZER_INTERFACE_NTUPLE_EVENTINFO_H_ +#define DEEPNTUPLES_DEEPNTUPLIZER_INTERFACE_NTUPLE_EVENTINFO_H_ + +#include "ntuple_content.h" + +#include + +#include "SimDataFormats/GeneratorProducts/interface/LHEEventProduct.h" + +/* + * For MC weights such as pileup, lhe, ... later: lepton scalefactors + */ +class ntuple_eventInfo: public ntuple_content{ +public: + ntuple_eventInfo():ntuple_content(), + isData_(false) +{} + + void getInput(const edm::ParameterSet& iConfig); + void initBranches(TTree* ); + void readEvent(const edm::Event& iEvent); + + //use either of these functions + + bool fillBranches(const pat::Jet &, const size_t& jetidx, const edm::View * coll=0); + + + void setLHEToken(edm::EDGetTokenT lheToken) { + lheToken_ = lheToken; + } + + +private: + + edm::EDGetTokenT lheToken_; + + edm::Handle lheInfo; + + bool isData_; + bool useLHEWeights_; + + // global variables + + float ntrueInt_; + + + std::vector pupWeights = {0., 0.9059208563049067, 0.4689946658078284, 0.4646384395209148, 0.35969952879169353, 0.20581098696265324, 0.1272975292012222, 0.11484070280016173, 0.18997631713506571, 0.2134442228038988, 0.2643260644534947, 0.38290419689123334, 0.5233231080095909, 0.6531355038202962, 0.7413472652417477, 0.8226986246368242, 0.909166618129074, 0.9754246515040906, 1.0116680456990728, 1.0419003275306946, 1.0762295787102802, 1.1034517536607453, 1.1240057591005752, 1.1262609366258989, 1.1198925605086503, 1.1078563848872773, 1.083911370342871, 1.0496801331833463, 1.0169474777740053, 0.9813073284102061, 0.9426647112682524, 0.9233559974737714, 0.894377685151131, 0.884518640484559, 0.8804996845439541, 0.888865624721422, 0.9107720191678217, 0.953824079957025, 1.0112115792549745, 1.0947266350670766, 1.1906625100966544, 1.3370686699103784, 1.510754710039529, 1.7098870624229212, 1.9391935863130325, 2.1529480239752585, 2.396292845558282, 2.7067102383965915, 2.9081731387455574, 3.126536829527805, 3.263323444233829, 3.3766746819738014, 3.3825183331846596, 3.332122539734733, 3.309580249670872, 2.962530063365449, 2.609107759179973, 2.4216997456337266, 2.228050917243899, 1.963846134469284, 1.844961576497657, 1.431817556288543, 1.5742387193813208, 1.731514171818786, 2.21989485741883, 2.8198818386713915, 3.8909891214054464, 5.4911613943458395, 8.610687700958811, 12.634799153629881, 20.32733145948569}; + + /////////branches + float event_weight_; + + +}; + + +#endif /* DEEPNTUPLES_DEEPNTUPLIZER_INTERFACE_NTUPLE_EVENTINFO_H_ */ diff --git a/DeepNtuplizer/plugins/DeepNtuplizer.cc b/DeepNtuplizer/plugins/DeepNtuplizer.cc index a57c64876f0..a0459b7eeb5 100644 --- a/DeepNtuplizer/plugins/DeepNtuplizer.cc +++ b/DeepNtuplizer/plugins/DeepNtuplizer.cc @@ -13,6 +13,8 @@ #include "../interface/ntuple_bTagVars.h" #include "../interface/ntuple_FatJetInfo.h" #include "../interface/ntuple_DeepVertex.h" +#include "../interface/ntuple_eventInfo.h" + //ROOT includes #include "TTree.h" @@ -126,6 +128,7 @@ DeepNtuplizer::DeepNtuplizer(const edm::ParameterSet& iConfig): //not implemented yet const bool useHerwigCompatibleMatching=iConfig.getParameter("useHerwigCompatible"); const bool isHerwig=iConfig.getParameter("isHerwig"); + const bool isData=iConfig.getParameter("isData"); ntuple_content::useoffsets = iConfig.getParameter("useOffsets"); @@ -157,7 +160,6 @@ DeepNtuplizer::DeepNtuplizer(const edm::ParameterSet& iConfig): jetinfo->setUseHerwigCompatibleMatching(useHerwigCompatibleMatching); jetinfo->setIsHerwig(isHerwig); - jetinfo->setIsData(isData); if(!isData){ jetinfo->setGenJetMatchReclusterToken( @@ -166,12 +168,7 @@ DeepNtuplizer::DeepNtuplizer(const edm::ParameterSet& iConfig): jetinfo->setGenJetMatchWithNuToken( consumes >( iConfig.getParameter( "genJetMatchWithNu" ))); - - } - jetinfo->setLHEToken( - consumes( - iConfig.getParameter("lheInfo"))); jetinfo->setGenParticlesToken( @@ -195,6 +192,13 @@ DeepNtuplizer::DeepNtuplizer(const edm::ParameterSet& iConfig): addModule(new ntuple_bTagVars()); + ntuple_eventInfo *evweight = new ntuple_eventInfo(); + if(!isData){ + evweight->setLHEToken(consumes(iConfig.getParameter("lheInfo"))); + } + + addModule(evweight); + if(runFatJets_){ auto *fatjetinfo = new ntuple_FatJetInfo(jetR); fatjetinfo->setGenParticleToken(consumes(iConfig.getParameter("pruned"))); diff --git a/DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py b/DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py index b364165df61..08d44627505 100644 --- a/DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py +++ b/DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py @@ -18,10 +18,7 @@ options.register('selectJets', True, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.bool,"select jets with good gen match") options.register('isData', False, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.bool, "switch off generator jets") options.register('deepNtuplizer',True, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.bool, "run deepNtuplizer or just the ttbar selection") -options.register('lheWeights',False, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.bool, "use LHE weights") -options.register('crossSection', 1.0, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.float, "cross section") -options.register('luminosity', 1.0, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.float, "luminosity") -options.register('nEvents', 1.0, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.float, "total number of the events for this process (to compute efficiency)") +options.register('lheWeights',True, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.bool, "use LHE weights") @@ -78,7 +75,7 @@ #process.source.fileNames=['file:./00E02A09-853C-E711-93FF-3417EBE644A7.root'] #store/data/Run2016H/SingleMuon/MINIAOD/18Apr2017-v1/00000/00E02A09-853C-E711-93FF-3417EBE644A7.root #process.source.fileNames=['file:./000C6E52-8BEC-E611-B3FF-0025905C42FE.root'] #isData=True -#process.source.fileNames=['file:./0693E0E7-97BE-E611-B32F-0CC47A78A3D8.root'] #isData=False +process.source.fileNames=['file:./0693E0E7-97BE-E611-B32F-0CC47A78A3D8.root'] #isData=False numberOfFiles = len(process.source.fileNames) numberOfJobs = options.nJobs @@ -380,9 +377,6 @@ process.deepntuplizer.isData = cms.bool(options.isData) process.deepntuplizer.useLHEWeights = cms.bool(options.lheWeights) -process.deepntuplizer.crossSection = cms.double(options.crossSection) -process.deepntuplizer.luminosity = cms.double(options.luminosity) -process.deepntuplizer.efficiency = cms.double(1./options.nEvents) if int(release.replace("_", "")) >= 840: diff --git a/DeepNtuplizer/python/DeepNtuplizer_cfi.py b/DeepNtuplizer/python/DeepNtuplizer_cfi.py index ed196255e99..23424df4a43 100644 --- a/DeepNtuplizer/python/DeepNtuplizer_cfi.py +++ b/DeepNtuplizer/python/DeepNtuplizer_cfi.py @@ -35,9 +35,6 @@ applySelection=cms.bool(True), isData=cms.bool(False), - useLHEWeights=cms.bool(False), + useLHEWeights=cms.bool(True), - crossSection=cms.double(1.0), - luminosity = cms.double(42.0), - efficiency = cms.double(1.0) #1/((effective) number of events ) diff --git a/DeepNtuplizer/src/ntuple_JetInfo.cc b/DeepNtuplizer/src/ntuple_JetInfo.cc index 6df19343f37..10ed3d60899 100644 --- a/DeepNtuplizer/src/ntuple_JetInfo.cc +++ b/DeepNtuplizer/src/ntuple_JetInfo.cc @@ -15,9 +15,6 @@ #include #include "DataFormats/Math/interface/deltaR.h" -#include -#include - using namespace std; void ntuple_JetInfo::getInput(const edm::ParameterSet& iConfig){ @@ -28,16 +25,10 @@ void ntuple_JetInfo::getInput(const edm::ParameterSet& iConfig){ jetAbsEtaMin_=(iConfig.getParameter("jetAbsEtaMin")); jetAbsEtaMax_=(iConfig.getParameter("jetAbsEtaMax")); - useLHEWeights_ = (iConfig.getParameter("useLHEWeights")); - crossSection_ = (iConfig.getParameter("crossSection")); - luminosity_ = (iConfig.getParameter("luminosity")); - efficiency_ = (iConfig.getParameter("efficiency")); - vector disc_names = iConfig.getParameter >("bDiscriminators"); for(auto& name : disc_names) { discriminators_[name] = 0.; } - } void ntuple_JetInfo::initBranches(TTree* tree){ @@ -92,7 +83,7 @@ void ntuple_JetInfo::initBranches(TTree* tree){ addBranch(tree,"jet_mass", &jet_mass_); addBranch(tree,"jet_energy", &jet_energy_); - addBranch(tree,"event_weight", &event_weight_); + //jet id addBranch(tree,"jet_looseId", &jet_looseId_); @@ -147,18 +138,19 @@ void ntuple_JetInfo::initBranches(TTree* tree){ void ntuple_JetInfo::readEvent(const edm::Event& iEvent){ + isData_ = iEvent.isRealData(); + iEvent.getByToken(qglToken_, qglHandle); iEvent.getByToken(ptDToken_, ptDHandle); iEvent.getByToken(axis2Token_, axis2Handle); iEvent.getByToken(multToken_, multHandle); - if(!iEvent.isRealData()){ + if(!isData_){ iEvent.getByToken(genJetMatchReclusterToken_, genJetMatchRecluster); iEvent.getByToken(genJetMatchWithNuToken_, genJetMatchWithNu); iEvent.getByToken(genParticlesToken_, genParticlesHandle); - iEvent.getByToken(lheToken_, lheInfo); } @@ -179,7 +171,7 @@ void ntuple_JetInfo::readEvent(const edm::Event& iEvent){ Bhadron_daughter_.clear(); //std::cout << " start search for a b in this event "<(genC); @@ -196,17 +188,17 @@ void ntuple_JetInfo::readEvent(const edm::Event& iEvent){ if(gen.daughter(0)->numberOfDaughters()>0) { - const reco::GenParticle &daughter_ = static_cast< const reco::GenParticle &>(*(gen.daughter(0)->daughter(0))); + const reco::GenParticle &daughter_ = static_cast< const reco::GenParticle &>(*(gen.daughter(0)->daughter(0))); - if(daughter_.vx()!=gen.vx()) - { - Bhadron_daughter_.push_back(daughter_); + if(daughter_.vx()!=gen.vx()) + { + Bhadron_daughter_.push_back(daughter_); + } + // else { + // std::cout << "only b daughters " << endl; + // } } - // else { - // std::cout << "only b daughters " << endl; - // } - } - else Bhadron_daughter_.push_back(gen); + else Bhadron_daughter_.push_back(gen); } else{ @@ -304,24 +296,8 @@ bool ntuple_JetInfo::fillBranches(const pat::Jet & jet, const size_t& jetidx, co ntrueInt_ = v.getTrueNumInteractions(); } } - double lheWeight = 1.; - - if(useLHEWeights_){ - lheWeight = lheInfo->weights()[0].wgt/std::abs(lheInfo->weights()[0].wgt); - } - - double pupWeight = 0; - if(ntrueInt_ < pupWeights.size()){ - pupWeight = pupWeights.at(ntrueInt_); - } - - event_weight_ = luminosity_ * crossSection_ * efficiency_ * lheWeight * pupWeight; - } - else{ - event_weight_ = luminosity_; } - rho_ = rhoInfo()[0]; diff --git a/DeepNtuplizer/src/ntuple_eventInfo.cc b/DeepNtuplizer/src/ntuple_eventInfo.cc new file mode 100644 index 00000000000..c7603493bbe --- /dev/null +++ b/DeepNtuplizer/src/ntuple_eventInfo.cc @@ -0,0 +1,64 @@ +/* + * ntuple_eventInfo.cc + * + * Created on: 20 Feb 2018 + * Author: dwalter + */ + +#include "../interface/ntuple_eventInfo.h" + + +#include + + + +void ntuple_eventInfo::getInput(const edm::ParameterSet& iConfig){ + + useLHEWeights_ = (iConfig.getParameter("useLHEWeights")); + +} +void ntuple_eventInfo::initBranches(TTree* tree){ + + addBranch(tree,"event_weight", &event_weight_); + +} + + +void ntuple_eventInfo::readEvent(const edm::Event& iEvent){ + + if(!iEvent.isRealData()){ + + iEvent.getByToken(lheToken_, lheInfo); + } + + if(!iEvent.isRealData()){ + for (auto const& v : *pupInfo()) { + int bx = v.getBunchCrossing(); + if (bx == 0) { + ntrueInt_ = v.getTrueNumInteractions(); + } + } + double lheWeight = 1.; + + if(useLHEWeights_){ + lheWeight = lheInfo->weights()[0].wgt/std::abs(lheInfo->weights()[0].wgt); + } + + double pupWeight = 0; + if(ntrueInt_ < pupWeights.size()){ + pupWeight = pupWeights.at(ntrueInt_); + } + + event_weight_ = lheWeight * pupWeight; + } + else{ + event_weight_ = 1.; + } + +} + +//use either of these functions + +bool ntuple_eventInfo::fillBranches(const pat::Jet & jet, const size_t& jetidx, const edm::View * coll){ + return true; +} From 5451a98bc4123d17a99dfe0e1a4a10d45cfb541e Mon Sep 17 00:00:00 2001 From: David Walter Date: Wed, 21 Feb 2018 11:24:27 +0100 Subject: [PATCH 05/17] add analyzer globalInfo.cc to keep track of the efficiency --- DeepNtuplizer/interface/ntuple_eventInfo.h | 2 + DeepNtuplizer/plugins/globalInfo.cc | 148 ++++++++++++++++++ .../production/DeepNtuplizer_tt_dilep.py | 34 ++-- DeepNtuplizer/src/ntuple_eventInfo.cc | 1 - 4 files changed, 172 insertions(+), 13 deletions(-) create mode 100644 DeepNtuplizer/plugins/globalInfo.cc diff --git a/DeepNtuplizer/interface/ntuple_eventInfo.h b/DeepNtuplizer/interface/ntuple_eventInfo.h index 095e0b2b830..af47bf977a6 100644 --- a/DeepNtuplizer/interface/ntuple_eventInfo.h +++ b/DeepNtuplizer/interface/ntuple_eventInfo.h @@ -11,6 +11,8 @@ #include "ntuple_content.h" #include +#include + #include "SimDataFormats/GeneratorProducts/interface/LHEEventProduct.h" diff --git a/DeepNtuplizer/plugins/globalInfo.cc b/DeepNtuplizer/plugins/globalInfo.cc new file mode 100644 index 00000000000..245805bcb57 --- /dev/null +++ b/DeepNtuplizer/plugins/globalInfo.cc @@ -0,0 +1,148 @@ +// -*- C++ -*- +// +// Package: DeepNTuples/DeepNtuplizer +// Class: globalInfo +// +/**\class globalInfo globalInfo.cc DeepNTuples/DeepNtuplizer/plugins/globalInfo.cc + Description: This analyzer is used to count the (effective) number of initial events. + In the LHE case, the events with negative lhe weights have to be substracted from these with positive lhe weights +*/ +// +// Original Author: David Walter +// Created: Tue, 20 Feb 2018 17:18:02 GMT +// +// + +// system include files +#include +#include +#include +#include + +// user include files +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/Framework/interface/one/EDAnalyzer.h" + +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" + +#include "FWCore/ParameterSet/interface/ParameterSet.h" + +#include "FWCore/ServiceRegistry/interface/Service.h" +#include "CommonTools/UtilAlgos/interface/TFileService.h" + +#include "SimDataFormats/GeneratorProducts/interface/LHEEventProduct.h" + + +class globalInfo : public edm::one::EDAnalyzer { + public: + globalInfo(const edm::ParameterSet&); + + ~globalInfo(); + + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); + + + private: + virtual void beginJob() override; + virtual void analyze(const edm::Event&, const edm::EventSetup&) override; + virtual void endJob() override; + + edm::Service fs; + edm::EDGetTokenT t_LHEInfo; + edm::Handle h_LHEWeights; + + long nEvents_ = 0; + long nNegLHEEvents_ = 0; + bool useLHEWeights_ = true; + + TList * infolist = new TList; + + + // ----------member data --------------------------- +}; + +// +// constants, enums and typedefs +// + +// +// static data member definitions +// + +// +// constructors and destructor +// +globalInfo::globalInfo(const edm::ParameterSet& iConfig): + t_LHEInfo(consumes (iConfig.getParameter("lheInfo"))) + { + useLHEWeights_ = (iConfig.getParameter("useLHEWeights")); + +} + + +globalInfo::~globalInfo() +{ + + // do anything here that needs to be done at desctruction time + // (e.g. close files, deallocate resources etc.) + +} + + +// +// member functions +// + +// ------------ method called for each event ------------ +void +globalInfo::analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) +{ + nEvents_++; + + if(useLHEWeights_){ + iEvent.getByToken(t_LHEInfo, h_LHEWeights); + double lheWeight = h_LHEWeights->weights()[0].wgt/std::abs(h_LHEWeights->weights()[0].wgt); + if(lheWeight < 0.){ + nNegLHEEvents_++; + } + } +} + + +// ------------ method called once each job just before starting event loop ------------ +void +globalInfo::beginJob() +{ +} + +// ------------ method called once each job just after ending the event loop ------------ +void +globalInfo::endJob() +{ + std::cout<<"total number of initial events is: "<make()); + + infolist->Add(new TNamed("nInitialEvents",std::to_string(nEvents_).c_str())); + +} + +// ------------ method fills 'descriptions' with the allowed parameters for the module ------------ +void +globalInfo::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + //The following says we do not know what parameters are allowed so do no validation + // Please change this to state exactly what you do use, even if it is no parameters + edm::ParameterSetDescription desc; + desc.setUnknown(); + descriptions.addDefault(desc); +} + +//define this as a plug-in +DEFINE_FWK_MODULE(globalInfo); \ No newline at end of file diff --git a/DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py b/DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py index 08d44627505..bea770cad59 100644 --- a/DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py +++ b/DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py @@ -10,12 +10,13 @@ options.register('inputScript', '', VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.string,"input Script") options.register('outputFile', 'output', VarParsing.VarParsing.multiplicity.singleton,VarParsing.VarParsing.varType.string, "output File (w/o .root)") -options.register('maxEvents', -1, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int,"maximum events") +options.register('maxEvents', 200, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int,"maximum events") options.register('skipEvents', 0, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int, "skip N events") options.register('job', 0, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int,"job number") options.register('nJobs', 1, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int, "total jobs") options.register('gluonReduction', 0.0, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.float, "gluon reduction") options.register('selectJets', True, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.bool,"select jets with good gen match") +options.register('globalTag', '', VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.string,"global tag for jet energy correction") options.register('isData', False, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.bool, "switch off generator jets") options.register('deepNtuplizer',True, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.bool, "run deepNtuplizer or just the ttbar selection") options.register('lheWeights',True, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.bool, "use LHE weights") @@ -46,10 +47,13 @@ process.load('Configuration.StandardSequences.MagneticField_cff') process.load('Configuration.StandardSequences.FrontierConditions_GlobalTag_cff') -if options.isData == False: - process.GlobalTag.globaltag = '80X_mcRun2_asymptotic_2016_TrancheIV_v8' # For MC Jet Energy correction -if options.isData == True: - process.GlobalTag.globaltag = '80X_dataRun2_2016SeptRepro_v7' # For Data Jet Energy correction +if options.globalTag == '': + if options.isData == False: + process.GlobalTag.globaltag = '80X_mcRun2_asymptotic_2016_TrancheIV_v8' # For MC Jet Energy correction + if options.isData == True: + process.GlobalTag.globaltag = '80X_dataRun2_2016SeptRepro_v7' # For Data Jet Energy correction +else: + process.GlobalTag.globaltag = options.globalTag process.maxEvents = cms.untracked.PSet(input=cms.untracked.int32(-1)) @@ -82,9 +86,14 @@ jobNumber = options.job process.source.fileNames = process.source.fileNames[jobNumber:numberOfFiles:numberOfJobs] -if options.nJobs > 1: - print ("running over these files:") - print (process.source.fileNames) +#if options.nJobs > 1: +print ("running over these files:") +print (process.source.fileNames) + +process.globalInfo = cms.EDAnalyzer('globalInfo', + lheInfo = cms.InputTag("externalLHEProducer"), + useLHEWeights=cms.bool(True) + ) process.source.skipEvents = cms.untracked.uint32(options.skipEvents) process.maxEvents = cms.untracked.PSet( @@ -392,13 +401,14 @@ paths=cms.untracked.vstring('p') ) + if options.isData: if options.deepNtuplizer: - process.p = cms.Path(process.TriggerSel + process.FinalSel + process.QGTagger + process.deepntuplizer) + process.p = cms.Path(process.globalInfo + process.TriggerSel + process.FinalSel + process.QGTagger + process.deepntuplizer) else: - process.p = cms.Path(process.TriggerSel + process.FinalSel + process.QGTagger) + process.p = cms.Path(process.globalInfo + process.TriggerSel + process.FinalSel + process.QGTagger) else: if options.deepNtuplizer: - process.p = cms.Path(process.TriggerSel + process.FinalSel + process.QGTagger + process.genJetSequence * process.deepntuplizer) + process.p = cms.Path(process.globalInfo + process.TriggerSel + process.FinalSel + process.QGTagger + process.genJetSequence * process.deepntuplizer) else: - process.p = cms.Path(process.TriggerSel + process.FinalSel + process.QGTagger + process.genJetSequence) + process.p = cms.Path(process.globalInfo + process.TriggerSel + process.FinalSel + process.QGTagger + process.genJetSequence) diff --git a/DeepNtuplizer/src/ntuple_eventInfo.cc b/DeepNtuplizer/src/ntuple_eventInfo.cc index c7603493bbe..b29f11c3a7f 100644 --- a/DeepNtuplizer/src/ntuple_eventInfo.cc +++ b/DeepNtuplizer/src/ntuple_eventInfo.cc @@ -20,7 +20,6 @@ void ntuple_eventInfo::getInput(const edm::ParameterSet& iConfig){ void ntuple_eventInfo::initBranches(TTree* tree){ addBranch(tree,"event_weight", &event_weight_); - } From eeabfb02d15872e660ef6ae59c9741e51100aef7 Mon Sep 17 00:00:00 2001 From: David Walter Date: Wed, 21 Feb 2018 14:03:57 +0100 Subject: [PATCH 06/17] compute pileup weights from root histograms instead of using a hardcoded array --- DeepNtuplizer/interface/ntuple_eventInfo.h | 16 +++++++++--- DeepNtuplizer/plugins/globalInfo.cc | 2 +- DeepNtuplizer/python/DeepNtuplizer_cfi.py | 6 +++++ DeepNtuplizer/src/ntuple_eventInfo.cc | 29 ++++++++++++++++++---- 4 files changed, 44 insertions(+), 9 deletions(-) diff --git a/DeepNtuplizer/interface/ntuple_eventInfo.h b/DeepNtuplizer/interface/ntuple_eventInfo.h index af47bf977a6..efbcef541ee 100644 --- a/DeepNtuplizer/interface/ntuple_eventInfo.h +++ b/DeepNtuplizer/interface/ntuple_eventInfo.h @@ -11,9 +11,13 @@ #include "ntuple_content.h" #include +#include +#include +#include #include + #include "SimDataFormats/GeneratorProducts/interface/LHEEventProduct.h" /* @@ -42,18 +46,24 @@ class ntuple_eventInfo: public ntuple_content{ private: edm::EDGetTokenT lheToken_; - edm::Handle lheInfo; bool isData_; bool useLHEWeights_; + std::string pupDataDir_; + std::string pupMCDir_; + + TFile *pupMCFile; + TFile *pupDataFile; + + TH1F * pupMCHist; + TH1F * pupDataHist; // global variables float ntrueInt_; - - std::vector pupWeights = {0., 0.9059208563049067, 0.4689946658078284, 0.4646384395209148, 0.35969952879169353, 0.20581098696265324, 0.1272975292012222, 0.11484070280016173, 0.18997631713506571, 0.2134442228038988, 0.2643260644534947, 0.38290419689123334, 0.5233231080095909, 0.6531355038202962, 0.7413472652417477, 0.8226986246368242, 0.909166618129074, 0.9754246515040906, 1.0116680456990728, 1.0419003275306946, 1.0762295787102802, 1.1034517536607453, 1.1240057591005752, 1.1262609366258989, 1.1198925605086503, 1.1078563848872773, 1.083911370342871, 1.0496801331833463, 1.0169474777740053, 0.9813073284102061, 0.9426647112682524, 0.9233559974737714, 0.894377685151131, 0.884518640484559, 0.8804996845439541, 0.888865624721422, 0.9107720191678217, 0.953824079957025, 1.0112115792549745, 1.0947266350670766, 1.1906625100966544, 1.3370686699103784, 1.510754710039529, 1.7098870624229212, 1.9391935863130325, 2.1529480239752585, 2.396292845558282, 2.7067102383965915, 2.9081731387455574, 3.126536829527805, 3.263323444233829, 3.3766746819738014, 3.3825183331846596, 3.332122539734733, 3.309580249670872, 2.962530063365449, 2.609107759179973, 2.4216997456337266, 2.228050917243899, 1.963846134469284, 1.844961576497657, 1.431817556288543, 1.5742387193813208, 1.731514171818786, 2.21989485741883, 2.8198818386713915, 3.8909891214054464, 5.4911613943458395, 8.610687700958811, 12.634799153629881, 20.32733145948569}; + std::vector pupWeights; /////////branches float event_weight_; diff --git a/DeepNtuplizer/plugins/globalInfo.cc b/DeepNtuplizer/plugins/globalInfo.cc index 245805bcb57..bb0945d3026 100644 --- a/DeepNtuplizer/plugins/globalInfo.cc +++ b/DeepNtuplizer/plugins/globalInfo.cc @@ -130,7 +130,7 @@ globalInfo::endJob() infolist = (fs->make()); - infolist->Add(new TNamed("nInitialEvents",std::to_string(nEvents_).c_str())); + infolist->Add(new TNamed("nInitialEvents",std::to_string(nEvents_ - nNegLHEEvents_).c_str())); } diff --git a/DeepNtuplizer/python/DeepNtuplizer_cfi.py b/DeepNtuplizer/python/DeepNtuplizer_cfi.py index 23424df4a43..782a62bdccd 100644 --- a/DeepNtuplizer/python/DeepNtuplizer_cfi.py +++ b/DeepNtuplizer/python/DeepNtuplizer_cfi.py @@ -1,4 +1,7 @@ import FWCore.ParameterSet.Config as cms +import os + +datapath=os.environ['CMSSW_BASE']+'/src/DeepNTuples/DeepNtuplizer/data/' deepntuplizer = cms.EDAnalyzer('DeepNtuplizer', vertices = cms.InputTag("offlineSlimmedPrimaryVertices"), @@ -37,4 +40,7 @@ isData=cms.bool(False), useLHEWeights=cms.bool(True), + pileupDataDir=cms.string(datapath+"pileup_data_2016.root"), + pileupMCDir=cms.string(datapath+"pileup_MC_2016.root") + ) diff --git a/DeepNtuplizer/src/ntuple_eventInfo.cc b/DeepNtuplizer/src/ntuple_eventInfo.cc index b29f11c3a7f..b5249d8f34c 100644 --- a/DeepNtuplizer/src/ntuple_eventInfo.cc +++ b/DeepNtuplizer/src/ntuple_eventInfo.cc @@ -8,13 +8,33 @@ #include "../interface/ntuple_eventInfo.h" -#include - - void ntuple_eventInfo::getInput(const edm::ParameterSet& iConfig){ useLHEWeights_ = (iConfig.getParameter("useLHEWeights")); + pupDataDir_ = (iConfig.getParameter("pileupDataDir")); + pupMCDir_ = (iConfig.getParameter("pileupMCDir")); + + if(pupDataDir_=="" || pupMCDir_==""){ + std::cout<<"no pileup histograms, proceed without pileup reweighting. \n"; + } + else{ + pupMCFile = new TFile(pupMCDir_.c_str()); + pupDataFile = new TFile(pupDataDir_.c_str()); + + pupMCHist = (TH1F*)pupMCFile->Get("pileup"); + pupDataHist = (TH1F*)pupDataFile->Get("pileup"); + + pupMCHist->Scale(1./pupMCHist->Integral()); + pupDataHist->Scale(1./pupDataHist->Integral()); + + pupWeights.push_back(1.0); + for(int bin = 1; bin < pupMCHist->GetNbinsX() + 1; bin++){ + pupWeights.push_back(pupDataHist->GetBinContent(bin)/pupMCHist->GetBinContent(bin)); + } + } + + } void ntuple_eventInfo::initBranches(TTree* tree){ @@ -43,11 +63,10 @@ void ntuple_eventInfo::readEvent(const edm::Event& iEvent){ lheWeight = lheInfo->weights()[0].wgt/std::abs(lheInfo->weights()[0].wgt); } - double pupWeight = 0; + double pupWeight = 1.; if(ntrueInt_ < pupWeights.size()){ pupWeight = pupWeights.at(ntrueInt_); } - event_weight_ = lheWeight * pupWeight; } else{ From 047ab1e61f74bb859a1479f832104a501237f1df Mon Sep 17 00:00:00 2001 From: David Walter Date: Wed, 21 Feb 2018 14:14:32 +0100 Subject: [PATCH 07/17] add pileup histograms --- DeepNtuplizer/data/pileup_MC_2016.root | Bin 0 -> 5900 bytes DeepNtuplizer/data/pileup_data_2016.root | Bin 0 -> 4840 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 DeepNtuplizer/data/pileup_MC_2016.root create mode 100644 DeepNtuplizer/data/pileup_data_2016.root diff --git a/DeepNtuplizer/data/pileup_MC_2016.root b/DeepNtuplizer/data/pileup_MC_2016.root new file mode 100644 index 0000000000000000000000000000000000000000..4a2a782096c82d51e5d24f1bfa038d70c9fdcc21 GIT binary patch literal 5900 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 literal 0 HcmV?d00001 diff --git a/DeepNtuplizer/data/pileup_data_2016.root b/DeepNtuplizer/data/pileup_data_2016.root new file mode 100644 index 0000000000000000000000000000000000000000..db1564ce9a6fa65d47df56a7368cf2260192d5ae GIT binary patch literal 4840 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 RuLb{_44sN}*GDJ?@E`ZB{YU@+ literal 0 HcmV?d00001 From 66a996518beaf7a42c296b87d91f67ea4fd3b79b Mon Sep 17 00:00:00 2001 From: David Walter Date: Thu, 22 Feb 2018 13:56:24 +0100 Subject: [PATCH 08/17] add first lepton scalefactor bugfixes --- .../data/EfficienciesAndSF_ID_GH.root | Bin 0 -> 215993 bytes DeepNtuplizer/interface/ntuple_eventInfo.h | 18 ++- DeepNtuplizer/plugins/DeepNtuplizer.cc | 1 + DeepNtuplizer/plugins/ElectronIdAdder.cc | 47 +++++--- DeepNtuplizer/plugins/MuonIdAdder.cc | 42 +++++-- .../production/DeepNtuplizer_tt_dilep.py | 114 ++++++++---------- DeepNtuplizer/python/DeepNtuplizer_cfi.py | 11 +- DeepNtuplizer/src/ntuple_eventInfo.cc | 67 ++++++++-- 8 files changed, 181 insertions(+), 119 deletions(-) create mode 100644 DeepNtuplizer/data/EfficienciesAndSF_ID_GH.root diff --git a/DeepNtuplizer/data/EfficienciesAndSF_ID_GH.root b/DeepNtuplizer/data/EfficienciesAndSF_ID_GH.root new file mode 100644 index 0000000000000000000000000000000000000000..7c59c95fb43fc060eef2952c48b6a6ea7975885f GIT binary patch literal 215993 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 WUq?tTa&K>R00031153GgHIx80*!+F~ literal 0 HcmV?d00001 diff --git a/DeepNtuplizer/interface/ntuple_eventInfo.h b/DeepNtuplizer/interface/ntuple_eventInfo.h index efbcef541ee..8a123f9f2d9 100644 --- a/DeepNtuplizer/interface/ntuple_eventInfo.h +++ b/DeepNtuplizer/interface/ntuple_eventInfo.h @@ -14,6 +14,7 @@ #include #include #include +#include #include @@ -37,27 +38,34 @@ class ntuple_eventInfo: public ntuple_content{ bool fillBranches(const pat::Jet &, const size_t& jetidx, const edm::View * coll=0); - void setLHEToken(edm::EDGetTokenT lheToken) { lheToken_ = lheToken; } + void setMuonsToken(edm::EDGetTokenT> muonToken){ + muonToken_ = muonToken; + } private: edm::EDGetTokenT lheToken_; + edm::EDGetTokenT> muonToken_; + edm::Handle lheInfo; + edm::Handle> muons; bool isData_; bool useLHEWeights_; + std::string pupDataDir_; std::string pupMCDir_; + std::string sfMuonIdDir_; + std::string sfMuonIdName_; - TFile *pupMCFile; - TFile *pupDataFile; + TH2F *sfMuonIdHist; - TH1F * pupMCHist; - TH1F * pupDataHist; + TAxis *sfMuonIdHist_xaxis; + TAxis *sfMuonIdHist_yaxis; // global variables diff --git a/DeepNtuplizer/plugins/DeepNtuplizer.cc b/DeepNtuplizer/plugins/DeepNtuplizer.cc index a0459b7eeb5..366785d26ae 100644 --- a/DeepNtuplizer/plugins/DeepNtuplizer.cc +++ b/DeepNtuplizer/plugins/DeepNtuplizer.cc @@ -195,6 +195,7 @@ DeepNtuplizer::DeepNtuplizer(const edm::ParameterSet& iConfig): ntuple_eventInfo *evweight = new ntuple_eventInfo(); if(!isData){ evweight->setLHEToken(consumes(iConfig.getParameter("lheInfo"))); + evweight->setMuonsToken(consumes>(iConfig.getParameter("sfMuons"))); } addModule(evweight); diff --git a/DeepNtuplizer/plugins/ElectronIdAdder.cc b/DeepNtuplizer/plugins/ElectronIdAdder.cc index 54b19e804d2..2a701e2b6c5 100644 --- a/DeepNtuplizer/plugins/ElectronIdAdder.cc +++ b/DeepNtuplizer/plugins/ElectronIdAdder.cc @@ -9,35 +9,45 @@ #include "DataFormats/PatCandidates/interface/Electron.h" #include "DataFormats/VertexReco/interface/Vertex.h" - - class ElectronIdAdder : public edm::EDProducer { public: - explicit ElectronIdAdder(const edm::ParameterSet& iConfig): - src_(consumes >(iConfig.getParameter("src"))), - idMap_(consumes >(iConfig.getParameter("idMap"))), - vSrc_(consumes > (iConfig.getParameter("vSrc"))){ - produces >(); - } + explicit ElectronIdAdder(const edm::ParameterSet& iConfig); ~ElectronIdAdder(){} + void produce(edm::Event & iEvent, const edm::EventSetup& iSetup) override; private: edm::EDGetTokenT > src_; edm::EDGetTokenT > idMap_; edm::EDGetTokenT > vSrc_; + + edm::Handle > electrons; + edm::Handle > map; + edm::Handle > vertex; + + double minPt_; + double maxAbsEta_; }; +ElectronIdAdder::ElectronIdAdder(const edm::ParameterSet& iConfig): + src_(consumes >(iConfig.getParameter("src"))), + idMap_(consumes >(iConfig.getParameter("idMap"))), + vSrc_(consumes > (iConfig.getParameter("vSrc"))){ + produces >(); + + minPt_=(iConfig.getParameter("minPt")); + maxAbsEta_=(iConfig.getParameter("maxAbsEta")); + + } + void ElectronIdAdder::produce(edm::Event & iEvent, const edm::EventSetup & es) { - edm::Handle > electrons; - edm::Handle > map; - edm::Handle > vertex; iEvent.getByToken(src_, electrons); iEvent.getByToken(idMap_, map); iEvent.getByToken(vSrc_, vertex); - std::vector * out = new std::vector; out->reserve(electrons->size()); + std::vector * out = new std::vector; + out->reserve(electrons->size()); for (size_t i = 0; i < electrons->size(); ++i){ const auto iElectron = electrons->ptrAt(i); @@ -71,14 +81,13 @@ void ElectronIdAdder::produce(edm::Event & iEvent, const edm::EventSetup & es) { } pat::Electron newele(*iElectron); - newele.addUserFloat("tightcutbased",(float)idresult); - newele.addUserFloat("notInEtaVetoRegion", (float)notInCrack); - newele.addUserFloat("inAbsD0",(float)inAbsD0); - newele.addUserFloat("inAbsDz",(float)inAbsDz); - out->push_back(newele); + + if(idresult && notInCrack && inAbsD0 && inAbsDz && iElectron->pt() > minPt_ && std::abs(iElectron->eta())push_back(newele); + } } - std::unique_ptr > ptr(out); - iEvent.put(std::move(ptr)); + std::unique_ptr > ptr(out); + iEvent.put(std::move(ptr)); } diff --git a/DeepNtuplizer/plugins/MuonIdAdder.cc b/DeepNtuplizer/plugins/MuonIdAdder.cc index be75a97c05b..1c7cae7af94 100644 --- a/DeepNtuplizer/plugins/MuonIdAdder.cc +++ b/DeepNtuplizer/plugins/MuonIdAdder.cc @@ -11,39 +11,55 @@ class MuonIdAdder : public edm::EDProducer { public: - explicit MuonIdAdder(const edm::ParameterSet& iConfig): - src_(consumes > (iConfig.getParameter("src"))), - vSrc_(consumes > (iConfig.getParameter("vSrc"))){ - produces >(); - } + explicit MuonIdAdder(const edm::ParameterSet&); ~MuonIdAdder(){} void produce(edm::Event & iEvent, const edm::EventSetup& iSetup) override; private: edm::EDGetTokenT > src_; edm::EDGetTokenT > vSrc_; + + edm::Handle > muons; + edm::Handle > vertex; + + double minPt_; + double maxAbsEta_; + double maxRMI_; }; +MuonIdAdder::MuonIdAdder(const edm::ParameterSet& iConfig): + src_(consumes > (iConfig.getParameter("src"))), + vSrc_(consumes > (iConfig.getParameter("vSrc"))){ + produces >(); + + minPt_=(iConfig.getParameter("minPt")); + maxAbsEta_=(iConfig.getParameter("maxAbsEta")); + maxRMI_ = (iConfig.getParameter("maxRMI")); + } + void MuonIdAdder::produce(edm::Event & iEvent, const edm::EventSetup & iSetup) { - edm::Handle > muons; - edm::Handle > vertex; + iEvent.getByToken(src_, muons); iEvent.getByToken(vSrc_, vertex); - std::vector * out = new std::vector; out->reserve(muons->size()); + std::vector * out = new std::vector; + out->reserve(muons->size()); for (size_t i = 0; i < muons->size(); ++i){ const auto muon = muons->ptrAt(i); bool idresult = muon->isTightMuon(*(vertex->ptrAt(0))); + double rmi = (muon->pfIsolationR04().sumChargedHadronPt +std::max(0.0, (muon->pfIsolationR04().sumNeutralHadronEt +muon->pfIsolationR04().sumPhotonEt -0.5*muon->pfIsolationR04().sumPUPt)))/muon->pt(); pat::Muon newmuon(*muon); - newmuon.addUserFloat("tightcutbased",(float)idresult); - out->push_back(newmuon); - } - std::unique_ptr > ptr(out); - iEvent.put(std::move(ptr)); + if(idresult && rmi < maxRMI_ && muon->pt() > minPt_ && std::abs(muon->eta())push_back(newmuon); + } + + } + std::unique_ptr > ptr(out); + iEvent.put(std::move(ptr)); } //define this as a plug-in diff --git a/DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py b/DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py index bea770cad59..ddc63e0812a 100644 --- a/DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py +++ b/DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py @@ -10,7 +10,7 @@ options.register('inputScript', '', VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.string,"input Script") options.register('outputFile', 'output', VarParsing.VarParsing.multiplicity.singleton,VarParsing.VarParsing.varType.string, "output File (w/o .root)") -options.register('maxEvents', 200, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int,"maximum events") +options.register('maxEvents', 500, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int,"maximum events") options.register('skipEvents', 0, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int, "skip N events") options.register('job', 0, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int,"job number") options.register('nJobs', 1, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int, "total jobs") @@ -140,7 +140,7 @@ ] ###### ttbar selection -outFileName = options.outputFile + '_' + str(options.job) + '.root' +outFileName = options.outputFile + '_00' + str(options.job) + '.root' print ('Using output file ' + outFileName) if options.deepNtuplizer: @@ -148,8 +148,8 @@ fileName=cms.string(outFileName)) else: process.MINIAODSIMEventContent.outputCommands.extend([ - 'keep *_GoodElectron_*_*', - 'keep *_GoodMuon_*_*', + 'keep *_goodElectrons_*_*', + 'keep *_goodMuons_*_*', 'keep *_GoodJets_*_*', 'keep *_GoodOFLeptonPair_*_*' ]) @@ -157,7 +157,7 @@ process.outmod = cms.OutputModule("PoolOutputModule", process.MINIAODSIMEventContent, SelectEvents = cms.untracked.PSet( - SelectEvents = cms.vstring('ttbaremupath') + SelectEvents = cms.vstring('p') ), fileName = cms.untracked.string(outFileName) ) @@ -189,61 +189,36 @@ throw = cms.bool(True) # throw exception on unknown path names ) # Electron Selection -process.EleIdEmbed = cms.EDProducer("ElectronIdAdder", +process.goodElectrons = cms.EDProducer("ElectronIdAdder", src=cms.InputTag("slimmedElectrons"), vSrc=cms.InputTag("offlineSlimmedPrimaryVertices"), - idMap=cms.InputTag("egmGsfElectronIDs:cutBasedElectronID-Summer16-80X-V1-tight") - ) - -process.GoodElectron = cms.EDFilter("CandViewSelector", - src = cms.InputTag("EleIdEmbed"), - cut = cms.string("pt > 20.0 && abs(eta)<2.4 " - "&& userFloat('tightcutbased')" - "&& userFloat('notInEtaVetoRegion')" - "&& userFloat('inAbsD0')" - "&& userFloat('inAbsDz')" - ) - ) + idMap=cms.InputTag("egmGsfElectronIDs:cutBasedElectronID-Summer16-80X-V1-tight"), + minPt=cms.double(20.0), + maxAbsEta=cms.double(2.4), + ) + ### Muon Selection -process.MuonIdEmbed = cms.EDProducer("MuonIdAdder", +process.goodMuons = cms.EDProducer("MuonIdAdder", src=cms.InputTag("slimmedMuons"), - vSrc=cms.InputTag("offlineSlimmedPrimaryVertices") + vSrc=cms.InputTag("offlineSlimmedPrimaryVertices"), + minPt=cms.double(20.0), + maxAbsEta=cms.double(2.4), + maxRMI=cms.double(0.15) ) -process.GoodMuon = cms.EDFilter("CandViewSelector", - src = cms.InputTag("MuonIdEmbed"), - cut = cms.string("pt > 20.0 && abs(eta)<2.4 " - "&& userFloat('tightcutbased')" - "&& (pfIsolationR04().sumChargedHadronPt + max(0.0, (pfIsolationR04().sumNeutralHadronEt + pfIsolationR04().sumPhotonEt -0.5*pfIsolationR04().sumPUPt)))/pt < 0.15" - ) -) -### Jets -# Jet Energy Corrections -if options.isData: - jetCorrections = cms.vstring(['L1FastJet', 'L2Relative', 'L3Absolute', 'L2L3Residual']) -else: - jetCorrections = cms.vstring(['L1FastJet', 'L2Relative', 'L3Absolute']) - -from PhysicsTools.PatAlgos.tools.jetTools import updateJetCollection - -updateJetCollection( - process, - jetSource = cms.InputTag('slimmedJets'), - labelName = 'UpdatedJEC', - jetCorrections = ('AK4PFchs', jetCorrections, 'None') -) +### Jets process.GoodJets = cms.EDProducer("PATJetCleaner", - src = cms.InputTag("updatedPatJetsUpdatedJEC"), + src = cms.InputTag("slimmedJets"), preselection = cms.string("pt>30 && abs(eta) < 2.4 && neutralHadronEnergyFraction < 0.99 " "&& neutralEmEnergyFraction < 0.99 && (chargedMultiplicity+neutralMultiplicity) > 1 " "&& chargedHadronEnergyFraction > 0.0 " "&& chargedMultiplicity > 0.0 && chargedEmEnergyFraction < 0.99 "), checkOverlaps = cms.PSet( muons = cms.PSet( - src = cms.InputTag("GoodMuon"), + src = cms.InputTag("goodMuons"), algorithm = cms.string("byDeltaR"), preselection = cms.string(""), deltaR = cms.double(0.4), @@ -252,7 +227,7 @@ requireNoOverlaps = cms.bool(True), # overlaps cause the jet to be discarded ), electrons = cms.PSet( - src = cms.InputTag("GoodElectron"), + src = cms.InputTag("goodElectrons"), algorithm = cms.string("byDeltaR"), preselection = cms.string(""), deltaR = cms.double(0.4), @@ -265,7 +240,7 @@ ) process.GoodOFLeptonPair = cms.EDProducer("CandViewShallowCloneCombiner", - decay = cms.string("GoodMuon@+ GoodElectron@-"), + decay = cms.string("goodMuons@+ goodElectrons@-"), cut = cms.string("20.0 < mass" "&& (daughter(0).pt > 25 || daughter(1).pt > 25)") ) @@ -277,23 +252,28 @@ ) ### end selection +# Jet Energy Corrections +if options.isData: + jetCorrections = cms.vstring(['L1FastJet', 'L2Relative', 'L3Absolute', 'L2L3Residual']) +else: + jetCorrections = cms.vstring(['L1FastJet', 'L2Relative', 'L3Absolute']) from PhysicsTools.PatAlgos.tools.jetTools import updateJetCollection updateJetCollection( - process, - labelName="DeepFlavour", - # jetSource=cms.InputTag('slimmedJetsAK8PFPuppiSoftDropPacked', 'SubJets'), # 'subjets from AK8' - jetSource=cms.InputTag('GoodJets'), # 'ak4Jets' - jetCorrections=('AK4PFchs', jetCorrections, 'None'), - pfCandidates=cms.InputTag('packedPFCandidates'), - pvSource=cms.InputTag("offlineSlimmedPrimaryVertices"), - svSource=cms.InputTag('slimmedSecondaryVertices'), - muSource=cms.InputTag('slimmedMuons'), - elSource=cms.InputTag('slimmedElectrons'), - btagInfos=bTagInfos, - btagDiscriminators=bTagDiscriminators, - explicitJTA=False -) + process, + labelName="DeepFlavour", + # jetSource=cms.InputTag('slimmedJetsAK8PFPuppiSoftDropPacked', 'SubJets'), # 'subjets from AK8' + jetSource=cms.InputTag('GoodJets'), # 'ak4Jets' + jetCorrections=('AK4PFchs', jetCorrections, 'None'), + pfCandidates=cms.InputTag('packedPFCandidates'), + pvSource=cms.InputTag("offlineSlimmedPrimaryVertices"), + svSource=cms.InputTag('slimmedSecondaryVertices'), + muSource=cms.InputTag('slimmedMuons'), + elSource=cms.InputTag('slimmedElectrons'), + btagInfos=bTagInfos, + btagDiscriminators=bTagDiscriminators, + explicitJTA=False + ) if hasattr(process, 'updatedPatJetsTransientCorrectedDeepFlavour'): process.updatedPatJetsTransientCorrectedDeepFlavour.addTagInfos = cms.bool(True) @@ -402,13 +382,13 @@ ) -if options.isData: - if options.deepNtuplizer: +if options.deepNtuplizer: + if options.isData: process.p = cms.Path(process.globalInfo + process.TriggerSel + process.FinalSel + process.QGTagger + process.deepntuplizer) else: - process.p = cms.Path(process.globalInfo + process.TriggerSel + process.FinalSel + process.QGTagger) -else: - if options.deepNtuplizer: process.p = cms.Path(process.globalInfo + process.TriggerSel + process.FinalSel + process.QGTagger + process.genJetSequence * process.deepntuplizer) - else: - process.p = cms.Path(process.globalInfo + process.TriggerSel + process.FinalSel + process.QGTagger + process.genJetSequence) +else: + process.p = cms.Path(process.TriggerSel + process.FinalSel) + + process.endp = cms.EndPath(process.outmod) + diff --git a/DeepNtuplizer/python/DeepNtuplizer_cfi.py b/DeepNtuplizer/python/DeepNtuplizer_cfi.py index 782a62bdccd..35a7283397f 100644 --- a/DeepNtuplizer/python/DeepNtuplizer_cfi.py +++ b/DeepNtuplizer/python/DeepNtuplizer_cfi.py @@ -40,7 +40,14 @@ isData=cms.bool(False), useLHEWeights=cms.bool(True), - pileupDataDir=cms.string(datapath+"pileup_data_2016.root"), - pileupMCDir=cms.string(datapath+"pileup_MC_2016.root") + #leave empty string if you don't want to use pileup weights + pileupData=cms.string(datapath+"pileup_data_2016.root"), + pileupMC=cms.string(datapath+"pileup_MC_2016.root"), + + #scalefactor information + sfMuons = cms.InputTag("goodMuons"), + # leave an empty string if you don't want to use a scalefactor + sfMuonId = cms.string(datapath+"EfficienciesAndSF_ID_GH.root"), + sfMuonIdName = cms.string("MC_NUM_TightID_DEN_genTracks_PAR_pt_eta/abseta_pt_ratio") ) diff --git a/DeepNtuplizer/src/ntuple_eventInfo.cc b/DeepNtuplizer/src/ntuple_eventInfo.cc index b5249d8f34c..1e26cfd4845 100644 --- a/DeepNtuplizer/src/ntuple_eventInfo.cc +++ b/DeepNtuplizer/src/ntuple_eventInfo.cc @@ -12,18 +12,22 @@ void ntuple_eventInfo::getInput(const edm::ParameterSet& iConfig){ useLHEWeights_ = (iConfig.getParameter("useLHEWeights")); - pupDataDir_ = (iConfig.getParameter("pileupDataDir")); - pupMCDir_ = (iConfig.getParameter("pileupMCDir")); + + pupDataDir_ = (iConfig.getParameter("pileupData")); + pupMCDir_ = (iConfig.getParameter("pileupMC")); + sfMuonIdDir_ = (iConfig.getParameter("sfMuonId")); + sfMuonIdName_ = (iConfig.getParameter("sfMuonIdName")); + if(pupDataDir_=="" || pupMCDir_==""){ std::cout<<"no pileup histograms, proceed without pileup reweighting. \n"; } else{ - pupMCFile = new TFile(pupMCDir_.c_str()); - pupDataFile = new TFile(pupDataDir_.c_str()); + TFile *pupMCFile = new TFile(pupMCDir_.c_str()); + TFile *pupDataFile = new TFile(pupDataDir_.c_str()); - pupMCHist = (TH1F*)pupMCFile->Get("pileup"); - pupDataHist = (TH1F*)pupDataFile->Get("pileup"); + TH1F *pupMCHist = (TH1F*)pupMCFile->Get("pileup"); + TH1F *pupDataHist = (TH1F*)pupDataFile->Get("pileup"); pupMCHist->Scale(1./pupMCHist->Integral()); pupDataHist->Scale(1./pupDataHist->Integral()); @@ -34,9 +38,20 @@ void ntuple_eventInfo::getInput(const edm::ParameterSet& iConfig){ } } + if(sfMuonIdDir_ == ""){ + std::cout<<"no muon id scalefactor histogram, proceed without muon id scalefactor"<Get(sfMuonIdName_.c_str()); + sfMuonIdHist_xaxis = sfMuonIdHist->GetXaxis(); + sfMuonIdHist_yaxis = sfMuonIdHist->GetYaxis(); + } } + + void ntuple_eventInfo::initBranches(TTree* tree){ addBranch(tree,"event_weight", &event_weight_); @@ -48,26 +63,52 @@ void ntuple_eventInfo::readEvent(const edm::Event& iEvent){ if(!iEvent.isRealData()){ iEvent.getByToken(lheToken_, lheInfo); - } + iEvent.getByToken(muonToken_, muons); - if(!iEvent.isRealData()){ + ///// pileup weights for (auto const& v : *pupInfo()) { int bx = v.getBunchCrossing(); if (bx == 0) { ntrueInt_ = v.getTrueNumInteractions(); } } - double lheWeight = 1.; + double pupWeight = 1.; + if(ntrueInt_ < pupWeights.size()){ + pupWeight = pupWeights.at(ntrueInt_); + } + ///// lhe weights + double lheWeight = 1.; if(useLHEWeights_){ lheWeight = lheInfo->weights()[0].wgt/std::abs(lheInfo->weights()[0].wgt); } - double pupWeight = 1.; - if(ntrueInt_ < pupWeights.size()){ - pupWeight = pupWeights.at(ntrueInt_); + /////scalefactors + // Muon scalefactors + double leadingMuon_pt = 0.; + double leadingMuon_eta = 0.; + for (size_t i = 0; i < muons->size(); ++i){ + const auto & muon = (*muons).at(i); + if(muon.pt() > leadingMuon_pt){ + leadingMuon_pt = muon.pt(); + leadingMuon_eta = muon.eta(); + } + } + // Muon ID + double muonIdSf = 1.; + if(sfMuonIdDir_ != ""){ + int binx = sfMuonIdHist_xaxis->FindBin(std::abs(leadingMuon_eta)); + int biny = sfMuonIdHist_yaxis->FindBin(leadingMuon_pt); + if(leadingMuon_pt > 120.) //dont take overflow bin, but the last one + biny -= 1; + muonIdSf = sfMuonIdHist->GetBinContent(binx, biny); } - event_weight_ = lheWeight * pupWeight; + + std::cout<<"leading muon has pt "<setMuonsToken(consumes>(iConfig.getParameter("sfMuons"))); + evweight->setMuonsToken(consumes >(iConfig.getParameter("sfMuons"))); + evweight->setElectronsToken(consumes >(iConfig.getParameter("sfElectrons"))); } addModule(evweight); diff --git a/DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py b/DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py index ddc63e0812a..37c68c00379 100644 --- a/DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py +++ b/DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py @@ -140,7 +140,7 @@ ] ###### ttbar selection -outFileName = options.outputFile + '_00' + str(options.job) + '.root' +outFileName = options.outputFile + '_' + str(options.job) + '.root' print ('Using output file ' + outFileName) if options.deepNtuplizer: @@ -204,7 +204,7 @@ vSrc=cms.InputTag("offlineSlimmedPrimaryVertices"), minPt=cms.double(20.0), maxAbsEta=cms.double(2.4), - maxRMI=cms.double(0.15) + maxRMI=cms.double(0.15) #RMI = relative muon isolation ) diff --git a/DeepNtuplizer/python/DeepNtuplizer_cfi.py b/DeepNtuplizer/python/DeepNtuplizer_cfi.py index 35a7283397f..ec03a715030 100644 --- a/DeepNtuplizer/python/DeepNtuplizer_cfi.py +++ b/DeepNtuplizer/python/DeepNtuplizer_cfi.py @@ -46,8 +46,16 @@ #scalefactor information sfMuons = cms.InputTag("goodMuons"), - # leave an empty string if you don't want to use a scalefactor + sfElectrons=cms.InputTag("goodElectrons"), + + # leave an empty string for the root file if you don't want to use a scalefactor sfMuonId = cms.string(datapath+"EfficienciesAndSF_ID_GH.root"), - sfMuonIdName = cms.string("MC_NUM_TightID_DEN_genTracks_PAR_pt_eta/abseta_pt_ratio") + sfMuonIdHist = cms.string("MC_NUM_TightID_DEN_genTracks_PAR_pt_eta/abseta_pt_ratio"), + sfMuonIso=cms.string(datapath+"EfficienciesAndSF_ISO_GH.root"), + sfMuonIsoHist=cms.string("TightISO_TightID_pt_eta/abseta_pt_ratio"), + sfMuonTracking=cms.string(datapath+"Tracking_EfficienciesAndSF_BCDEFGH.root"), + sfMuonTrackingHist=cms.string("ratio_eff_aeta_dr030e030_corr"), + sfElIdAndIso=cms.string(datapath+"egammaEffi.txt_EGM2D.root"), + sfElIdAndIsoHist=cms.string("EGamma_SF2D"), ) diff --git a/DeepNtuplizer/src/ntuple_eventInfo.cc b/DeepNtuplizer/src/ntuple_eventInfo.cc index 1e26cfd4845..e1692597ac0 100644 --- a/DeepNtuplizer/src/ntuple_eventInfo.cc +++ b/DeepNtuplizer/src/ntuple_eventInfo.cc @@ -16,12 +16,16 @@ void ntuple_eventInfo::getInput(const edm::ParameterSet& iConfig){ pupDataDir_ = (iConfig.getParameter("pileupData")); pupMCDir_ = (iConfig.getParameter("pileupMC")); sfMuonIdDir_ = (iConfig.getParameter("sfMuonId")); - sfMuonIdName_ = (iConfig.getParameter("sfMuonIdName")); - - - if(pupDataDir_=="" || pupMCDir_==""){ + sfMuonIdName_ = (iConfig.getParameter("sfMuonIdHist")); + sfMuonIsoDir_ = (iConfig.getParameter("sfMuonIso")); + sfMuonIsoName_ = (iConfig.getParameter("sfMuonIsoHist")); + sfMuonTrackingDir_ = (iConfig.getParameter("sfMuonTracking")); + sfMuonTrackingName_ = (iConfig.getParameter("sfMuonTrackingHist")); + sfElIdAndIsoDir_ = (iConfig.getParameter("sfElIdAndIso")); + sfElIdAndIsoName_ = (iConfig.getParameter("sfElIdAndIsoHist")); + + if(pupDataDir_=="" || pupMCDir_=="") std::cout<<"no pileup histograms, proceed without pileup reweighting. \n"; - } else{ TFile *pupMCFile = new TFile(pupMCDir_.c_str()); TFile *pupDataFile = new TFile(pupDataDir_.c_str()); @@ -38,9 +42,8 @@ void ntuple_eventInfo::getInput(const edm::ParameterSet& iConfig){ } } - if(sfMuonIdDir_ == ""){ + if(sfMuonIdDir_ == "") std::cout<<"no muon id scalefactor histogram, proceed without muon id scalefactor"<GetXaxis(); sfMuonIdHist_yaxis = sfMuonIdHist->GetYaxis(); } + + if(sfMuonIsoDir_ == "") + std::cout<<"no muon iso scalefactor histogram, proceed without muon id scalefactor"<Get(sfMuonIsoName_.c_str()); + + sfMuonIsoHist_xaxis = sfMuonIsoHist->GetXaxis(); + sfMuonIsoHist_yaxis = sfMuonIsoHist->GetYaxis(); + } + + if(sfElIdAndIsoDir_ == ""){ + std::cout<<"no electron id and iso scalefactor histogram, proceed without electron id and iso scalefactor"<Get(sfElIdAndIsoName_.c_str()); + + sfElIdAndIsoHist_xaxis = sfElIdAndIsoHist->GetXaxis(); + sfElIdAndIsoHist_yaxis = sfElIdAndIsoHist->GetYaxis(); + } + + if(sfMuonTrackingDir_ == ""){ + std::cout<<"no electron id and iso scalefactor histogram, proceed without electron id and iso scalefactor"<Get(sfMuonTrackingName_.c_str()); + + readHistoFromGraph(sfMuonTrackingTGraph, &sfMuonTrackingHist, "sfMuonTrackingHist"); + + sfMuonTrackingHist_axis = sfMuonTrackingHist->GetXaxis(); + } } @@ -64,6 +103,7 @@ void ntuple_eventInfo::readEvent(const edm::Event& iEvent){ iEvent.getByToken(lheToken_, lheInfo); iEvent.getByToken(muonToken_, muons); + iEvent.getByToken(electronToken_, electrons); ///// pileup weights for (auto const& v : *pupInfo()) { @@ -103,12 +143,44 @@ void ntuple_eventInfo::readEvent(const edm::Event& iEvent){ biny -= 1; muonIdSf = sfMuonIdHist->GetBinContent(binx, biny); } + // Muon ISO + double muonIsoSf = 1.; + if(sfMuonIsoDir_ != ""){ + int binx = sfMuonIsoHist_xaxis->FindBin(std::abs(leadingMuon_eta)); + int biny = sfMuonIsoHist_yaxis->FindBin(leadingMuon_pt); + if(leadingMuon_pt > 120.) //dont take overflow bin, but the last one + biny -= 1; + muonIsoSf = sfMuonIsoHist->GetBinContent(binx, biny); + } + //Muon tracking + double muonTrackingSf = 1.; + if(sfMuonTrackingDir_ != ""){ + int binx = sfMuonTrackingHist_axis->FindBin(std::abs(leadingMuon_eta)); + muonTrackingSf = sfMuonTrackingHist->GetBinContent(binx); + } - std::cout<<"leading muon has pt "<FindBin(std::abs(leadingElectron_sueta)); + int biny = sfElIdAndIsoHist_yaxis->FindBin(leadingElectron_pt); + if(leadingElectron_pt > 120.) + biny -= 1; + elIdAndIsoSf = sfElIdAndIsoHist->GetBinContent(binx, biny); + } - event_weight_ = lheWeight * pupWeight * muonIdSf; + event_weight_ = lheWeight * pupWeight * muonIdSf * muonIsoSf * muonTrackingSf * elIdAndIsoSf; } else{ event_weight_ = 1.; @@ -121,3 +193,40 @@ void ntuple_eventInfo::readEvent(const edm::Event& iEvent){ bool ntuple_eventInfo::fillBranches(const pat::Jet & jet, const size_t& jetidx, const edm::View * coll){ return true; } + +void readHistoFromGraph(TGraphAsymmErrors* graph, TH1D** h, TString name) +{ + const int npoints = graph->GetN(); + const double* x_centers = graph->GetX(); + const double* y_centers = graph->GetY(); + double x_lows[npoints]; + double x_highs[npoints]; + double y_lows[npoints]; + double y_highs[npoints]; + for(int i=0; iGetErrorXlow(i); + x_highs[i] = graph->GetErrorXhigh(i); + y_lows[i] = graph->GetErrorYlow(i); + y_highs[i] = graph->GetErrorYhigh(i); + } + + double x_edges[npoints+1]; + for(int i=0; iSetDirectory(0); // without this the histo will get deleted when a currently open TFile is closed + + for(int i=0; iSetBinContent(i+1, y_centers[i]); + (*h)->SetBinError(i+1, std::max(y_lows[i], y_highs[i])); +// cout << (*h)->GetBinError(i) << endl; + } +} From 5aa953de02fab079123b1305d10206cddf81acd3 Mon Sep 17 00:00:00 2001 From: David Walter Date: Thu, 22 Feb 2018 17:06:36 +0100 Subject: [PATCH 10/17] save effective event number in a new tree with one branch and one entry --- DeepNtuplizer/interface/ntuple_eventInfo.h | 32 +++++++++++++++++++--- DeepNtuplizer/plugins/globalInfo.cc | 19 +++++++++---- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/DeepNtuplizer/interface/ntuple_eventInfo.h b/DeepNtuplizer/interface/ntuple_eventInfo.h index 8a123f9f2d9..e358ad032be 100644 --- a/DeepNtuplizer/interface/ntuple_eventInfo.h +++ b/DeepNtuplizer/interface/ntuple_eventInfo.h @@ -15,12 +15,15 @@ #include #include #include +#include "TGraphAsymmErrors.h" #include #include "SimDataFormats/GeneratorProducts/interface/LHEEventProduct.h" +void readHistoFromGraph(TGraphAsymmErrors* graph, TH1D** h, TString name); + /* * For MC weights such as pileup, lhe, ... later: lepton scalefactors */ @@ -41,18 +44,24 @@ class ntuple_eventInfo: public ntuple_content{ void setLHEToken(edm::EDGetTokenT lheToken) { lheToken_ = lheToken; } - void setMuonsToken(edm::EDGetTokenT> muonToken){ + void setMuonsToken(edm::EDGetTokenT > muonToken){ muonToken_ = muonToken; } + void setElectronsToken(edm::EDGetTokenT > electronToken){ + electronToken_ = electronToken; + } private: edm::EDGetTokenT lheToken_; - edm::EDGetTokenT> muonToken_; + edm::EDGetTokenT > muonToken_; + edm::EDGetTokenT > electronToken_; edm::Handle lheInfo; - edm::Handle> muons; + edm::Handle > muons; + edm::Handle > electrons; + bool isData_; bool useLHEWeights_; @@ -61,16 +70,31 @@ class ntuple_eventInfo: public ntuple_content{ std::string pupMCDir_; std::string sfMuonIdDir_; std::string sfMuonIdName_; + std::string sfMuonIsoDir_; + std::string sfMuonIsoName_; + std::string sfMuonTrackingDir_; + std::string sfMuonTrackingName_; + std::string sfElIdAndIsoDir_; + std::string sfElIdAndIsoName_; + TH2F *sfMuonIdHist; + TH2F *sfMuonIsoHist; + TH2F *sfElIdAndIsoHist; + TGraphAsymmErrors* sfMuonTrackingTGraph; + TH1D *sfMuonTrackingHist; TAxis *sfMuonIdHist_xaxis; TAxis *sfMuonIdHist_yaxis; + TAxis *sfMuonIsoHist_xaxis; + TAxis *sfMuonIsoHist_yaxis; + TAxis *sfElIdAndIsoHist_xaxis; + TAxis *sfElIdAndIsoHist_yaxis; + TAxis *sfMuonTrackingHist_axis; // global variables float ntrueInt_; - std::vector pupWeights; /////////branches diff --git a/DeepNtuplizer/plugins/globalInfo.cc b/DeepNtuplizer/plugins/globalInfo.cc index bb0945d3026..525b9d53eb3 100644 --- a/DeepNtuplizer/plugins/globalInfo.cc +++ b/DeepNtuplizer/plugins/globalInfo.cc @@ -32,6 +32,8 @@ #include "CommonTools/UtilAlgos/interface/TFileService.h" #include "SimDataFormats/GeneratorProducts/interface/LHEEventProduct.h" +#include "TTree.h" + class globalInfo : public edm::one::EDAnalyzer { @@ -52,11 +54,12 @@ class globalInfo : public edm::one::EDAnalyzer { edm::EDGetTokenT t_LHEInfo; edm::Handle h_LHEWeights; - long nEvents_ = 0; - long nNegLHEEvents_ = 0; + int nEvents_ = 0; + int nNegLHEEvents_ = 0; + int nEffEvents_ = 0; bool useLHEWeights_ = true; - TList * infolist = new TList; + TTree * tree_ = new TTree(); // ----------member data --------------------------- @@ -120,17 +123,21 @@ globalInfo::beginJob() void globalInfo::endJob() { + nEffEvents_ = nEvents_ - nNegLHEEvents_; std::cout<<"total number of initial events is: "<make()); + tree_=(fs->make("tree" ,"tree" )); + + tree_->Branch("nEffEvents",&nEffEvents_,"nEffEvents/I"); + + tree_->Fill(); - infolist->Add(new TNamed("nInitialEvents",std::to_string(nEvents_ - nNegLHEEvents_).c_str())); } From 1c80c1790f99ed9e01191a55d7b1b517a5cb38b7 Mon Sep 17 00:00:00 2001 From: David Walter Date: Fri, 2 Mar 2018 11:08:14 +0100 Subject: [PATCH 11/17] changes in plotting tools --- DeepNtuplizer/plots/plot_event.py | 515 +++++++++++++++++++++++++++ DeepNtuplizer/plots/plot_features.py | 136 ++++--- 2 files changed, 598 insertions(+), 53 deletions(-) create mode 100644 DeepNtuplizer/plots/plot_event.py diff --git a/DeepNtuplizer/plots/plot_event.py b/DeepNtuplizer/plots/plot_event.py new file mode 100644 index 00000000000..10dacf5297f --- /dev/null +++ b/DeepNtuplizer/plots/plot_event.py @@ -0,0 +1,515 @@ + +import pdb +from ROOT import TH1F, TFile, TCanvas, gROOT, gStyle, THStack, TLegend, TGaxis, gPad +import numpy as np +import os +from array import array +import datetime +from DataFormats.FWLite import Events, Handle + +gROOT.SetBatch() # don't pop up canvases +gROOT.SetStyle('Plain') # white background +gStyle.SetFillStyle(0) +TGaxis.SetMaxDigits(4) # Force scientific notation for numbers with more than 4 digits + +class pileupweight: + """ DOC """ + + def __init__(self, file_pileup_MC, file_pileup_Data): + hist_mc = file_pileup_MC.Get("pileup") + hist_data = file_pileup_Data.Get("pileup") + self.pupWeights = [0] + hist_mc.Scale(1. / hist_mc.Integral()) + hist_data.Scale(1. / hist_data.Integral()) + for bin in range(1, hist_data.GetNbinsX() + 2): + if hist_mc.GetBinContent(bin) != 0: + w = hist_data.GetBinContent(bin) / hist_mc.GetBinContent(bin) + self.pupWeights.append(w) + else: + self.pupWeights.append(1) + + def getPileupWeight(self,nInteractions): + if nInteractions >= len(self.pupWeights): + return 0 + return self.pupWeights[nInteractions] + +class scaleFactor(): + """ + class for isolation and id scale factors + hist is the 2d histogram with the scale factor with abs(eta) on x and pt on y + """ + def __init__(self,hist): + self.hist = hist + self.xaxis = self.hist.GetXaxis() + self.yaxis = self.hist.GetYaxis() + self.binx = 0 + self.biny = 0 + self.scalefactor = 1. + self.maxBinX = self.xaxis.GetLast() + self.maxBinY = self.yaxis.GetLast() + self.minPt = self.xaxis.GetXmin() + self.maxPt = self.xaxis.GetXmax() + self.minEta = self.yaxis.GetXmin() + self.maxEta = self.yaxis.GetXmax() + + def getScalefactor(self,abseta,pt): + + self.binx = self.xaxis.FindBin(abseta) + self.biny = self.yaxis.FindBin(pt) + if pt >= self.maxPt: self.biny = self.maxBinY + self.scalefactor = self.hist.GetBinContent(self.binx, self.biny) + return self.scalefactor + + +class scaleFactor_tracking(): + """ + class for tracking scale factors + the tracking scale factors are saved in a TGraphAsymmErrors object which has to be written in a histogram first + """ + def __init__(self,graph, name): + self.graph = graph + self.npoints = self.graph.GetN() + self.x_centers = self.graph.GetX() + self.y_centers = self.graph.GetY() + self.x_lows = np.zeros(self.npoints) + self.x_highs = np.zeros(self.npoints) + self.y_lows = np.zeros(self.npoints) + self.y_highs = np.zeros(self.npoints) + self.x_edges = np.zeros(self.npoints +1) + + for i in range(0,self.npoints): + self.x_lows[i] = self.graph.GetErrorXlow(i) + self.x_highs[i] = self.graph.GetErrorXhigh(i) + self.y_lows[i] = self.graph.GetErrorYlow(i) + self.y_lows[i] = self.graph.GetErrorYhigh(i) + + self.x_edges[i] = self.x_centers[i] - self.x_lows[i] + self.x_edges[self.npoints] = self.x_centers[self.npoints - 1] + self.x_highs[self.npoints-1] + self.hist = TH1F(name, name,self.npoints,self.x_edges) + + for i in range(0,self.npoints): + self.hist.SetBinContent(i+1, self.y_centers[i]) + self.hist.SetBinError(i+1, max(self.y_lows[i], self.y_highs[i])) + + self.bin = 0 + self.axis = self.hist.GetXaxis() + self.scalefactor = 1. + + def getScalefactor(self,eta): + self.bin = self.axis.FindBin(abs(eta)) + self.scalefactor = self.hist.GetBinContent(self.bin) + return self.scalefactor + + +class process: + """ DOC """ + datadir = "/afs/desy.de/user/d/dwalter/CMSSW_8_0_29/src/DeepNTuples/DeepNtuplizer/data/" + pupw = pileupweight( + TFile(datadir + "MyMCPileupHist.root"), + TFile(datadir + "MyDataPileupHist.root") + ) + # muon scalefactor hists from https://twiki.cern.ch/twiki/bin/viewauth/CMS/MuonWorkInProgressAndPagResults + file_sf_muon_id_GH = TFile(datadir + "EfficienciesAndSF_ID_GH.root") + file_sf_muon_iso_GH = TFile(datadir + "EfficienciesAndSF_ISO_GH.root") + file_sf_muon_tracking = TFile(datadir + "Tracking_EfficienciesAndSF_BCDEFGH.root") + # electron scalefactor hists from https://twiki.cern.ch/twiki/bin/view/CMS/EgammaIDRecipesRun2 + # -> Electron cut-based 80XID WPs. Scale factors for 80X -> Tight cut-based ID WP scale factor (root file) + # id and iso is combined in one file, there is no tracking for the electron + file_sf_el_id = TFile(datadir + "egammaEffi.txt_EGM2D.root" + ) + + h_sf_muon_id_GH = file_sf_muon_id_GH.Get("MC_NUM_TightID_DEN_genTracks_PAR_pt_eta/abseta_pt_ratio") + h_sf_muon_iso_GH = file_sf_muon_iso_GH.Get("TightISO_TightID_pt_eta/abseta_pt_ratio") + g_sf_muon_tracking = file_sf_muon_tracking.Get("ratio_eff_aeta_dr030e030_corr") + h_sf_el_id = file_sf_el_id.Get("EGamma_SF2D") + + sf_muon_id = scaleFactor(h_sf_muon_id_GH) + sf_muon_iso = scaleFactor(h_sf_muon_iso_GH) + sf_muon_tracking = scaleFactor_tracking(g_sf_muon_tracking,"sf_muon_tracking") + sf_el_id = scaleFactor(h_sf_el_id) + + muonhandle = Handle('edm::OwnVector >') + muonlabel = ("GoodMuon") + electronhandle = Handle('edm::OwnVector >') + electronlabel = ("GoodElectron") + jethandle = Handle('vector') + jetlabel = ("GoodJets") + ### LHE weights + LHEweighthandle = Handle('LHEEventProduct') + LHEweightlabel = ("externalLHEProducer") + + ## Pileup reweighting + puphandle = Handle('vector') + puplabel = ("slimmedAddPileupInfo") + + hs_ll_pt = THStack("hs_ll_pt", "ll pt") + hs_ll_eta = THStack("hs_ll_eta", "ll eta") + hs_tl_pt = THStack("hs_tl_pt", "tl pt") + hs_tl_eta = THStack("hs_tl_eta", "tl eta") + hs_j_n = THStack("hs_njets", "jet number") + + hs_list = hs_ll_pt, hs_ll_eta, hs_tl_pt, hs_tl_eta, hs_j_n + + collection = [] + hists_data = None + + def __init__(self, name, isData=False, color=1): + self.name = name + self.isData = isData + self.h_ll_pt = TH1F(self.name + "_ll_pt", "pt of leading lepton in " + self.name, 10, array('d', [0, 25, 30, 35, 40, 45, 50, 60, 70, 100, 200])) + self.h_ll_eta = TH1F(self.name + "_ll_eta", "eta of the leading leption in " + self.name, 20, -2.4, 2.4) + self.h_tl_pt = TH1F(self.name + "_tl_pt", "pt of leading lepton in " + self.name, 11, array('d', [0, 20, 25, 30, 35, 40, 45, 50, 60, 70, 100, 200])) + self.h_tl_eta = TH1F(self.name + "_tl_eta", "eta of the leading leption in " + self.name, 20, -2.4, 2.4) + self.h_njets = TH1F(self.name + "_njets", "number of jets in " +self.name, 10, -0.5, 9.5) + + self.hists = self.h_ll_pt, self.h_ll_eta, self.h_tl_pt, self.h_tl_eta, self.h_njets + + self.integral = 0. + + #remove status boxes + for hist in self.hists: + hist.SetStats(False) + + if self.isData==False: + process.collection.append(self) + for hist in self.hists: + hist.SetFillColor(color) + else: + process.hists_data = self + for hist in self.hists: + hist.SetTitle("") + # hist.SetTitleSize(0.05, "xyz") + hist.SetTitleFont(42, "t") + hist.SetTitleFont(42, "xyz") + hist.SetLabelFont(42, "xyz") + self.h_ll_pt.SetXTitle("leading lept. p_{T} (GeV)") + self.h_ll_eta.SetXTitle("leading lept. eta") + self.h_tl_pt.SetXTitle("trailing lept. p_{T} (GeV)") + self.h_tl_eta.SetXTitle("trailing lept. eta") + self.h_njets.SetXTitle("N_{Jet}") + + self.h_ll_pt.SetYTitle("Events/GeV") + self.h_ll_pt.GetYaxis().SetTitleOffset(1.2) + self.h_ll_eta.SetYTitle("Events/0.25") + self.h_tl_pt.SetYTitle("Events/GeV") + self.h_tl_eta.SetYTitle("Events/0.25") + self.h_njets.SetYTitle("Events") + + def fillHists(self, infile, islist=True, useLHEWeights=False, isData=False, eventIDs=[]): + print("start to fill hist: " + str(datetime.datetime.now())) + nevents = 0 + directory = '' + + if islist is True: + print("loop over filelist " + str(infile)) + filelist = open(infile, 'r') + ifile = filelist.readline() + ifile = ifile[:-1] + directory = infile[:-len(infile.split('/')[-1])] + else: + ifile = infile + + while ifile != '': + print("process file ", ifile) + events = Events(directory + ifile) + + ### EVENT LOOP + for event in events: + eventID = event.eventAuxiliary().event() + + if isData: # avoid double counting + if eventID in eventIDs: + # print("this event was already processed") + continue + eventIDs = np.append(eventIDs, eventID) + + nevents += 1 + leadingPt = 10 + leadingEta = 0 + trailingPt = 10 + trailingEta = 0 + leadingMuonPt = 10 + leadingMuonEta = 0 + leadingElPt = 10 + leadingElEta = 0 + leadingElSuEta = 0 + weight = 1. + + # Fill muon hists + event.getByLabel(process.muonlabel, process.muonhandle) + muons = process.muonhandle.product() # get the product + + for muon in muons: + if muon.pt() > leadingMuonPt: + leadingMuonPt = muon.pt() + leadingMuonEta = muon.eta() + + # Fill electron hists + event.getByLabel(process.electronlabel, process.electronhandle) + electrons = process.electronhandle.product() + for electron in electrons: + + if electron.pt() > leadingElPt: + leadingElPt = electron.pt() + leadingElEta = electron.eta() + leadingElSuEta = electron.superCluster().eta() + + if leadingMuonPt > leadingElPt: + leadingPt = leadingMuonPt + leadingEta = leadingMuonEta + trailingPt = leadingElPt + trailingEta = leadingElEta + else: + leadingPt = leadingElPt + leadingEta = leadingElEta + trailingPt = leadingMuonPt + trailingEta = leadingMuonEta + + + + # Fill jet hists + event.getByLabel(process.jetlabel, process.jethandle) + jets = process.jethandle.product() + + numJets = len(jets) + + # Compute Event weights + if useLHEWeights == True: + event.getByLabel(process.LHEweightlabel, process.LHEweighthandle) + weights = process.LHEweighthandle.product() + weight = weights.weights()[0].wgt / abs(weights.weights()[0].wgt) + + if isData == False: + event.getByLabel(process.puplabel, process.puphandle) + pupInfos = process.puphandle.product() + for pupInfo in pupInfos: + if (pupInfo.getBunchCrossing() == 0): + weight *= process.pupw.getPileupWeight(int(pupInfo.getTrueNumInteractions())) + + weight *= process.sf_muon_id.getScalefactor(abs(leadingMuonEta), leadingMuonPt) + weight *= process.sf_muon_iso.getScalefactor(abs(leadingMuonEta), leadingMuonPt) + weight *= process.sf_muon_tracking.getScalefactor(abs(leadingMuonEta)) + weight *= process.sf_el_id.getScalefactor(abs(leadingElSuEta), leadingElPt) + + + self.h_ll_pt.Fill(leadingPt, weight) + self.h_ll_eta.Fill(leadingEta, weight) + self.h_tl_pt.Fill(trailingPt, weight) + self.h_tl_eta.Fill(trailingEta, weight) + self.h_njets.Fill(numJets, weight) + + if islist is True: + ifile = filelist.readline() + ifile = ifile[:-1] + else: + break + + if islist is True: + print("close filelist") + filelist.close() + + print("processed events ", nevents) + self.save_hists() + + def scale_hists(self,sigma=1.,lumi=1.,eff=1.): + for hist in self.hists: + hist.Scale(sigma*lumi*eff) + self.integral = self.hists[0].Integral() + + self.divideByBinWidth(self.hists[0]) + self.divideByBinWidth(self.hists[2]) + self.hists[1].Scale(4) + self.hists[3].Scale(4) + + def divideByBinWidth(self,hist): + for ibin in range(0, len(hist)): + content = hist.GetBinContent(ibin) + content /= hist.GetBinWidth(ibin) + hist.SetBinContent(ibin, content) + + def save_hists(self): + f1 = TFile(self.name + ".root", "RECREATE") + for hist in self.hists: + hist.Write() + f1.Close() + + def load_hists(self): + print "load " + self.name + f1 = TFile(self.name + ".root", "READ") + self.h_ll_pt.Add(f1.Get(self.name + "_ll_pt")) + self.h_ll_eta.Add(f1.Get(self.name + "_ll_eta")) + self.h_tl_pt.Add(f1.Get(self.name + "_tl_pt")) + self.h_tl_eta.Add(f1.Get(self.name + "_tl_eta")) + self.h_njets.Add(f1.Get(self.name + "_njets")) + + f1.Close() + + def draw_hists(self): + canvas = TCanvas(self.name, "", 800, 600) + for hist in self.hists: + canvas.Clear() + hist.Draw("HIST") + canvas.Print(hist.GetName()+".png") + + def setMinMax(self, y_min_ll_pt, y_max_ll_pt, y_min_ll_eta, y_max_ll_eta, y_min_tl_pt, y_max_tl_pt, y_min_tl_eta, y_max_tl_eta, y_min_njets, y_max_njets): + self.hists[0].SetMinimum(y_min_ll_pt) + self.hists[0].SetMaximum(y_max_ll_pt) + self.hists[1].SetMinimum(y_min_ll_eta) + self.hists[1].SetMaximum(y_max_ll_eta) + self.hists[2].SetMinimum(y_min_tl_pt) + self.hists[2].SetMaximum(y_max_tl_pt) + self.hists[3].SetMinimum(y_min_tl_eta) + self.hists[3].SetMaximum(y_max_tl_eta) + self.hists[4].SetMinimum(y_min_njets) + self.hists[4].SetMaximum(y_max_njets) + + + @classmethod + def make_stacks(cls): + for proc in cls.collection: + for i,hist in enumerate(proc.hists): + cls.hs_list[i].Add(hist) + + + @classmethod + def print_stacks(cls): + cls.make_stacks() + + leg = TLegend(0.59, 0.54, 0.89, 0.84) + leg.SetBorderSize(0) + leg.SetTextFont(42) + leg.AddEntry(cls.hists_data.hists[0], "data", "lep") + leg.AddEntry(cls.collection[8].hists[0], "t#bar{t}", "f") + leg.AddEntry(cls.collection[0].hists[0], "DY", "f") + leg.AddEntry(cls.collection[2].hists[0], "VV", "f") + leg.AddEntry(cls.collection[6].hists[0], "Wt/W#bar{t}", "f") + leg.AddEntry(cls.collection[5].hists[0], "W+Jets", "f") + + leg21 = TLegend(0.19, 0.69, 0.39, 0.84) + leg21.SetBorderSize(0) + leg21.SetTextFont(42) + leg21.AddEntry(cls.hists_data.hists[0], "data", "lep") + leg21.AddEntry(cls.collection[8].hists[0], "t#bar{t}", "f") + leg21.AddEntry(cls.collection[0].hists[0], "DY", "f") + + leg22 = TLegend(0.69, 0.69, 0.89, 0.84) + leg22.SetBorderSize(0) + leg22.SetTextFont(42) + leg22.AddEntry(cls.collection[2].hists[0], "VV", "f") + leg22.AddEntry(cls.collection[6].hists[0], "Wt/W#bar{t}", "f") + leg22.AddEntry(cls.collection[5].hists[0], "W+Jets", "f") + + leg.SetFillStyle(0) # make transparent + leg21.SetFillStyle(0) + leg22.SetFillStyle(0) + + canvas = TCanvas("final", "title", 800, 600) + for i in (0, 2, 4): + canvas.Clear() + cls.hists_data.hists[i].Draw("PE") + cls.hs_list[i].Draw("HIST same") + cls.hists_data.hists[i].Draw("PE same") + gPad.RedrawAxis() # draw axis in foreground + leg.Draw("same") + canvas.Print("stacks_" + str(i) + ".png") + + for i in (1, 3): + canvas.Clear() + cls.hists_data.hists[i].Draw("PE") + cls.hs_list[i].Draw("HIST same") + cls.hists_data.hists[i].Draw("PE same") + gPad.RedrawAxis() # draw axis in foreground + leg21.Draw("same") + leg22.Draw("same") + canvas.Print("stacks_" + str(i) + ".png") + + + +dy10to50 = process("dy10to50", color=593) +dy50 = process("dy50", color=593) +ww = process("ww", color=393) +wz = process("wz", color=393) +zz = process("zz", color=393) +wjets = process("wjets", color=409) +wt = process("wt", color=609) +wantit = process("wantit", color=609) +tt = process("tt", color=625) +data = process("data",isData=True) + + +# dy10to50.fillHists("dy10to50.txt",useLHEWeights=True) +# dy50.fillHists("dy50.txt",useLHEWeights=True) +# ww.fillHists("ww.txt") +# wz.fillHists("wz.txt") +# zz.fillHists("zz.txt") +# wjets.fillHists("wjets.txt",useLHEWeights=True) +# wt.fillHists("wt.txt") +# wantit.fillHists("wantit.txt") +# tt.fillHists("tt.txt") +# data.fillHists("data.txt",isData=True) + +for ip in process.collection: + ip.load_hists() +process.hists_data.load_hists() + +lumi_total = 35.9 +lumi_data = 8.746 + +sigma_tt = 831760 +sigma_dy50 = 6025200 +sigma_dy10to50 = 22635100 +sigma_ww = 118700 +sigma_wz = 44900 +sigma_zz = 15400 +sigma_wantit = 35600 +sigma_wt = 35600 +sigma_wjets = 61526700 + +# Efficiency = 1/(number of events before cuts), in case of lheweights its the +# effective number of events (in this case: number of events with positive weights - number of events with negative weights) +eff_tt = 1./(77081156 + 77867738) +eff_dy50 = 1./81781052 # effective number of events +#eff_dy50 = 1./122055388 # true number of events +eff_dy10to50 = 1./47946519 # effective number of events +#eff_dy10to50 = 1./65888233 # true number of events +eff_ww = 1./994012 +eff_wz = 1./1000000 +eff_zz = 1./998034 +eff_wantit = 1./6933094 +eff_wt = 1./6952830 +eff_wjets = 1./16497031 # effective number of events +#eff_wjets = 1./24120319 # true number of events + +data.scale_hists( lumi=lumi_total/lumi_data) +tt.scale_hists(sigma = sigma_tt, lumi = lumi_total, eff = eff_tt) +dy50.scale_hists(sigma = sigma_dy50, lumi = lumi_total, eff = eff_dy50) +dy10to50.scale_hists(sigma = sigma_dy10to50,lumi = lumi_total, eff = eff_dy10to50) +ww.scale_hists(sigma = sigma_ww, lumi = lumi_total, eff = eff_ww) +wz.scale_hists(sigma = sigma_wz, lumi = lumi_total, eff = eff_wz) +zz.scale_hists(sigma = sigma_zz, lumi = lumi_total, eff = eff_zz) +wantit.scale_hists(sigma = sigma_wantit, lumi = lumi_total, eff = eff_wantit) +wt.scale_hists(sigma = sigma_wt, lumi = lumi_total, eff = eff_wt) +wjets.scale_hists(sigma = sigma_wjets, lumi = lumi_total, eff = eff_wjets) + +data.setMinMax(0,8000,0,160000,0,18500,0,150000,0,140000) +title='180227' + +directory = os.path.dirname('./plots_'+title+'/') +# make a canvas, draw, and save it +if not os.path.exists(directory): + os.makedirs(directory) +os.chdir(directory) + +integral_mc = 0. +integral_data = process.hists_data.integral +for ip in process.collection: + integral_mc += ip.integral +print "integral of mc events is " + str(integral_mc) +print "integral of data events is " + str(integral_data) +print "data/mc = " +str(integral_data/integral_mc) + +#for ip in process.collection: +# ip.draw_hists() +#process.hists_data.draw_hists() + +process.print_stacks() \ No newline at end of file diff --git a/DeepNtuplizer/plots/plot_features.py b/DeepNtuplizer/plots/plot_features.py index eb28364ce05..77e263a64d0 100644 --- a/DeepNtuplizer/plots/plot_features.py +++ b/DeepNtuplizer/plots/plot_features.py @@ -12,6 +12,7 @@ from array import array import matplotlib.pyplot as plt +import matplotlib.patches as mpatches import root_numpy as rn import numpy as np @@ -56,6 +57,18 @@ def hist_bin_uncertainty(data, weights, bin_edges): return bin_uncertainties +class feature: + """ DOC """ + + + def __init__(self, name, bins,ymax=None,fillopt='', xlabel='',description=''): + self.name = name + self.bins = bins + self.fillopt=fillopt + self.xlabel=xlabel + self.description=description + self.ymax=ymax + class datacollection: """ DOC """ @@ -64,9 +77,7 @@ class datacollection: def __init__(self, filenames_mc, filenames_data = None): self.features = [] - self.bins_list = [] - self.fillopt_list = [] - self.freqs_list = [] + self.scalefactor_data = 1. self.filenames_mc = filenames_mc self.filenames_data = filenames_data @@ -78,20 +89,20 @@ def __init__(self, filenames_mc, filenames_data = None): def fill(self): print 'load samples' - self.collection_mc = rn.root2array(self.filenames_mc, "deepntuplizer/tree", list(set(self.features))) + branches = [] + for ifeature in self.features: + branches.append(ifeature.name) + self.collection_mc = rn.root2array(self.filenames_mc, "deepntuplizer/tree", list(set(branches))) self.weight_mc = rn.root2array(self.filenames_mc, "deepntuplizer/tree", "event_weight") if self.filenames_data != None: - self.collection_data = rn.root2array(self.filenames_data, "deepntuplizer/tree", list(set(self.features))) + self.collection_data = rn.root2array(self.filenames_data, "deepntuplizer/tree", list(set(branches))) self.weight_data = rn.root2array(self.filenames_data, "deepntuplizer/tree", "event_weight") #pdb.set_trace() - def add_feature(self,feature, bins, fillopt=''): - self.features.append(feature) - self.bins_list.append(bins) - self.fillopt_list.append(fillopt) - + def add_feature(self,fname, bins, ymax=None, fillopt='',xlabel='',description=''): + self.features.append(feature(fname,bins,ymax,fillopt,xlabel,description)) def scale_data(self,sf): @@ -99,61 +110,70 @@ def scale_data(self,sf): def plot_features(self): - #pdb.set_trace() - for i, var in enumerate(self.features): - print 'make plot for feature '+var + for ifeature in self.features: + print 'make plot for feature '+ifeature.name - if 'all' in self.fillopt_list[i]: - flat_col_mc = np.concatenate(self.collection_mc[var], axis=-1) - freqlist = [len(j) for j in self.collection_mc[var]] + if 'all' in ifeature.fillopt: + flat_col_mc = np.concatenate(self.collection_mc[ifeature.name], axis=-1) + freqlist = [len(j) for j in self.collection_mc[ifeature.name]] flat_weight_mc = np.repeat(self.weight_mc, freqlist) - flat_col_data = np.concatenate(self.collection_data[var], axis=-1) - freqlist = [len(j) for j in self.collection_data[var]] + flat_col_data = np.concatenate(self.collection_data[ifeature.name], axis=-1) + freqlist = [len(j) for j in self.collection_data[ifeature.name]] flat_weight_data = np.repeat(self.weight_data, freqlist) - entries_mc, binEdges = np.histogram(flat_col_mc, self.bins_list[i], weights=flat_weight_mc) - entries_data, _ = np.histogram(flat_col_data, self.bins_list[i], weights=flat_weight_data) + entries_mc, binEdges = np.histogram(flat_col_mc, ifeature.bins, weights=flat_weight_mc) + entries_data, _ = np.histogram(flat_col_data, ifeature.bins, weights=flat_weight_data) err_mc = hist_bin_uncertainty(flat_col_mc, flat_weight_mc, binEdges) err_data = hist_bin_uncertainty(flat_col_data, flat_weight_data, binEdges) - if 'max' in self.fillopt_list[i]: - max_col_mc = np.empty((self.collection_mc[var].shape)) - max_col_data = np.empty((self.collection_data[var].shape)) - for j,arr in enumerate(self.collection_mc[var]): + if 'max' in ifeature.fillopt: + max_col_mc = np.empty((self.collection_mc[ifeature.name].shape)) + max_col_data = np.empty((self.collection_data[ifeature.name].shape)) + for j,arr in enumerate(self.collection_mc[ifeature.name]): if len(arr) > 0: max_col_mc[j] = np.amax(arr) + else: + max_col_mc[j] = 0. - for j, arr in enumerate(self.collection_data[var]): + for j, arr in enumerate(self.collection_data[ifeature.name]): if len(arr) > 0: max_col_data[j] = np.amax(arr) - entries_mc, binEdges = np.histogram(max_col_mc, self.bins_list[i], weights=self.weight_mc) - entries_data, _ = np.histogram(max_col_data, self.bins_list[i], weights=self.weight_data) + else: + max_col_data[j] = 0. + entries_mc, binEdges = np.histogram(max_col_mc, ifeature.bins, weights=self.weight_mc) + entries_data, _ = np.histogram(max_col_data, ifeature.bins, weights=self.weight_data) err_mc = hist_bin_uncertainty(max_col_mc, self.weight_mc, binEdges) err_data = hist_bin_uncertainty(max_col_data, self.weight_data, binEdges) - if self.fillopt_list[i] == '': - entries_mc, binEdges = np.histogram(self.collection_mc[var], self.bins_list[i], weights=self.weight_mc) - entries_data, _ = np.histogram(self.collection_data[var], self.bins_list[i], weights=self.weight_data) - err_mc = hist_bin_uncertainty(self.collection_mc[var],self.weight_mc,binEdges) - err_data = hist_bin_uncertainty(self.collection_data[var], self.weight_data, binEdges) + if ifeature.fillopt == '': + entries_mc, binEdges = np.histogram(self.collection_mc[ifeature.name], ifeature.bins, weights=self.weight_mc) + entries_data, _ = np.histogram(self.collection_data[ifeature.name], ifeature.bins, weights=self.weight_data) + err_mc = hist_bin_uncertainty(self.collection_mc[ifeature.name],self.weight_mc,binEdges) + err_data = hist_bin_uncertainty(self.collection_data[ifeature.name], self.weight_data, binEdges) plt.cla() fig, ax = plt.subplots() bincenters = 0.5 * (binEdges[1:] + binEdges[:-1]) binWidth = binEdges[1:] - binEdges[:-1] - plt.bar(bincenters, entries_mc, yerr = err_mc, width = binWidth, align='center', color='w') - plt.errorbar(bincenters,entries_data*self.scalefactor_data, yerr=err_data*self.scalefactor_data, fmt='k.',ecolor='k') + ax.bar(bincenters, entries_mc, yerr = err_mc, width = binWidth, align='center', color='w', edgecolor='k',ecolor='k', label='mc') + ax.errorbar(bincenters,entries_data*self.scalefactor_data, yerr=err_data*self.scalefactor_data, fmt='k.',ecolor='k', label='data') + ax.legend() ax.set_xlim(binEdges[0], binEdges[-1]) ax.set_ylabel('weighted frequency') - ax.set_xlabel(var) - ax.set_title(self.fillopt_list[i]+' entries of '+var+' in GoodJets') + ax.set_xlabel(ifeature.xlabel) + #ax.set_title(ifeature.fillopt+' entries of '+ifeature.name+' in GoodJets') ax.set_ylim(bottom=0) + if ifeature.ymax != None: + ax.set_ylim(top=ifeature.ymax) + x_min, x_max = ax.get_xlim() + y_min, y_max = ax.get_ylim() + #ax.text(x_min + 0.01*(x_max-x_min),y_max*0.95,ifeature.description) - plt.savefig(var+"_"+self.fillopt_list[i]+".png") - + ax.ticklabel_format(style='sci', scilimits=(-3, 4), axis='both') + plt.savefig(ifeature.name+"_"+ifeature.fillopt+".png") @@ -164,21 +184,31 @@ def plot_features(self): files_data = "muonEG_H_0.root" dc = datacollection(files_mc,files_data) -dc.add_feature("nCpfcand", np.arange(0,30,1)) -dc.add_feature("nNpfcand", np.arange(0,30,1)) -dc.add_feature("jet_pt", np.arange(0,320,20)) -dc.add_feature("jet_eta", np.arange(-2.4,2.8,0.4)) -dc.add_feature("npv", np.arange(0,50,1)) -dc.add_feature("nsv", np.arange(0,10,1)) - -dc.add_feature("Cpfcan_pt", np.arange(0,105,5),fillopt='max') -dc.add_feature("Npfcan_pt", np.arange(0,105,5),fillopt='max') -dc.add_feature("sv_pt", np.arange(0,110,10),fillopt='max') - -dc.add_feature("Cpfcan_pt", np.arange(0,55,2.5),fillopt='all') -dc.add_feature("Npfcan_pt", np.arange(0,55,2.5),fillopt='all') -dc.add_feature("sv_pt", np.arange(0,110,10),fillopt='all') -dc.add_feature("sv_deltaR", np.arange(0,110,10),fillopt='all') + +dc.add_feature("jet_pt", np.arange(0,390,15), xlabel='$p_\mathrm{T}(j)$ (GeV)', description='jet') +dc.add_feature("jet_eta", np.arange(-2.4,2.6,0.2), xlabel='$\eta(j)$', description='jet') +dc.add_feature("nCpfcand", np.arange(-0.5,30.5,1), xlabel='$N_\mathrm{cPF}$', description='charged particle flow candidate') +dc.add_feature("nNpfcand", np.arange(-0.5,30.5,1), xlabel='$N_\mathrm{nPF}$', description='neutral particle flow candidate') +dc.add_feature("npv", np.arange(-0.5,50.5,1), xlabel='$N_\mathrm{SV}$', description='primary vertices') +dc.add_feature("nsv", np.arange(-0.5,5.5,1), xlabel='$N_\mathrm{PV}$', description='secondary vertices') +dc.add_feature("TagVarCSV_trackSumJetEtRatio", np.arange(0.,1.04,0.04), xlabel='trackSumJetEtRatio', description='des') +dc.add_feature("TagVarCSV_trackSumJetDeltaR", np.arange(0.,0.26,0.01), xlabel='trackSumJetDeltaR', description='des') +dc.add_feature("TagVarCSV_vertexCategory", np.arange(-0.5,4.5,1), xlabel='vertexCategory', description='des') +dc.add_feature("TagVarCSV_trackSip2dValAboveCharm", np.array((-1.1,-0.9,-0.1,-0.08,-0.06,-0.04,-0.02,0.,0.02,0.04,0.06,0.08,0.1,0.12,0.14,0.16,0.18,0.2,0.22)), xlabel='trackSip2dValAboveCharm', description='des') +dc.add_feature("TagVarCSV_trackSip2dSigAboveCharm", np.arange(-1,21,1), xlabel='trackSip2dSigAboveCharm', description='des') +dc.add_feature("TagVarCSV_trackSip3dValAboveCharm", np.array((-1.1,-0.9,-0.1,-0.08,-0.06,-0.04,-0.02,0.,0.02,0.04,0.06,0.08,0.1,0.12,0.14,0.16,0.18,0.2,0.22)), xlabel='trackSip3dValAboveCharm', description='des') +dc.add_feature("TagVarCSV_trackSip3dSigAboveCharm", np.arange(-1,21,1), xlabel='trackSip3dSigAboveCharm', description='des') +dc.add_feature("TagVarCSV_jetNSelectedTracks", np.arange(0,21,1), xlabel='jetNSelectedTracks', description='des') +dc.add_feature("TagVarCSV_jetNTracksEtaRel", np.arange(0,16,1), xlabel='jetNTracksEtaRel', description='des') + +#dc.add_feature("Cpfcan_pt", np.arange(0,105,5),fillopt='max',ymax=225000, xlabel='$p_\mathrm{T}(j)$ (GeV)', description='charged particle flow candidate') +#dc.add_feature("Npfcan_pt", np.arange(0,105,5),fillopt='max',xlabel='$p_\mathrm{T}$ (GeV)', description='neutral particle flow candidate') +#dc.add_feature("sv_pt", np.arange(0,110,10),fillopt='max', xlabel='$p_\mathrm{T}$ (GeV)', description='secondary vertice') + +#dc.add_feature("Cpfcan_pt", np.arange(0,55,2.5),fillopt='all',ymax=5500000, xlabel='$p_\mathrm{T}$ (GeV)', description='charged particle flow candidate') +#dc.add_feature("Npfcan_pt", np.arange(0,55,2.5),fillopt='all',ymax=6500000, xlabel='$p_\mathrm{T}$ (GeV)', description='neutral particle flow candidate') +#dc.add_feature("sv_pt", np.arange(0,110,10),fillopt='all',ymax=190000, xlabel='$p_\mathrm{T}$ (GeV)', description='secondary vertice') +#dc.add_feature("sv_deltaR", np.arange(-0.5,0.02,0.02),fillopt='all', xlabel='$\Delta R$', description='secondary vertice') From 9b6649d54adee3b76fecb89ce6f727105d10dbd6 Mon Sep 17 00:00:00 2001 From: David Walter Date: Tue, 17 Apr 2018 16:29:25 +0200 Subject: [PATCH 12/17] include ttbar semileptonic eventselection, include muon scalefactor, moved selection specific configs to DeepNtuplizer_'selection' --- .../data/EfficienciesAndSF_Period4.root | Bin 0 -> 81373 bytes DeepNtuplizer/interface/ntuple_eventInfo.h | 6 +- DeepNtuplizer/plugins/ttsemilepFilter.cc | 250 +++++++++++ .../production/DeepNtuplizer_tt_dilep.py | 32 +- .../production/DeepNtuplizer_tt_semilep.py | 402 ++++++++++++++++++ DeepNtuplizer/python/DeepNtuplizer_cfi.py | 29 +- DeepNtuplizer/src/ntuple_eventInfo.cc | 25 +- 7 files changed, 722 insertions(+), 22 deletions(-) create mode 100644 DeepNtuplizer/data/EfficienciesAndSF_Period4.root create mode 100644 DeepNtuplizer/plugins/ttsemilepFilter.cc create mode 100644 DeepNtuplizer/production/DeepNtuplizer_tt_semilep.py diff --git a/DeepNtuplizer/data/EfficienciesAndSF_Period4.root b/DeepNtuplizer/data/EfficienciesAndSF_Period4.root new file mode 100644 index 0000000000000000000000000000000000000000..6806d8ad16107a46605e720c79ef1ee16ddaf0d0 GIT binary patch literal 81373 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

WZu45(J$WFxtQt~6rOCGv~?@t&$~+g5FRN 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 minMT_muonMETpair + + Implementation: + [Notes on implementation] +*/ +// +// Original Author: David Walter +// Created: Thu, 12 Apr 2018 17:00:08 GMT +// +// + + +// system include files +#include + +// user include files +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/Framework/interface/stream/EDFilter.h" + +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" + +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Utilities/interface/StreamID.h" + +#include "DataFormats/PatCandidates/interface/Muon.h" +#include "DataFormats/PatCandidates/interface/Electron.h" +#include "DataFormats/PatCandidates/interface/Jet.h" +#include "DataFormats/PatCandidates/interface/MET.h" + + +// +// class declaration +// + +class ttsemilepFilter : public edm::stream::EDFilter<> { + public: + explicit ttsemilepFilter(const edm::ParameterSet&); + ~ttsemilepFilter(); + + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); + + private: + virtual void beginStream(edm::StreamID) override; + virtual bool filter(edm::Event&, const edm::EventSetup&) override; + virtual void endStream() override; + + //virtual void beginRun(edm::Run const&, edm::EventSetup const&) override; + //virtual void endRun(edm::Run const&, edm::EventSetup const&) override; + //virtual void beginLuminosityBlock(edm::LuminosityBlock const&, edm::EventSetup const&) override; + //virtual void endLuminosityBlock(edm::LuminosityBlock const&, edm::EventSetup const&) override; + + // ----------member data --------------------------- + + edm::EDGetTokenT > src_muons; + edm::EDGetTokenT > src_electrons; + edm::EDGetTokenT > src_jets; + edm::EDGetTokenT > src_mets; + + + edm::Handle > muons; + edm::Handle > electrons; + edm::Handle > jets; + edm::Handle > mets; + + double minMT_muonMETpair = 0.; + + /* + double min_chi2 = 0; + double m_w = 80.4; + double m_t = 173.1; + + int first_q = 0; + int second_q = 0; + int first_b = 0; + int second_b = 0; + + const std::string btag = "pfCSV_v2JetTags:probb"; + */ + +}; + +// +// constants, enums and typedefs +// + +// +// static data member definitions +// + +// +// constructors and destructor +// +ttsemilepFilter::ttsemilepFilter(const edm::ParameterSet& iConfig): + src_muons(consumes > (iConfig.getParameter("src_muons"))), + src_electrons(consumes > (iConfig.getParameter("src_electrons"))), + src_jets(consumes > (iConfig.getParameter("src_jets"))), + src_mets(consumes > (iConfig.getParameter("src_mets"))){ + //now do what ever initialization is needed + + //minPt_muon=(iConfig.getParameter("minPt_muon")); + //minPt_jet=(iConfig.getParameter("minPt_jet")); + minMT_muonMETpair=(iConfig.getParameter("cut_minMT_muonMETpair")); +} + + +ttsemilepFilter::~ttsemilepFilter() +{ + + // do anything here that needs to be done at destruction time + // (e.g. close files, deallocate resources etc.) + +} + + +// +// member functions +// + +// ------------ method called on each new Event ------------ +bool +ttsemilepFilter::filter(edm::Event& iEvent, const edm::EventSetup& iSetup) +{ + iEvent.getByToken(src_muons, muons); + iEvent.getByToken(src_electrons, electrons); + iEvent.getByToken(src_jets, jets); + iEvent.getByToken(src_mets, mets); + + if(muons->size()!=1) + return false; + + if(electrons->size()!=0) + return false; + + if(jets->size()!=4) + return false; + + if(mets->size()==0){ //this should normally not happen, is the file corrupted?? + std::cout<<"there was an event with no met object, strange ..."<ptrAt(0); + const auto met = mets->ptrAt(0); + + double mWt = std::sqrt(2*(muon->pt()*met->pt() - muon->px()*met->px() - muon->py()*met->py())); + + //leptonic decaying W reconstruction + if(mWt < minMT_muonMETpair) + return false; + + //hadronically decaying t reconstruction + /* + for(size_t i = 0; i < jets->size(); ++i){ + for(size_t j = i+1; j < jets->size(); ++j){ + if(i!=j){ + double m_2jet = (jets->ptrAt(i)->p4() + jets->ptrAt(j)->p4()).M(); + + for(size_t k = 0; k < jets->size(); ++k){ + if(i!= j && i!=k && j!=k){ + double m_3jet = (jets->ptrAt(i)->p4() + jets->ptrAt(j)->p4() + jets->ptrAt(k)->p4()).M(); + + double chi2 = - std::log(std::pow(m_w - m_2jet,2)/m_2jet + std::pow(m_t - m_3jet,2)/m_3jet); + std::cout<<"combination ("<= 840: process.deepntuplizer.tagInfoName = cms.string('pfDeepCSV') diff --git a/DeepNtuplizer/production/DeepNtuplizer_tt_semilep.py b/DeepNtuplizer/production/DeepNtuplizer_tt_semilep.py new file mode 100644 index 00000000000..b11dbd9f115 --- /dev/null +++ b/DeepNtuplizer/production/DeepNtuplizer_tt_semilep.py @@ -0,0 +1,402 @@ +# this can be run with CMSSW 8_0_29; in CMSSW 8_0_25 the module 'cutBasedElectronID_Summer16_80X_V1_cff' is missing +#basically deepntuplizer with tt semileptonic selection + +import FWCore.ParameterSet.Config as cms + +import FWCore.ParameterSet.VarParsing as VarParsing +### parsing job options +import sys + +options = VarParsing.VarParsing() + +options.register('inputScript', '', VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.string,"input Script") +options.register('outputFile', 'output', VarParsing.VarParsing.multiplicity.singleton,VarParsing.VarParsing.varType.string, "output File (w/o .root)") +options.register('maxEvents', -1, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int,"maximum events") +options.register('skipEvents', 0, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int, "skip N events") +options.register('job', 0, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int,"job number") +options.register('nJobs', 1, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int, "total jobs") +options.register('gluonReduction', 0.0, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.float, "gluon reduction") +options.register('selectJets', True, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.bool,"select jets with good gen match") +options.register('globalTag', '', VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.string,"global tag for jet energy correction") +options.register('isData', False, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.bool, "switch off generator jets") +options.register('deepNtuplizer',True, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.bool, "run deepNtuplizer or just the ttbar selection") +options.register('lheWeights',False, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.bool, "use LHE weights") + + + +import os + +release = os.environ['CMSSW_VERSION'][6:12] +print("Using release " + release) + +options.register( + 'inputFiles', '', + VarParsing.VarParsing.multiplicity.list, + VarParsing.VarParsing.varType.string, + "input files (default is the tt RelVal)" +) + +if hasattr(sys, "argv"): + options.parseArguments() + +process = cms.Process("semilepSelectedDNNFiller") + +process.load("FWCore.MessageService.MessageLogger_cfi") +process.load("Configuration.EventContent.EventContent_cff") +process.load('Configuration.StandardSequences.Services_cff') +process.load('Configuration.StandardSequences.GeometryRecoDB_cff') +process.load('Configuration.StandardSequences.MagneticField_cff') +process.load('Configuration.StandardSequences.FrontierConditions_GlobalTag_cff') + +if options.globalTag == '': + if options.isData == False: + process.GlobalTag.globaltag = '80X_mcRun2_asymptotic_2016_TrancheIV_v8' # For MC Jet Energy correction + if options.isData == True: + process.GlobalTag.globaltag = '80X_dataRun2_2016SeptRepro_v7' # For Data Jet Energy correction +else: + process.GlobalTag.globaltag = options.globalTag + +process.maxEvents = cms.untracked.PSet(input=cms.untracked.int32(-1)) + +process.load('FWCore.MessageService.MessageLogger_cfi') +process.MessageLogger.cerr.FwkReport.reportEvery = 10 +if options.inputScript == '': # this is probably for testing + process.MessageLogger.cerr.FwkReport.reportEvery = 100 + +process.options = cms.untracked.PSet( + allowUnscheduled=cms.untracked.bool(True), + wantSummary=cms.untracked.bool(False), + SkipEvent = cms.untracked.vstring('ProductNotFound') +) + + +process.load('DeepNTuples.DeepNtuplizer.samples.TTJetsPhase1_cfg') # default input + +if options.inputFiles: + process.source.fileNames = options.inputFiles + +if options.inputScript != '' and options.inputScript != 'DeepNTuples.DeepNtuplizer.samples.TTJetsPhase1_cfg': + process.load(options.inputScript) + + +#process.source.fileNames=['file:./00E02A09-853C-E711-93FF-3417EBE644A7.root'] #store/data/Run2016H/SingleMuon/MINIAOD/18Apr2017-v1/00000/00E02A09-853C-E711-93FF-3417EBE644A7.root +#process.source.fileNames=['file:./000C6E52-8BEC-E611-B3FF-0025905C42FE.root'] #isData=True +#process.source.fileNames=['file:./0693E0E7-97BE-E611-B32F-0CC47A78A3D8.root'] #isData=False +#process.source.fileNames=['file:./EE95DEDC-96BE-E611-B45D-A0000420FE80.root'] #isData=False +process.source.fileNames=['file:./0693E0E7-97BE-E611-B32F-0CC47A78A3D8.root'] #store/mc/RunIISummer16MiniAODv2/TT_TuneCUETP8M2T4_13TeV-powheg-pythia8/MINIAODSIM/PUMoriond17_80X_mcRun2_asymptotic_2016_TrancheIV_v6-v1/50000/ +#process.source.fileNames=['file:./00E02A09-853C-E711-93FF-3417EBE644A7.root'] #store/data/Run2016H/SingleMuon/MINIAOD/18Apr2017-v1/00000/ + + +numberOfFiles = len(process.source.fileNames) +numberOfJobs = options.nJobs +jobNumber = options.job + +process.source.fileNames = process.source.fileNames[jobNumber:numberOfFiles:numberOfJobs] +#if options.nJobs > 1: +print ("running over these files:") +print (process.source.fileNames) + +process.globalInfo = cms.EDAnalyzer('globalInfo', + lheInfo = cms.InputTag("externalLHEProducer"), + useLHEWeights=cms.bool(options.lheWeights) + ) + +process.source.skipEvents = cms.untracked.uint32(options.skipEvents) +process.maxEvents = cms.untracked.PSet( + input=cms.untracked.int32(options.maxEvents) +) + +if int(release.replace("_", "")) >= 8400 or int(release.replace("_", "")) == 8029: + bTagInfos = [ + 'pfImpactParameterTagInfos', + 'pfInclusiveSecondaryVertexFinderTagInfos', + 'pfDeepCSVTagInfos'] +else: + bTagInfos = [ + 'pfImpactParameterTagInfos', + 'pfInclusiveSecondaryVertexFinderTagInfos', + 'deepNNTagInfos', + ] + +if int(release.replace("_", "")) >= 8400 or int(release.replace("_", "")) == 8029: + bTagDiscriminators = [ + 'softPFMuonBJetTags', + 'softPFElectronBJetTags', + 'pfJetBProbabilityBJetTags', + 'pfJetProbabilityBJetTags', + 'pfCombinedInclusiveSecondaryVertexV2BJetTags', + 'pfDeepCSVJetTags:probudsg', # to be fixed with new names + 'pfDeepCSVJetTags:probb', + 'pfDeepCSVJetTags:probc', + 'pfDeepCSVJetTags:probbb', + 'pfDeepCSVJetTags:probcc', + ] +else: + bTagDiscriminators = [ + 'softPFMuonBJetTags', + 'softPFElectronBJetTags', + 'pfJetBProbabilityBJetTags', + 'pfJetProbabilityBJetTags', + 'pfCombinedInclusiveSecondaryVertexV2BJetTags', + 'deepFlavourJetTags:probudsg', # to be fixed with new names + 'deepFlavourJetTags:probb', + 'deepFlavourJetTags:probc', + 'deepFlavourJetTags:probbb', + 'deepFlavourJetTags:probcc', + ] + +###### semilep selection +outFileName = options.outputFile + '_ntuples_180417_' + str(options.job) + '.root' +print ('Using output file ' + outFileName) + +if options.deepNtuplizer: + process.TFileService = cms.Service("TFileService", + fileName=cms.string(outFileName)) +else: + process.MINIAODSIMEventContent.outputCommands.extend([ + 'keep *_goodElectrons_*_*', + 'keep *_goodMuons_*_*', + 'keep *_goodJets_*_*', + ]) + + process.outmod = cms.OutputModule("PoolOutputModule", + process.MINIAODSIMEventContent, + SelectEvents = cms.untracked.PSet( + SelectEvents = cms.vstring('p') + ), + fileName = cms.untracked.string(outFileName) + ) + +from PhysicsTools.SelectorUtils.tools.vid_id_tools import * +dataFormat = DataFormat.MiniAOD +switchOnVIDElectronIdProducer(process, dataFormat) +my_id_modules = [ + 'RecoEgamma.ElectronIdentification.Identification.cutBasedElectronID_Summer16_80X_V1_cff' +] +for idmod in my_id_modules: + setupAllVIDIdsInModule(process,idmod,setupVIDElectronSelection) + + +#HighLevelTrigger +HLTlistSM = cms.vstring("HLT_IsoTkMu24_v*", #Run B-H + "HLT_IsoMu24_v*" #Run B-H + ) +process.TriggerSel = cms.EDFilter("HLTHighLevel", + TriggerResultsTag = cms.InputTag("TriggerResults","","HLT"), + HLTPaths = cms.vstring(HLTlistSM), + eventSetupPathsKey = cms.string(''), # not empty => use read paths from AlCaRecoTriggerBitsRcd via this key + andOr = cms.bool(True), # how to deal with multiple triggers: True (OR) accept if ANY is true, False (AND) accept if ALL are true + throw = cms.bool(True) # throw exception on unknown path names +) +### Electron Selection +process.goodElectrons = cms.EDProducer("ElectronIdAdder", + src=cms.InputTag("slimmedElectrons"), + vSrc=cms.InputTag("offlineSlimmedPrimaryVertices"), + idMap=cms.InputTag("egmGsfElectronIDs:cutBasedElectronID-Summer16-80X-V1-tight"), + minPt=cms.double(20.0), + maxAbsEta=cms.double(2.4), + ) + +### Muon Selection +process.goodMuons = cms.EDProducer("MuonIdAdder", + src=cms.InputTag("slimmedMuons"), + vSrc=cms.InputTag("offlineSlimmedPrimaryVertices"), + minPt=cms.double(30.0), + maxAbsEta=cms.double(2.4), + maxRMI=cms.double(0.15) #RMI = relative muon isolation + ) + +### Jet Selection +process.goodJets = cms.EDProducer("PATJetCleaner", + src = cms.InputTag("slimmedJets"), + preselection = cms.string("pt>30 && abs(eta) < 2.4 && neutralHadronEnergyFraction < 0.99 " + "&& neutralEmEnergyFraction < 0.99 && (chargedMultiplicity+neutralMultiplicity) > 1 " + "&& chargedHadronEnergyFraction > 0.0 " + "&& chargedMultiplicity > 0.0 && chargedEmEnergyFraction < 0.99 "), + checkOverlaps = cms.PSet( + muons = cms.PSet( + src = cms.InputTag("goodMuons"), + algorithm = cms.string("byDeltaR"), + preselection = cms.string(""), + deltaR = cms.double(0.4), + checkRecoComponents = cms.bool(False), # don't check if they share some AOD object ref + pairCut = cms.string(""), + requireNoOverlaps = cms.bool(True), # overlaps cause the jet to be discarded + ), + electrons = cms.PSet( + src = cms.InputTag("goodElectrons"), + algorithm = cms.string("byDeltaR"), + preselection = cms.string(""), + deltaR = cms.double(0.4), + checkRecoComponents = cms.bool(False), # don't check if they share some AOD object ref + pairCut = cms.string(""), + requireNoOverlaps = cms.bool(True), # overlaps cause the jet to be discarded + ) + ), + finalCut = cms.string('') + ) + + +### Event Filter +process.ttsemilepFilter = cms.EDFilter("ttsemilepFilter", + src_muons = cms.InputTag("goodMuons"), + src_electrons = cms.InputTag("goodElectrons"), + src_jets = cms.InputTag("goodJets"), + src_mets = cms.InputTag("slimmedMETs"), + cut_minMT_muonMETpair = cms.double(50.0) + ) + + + +### end selection + +# Jet Energy Corrections +if options.isData: + jetCorrections = cms.vstring(['L1FastJet', 'L2Relative', 'L3Absolute', 'L2L3Residual']) +else: + jetCorrections = cms.vstring(['L1FastJet', 'L2Relative', 'L3Absolute']) + +from PhysicsTools.PatAlgos.tools.jetTools import updateJetCollection +updateJetCollection( + process, + labelName="DeepFlavour", + # jetSource=cms.InputTag('slimmedJetsAK8PFPuppiSoftDropPacked', 'SubJets'), # 'subjets from AK8' + jetSource=cms.InputTag('goodJets'), # 'ak4Jets' + jetCorrections=('AK4PFchs', jetCorrections, 'None'), + pfCandidates=cms.InputTag('packedPFCandidates'), + pvSource=cms.InputTag("offlineSlimmedPrimaryVertices"), + svSource=cms.InputTag('slimmedSecondaryVertices'), + muSource=cms.InputTag('slimmedMuons'), + elSource=cms.InputTag('slimmedElectrons'), + btagInfos=bTagInfos, + btagDiscriminators=bTagDiscriminators, + explicitJTA=False + ) + +if hasattr(process, 'updatedPatJetsTransientCorrectedDeepFlavour'): + process.updatedPatJetsTransientCorrectedDeepFlavour.addTagInfos = cms.bool(True) + process.updatedPatJetsTransientCorrectedDeepFlavour.addBTagInfo = cms.bool(True) +else: + raise ValueError( + 'I could not find updatedPatJetsTransientCorrectedDeepFlavour to embed the tagInfos, please check the cfg') + +# QGLikelihood +process.load("DeepNTuples.DeepNtuplizer.QGLikelihood_cfi") +process.es_prefer_jec = cms.ESPrefer("PoolDBESSource", "QGPoolDBESSource") +process.load('RecoJets.JetProducers.QGTagger_cfi') +process.QGTagger.srcJets = cms.InputTag("selectedUpdatedPatJetsDeepFlavour") +process.QGTagger.jetsLabel = cms.string('QGL_AK4PFchs') + +from RecoJets.JetProducers.ak4GenJets_cfi import ak4GenJets + +process.ak4GenJetsWithNu = ak4GenJets.clone(src='packedGenParticles') + +## Filter out neutrinos from packed GenParticles +process.packedGenParticlesForJetsNoNu = cms.EDFilter("CandPtrSelector", src=cms.InputTag("packedGenParticles"), + cut=cms.string( + "abs(pdgId) != 12 && abs(pdgId) != 14 && abs(pdgId) != 16")) +## Define GenJets +process.ak4GenJetsRecluster = ak4GenJets.clone(src='packedGenParticlesForJetsNoNu') + +process.patGenJetMatchWithNu = cms.EDProducer("GenJetMatcher", # cut on deltaR; pick best by deltaR + src=cms.InputTag("selectedUpdatedPatJetsDeepFlavour"), + # RECO jets (any View is ok) + matched=cms.InputTag("ak4GenJetsWithNu"), + # GEN jets (must be GenJetCollection) + mcPdgId=cms.vint32(), # n/a + mcStatus=cms.vint32(), # n/a + checkCharge=cms.bool(False), # n/a + maxDeltaR=cms.double(0.4), # Minimum deltaR for the match + # maxDPtRel = cms.double(3.0), # Minimum deltaPt/Pt for the match (not used in GenJetMatcher) + resolveAmbiguities=cms.bool(True), + # Forbid two RECO objects to match to the same GEN object + resolveByMatchQuality=cms.bool(False), + # False = just match input in order; True = pick lowest deltaR pair first + ) + +process.patGenJetMatchRecluster = cms.EDProducer("GenJetMatcher", # cut on deltaR; pick best by deltaR + src=cms.InputTag("selectedUpdatedPatJetsDeepFlavour"), + # RECO jets (any View is ok) + matched=cms.InputTag("ak4GenJetsRecluster"), + # GEN jets (must be GenJetCollection) + mcPdgId=cms.vint32(), # n/a + mcStatus=cms.vint32(), # n/a + checkCharge=cms.bool(False), # n/a + maxDeltaR=cms.double(0.4), # Minimum deltaR for the match + # maxDPtRel = cms.double(3.0), # Minimum deltaPt/Pt for the match (not used in GenJetMatcher) + resolveAmbiguities=cms.bool(True), + # Forbid two RECO objects to match to the same GEN object + resolveByMatchQuality=cms.bool(False), + # False = just match input in order; True = pick lowest deltaR pair first + ) + +process.genJetSequence = cms.Sequence(process.packedGenParticlesForJetsNoNu + * process.ak4GenJetsWithNu + * process.ak4GenJetsRecluster + * process.patGenJetMatchWithNu + * process.patGenJetMatchRecluster) + +# Very Loose IVF SV collection +from PhysicsTools.PatAlgos.tools.helpers import loadWithPrefix + +loadWithPrefix(process, 'RecoVertex.AdaptiveVertexFinder.inclusiveVertexing_cff', "looseIVF") +process.looseIVFinclusiveCandidateVertexFinder.primaryVertices = cms.InputTag("offlineSlimmedPrimaryVertices") +process.looseIVFinclusiveCandidateVertexFinder.tracks = cms.InputTag("packedPFCandidates") +process.looseIVFinclusiveCandidateVertexFinder.vertexMinDLen2DSig = cms.double(0.) +process.looseIVFinclusiveCandidateVertexFinder.vertexMinDLenSig = cms.double(0.) +process.looseIVFinclusiveCandidateVertexFinder.fitterSigmacut = 20 + +process.looseIVFcandidateVertexArbitrator.primaryVertices = cms.InputTag("offlineSlimmedPrimaryVertices") +process.looseIVFcandidateVertexArbitrator.tracks = cms.InputTag("packedPFCandidates") +process.looseIVFcandidateVertexArbitrator.secondaryVertices = cms.InputTag("looseIVFcandidateVertexMerger") +process.looseIVFcandidateVertexArbitrator.fitterSigmacut = 20 + +datapath=os.environ['CMSSW_BASE']+'/src/DeepNTuples/DeepNtuplizer/data/' +#datapath='' + +# DeepNtuplizer configurations +process.load("DeepNTuples.DeepNtuplizer.DeepNtuplizer_cfi") +process.deepntuplizer.jets = cms.InputTag('selectedUpdatedPatJetsDeepFlavour') +process.deepntuplizer.bDiscriminators = bTagDiscriminators +process.deepntuplizer.bDiscriminators.append('pfCombinedMVAV2BJetTags') +process.deepntuplizer.LooseSVs = cms.InputTag("looseIVFinclusiveCandidateSecondaryVertices") +process.deepntuplizer.applySelection = cms.bool(options.selectJets) +process.deepntuplizer.isData = cms.bool(options.isData) +process.deepntuplizer.useLHEWeights = cms.bool(options.lheWeights) +process.deepntuplizer.pileupData=cms.string(datapath+"pileup_data_2016.root") +process.deepntuplizer.pileupMC=cms.string(datapath+"pileup_MC_2016.root") +process.deepntuplizer.sfMuons = cms.InputTag("goodMuons") +process.deepntuplizer.sfMuonTrigger=cms.string(datapath + "EfficienciesAndSF_Period4.root") +process.deepntuplizer.sfMuonTriggerHist = cms.string("IsoMu24_OR_IsoTkMu24_PtEtaBins/abseta_pt_ratio") +process.deepntuplizer.sfMuonId = cms.string(datapath+"EfficienciesAndSF_ID_GH.root") +process.deepntuplizer.sfMuonIdHist = cms.string("MC_NUM_TightID_DEN_genTracks_PAR_pt_eta/abseta_pt_ratio") +process.deepntuplizer.sfMuonIso=cms.string(datapath+"EfficienciesAndSF_ISO_GH.root") +process.deepntuplizer.sfMuonIsoHist=cms.string("TightISO_TightID_pt_eta/abseta_pt_ratio") +process.deepntuplizer.sfMuonTracking=cms.string(datapath+"Tracking_EfficienciesAndSF_BCDEFGH.root") +process.deepntuplizer.sfMuonTrackingHist=cms.string("ratio_eff_aeta_dr030e030_corr") + + +if int(release.replace("_", "")) >= 840: + process.deepntuplizer.tagInfoName = cms.string('pfDeepCSV') + +process.deepntuplizer.gluonReduction = cms.double(options.gluonReduction) + +# 1631 +process.ProfilerService = cms.Service( + "ProfilerService", + firstEvent=cms.untracked.int32(1631), + lastEvent=cms.untracked.int32(1641), + paths=cms.untracked.vstring('p') +) + + +if options.deepNtuplizer: + if options.isData: + process.p = cms.Path(process.globalInfo + process.TriggerSel + process.ttsemilepFilter + process.QGTagger + process.deepntuplizer) + else: + process.p = cms.Path(process.globalInfo + process.TriggerSel + process.ttsemilepFilter + process.QGTagger + process.genJetSequence * process.deepntuplizer) +else: + process.p = cms.Path(process.TriggerSel + process.ttsemilepFilter) + + process.endp = cms.EndPath(process.outmod) + diff --git a/DeepNtuplizer/python/DeepNtuplizer_cfi.py b/DeepNtuplizer/python/DeepNtuplizer_cfi.py index ec03a715030..1ed5b87a70a 100644 --- a/DeepNtuplizer/python/DeepNtuplizer_cfi.py +++ b/DeepNtuplizer/python/DeepNtuplizer_cfi.py @@ -1,7 +1,6 @@ import FWCore.ParameterSet.Config as cms import os -datapath=os.environ['CMSSW_BASE']+'/src/DeepNTuples/DeepNtuplizer/data/' deepntuplizer = cms.EDAnalyzer('DeepNtuplizer', vertices = cms.InputTag("offlineSlimmedPrimaryVertices"), @@ -41,21 +40,25 @@ useLHEWeights=cms.bool(True), #leave empty string if you don't want to use pileup weights - pileupData=cms.string(datapath+"pileup_data_2016.root"), - pileupMC=cms.string(datapath+"pileup_MC_2016.root"), + pileupData=cms.string(""), + pileupMC=cms.string(""), #scalefactor information - sfMuons = cms.InputTag("goodMuons"), - sfElectrons=cms.InputTag("goodElectrons"), + sfMuons = cms.InputTag("slimmedMuons"), + sfElectrons=cms.InputTag("slimmedElectrons"), # leave an empty string for the root file if you don't want to use a scalefactor - sfMuonId = cms.string(datapath+"EfficienciesAndSF_ID_GH.root"), - sfMuonIdHist = cms.string("MC_NUM_TightID_DEN_genTracks_PAR_pt_eta/abseta_pt_ratio"), - sfMuonIso=cms.string(datapath+"EfficienciesAndSF_ISO_GH.root"), - sfMuonIsoHist=cms.string("TightISO_TightID_pt_eta/abseta_pt_ratio"), - sfMuonTracking=cms.string(datapath+"Tracking_EfficienciesAndSF_BCDEFGH.root"), - sfMuonTrackingHist=cms.string("ratio_eff_aeta_dr030e030_corr"), - sfElIdAndIso=cms.string(datapath+"egammaEffi.txt_EGM2D.root"), - sfElIdAndIsoHist=cms.string("EGamma_SF2D"), + sfMuonTrigger=cms.string(""), + sfMuonTriggerHist = cms.string(""), + sfMuonId = cms.string(""), + sfMuonIdHist = cms.string(""), + sfMuonIso=cms.string(""), + sfMuonIsoHist=cms.string(""), + sfMuonTracking=cms.string(""), + sfMuonTrackingHist=cms.string(""), + sfElIdAndIso=cms.string(""), + sfElIdAndIsoHist=cms.string(""), + + ) diff --git a/DeepNtuplizer/src/ntuple_eventInfo.cc b/DeepNtuplizer/src/ntuple_eventInfo.cc index e1692597ac0..7f32adc3fbd 100644 --- a/DeepNtuplizer/src/ntuple_eventInfo.cc +++ b/DeepNtuplizer/src/ntuple_eventInfo.cc @@ -15,6 +15,8 @@ void ntuple_eventInfo::getInput(const edm::ParameterSet& iConfig){ pupDataDir_ = (iConfig.getParameter("pileupData")); pupMCDir_ = (iConfig.getParameter("pileupMC")); + sfMuonTriggerDir_ = (iConfig.getParameter("sfMuonTrigger")); + sfMuonTriggerName_ = (iConfig.getParameter("sfMuonTriggerHist")); sfMuonIdDir_ = (iConfig.getParameter("sfMuonId")); sfMuonIdName_ = (iConfig.getParameter("sfMuonIdHist")); sfMuonIsoDir_ = (iConfig.getParameter("sfMuonIso")); @@ -42,6 +44,17 @@ void ntuple_eventInfo::getInput(const edm::ParameterSet& iConfig){ } } + if(sfMuonTriggerDir_ == "") + std::cout<<"no muon trigger scalefactor histogram, proceed without muon trigger scalefactor"<Get(sfMuonTriggerName_.c_str()); + + sfMuonTriggerHist_xaxis = sfMuonTriggerHist->GetXaxis(); + sfMuonTriggerHist_yaxis = sfMuonTriggerHist->GetYaxis(); + } + if(sfMuonIdDir_ == "") std::cout<<"no muon id scalefactor histogram, proceed without muon id scalefactor"<FindBin(std::abs(leadingMuon_eta)); + int biny = sfMuonTriggerHist_yaxis->FindBin(leadingMuon_pt); + if(leadingMuon_pt > 500.) //dont take overflow bin, but the last one + biny -= 1; + muonTriggerSf = sfMuonTriggerHist->GetBinContent(binx, biny); + } + // Muon ID double muonIdSf = 1.; if(sfMuonIdDir_ != ""){ @@ -180,7 +203,7 @@ void ntuple_eventInfo::readEvent(const edm::Event& iEvent){ } - event_weight_ = lheWeight * pupWeight * muonIdSf * muonIsoSf * muonTrackingSf * elIdAndIsoSf; + event_weight_ = lheWeight * pupWeight * muonTriggerSf * muonIdSf * muonIsoSf * muonTrackingSf * elIdAndIsoSf; } else{ event_weight_ = 1.; From 8a38c07d47bd5f0b4b19170e38b8b506ecae8e67 Mon Sep 17 00:00:00 2001 From: David Walter Date: Thu, 17 May 2018 09:46:56 +0200 Subject: [PATCH 13/17] new workflow for eventweights, bug fixes and small changes --- DeepNtuplizer/interface/ntuple_JetInfo.h | 3 +- DeepNtuplizer/interface/ntuple_eventInfo.h | 63 ++-- DeepNtuplizer/interface/sorting_modules.h | 17 +- .../{plot_event.py => plot_event_ttdilep.py} | 222 +++++++++----- DeepNtuplizer/plugins/DeepNtuplizer.cc | 20 +- DeepNtuplizer/plugins/globalInfo.cc | 10 +- .../production/DeepNtuplizer_tt_dilep.py | 78 +++-- .../production/DeepNtuplizer_tt_semilep.py | 59 ++-- DeepNtuplizer/python/DeepNtuplizer_cfi.py | 32 ++- DeepNtuplizer/python/QGLikelihood_cfi.py | 1 + DeepNtuplizer/src/ntuple_JetInfo.cc | 22 +- DeepNtuplizer/src/ntuple_eventInfo.cc | 272 ++++++++++-------- DeepNtuplizer/src/ntuple_pfCands.cc | 22 +- 13 files changed, 521 insertions(+), 300 deletions(-) rename DeepNtuplizer/plots/{plot_event.py => plot_event_ttdilep.py} (75%) diff --git a/DeepNtuplizer/interface/ntuple_JetInfo.h b/DeepNtuplizer/interface/ntuple_JetInfo.h index 215bc148bb1..efc9ed40027 100644 --- a/DeepNtuplizer/interface/ntuple_JetInfo.h +++ b/DeepNtuplizer/interface/ntuple_JetInfo.h @@ -23,7 +23,7 @@ class ntuple_JetInfo: public ntuple_content{ useherwcompat_matching_(false), isherwig_(false), isData_(false) -{} + {} void getInput(const edm::ParameterSet& iConfig); void initBranches(TTree* ); @@ -132,6 +132,7 @@ class ntuple_JetInfo: public ntuple_content{ bool useherwcompat_matching_; bool isherwig_; bool isData_; + bool removeUndefined_; /////////branches diff --git a/DeepNtuplizer/interface/ntuple_eventInfo.h b/DeepNtuplizer/interface/ntuple_eventInfo.h index 9fae4dd1ece..bb84b1eb1c6 100644 --- a/DeepNtuplizer/interface/ntuple_eventInfo.h +++ b/DeepNtuplizer/interface/ntuple_eventInfo.h @@ -23,6 +23,11 @@ #include "SimDataFormats/GeneratorProducts/interface/LHEEventProduct.h" void readHistoFromGraph(TGraphAsymmErrors* graph, TH1D** h, TString name); +void initializeScalefactor(std::vector dirs, std::vector names, std::vector* sfHists, std::vector periods); +void initializeScalefactor(std::vector dirs, std::vector names, std::vector* sfHists, std::vector periods); +double getScalefactor(double x, double y, std::vector hists, unsigned int period); +double getScalefactor(double x, std::vector hists, unsigned int period); + /* * For MC weights such as pileup, lhe, ... later: lepton scalefactors @@ -66,35 +71,38 @@ class ntuple_eventInfo: public ntuple_content{ bool isData_; bool useLHEWeights_; + std::vector lumis; + std::vector periods; + std::string pupDataDir_; std::string pupMCDir_; - std::string sfMuonTriggerDir_; - std::string sfMuonTriggerName_; - std::string sfMuonIdDir_; - std::string sfMuonIdName_; - std::string sfMuonIsoDir_; - std::string sfMuonIsoName_; - std::string sfMuonTrackingDir_; - std::string sfMuonTrackingName_; - std::string sfElIdAndIsoDir_; - std::string sfElIdAndIsoName_; - - TH2F *sfMuonTriggerHist; - TH2F *sfMuonIdHist; - TH2F *sfMuonIsoHist; - TH2F *sfElIdAndIsoHist; - TGraphAsymmErrors* sfMuonTrackingTGraph; - TH1D *sfMuonTrackingHist; - - TAxis *sfMuonTriggerHist_xaxis; - TAxis *sfMuonTriggerHist_yaxis; - TAxis *sfMuonIdHist_xaxis; - TAxis *sfMuonIdHist_yaxis; - TAxis *sfMuonIsoHist_xaxis; - TAxis *sfMuonIsoHist_yaxis; - TAxis *sfElIdAndIsoHist_xaxis; - TAxis *sfElIdAndIsoHist_yaxis; - TAxis *sfMuonTrackingHist_axis; + + //std::string sfTrigger_mu_BCDEF_Dir_; + //std::string sfTrigger_mu_BCDEF_Name_; + //std::string sfTrigger_mu_GH_Dir_; + //std::string sfTrigger_mu_GH_Name_; + + std::vector sfTrigger_mu_Dir_; + std::vector sfTrigger_mu_Name_; + std::vector sfTrigger_emu_Dir_; + std::vector sfTrigger_emu_Name_; + std::vector sfMuonId_Dir_; + std::vector sfMuonId_Name_; + std::vector sfMuonIso_Dir_; + std::vector sfMuonIso_Name_; + std::vector sfElIdAndIso_Dir_; + std::vector sfElIdAndIso_Name_; + std::vector sfMuonTracking_Dir_; + std::vector sfMuonTracking_Name_; + + std::vector sfTrigger_mu_Hist; + std::vector sfTrigger_emu_Hist; + std::vector sfMuonId_Hist; + std::vector sfMuonIso_Hist; + std::vector sfElIdAndIso_Hist; + + std::vector sfMuonTracking_Hist; + // global variables @@ -105,6 +113,7 @@ class ntuple_eventInfo: public ntuple_content{ float event_weight_; + }; diff --git a/DeepNtuplizer/interface/sorting_modules.h b/DeepNtuplizer/interface/sorting_modules.h index dbd16082401..cb0fb3fc719 100644 --- a/DeepNtuplizer/interface/sorting_modules.h +++ b/DeepNtuplizer/interface/sorting_modules.h @@ -100,10 +100,23 @@ class sortingClass{ } static bool compareByABCInv(const sortingClass& a, const sortingClass& b){ - return !compareByABC(a,b); + + compareResult tmpres=compare(a,b,0); + if(tmpres==cmp_smaller) return false; + if(tmpres==cmp_greater) return true; + + tmpres=compare(a,b,1); + if(tmpres==cmp_smaller) return false; + if(tmpres==cmp_greater) return true; + + tmpres=compare(a,b,2); + if(tmpres==cmp_smaller) return false; + if(tmpres==cmp_greater) return true; + + return false; } - //private: + //private: float sortValA,sortValB,sortValC; diff --git a/DeepNtuplizer/plots/plot_event.py b/DeepNtuplizer/plots/plot_event_ttdilep.py similarity index 75% rename from DeepNtuplizer/plots/plot_event.py rename to DeepNtuplizer/plots/plot_event_ttdilep.py index 10dacf5297f..9f203f51a89 100644 --- a/DeepNtuplizer/plots/plot_event.py +++ b/DeepNtuplizer/plots/plot_event_ttdilep.py @@ -1,6 +1,6 @@ import pdb -from ROOT import TH1F, TFile, TCanvas, gROOT, gStyle, THStack, TLegend, TGaxis, gPad +from ROOT import TH1F, TFile, TCanvas, gROOT, gStyle, THStack, TLegend, TGaxis, gPad, TPad, TGraph, TLine import numpy as np import os from array import array @@ -11,6 +11,10 @@ gROOT.SetStyle('Plain') # white background gStyle.SetFillStyle(0) TGaxis.SetMaxDigits(4) # Force scientific notation for numbers with more than 4 digits +#gStyle.SetBorderSize(0) +#gStyle.SetTextFont(43) +#gStyle.SetTextSize(14) + class pileupweight: """ DOC """ @@ -47,16 +51,17 @@ def __init__(self,hist): self.scalefactor = 1. self.maxBinX = self.xaxis.GetLast() self.maxBinY = self.yaxis.GetLast() - self.minPt = self.xaxis.GetXmin() - self.maxPt = self.xaxis.GetXmax() - self.minEta = self.yaxis.GetXmin() - self.maxEta = self.yaxis.GetXmax() + self.minX = self.xaxis.GetXmin() + self.maxX = self.xaxis.GetXmax() + self.minY = self.yaxis.GetXmin() + self.maxY = self.yaxis.GetXmax() - def getScalefactor(self,abseta,pt): + def getScalefactor(self,x,y): - self.binx = self.xaxis.FindBin(abseta) - self.biny = self.yaxis.FindBin(pt) - if pt >= self.maxPt: self.biny = self.maxBinY + self.binx = self.xaxis.FindBin(x) + self.biny = self.yaxis.FindBin(y) + if x >= self.maxX: self.binx = self.maxBinX + if y >= self.maxY: self.biny = self.maxBinY self.scalefactor = self.hist.GetBinContent(self.binx, self.biny) return self.scalefactor @@ -109,31 +114,40 @@ class process: TFile(datadir + "MyDataPileupHist.root") ) # muon scalefactor hists from https://twiki.cern.ch/twiki/bin/viewauth/CMS/MuonWorkInProgressAndPagResults + file_sf_emu_trigger = TFile(datadir + "triggerSummary_emu_ReReco2016_ttH.root") file_sf_muon_id_GH = TFile(datadir + "EfficienciesAndSF_ID_GH.root") file_sf_muon_iso_GH = TFile(datadir + "EfficienciesAndSF_ISO_GH.root") file_sf_muon_tracking = TFile(datadir + "Tracking_EfficienciesAndSF_BCDEFGH.root") + # electron scalefactor hists from https://twiki.cern.ch/twiki/bin/view/CMS/EgammaIDRecipesRun2 # -> Electron cut-based 80XID WPs. Scale factors for 80X -> Tight cut-based ID WP scale factor (root file) # id and iso is combined in one file, there is no tracking for the electron file_sf_el_id = TFile(datadir + "egammaEffi.txt_EGM2D.root" ) + h_sf_emu_trigger = file_sf_emu_trigger.Get("scalefactor_eta2d_with_syst") h_sf_muon_id_GH = file_sf_muon_id_GH.Get("MC_NUM_TightID_DEN_genTracks_PAR_pt_eta/abseta_pt_ratio") h_sf_muon_iso_GH = file_sf_muon_iso_GH.Get("TightISO_TightID_pt_eta/abseta_pt_ratio") g_sf_muon_tracking = file_sf_muon_tracking.Get("ratio_eff_aeta_dr030e030_corr") h_sf_el_id = file_sf_el_id.Get("EGamma_SF2D") + sf_emu_trigger = scaleFactor(h_sf_emu_trigger) sf_muon_id = scaleFactor(h_sf_muon_id_GH) sf_muon_iso = scaleFactor(h_sf_muon_iso_GH) sf_muon_tracking = scaleFactor_tracking(g_sf_muon_tracking,"sf_muon_tracking") sf_el_id = scaleFactor(h_sf_el_id) - muonhandle = Handle('edm::OwnVector >') - muonlabel = ("GoodMuon") - electronhandle = Handle('edm::OwnVector >') - electronlabel = ("GoodElectron") + muonhandle = Handle("vector") +#muonhandle = Handle('edm::OwnVector >') + muonlabel = ("goodMuons") +#muonlabel = ("GoodMuon") + electronhandle = Handle("vector") +#electronhandle = Handle('edm::OwnVector >') + electronlabel = ("goodElectrons") +#electronlabel = ("GoodElectron") jethandle = Handle('vector') - jetlabel = ("GoodJets") + jetlabel = ('slimmedJets') +#jetlabel = ("GoodJets") ### LHE weights LHEweighthandle = Handle('LHEEventProduct') LHEweightlabel = ("externalLHEProducer") @@ -153,6 +167,9 @@ class process: collection = [] hists_data = None + tsize = 20 + tfont = 43 + def __init__(self, name, isData=False, color=1): self.name = name self.isData = isData @@ -176,12 +193,7 @@ def __init__(self, name, isData=False, color=1): hist.SetFillColor(color) else: process.hists_data = self - for hist in self.hists: - hist.SetTitle("") - # hist.SetTitleSize(0.05, "xyz") - hist.SetTitleFont(42, "t") - hist.SetTitleFont(42, "xyz") - hist.SetLabelFont(42, "xyz") + self.h_ll_pt.SetXTitle("leading lept. p_{T} (GeV)") self.h_ll_eta.SetXTitle("leading lept. eta") self.h_tl_pt.SetXTitle("trailing lept. p_{T} (GeV)") @@ -195,6 +207,8 @@ def __init__(self, name, isData=False, color=1): self.h_tl_eta.SetYTitle("Events/0.25") self.h_njets.SetYTitle("Events") + self.h_njets.GetXaxis().SetNdivisions(10,0,0) + def fillHists(self, infile, islist=True, useLHEWeights=False, isData=False, eventIDs=[]): print("start to fill hist: " + str(datetime.datetime.now())) nevents = 0 @@ -286,6 +300,7 @@ def fillHists(self, infile, islist=True, useLHEWeights=False, isData=False, even if (pupInfo.getBunchCrossing() == 0): weight *= process.pupw.getPileupWeight(int(pupInfo.getTrueNumInteractions())) + weight *= process.sf_emu_trigger.getScalefactor(abs(leadingElEta),abs(leadingMuonEta)) weight *= process.sf_muon_id.getScalefactor(abs(leadingMuonEta), leadingMuonPt) weight *= process.sf_muon_iso.getScalefactor(abs(leadingMuonEta), leadingMuonPt) weight *= process.sf_muon_tracking.getScalefactor(abs(leadingMuonEta)) @@ -335,14 +350,18 @@ def save_hists(self): def load_hists(self): print "load " + self.name - f1 = TFile(self.name + ".root", "READ") - self.h_ll_pt.Add(f1.Get(self.name + "_ll_pt")) - self.h_ll_eta.Add(f1.Get(self.name + "_ll_eta")) - self.h_tl_pt.Add(f1.Get(self.name + "_tl_pt")) - self.h_tl_eta.Add(f1.Get(self.name + "_tl_eta")) - self.h_njets.Add(f1.Get(self.name + "_njets")) - f1.Close() + if(os.path.isfile(self.name + ".root")): + f1 = TFile(self.name + ".root", "READ") + self.h_ll_pt.Add(f1.Get(self.name + "_ll_pt")) + self.h_ll_eta.Add(f1.Get(self.name + "_ll_eta")) + self.h_tl_pt.Add(f1.Get(self.name + "_tl_pt")) + self.h_tl_eta.Add(f1.Get(self.name + "_tl_eta")) + self.h_njets.Add(f1.Get(self.name + "_njets")) + + f1.Close() + else: + print("no file for this process") def draw_hists(self): canvas = TCanvas(self.name, "", 800, 600) @@ -363,7 +382,6 @@ def setMinMax(self, y_min_ll_pt, y_max_ll_pt, y_min_ll_eta, y_max_ll_eta, y_min_ self.hists[4].SetMinimum(y_min_njets) self.hists[4].SetMaximum(y_max_njets) - @classmethod def make_stacks(cls): for proc in cls.collection: @@ -377,50 +395,111 @@ def print_stacks(cls): leg = TLegend(0.59, 0.54, 0.89, 0.84) leg.SetBorderSize(0) - leg.SetTextFont(42) - leg.AddEntry(cls.hists_data.hists[0], "data", "lep") + leg.SetTextFont(cls.tfont) + leg.AddEntry(cls.hists_data.hists[0], "data", "ep") leg.AddEntry(cls.collection[8].hists[0], "t#bar{t}", "f") - leg.AddEntry(cls.collection[0].hists[0], "DY", "f") - leg.AddEntry(cls.collection[2].hists[0], "VV", "f") leg.AddEntry(cls.collection[6].hists[0], "Wt/W#bar{t}", "f") leg.AddEntry(cls.collection[5].hists[0], "W+Jets", "f") + leg.AddEntry(cls.collection[2].hists[0], "VV", "f") + leg.AddEntry(cls.collection[0].hists[0], "DY", "f") leg21 = TLegend(0.19, 0.69, 0.39, 0.84) leg21.SetBorderSize(0) - leg21.SetTextFont(42) - leg21.AddEntry(cls.hists_data.hists[0], "data", "lep") + leg21.SetTextFont(cls.tfont) + leg21.AddEntry(cls.hists_data.hists[0], "data", "ep") leg21.AddEntry(cls.collection[8].hists[0], "t#bar{t}", "f") - leg21.AddEntry(cls.collection[0].hists[0], "DY", "f") + leg21.AddEntry(cls.collection[6].hists[0], "Wt/W#bar{t}", "f") leg22 = TLegend(0.69, 0.69, 0.89, 0.84) leg22.SetBorderSize(0) - leg22.SetTextFont(42) - leg22.AddEntry(cls.collection[2].hists[0], "VV", "f") - leg22.AddEntry(cls.collection[6].hists[0], "Wt/W#bar{t}", "f") + leg22.SetTextFont(cls.tfont) leg22.AddEntry(cls.collection[5].hists[0], "W+Jets", "f") + leg22.AddEntry(cls.collection[2].hists[0], "VV", "f") + leg22.AddEntry(cls.collection[0].hists[0], "DY", "f") leg.SetFillStyle(0) # make transparent leg21.SetFillStyle(0) leg22.SetFillStyle(0) - canvas = TCanvas("final", "title", 800, 600) - for i in (0, 2, 4): - canvas.Clear() - cls.hists_data.hists[i].Draw("PE") + canvas = TCanvas("c1","Example 2 pads (20,80)",200,10,800,600) + #canvas.SetBottomMargin(0.25) + pad1 = TPad("pad1", "The pad 80% of the height", 0, 0.2, 1, 1.0) + pad2 = TPad("pad2", "The pad 20% of the height", 0, 0.05, 1, 0.2) + + pad1.SetLeftMargin(0.15) + pad1.SetRightMargin(0.1) + pad2.SetLeftMargin(0.15) + pad2.SetRightMargin(0.1) + + pad1.SetBottomMargin(0.02) + pad2.SetTopMargin(0.02) + pad2.SetBottomMargin(0.25) + + pad1.Draw() + pad2.Draw() + for i, h_data in enumerate(cls.hists_data.hists): + + h_data.SetTitle("") + h_data.GetXaxis().SetLabelFont(cls.tfont) + h_data.GetXaxis().SetLabelSize(0) + h_data.GetXaxis().SetTitleSize(0) + h_data.GetYaxis().SetLabelFont(cls.tfont) + h_data.GetYaxis().SetLabelSize(cls.tsize) + h_data.GetYaxis().SetTitleFont(cls.tfont) + h_data.GetYaxis().SetTitleSize(cls.tsize) + h_data.GetYaxis().SetTitleOffset(1.5) + + h_data.SetMarkerStyle(20) + #pad1.Clear() + #pad2.Clear() + pad1.cd() + + h_data.Draw("E1") cls.hs_list[i].Draw("HIST same") - cls.hists_data.hists[i].Draw("PE same") + h_data.Draw("E1 same") gPad.RedrawAxis() # draw axis in foreground - leg.Draw("same") - canvas.Print("stacks_" + str(i) + ".png") - for i in (1, 3): - canvas.Clear() - cls.hists_data.hists[i].Draw("PE") - cls.hs_list[i].Draw("HIST same") - cls.hists_data.hists[i].Draw("PE same") - gPad.RedrawAxis() # draw axis in foreground - leg21.Draw("same") - leg22.Draw("same") + if i%2 == 0: + leg.Draw("same") + else: + leg21.Draw("same") + leg22.Draw("same") + + pad2.cd() + h_ratio = TH1F(cls.hs_list[i].GetStack().Last()) + + h_ratio.SetTitle("") + h_ratio.GetXaxis().SetLabelFont(cls.tfont) + h_ratio.GetXaxis().SetLabelSize(cls.tsize) + h_ratio.GetYaxis().SetLabelFont(cls.tfont) + h_ratio.GetYaxis().SetLabelSize(cls.tsize) + h_ratio.GetXaxis().SetTitleFont(cls.tfont) + h_ratio.GetXaxis().SetTitleSize(cls.tsize) + h_ratio.GetYaxis().SetTitleFont(cls.tfont) + h_ratio.GetYaxis().SetTitleSize(cls.tsize) + h_ratio.GetXaxis().SetTitleOffset(7.) + h_ratio.GetYaxis().SetTitleOffset(1.5) + h_ratio.GetYaxis().SetNdivisions(403) + h_ratio.GetXaxis().SetTickLength(0.15) + + if i ==4: + h_ratio.GetXaxis().SetNdivisions(10, 0, 0) + + h_ratio.SetMarkerStyle(20) + h_ratio.SetXTitle(h_data.GetXaxis().GetTitle()) + + h_ratio.Divide(h_data) + h_ratio.GetYaxis().SetTitle("mc/data") + + h_ratio.SetMinimum(0.75) + h_ratio.SetMaximum(1.25) + + + middleLine = TLine(h_ratio.GetXaxis().GetXmin(),1. ,h_ratio.GetXaxis().GetXmax(), 1.) + + h_ratio.Draw("e1") + middleLine.Draw("same") + gStyle.SetErrorX(0.) canvas.Print("stacks_" + str(i) + ".png") @@ -437,20 +516,20 @@ def print_stacks(cls): data = process("data",isData=True) -# dy10to50.fillHists("dy10to50.txt",useLHEWeights=True) -# dy50.fillHists("dy50.txt",useLHEWeights=True) -# ww.fillHists("ww.txt") -# wz.fillHists("wz.txt") -# zz.fillHists("zz.txt") -# wjets.fillHists("wjets.txt",useLHEWeights=True) -# wt.fillHists("wt.txt") -# wantit.fillHists("wantit.txt") -# tt.fillHists("tt.txt") -# data.fillHists("data.txt",isData=True) +dy10to50.fillHists("dy10to50.txt",useLHEWeights=True) +dy50.fillHists("dy50.txt",useLHEWeights=True) +ww.fillHists("ww.txt") +wz.fillHists("wz.txt") +zz.fillHists("zz.txt") +wjets.fillHists("wjets.txt",useLHEWeights=True) +#wt.fillHists("wt.txt") +wantit.fillHists("wantit.txt") +tt.fillHists("tt.txt") +data.fillHists("data.txt",isData=True) -for ip in process.collection: - ip.load_hists() -process.hists_data.load_hists() +#for ip in process.collection: +# ip.load_hists() +#process.hists_data.load_hists() lumi_total = 35.9 lumi_data = 8.746 @@ -468,17 +547,18 @@ def print_stacks(cls): # Efficiency = 1/(number of events before cuts), in case of lheweights its the # effective number of events (in this case: number of events with positive weights - number of events with negative weights) eff_tt = 1./(77081156 + 77867738) +#eff_tt = 1./(77013872) eff_dy50 = 1./81781052 # effective number of events -#eff_dy50 = 1./122055388 # true number of events +#eff_dy50 = 1./122055388 # true number of events eff_dy10to50 = 1./47946519 # effective number of events -#eff_dy10to50 = 1./65888233 # true number of events +#eff_dy10to50 = 1./65888233 # true number of events eff_ww = 1./994012 eff_wz = 1./1000000 eff_zz = 1./998034 eff_wantit = 1./6933094 eff_wt = 1./6952830 eff_wjets = 1./16497031 # effective number of events -#eff_wjets = 1./24120319 # true number of events +#eff_wjets = 1./24120319 # true number of events data.scale_hists( lumi=lumi_total/lumi_data) tt.scale_hists(sigma = sigma_tt, lumi = lumi_total, eff = eff_tt) @@ -491,8 +571,8 @@ def print_stacks(cls): wt.scale_hists(sigma = sigma_wt, lumi = lumi_total, eff = eff_wt) wjets.scale_hists(sigma = sigma_wjets, lumi = lumi_total, eff = eff_wjets) -data.setMinMax(0,8000,0,160000,0,18500,0,150000,0,140000) -title='180227' +data.setMinMax(0,20000,0,300000,0,18500,0,150000,0,140000) +title='180327' directory = os.path.dirname('./plots_'+title+'/') # make a canvas, draw, and save it diff --git a/DeepNtuplizer/plugins/DeepNtuplizer.cc b/DeepNtuplizer/plugins/DeepNtuplizer.cc index 11445356166..2a4f2da193e 100644 --- a/DeepNtuplizer/plugins/DeepNtuplizer.cc +++ b/DeepNtuplizer/plugins/DeepNtuplizer.cc @@ -139,6 +139,7 @@ DeepNtuplizer::DeepNtuplizer(const edm::ParameterSet& iConfig): ntuple_SV* svmodule=new ntuple_SV("", jetR); addModule(svmodule); + //Loose IVF vertices //ntuple_SV* svmodule_LooseIVF=new ntuple_SV("LooseIVF_", jetR); //svmodule_LooseIVF->setSVToken( @@ -190,16 +191,18 @@ DeepNtuplizer::DeepNtuplizer(const edm::ParameterSet& iConfig): addModule(pfcands); - addModule(new ntuple_bTagVars()); - - ntuple_eventInfo *evweight = new ntuple_eventInfo(); + ntuple_bTagVars * btagvars = new ntuple_bTagVars(); + addModule(btagvars); if(!isData){ + ntuple_eventInfo *evweight = new ntuple_eventInfo(); + evweight->setLHEToken(consumes(iConfig.getParameter("lheInfo"))); evweight->setMuonsToken(consumes >(iConfig.getParameter("sfMuons"))); evweight->setElectronsToken(consumes >(iConfig.getParameter("sfElectrons"))); + + addModule(evweight); } - addModule(evweight); if(runFatJets_){ auto *fatjetinfo = new ntuple_FatJetInfo(jetR); @@ -213,9 +216,9 @@ DeepNtuplizer::DeepNtuplizer(const edm::ParameterSet& iConfig): * * parse the input parameters (if any) */ - for(auto& m: modules_) + for(auto& m: modules_){ m->getInput(iConfig); - + } } @@ -231,7 +234,6 @@ DeepNtuplizer::~DeepNtuplizer() void DeepNtuplizer::analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) { - //global info edm::Handle vertices; @@ -270,13 +272,16 @@ DeepNtuplizer::analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) edm::View::const_iterator jetIter; // loop over the jets + //for (edm::View::const_iterator jetIter = jets->begin(); jetIter != jets->end(); ++jetIter) { for(size_t j=0;jbegin()+jetidx; const pat::Jet& jet = *jetIter; + if(jet.genJet()) njetswithgenjet_++; @@ -292,6 +297,7 @@ DeepNtuplizer::analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) njetsselected_++; } } // end of looping over the jets + } diff --git a/DeepNtuplizer/plugins/globalInfo.cc b/DeepNtuplizer/plugins/globalInfo.cc index 525b9d53eb3..1572d72fe98 100644 --- a/DeepNtuplizer/plugins/globalInfo.cc +++ b/DeepNtuplizer/plugins/globalInfo.cc @@ -76,10 +76,12 @@ class globalInfo : public edm::one::EDAnalyzer { // // constructors and destructor // -globalInfo::globalInfo(const edm::ParameterSet& iConfig): - t_LHEInfo(consumes (iConfig.getParameter("lheInfo"))) - { +globalInfo::globalInfo(const edm::ParameterSet& iConfig){ + useLHEWeights_ = (iConfig.getParameter("useLHEWeights")); + if(useLHEWeights_){ + t_LHEInfo = consumes (iConfig.getParameter("lheInfo")); + } } @@ -123,7 +125,7 @@ globalInfo::beginJob() void globalInfo::endJob() { - nEffEvents_ = nEvents_ - nNegLHEEvents_; + nEffEvents_ = nEvents_ - 2 * nNegLHEEvents_; std::cout<<"total number of initial events is: "<30 && abs(eta) < 2.4 && neutralHadronEnergyFraction < 0.99 " "&& neutralEmEnergyFraction < 0.99 && (chargedMultiplicity+neutralMultiplicity) > 1 " @@ -265,7 +278,7 @@ process, labelName="DeepFlavour", # jetSource=cms.InputTag('slimmedJetsAK8PFPuppiSoftDropPacked', 'SubJets'), # 'subjets from AK8' - jetSource=cms.InputTag('GoodJets'), # 'ak4Jets' + jetSource=cms.InputTag('goodJets'), # 'ak4Jets' jetCorrections=('AK4PFchs', jetCorrections, 'None'), pfCandidates=cms.InputTag('packedPFCandidates'), pvSource=cms.InputTag("offlineSlimmedPrimaryVertices"), @@ -355,8 +368,8 @@ process.looseIVFcandidateVertexArbitrator.secondaryVertices = cms.InputTag("looseIVFcandidateVertexMerger") process.looseIVFcandidateVertexArbitrator.fitterSigmacut = 20 -#datapath=os.environ['CMSSW_BASE']+'/src/DeepNTuples/DeepNtuplizer/data/' -datapath='' +datapath=os.environ['CMSSW_BASE']+'/src/DeepNTuples/DeepNtuplizer/data/' +#datapath='' # DeepNtuplizer configurations process.load("DeepNTuples.DeepNtuplizer.DeepNtuplizer_cfi") @@ -364,9 +377,9 @@ process.deepntuplizer.bDiscriminators = bTagDiscriminators process.deepntuplizer.bDiscriminators.append('pfCombinedMVAV2BJetTags') process.deepntuplizer.LooseSVs = cms.InputTag("looseIVFinclusiveCandidateSecondaryVertices") - process.deepntuplizer.applySelection = cms.bool(options.selectJets) +process.deepntuplizer.removeUndefined = cms.bool(False) process.deepntuplizer.isData = cms.bool(options.isData) process.deepntuplizer.useLHEWeights = cms.bool(options.lheWeights) @@ -376,14 +389,31 @@ process.deepntuplizer.sfMuons = cms.InputTag("goodMuons") process.deepntuplizer.sfElectrons=cms.InputTag("goodElectrons") -process.deepntuplizer.sfMuonId = cms.string(datapath+"EfficienciesAndSF_ID_GH.root") -process.deepntuplizer.sfMuonIdHist = cms.string("MC_NUM_TightID_DEN_genTracks_PAR_pt_eta/abseta_pt_ratio") -process.deepntuplizer.sfMuonIso=cms.string(datapath+"EfficienciesAndSF_ISO_GH.root") -process.deepntuplizer.sfMuonIsoHist=cms.string("TightISO_TightID_pt_eta/abseta_pt_ratio") -process.deepntuplizer.sfMuonTracking=cms.string(datapath+"Tracking_EfficienciesAndSF_BCDEFGH.root") -process.deepntuplizer.sfMuonTrackingHist=cms.string("ratio_eff_aeta_dr030e030_corr") -process.deepntuplizer.sfElIdAndIso=cms.string(datapath+"egammaEffi.txt_EGM2D.root") -process.deepntuplizer.sfElIdAndIsoHist=cms.string("EGamma_SF2D") +process.deepntuplizer.periods=cms.vstring("2016BtoF","2016G","2016H") +process.deepntuplizer.lumis=cms.vdouble(5.404+2.396+4.243+4.054+3.105,7.544,8.453) + +#emu trigger scalefactors from +# https://gitlab.cern.ch/ttH/reference/blob/955cff0b09f2c95bc480ae0bf3145aab9ce08fcc/definitions/Moriond17.md#64-trigger-scale-factors +# https://gitlab.cern.ch/ttH/reference/blob/955cff0b09f2c95bc480ae0bf3145aab9ce08fcc/definitions/Moriond17.md#41-triggers +process.deepntuplizer.sfTrigger_emu=cms.vstring(datapath + "triggerSummary_emu_ReReco2016_ttH.root") +process.deepntuplizer.sfTrigger_emu_Hist = cms.vstring("scalefactor_eta2d_with_syst") + +process.deepntuplizer.sfMuonId = cms.vstring(datapath+"EfficienciesAndSF_ID_BCDEF.root", + datapath + "EfficienciesAndSF_ID_GH.root", + datapath + "EfficienciesAndSF_ID_GH.root") +process.deepntuplizer.sfMuonId_Hist = cms.vstring("MC_NUM_TightID_DEN_genTracks_PAR_pt_eta/abseta_pt_ratio", + "MC_NUM_TightID_DEN_genTracks_PAR_pt_eta/abseta_pt_ratio", + "MC_NUM_TightID_DEN_genTracks_PAR_pt_eta/abseta_pt_ratio") +process.deepntuplizer.sfMuonIso=cms.vstring(datapath + "EfficienciesAndSF_ISO_BCDEF.root", + datapath + "EfficienciesAndSF_ISO_GH.root", + datapath + "EfficienciesAndSF_ISO_GH.root") +process.deepntuplizer.sfMuonIso_Hist=cms.vstring("TightISO_TightID_pt_eta/abseta_pt_ratio", + "TightISO_TightID_pt_eta/abseta_pt_ratio", + "TightISO_TightID_pt_eta/abseta_pt_ratio") +process.deepntuplizer.sfMuonTracking=cms.vstring(datapath+"Tracking_EfficienciesAndSF_BCDEFGH.root") +process.deepntuplizer.sfMuonTracking_Hist=cms.vstring("ratio_eff_aeta_dr030e030_corr") +process.deepntuplizer.sfElIdAndIso=cms.vstring(datapath+"egammaEffi.txt_EGM2D.root") +process.deepntuplizer.sfElIdAndIso_Hist=cms.vstring("EGamma_SF2D") if int(release.replace("_", "")) >= 840: diff --git a/DeepNtuplizer/production/DeepNtuplizer_tt_semilep.py b/DeepNtuplizer/production/DeepNtuplizer_tt_semilep.py index b11dbd9f115..0c458e9811f 100644 --- a/DeepNtuplizer/production/DeepNtuplizer_tt_semilep.py +++ b/DeepNtuplizer/production/DeepNtuplizer_tt_semilep.py @@ -22,8 +22,6 @@ options.register('deepNtuplizer',True, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.bool, "run deepNtuplizer or just the ttbar selection") options.register('lheWeights',False, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.bool, "use LHE weights") - - import os release = os.environ['CMSSW_VERSION'][6:12] @@ -57,6 +55,9 @@ process.GlobalTag.globaltag = options.globalTag process.maxEvents = cms.untracked.PSet(input=cms.untracked.int32(-1)) +#process.PoolSource = cms.untracked.PSet( +# firstEvent = cms.untracked.uint32(33285817), +#) process.load('FWCore.MessageService.MessageLogger_cfi') process.MessageLogger.cerr.FwkReport.reportEvery = 10 @@ -85,8 +86,9 @@ #process.source.fileNames=['file:./EE95DEDC-96BE-E611-B45D-A0000420FE80.root'] #isData=False process.source.fileNames=['file:./0693E0E7-97BE-E611-B32F-0CC47A78A3D8.root'] #store/mc/RunIISummer16MiniAODv2/TT_TuneCUETP8M2T4_13TeV-powheg-pythia8/MINIAODSIM/PUMoriond17_80X_mcRun2_asymptotic_2016_TrancheIV_v6-v1/50000/ #process.source.fileNames=['file:./00E02A09-853C-E711-93FF-3417EBE644A7.root'] #store/data/Run2016H/SingleMuon/MINIAOD/18Apr2017-v1/00000/ +#process.source.fileNames=['file:./F21AE451-7EBA-E611-9399-0025905B858E.root'] #store/mc/RunIISummer16MiniAODv2/TT_TuneCUETP8M2T4_13TeV-powheg-pythia8/MINIAODSIM/PUMoriond17_backup_80X_mcRun2_asymptotic_2016_TrancheIV_v6-v1/00000/ - +#process.source.fileNames=['file:./00CC509E-0C3B-E711-98F2-0242AC130004.root'] #Run2016B/SingleMuon/MINIAOD/18Apr2017_ver2-v1/ numberOfFiles = len(process.source.fileNames) numberOfJobs = options.nJobs jobNumber = options.job @@ -146,7 +148,7 @@ ] ###### semilep selection -outFileName = options.outputFile + '_ntuples_180417_' + str(options.job) + '.root' +outFileName = options.outputFile + '_' + str(options.job) + '.root' print ('Using output file ' + outFileName) if options.deepNtuplizer: @@ -361,19 +363,40 @@ process.deepntuplizer.bDiscriminators.append('pfCombinedMVAV2BJetTags') process.deepntuplizer.LooseSVs = cms.InputTag("looseIVFinclusiveCandidateSecondaryVertices") process.deepntuplizer.applySelection = cms.bool(options.selectJets) + +process.deepntuplizer.removeUndefined = cms.bool(False) process.deepntuplizer.isData = cms.bool(options.isData) process.deepntuplizer.useLHEWeights = cms.bool(options.lheWeights) process.deepntuplizer.pileupData=cms.string(datapath+"pileup_data_2016.root") process.deepntuplizer.pileupMC=cms.string(datapath+"pileup_MC_2016.root") + process.deepntuplizer.sfMuons = cms.InputTag("goodMuons") -process.deepntuplizer.sfMuonTrigger=cms.string(datapath + "EfficienciesAndSF_Period4.root") -process.deepntuplizer.sfMuonTriggerHist = cms.string("IsoMu24_OR_IsoTkMu24_PtEtaBins/abseta_pt_ratio") -process.deepntuplizer.sfMuonId = cms.string(datapath+"EfficienciesAndSF_ID_GH.root") -process.deepntuplizer.sfMuonIdHist = cms.string("MC_NUM_TightID_DEN_genTracks_PAR_pt_eta/abseta_pt_ratio") -process.deepntuplizer.sfMuonIso=cms.string(datapath+"EfficienciesAndSF_ISO_GH.root") -process.deepntuplizer.sfMuonIsoHist=cms.string("TightISO_TightID_pt_eta/abseta_pt_ratio") -process.deepntuplizer.sfMuonTracking=cms.string(datapath+"Tracking_EfficienciesAndSF_BCDEFGH.root") -process.deepntuplizer.sfMuonTrackingHist=cms.string("ratio_eff_aeta_dr030e030_corr") + +#process.deepntuplizer.lumi_BCDEF=cms.double(5.404+2.396+4.256+4.054+3.105) +#process.deepntuplizer.lumi_G=cms.double(7.179) +#process.deepntuplizer.lumi_H=cms.double(8.746) +process.deepntuplizer.periods=cms.vstring("2016BtoF","2016GH") +process.deepntuplizer.lumis=cms.vdouble(5.404+2.396+4.256+4.054+3.105, 7.179+8.746) + + + +process.deepntuplizer.sfTrigger_mu=cms.vstring(datapath + "EfficienciesAndSF_RunBtoF.root", + datapath + "EfficienciesAndSF_Period4.root") +process.deepntuplizer.sfTrigger_mu_Hist=cms.vstring("IsoMu24_OR_IsoTkMu24_PtEtaBins/abseta_pt_ratio", + "IsoMu24_OR_IsoTkMu24_PtEtaBins/abseta_pt_ratio") + +process.deepntuplizer.sfMuonId = cms.vstring(datapath+"EfficienciesAndSF_ID_BCDEF.root", + datapath+"EfficienciesAndSF_ID_GH.root") +process.deepntuplizer.sfMuonId_Hist = cms.vstring("MC_NUM_TightID_DEN_genTracks_PAR_pt_eta/abseta_pt_ratio", + "MC_NUM_TightID_DEN_genTracks_PAR_pt_eta/abseta_pt_ratio") + +process.deepntuplizer.sfMuonIso=cms.vstring(datapath+"EfficienciesAndSF_ISO_BCDEF.root", + datapath+"EfficienciesAndSF_ISO_GH.root") +process.deepntuplizer.sfMuonIso_Hist=cms.vstring("TightISO_TightID_pt_eta/abseta_pt_ratio", + "TightISO_TightID_pt_eta/abseta_pt_ratio") + +process.deepntuplizer.sfMuonTracking=cms.vstring(datapath+"Tracking_EfficienciesAndSF_BCDEFGH.root") +process.deepntuplizer.sfMuonTracking_Hist=cms.vstring("ratio_eff_aeta_dr030e030_corr") if int(release.replace("_", "")) >= 840: @@ -382,12 +405,12 @@ process.deepntuplizer.gluonReduction = cms.double(options.gluonReduction) # 1631 -process.ProfilerService = cms.Service( - "ProfilerService", - firstEvent=cms.untracked.int32(1631), - lastEvent=cms.untracked.int32(1641), - paths=cms.untracked.vstring('p') -) +#process.ProfilerService = cms.Service( +# "ProfilerService", +# firstEvent=cms.untracked.int32(1631), +# lastEvent=cms.untracked.int32(1641), +# paths=cms.untracked.vstring('p') +#) if options.deepNtuplizer: diff --git a/DeepNtuplizer/python/DeepNtuplizer_cfi.py b/DeepNtuplizer/python/DeepNtuplizer_cfi.py index 1ed5b87a70a..2b10f5b02af 100644 --- a/DeepNtuplizer/python/DeepNtuplizer_cfi.py +++ b/DeepNtuplizer/python/DeepNtuplizer_cfi.py @@ -36,6 +36,7 @@ useOffsets=cms.bool(True), applySelection=cms.bool(True), + removeUndefined=cms.bool(True), isData=cms.bool(False), useLHEWeights=cms.bool(True), @@ -47,17 +48,26 @@ sfMuons = cms.InputTag("slimmedMuons"), sfElectrons=cms.InputTag("slimmedElectrons"), - # leave an empty string for the root file if you don't want to use a scalefactor - sfMuonTrigger=cms.string(""), - sfMuonTriggerHist = cms.string(""), - sfMuonId = cms.string(""), - sfMuonIdHist = cms.string(""), - sfMuonIso=cms.string(""), - sfMuonIsoHist=cms.string(""), - sfMuonTracking=cms.string(""), - sfMuonTrackingHist=cms.string(""), - sfElIdAndIso=cms.string(""), - sfElIdAndIsoHist=cms.string(""), + periods=cms.vstring(), + lumis=cms.vdouble(), + + # The scalefactors can be computed on different ways: + # - empty vector to not use a specific scalefactor, + # - one string to use the same hist for all periods + # - number of strings equal to number of periods to use a different hist for each period + sfTrigger_mu=cms.vstring(), + sfTrigger_mu_Hist = cms.vstring(), + + sfTrigger_emu=cms.vstring(), + sfTrigger_emu_Hist=cms.vstring(), + sfMuonId = cms.vstring(), + sfMuonId_Hist = cms.vstring(), + sfMuonIso=cms.vstring(), + sfMuonIso_Hist=cms.vstring(), + sfMuonTracking=cms.vstring(), + sfMuonTracking_Hist=cms.vstring(), + sfElIdAndIso=cms.vstring(), + sfElIdAndIso_Hist=cms.vstring(), diff --git a/DeepNtuplizer/python/QGLikelihood_cfi.py b/DeepNtuplizer/python/QGLikelihood_cfi.py index 65caa455bbe..ee7c35c2331 100644 --- a/DeepNtuplizer/python/QGLikelihood_cfi.py +++ b/DeepNtuplizer/python/QGLikelihood_cfi.py @@ -4,6 +4,7 @@ qgDatabaseVersion = 'cmssw8020_v2' databasepath=os.environ['CMSSW_BASE']+'/src/DeepNTuples/DeepNtuplizer/data/QGL_cmssw8020_v2.db' +#databasepath='QGL_cmssw8020_v2.db' from CondCore.CondDB.CondDB_cfi import * QGPoolDBESSource = cms.ESSource("PoolDBESSource", diff --git a/DeepNtuplizer/src/ntuple_JetInfo.cc b/DeepNtuplizer/src/ntuple_JetInfo.cc index 10ed3d60899..dfa4fdb514a 100644 --- a/DeepNtuplizer/src/ntuple_JetInfo.cc +++ b/DeepNtuplizer/src/ntuple_JetInfo.cc @@ -25,6 +25,8 @@ void ntuple_JetInfo::getInput(const edm::ParameterSet& iConfig){ jetAbsEtaMin_=(iConfig.getParameter("jetAbsEtaMin")); jetAbsEtaMax_=(iConfig.getParameter("jetAbsEtaMax")); + removeUndefined_=(iConfig.getParameter("removeUndefined")); + vector disc_names = iConfig.getParameter >("bDiscriminators"); for(auto& name : disc_names) { discriminators_[name] = 0.; @@ -194,9 +196,10 @@ void ntuple_JetInfo::readEvent(const edm::Event& iEvent){ { Bhadron_daughter_.push_back(daughter_); } - // else { + else { // std::cout << "only b daughters " << endl; - // } + Bhadron_daughter_.push_back(gen); + } } else Bhadron_daughter_.push_back(gen); @@ -276,8 +279,6 @@ bool ntuple_JetInfo::fillBranches(const pat::Jet & jet, const size_t& jetidx, co // often we have way to many gluons that we do not need. This randomply reduces the gluons if (gluonReduction_>0 && jet.partonFlavour()==21) if(TRandom_.Uniform()>gluonReduction_) returnval=false; - - if(jet.genJet()==NULL)returnval=false; } @@ -387,16 +388,16 @@ bool ntuple_JetInfo::fillBranches(const pat::Jet & jet, const size_t& jetidx, co } } - if(!jet.genJet()){//for data - isUndefined_=1;isPhysUndefined_=1; + if(!jet.genJet() || jet.genJet()==NULL){ + isUndefined_=1; + isPhysUndefined_=1; + if(removeUndefined_) returnval=false; } if(isData_){ isRealData_=1; } - else{ - if(isUndefined_ && isPhysUndefined_) returnval=false; //skip event, if neither standard flavor definition nor physics definition fallback define a "proper flavor" - } + pat::JetCollection h; jet_pt_ = jet.correctedJet("Uncorrected").pt(); @@ -489,9 +490,6 @@ bool ntuple_JetInfo::fillBranches(const pat::Jet & jet, const size_t& jetidx, co y_axis2_ = std::get<5>(qgtuple); y_pt_dr_log_=std::get<6>(qgtuple); - - - return returnval; } diff --git a/DeepNtuplizer/src/ntuple_eventInfo.cc b/DeepNtuplizer/src/ntuple_eventInfo.cc index 7f32adc3fbd..cae3d9f3778 100644 --- a/DeepNtuplizer/src/ntuple_eventInfo.cc +++ b/DeepNtuplizer/src/ntuple_eventInfo.cc @@ -13,18 +13,27 @@ void ntuple_eventInfo::getInput(const edm::ParameterSet& iConfig){ useLHEWeights_ = (iConfig.getParameter("useLHEWeights")); + periods = (iConfig.getParameter>("periods")); + lumis = (iConfig.getParameter>("lumis")); + pupDataDir_ = (iConfig.getParameter("pileupData")); pupMCDir_ = (iConfig.getParameter("pileupMC")); - sfMuonTriggerDir_ = (iConfig.getParameter("sfMuonTrigger")); - sfMuonTriggerName_ = (iConfig.getParameter("sfMuonTriggerHist")); - sfMuonIdDir_ = (iConfig.getParameter("sfMuonId")); - sfMuonIdName_ = (iConfig.getParameter("sfMuonIdHist")); - sfMuonIsoDir_ = (iConfig.getParameter("sfMuonIso")); - sfMuonIsoName_ = (iConfig.getParameter("sfMuonIsoHist")); - sfMuonTrackingDir_ = (iConfig.getParameter("sfMuonTracking")); - sfMuonTrackingName_ = (iConfig.getParameter("sfMuonTrackingHist")); - sfElIdAndIsoDir_ = (iConfig.getParameter("sfElIdAndIso")); - sfElIdAndIsoName_ = (iConfig.getParameter("sfElIdAndIsoHist")); + + sfTrigger_mu_Dir_ = (iConfig.getParameter>("sfTrigger_mu")); + sfTrigger_mu_Name_ = (iConfig.getParameter>("sfTrigger_mu_Hist")); + + sfTrigger_emu_Dir_ = (iConfig.getParameter>("sfTrigger_emu")); + sfTrigger_emu_Name_ = (iConfig.getParameter>("sfTrigger_emu_Hist")); + sfMuonId_Dir_ = (iConfig.getParameter>("sfMuonId")); + sfMuonId_Name_ = (iConfig.getParameter>("sfMuonId_Hist")); + sfMuonIso_Dir_ = (iConfig.getParameter>("sfMuonIso")); + sfMuonIso_Name_ = (iConfig.getParameter>("sfMuonIso_Hist")); + sfElIdAndIso_Dir_ = (iConfig.getParameter>("sfElIdAndIso")); + sfElIdAndIso_Name_ = (iConfig.getParameter>("sfElIdAndIso_Hist")); + + sfMuonTracking_Dir_ = (iConfig.getParameter>("sfMuonTracking")); + sfMuonTracking_Name_ = (iConfig.getParameter>("sfMuonTracking_Hist")); + if(pupDataDir_=="" || pupMCDir_=="") std::cout<<"no pileup histograms, proceed without pileup reweighting. \n"; @@ -44,69 +53,19 @@ void ntuple_eventInfo::getInput(const edm::ParameterSet& iConfig){ } } - if(sfMuonTriggerDir_ == "") - std::cout<<"no muon trigger scalefactor histogram, proceed without muon trigger scalefactor"<Get(sfMuonTriggerName_.c_str()); - - sfMuonTriggerHist_xaxis = sfMuonTriggerHist->GetXaxis(); - sfMuonTriggerHist_yaxis = sfMuonTriggerHist->GetYaxis(); - } - - if(sfMuonIdDir_ == "") - std::cout<<"no muon id scalefactor histogram, proceed without muon id scalefactor"<Get(sfMuonIdName_.c_str()); - - sfMuonIdHist_xaxis = sfMuonIdHist->GetXaxis(); - sfMuonIdHist_yaxis = sfMuonIdHist->GetYaxis(); - } - - if(sfMuonIsoDir_ == "") - std::cout<<"no muon iso scalefactor histogram, proceed without muon id scalefactor"<Get(sfMuonIsoName_.c_str()); + initializeScalefactor(sfTrigger_mu_Dir_, sfTrigger_mu_Name_, &sfTrigger_mu_Hist, periods); + initializeScalefactor(sfTrigger_emu_Dir_, sfTrigger_emu_Name_, &sfTrigger_emu_Hist, periods); + initializeScalefactor(sfMuonId_Dir_, sfMuonId_Name_, &sfMuonId_Hist, periods); + initializeScalefactor(sfMuonIso_Dir_, sfMuonIso_Name_, &sfMuonIso_Hist, periods); + initializeScalefactor(sfElIdAndIso_Dir_, sfElIdAndIso_Name_, &sfElIdAndIso_Hist, periods); + initializeScalefactor(sfMuonTracking_Dir_, sfMuonTracking_Name_, &sfMuonTracking_Hist, periods); - sfMuonIsoHist_xaxis = sfMuonIsoHist->GetXaxis(); - sfMuonIsoHist_yaxis = sfMuonIsoHist->GetYaxis(); - } - - if(sfElIdAndIsoDir_ == ""){ - std::cout<<"no electron id and iso scalefactor histogram, proceed without electron id and iso scalefactor"<Get(sfElIdAndIsoName_.c_str()); - - sfElIdAndIsoHist_xaxis = sfElIdAndIsoHist->GetXaxis(); - sfElIdAndIsoHist_yaxis = sfElIdAndIsoHist->GetYaxis(); - } - - if(sfMuonTrackingDir_ == ""){ - std::cout<<"no electron id and iso scalefactor histogram, proceed without electron id and iso scalefactor"<Get(sfMuonTrackingName_.c_str()); - - readHistoFromGraph(sfMuonTrackingTGraph, &sfMuonTrackingHist, "sfMuonTrackingHist"); - - sfMuonTrackingHist_axis = sfMuonTrackingHist->GetXaxis(); - } } void ntuple_eventInfo::initBranches(TTree* tree){ - addBranch(tree,"event_weight", &event_weight_); + addBranch(tree,"event_weight", &event_weight_,"event_weight_/f" ); } @@ -136,8 +95,8 @@ void ntuple_eventInfo::readEvent(const edm::Event& iEvent){ lheWeight = lheInfo->weights()[0].wgt/std::abs(lheInfo->weights()[0].wgt); } - /////scalefactors - // Muon scalefactors + ///// scalefactors + double leadingMuon_pt = 0.; double leadingMuon_eta = 0.; for (size_t i = 0; i < muons->size(); ++i){ @@ -147,63 +106,46 @@ void ntuple_eventInfo::readEvent(const edm::Event& iEvent){ leadingMuon_eta = muon.eta(); } } - // Muon Trigger - double muonTriggerSf = 1.; - if(sfMuonTriggerDir_ != ""){ - int binx = sfMuonTriggerHist_xaxis->FindBin(std::abs(leadingMuon_eta)); - int biny = sfMuonTriggerHist_yaxis->FindBin(leadingMuon_pt); - if(leadingMuon_pt > 500.) //dont take overflow bin, but the last one - biny -= 1; - muonTriggerSf = sfMuonTriggerHist->GetBinContent(binx, biny); - } - - // Muon ID - double muonIdSf = 1.; - if(sfMuonIdDir_ != ""){ - int binx = sfMuonIdHist_xaxis->FindBin(std::abs(leadingMuon_eta)); - int biny = sfMuonIdHist_yaxis->FindBin(leadingMuon_pt); - if(leadingMuon_pt > 120.) //dont take overflow bin, but the last one - biny -= 1; - muonIdSf = sfMuonIdHist->GetBinContent(binx, biny); - } - // Muon ISO - double muonIsoSf = 1.; - if(sfMuonIsoDir_ != ""){ - int binx = sfMuonIsoHist_xaxis->FindBin(std::abs(leadingMuon_eta)); - int biny = sfMuonIsoHist_yaxis->FindBin(leadingMuon_pt); - if(leadingMuon_pt > 120.) //dont take overflow bin, but the last one - biny -= 1; - muonIsoSf = sfMuonIsoHist->GetBinContent(binx, biny); - } - //Muon tracking - double muonTrackingSf = 1.; - if(sfMuonTrackingDir_ != ""){ - int binx = sfMuonTrackingHist_axis->FindBin(std::abs(leadingMuon_eta)); - muonTrackingSf = sfMuonTrackingHist->GetBinContent(binx); - } - - // Electron scalefactors double leadingElectron_pt = 0.; double leadingElectron_sueta = 0.; + double leadingElectron_eta = 0.; for (size_t i = 0; i < electrons->size(); ++i){ const auto & electron = (*electrons).at(i); if(electron.pt() > leadingElectron_pt){ leadingElectron_pt = electron.pt(); leadingElectron_sueta = electron.superCluster()->eta(); + leadingElectron_eta = electron.eta(); } } - //Electron ID and ISO - double elIdAndIsoSf = 1.; - if(sfElIdAndIsoDir_ != ""){ - int binx = sfElIdAndIsoHist_xaxis->FindBin(std::abs(leadingElectron_sueta)); - int biny = sfElIdAndIsoHist_yaxis->FindBin(leadingElectron_pt); - if(leadingElectron_pt > 120.) - biny -= 1; - elIdAndIsoSf = sfElIdAndIsoHist->GetBinContent(binx, biny); - } - event_weight_ = lheWeight * pupWeight * muonTriggerSf * muonIdSf * muonIsoSf * muonTrackingSf * elIdAndIsoSf; + event_weight_ = 0.; + for(unsigned int i=0; i< periods.size(); i++){ + + double isf = 1.; + + isf *= getScalefactor(std::abs(leadingMuon_eta), leadingMuon_pt, sfTrigger_mu_Hist, i); + isf *= getScalefactor(std::abs(leadingElectron_eta), std::abs(leadingMuon_eta), sfTrigger_emu_Hist, i); + isf *= getScalefactor(std::abs(leadingMuon_eta), leadingMuon_pt, sfMuonId_Hist, i); + isf *= getScalefactor(std::abs(leadingMuon_eta), leadingMuon_pt, sfMuonIso_Hist, i); + isf *= getScalefactor(std::abs(leadingElectron_sueta), leadingElectron_pt, sfElIdAndIso_Hist, i); + isf *= getScalefactor(std::abs(leadingMuon_eta), sfMuonTracking_Hist, i); + + //std::cout< hists, unsigned int period){ + + if(hists.size()==0) return 1.; + else if(hists.size()==1){ + int bin = hists[0]->GetXaxis()->FindBin(x); + if(x > hists[0]->GetXaxis()->GetXmax()) //dont take overflow bins, but the last ones + bin -= 1; + return(hists[0]->GetBinContent(bin)); + } + else if(hists.size() > period){ + int bin = hists[period]->GetXaxis()->FindBin(x); + if(x > hists[period]->GetXaxis()->GetXmax()) //dont take overflow bins, but the last ones + bin -= 1; + return(hists[period]->GetBinContent(bin)); + } + else std::cout<<"ERROR: something went wrong in getScalefactor function"< dirs, std::vector names, std::vector *sfHists, std::vector periods){ + if(dirs.size()==0) + std::cout<<"no scalefactor "<push_back((TH2F*)file->Get(names[i].c_str())); + } + } + else if(dirs.size()==1){ + std::cout<<"initialize one scalefactor histogram for all periods " <push_back((TH2F*)file->Get(names[0].c_str())); + } + else{ + std::cout<<"ERROR: something went wrong by initialization of a scalefactor " < dirs, std::vector names, std::vector *sfHists, std::vector periods){ + if(dirs.size()==0) + std::cout<<"no scalefactor "<Get(names[i].c_str()); + readHistoFromGraph(sfTGraph, &hist, "sfMuonTrackingHist"); + sfHists->push_back(hist); + } + } + else if(dirs.size()==1){ + std::cout<<"initialize one scalefactor histogram for all periods " <Get(names[0].c_str()); + readHistoFromGraph(sfTGraph, &hist, "sfMuonTrackingHist"); + sfHists->push_back(hist); + } + else{ + std::cout<<"ERROR: something went wrong by initialization of a scalefactor " <GetN(); diff --git a/DeepNtuplizer/src/ntuple_pfCands.cc b/DeepNtuplizer/src/ntuple_pfCands.cc index 88333895b1f..6dfdfffba76 100644 --- a/DeepNtuplizer/src/ntuple_pfCands.cc +++ b/DeepNtuplizer/src/ntuple_pfCands.cc @@ -246,6 +246,11 @@ void ntuple_pfCands::readEvent(const edm::Event& iEvent){ //use either of these functions bool ntuple_pfCands::fillBranches(const pat::Jet & jet, const size_t& jetidx, const edm::View * coll){ + if(jet.pt() > 99.07 && jet.pt()< 99.08){ + std::cout<<" pfCands ..."<pt()/jet_uncorr_pt)); } else{ - sortedneutrals.push_back(sorting::sortingClass - (i, -1, -mindrsvpfcand(PackedCandidate), PackedCandidate->pt()/jet_uncorr_pt)); + sorting::sortingClass ineutral = sorting::sortingClass(i, -1, -mindrsvpfcand(PackedCandidate), PackedCandidate->pt()/jet_uncorr_pt); + sortedneutrals.push_back(ineutral); } } } + std::sort(sortedcharged.begin(),sortedcharged.end(),sorting::sortingClass::compareByABCInv); std::sort(sortedneutrals.begin(),sortedneutrals.end(),sorting::sortingClass::compareByABCInv); + // counts neutral and charged candicates n_Cpfcand_ = std::min(sortedcharged.size(),max_pfcand_); n_Npfcand_ = std::min(sortedneutrals.size(),max_pfcand_); std::vector sortedchargedindices,sortedneutralsindices; - sortedchargedindices=sorting::invertSortingVector(sortedcharged); - sortedneutralsindices=sorting::invertSortingVector(sortedneutrals); - - + sortedchargedindices=sorting::invertSortingVector(sortedcharged); + sortedneutralsindices=sorting::invertSortingVector(sortedneutrals); @@ -459,6 +464,11 @@ bool ntuple_pfCands::fillBranches(const pat::Jet & jet, const size_t& jetidx, co nCpfcand_=n_Cpfcand_; nNpfcand_=n_Npfcand_; + if(jet.eta() == -1.039){ + std::cout<<" end pfCands ..."< Date: Thu, 17 May 2018 14:31:18 +0200 Subject: [PATCH 14/17] include trigger information to use different triggers in different periods --- DeepNtuplizer/interface/ntuple_eventInfo.h | 7 ++ DeepNtuplizer/interface/triggerInfo.h | 36 ++++++++ DeepNtuplizer/plugins/DeepNtuplizer.cc | 1 + .../production/DeepNtuplizer_tt_dilep.py | 4 + .../production/DeepNtuplizer_tt_semilep.py | 6 +- DeepNtuplizer/python/DeepNtuplizer_cfi.py | 12 ++- DeepNtuplizer/src/ntuple_eventInfo.cc | 13 ++- DeepNtuplizer/src/triggerInfo.cpp | 91 +++++++++++++++++++ 8 files changed, 161 insertions(+), 9 deletions(-) create mode 100644 DeepNtuplizer/interface/triggerInfo.h create mode 100644 DeepNtuplizer/src/triggerInfo.cpp diff --git a/DeepNtuplizer/interface/ntuple_eventInfo.h b/DeepNtuplizer/interface/ntuple_eventInfo.h index bb84b1eb1c6..8909828aef7 100644 --- a/DeepNtuplizer/interface/ntuple_eventInfo.h +++ b/DeepNtuplizer/interface/ntuple_eventInfo.h @@ -9,6 +9,7 @@ #define DEEPNTUPLES_DEEPNTUPLIZER_INTERFACE_NTUPLE_EVENTINFO_H_ #include "ntuple_content.h" +#include "triggerInfo.h" #include #include @@ -55,6 +56,10 @@ class ntuple_eventInfo: public ntuple_content{ void setElectronsToken(edm::EDGetTokenT > electronToken){ electronToken_ = electronToken; } + void setTriggerToken(edm::EDGetTokenT triggerToken){ + triggerToken_ = triggerToken; + } + private: @@ -62,6 +67,7 @@ class ntuple_eventInfo: public ntuple_content{ edm::EDGetTokenT lheToken_; edm::EDGetTokenT > muonToken_; edm::EDGetTokenT > electronToken_; + edm::EDGetTokenT triggerToken_; edm::Handle lheInfo; edm::Handle > muons; @@ -103,6 +109,7 @@ class ntuple_eventInfo: public ntuple_content{ std::vector sfMuonTracking_Hist; + std::vector triggers; // global variables diff --git a/DeepNtuplizer/interface/triggerInfo.h b/DeepNtuplizer/interface/triggerInfo.h new file mode 100644 index 00000000000..74ba7725f53 --- /dev/null +++ b/DeepNtuplizer/interface/triggerInfo.h @@ -0,0 +1,36 @@ +/* + * treeReader.h + * + * Created on: 17 May 2018 + * Author: dwalter + */ + +#ifndef DEEPNTUPLES_DEEPNTUPLIZER_INTERFACE_TRIGGERINFO_H_ +#define DEEPNTUPLES_DEEPNTUPLIZER_INTERFACE_TRIGGERINFO_H_ + + +#include +#include +#include "FWCore/Common/interface/TriggerNames.h" +#include "DataFormats/Common/interface/TriggerResults.h" +#include "DataFormats/PatCandidates/interface/TriggerObjectStandAlone.h" +#include "DataFormats/PatCandidates/interface/PackedTriggerPrescales.h" +#include "FWCore/Framework/interface/Event.h" + +class TriggerInfo { + +public: + TriggerInfo(const edm::Event& iEvent, + const edm::EDGetTokenT& triggerBitsToken); + bool IsTriggered(std::string triggername) const ; + bool Exists(std::string triggername) const ; + bool IsAnyTriggered(std::vector< std::string > triggers) const ; + bool IsAnyTriggered(std::string triggerstring) const; + void ListTriggers() ; + std::map GetTriggers() const; +private: + std::map triggers; + std::vector triggernames; +}; + +#endif diff --git a/DeepNtuplizer/plugins/DeepNtuplizer.cc b/DeepNtuplizer/plugins/DeepNtuplizer.cc index 2a4f2da193e..c1def2b9fba 100644 --- a/DeepNtuplizer/plugins/DeepNtuplizer.cc +++ b/DeepNtuplizer/plugins/DeepNtuplizer.cc @@ -199,6 +199,7 @@ DeepNtuplizer::DeepNtuplizer(const edm::ParameterSet& iConfig): evweight->setLHEToken(consumes(iConfig.getParameter("lheInfo"))); evweight->setMuonsToken(consumes >(iConfig.getParameter("sfMuons"))); evweight->setElectronsToken(consumes >(iConfig.getParameter("sfElectrons"))); + evweight->setTriggerToken(consumes(iConfig.getParameter("triggerToken"))); addModule(evweight); } diff --git a/DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py b/DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py index 68ea37d6326..39304554963 100644 --- a/DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py +++ b/DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py @@ -392,6 +392,10 @@ process.deepntuplizer.periods=cms.vstring("2016BtoF","2016G","2016H") process.deepntuplizer.lumis=cms.vdouble(5.404+2.396+4.243+4.054+3.105,7.544,8.453) +process.deepntuplizer.triggers=cms.vstring("HLT_Mu23_TrkIsoVVL_Ele12_CaloIdL_TrackIdL_IsoVL_v*||HLT_Mu8_TrkIsoVVL_Ele23_CaloIdL_TrackIdL_IsoVL_v*", #Run B-G + "HLT_Mu23_TrkIsoVVL_Ele12_CaloIdL_TrackIdL_IsoVL_v*||HLT_Mu8_TrkIsoVVL_Ele23_CaloIdL_TrackIdL_IsoVL_v*", #Run B-G + "HLT_Mu23_TrkIsoVVL_Ele12_CaloIdL_TrackIdL_IsoVL_DZ_v*||HLT_Mu8_TrkIsoVVL_Ele23_CaloIdL_TrackIdL_IsoVL_DZ_v*") #Run H + #emu trigger scalefactors from # https://gitlab.cern.ch/ttH/reference/blob/955cff0b09f2c95bc480ae0bf3145aab9ce08fcc/definitions/Moriond17.md#64-trigger-scale-factors # https://gitlab.cern.ch/ttH/reference/blob/955cff0b09f2c95bc480ae0bf3145aab9ce08fcc/definitions/Moriond17.md#41-triggers diff --git a/DeepNtuplizer/production/DeepNtuplizer_tt_semilep.py b/DeepNtuplizer/production/DeepNtuplizer_tt_semilep.py index 0c458e9811f..def14a47828 100644 --- a/DeepNtuplizer/production/DeepNtuplizer_tt_semilep.py +++ b/DeepNtuplizer/production/DeepNtuplizer_tt_semilep.py @@ -372,14 +372,10 @@ process.deepntuplizer.sfMuons = cms.InputTag("goodMuons") -#process.deepntuplizer.lumi_BCDEF=cms.double(5.404+2.396+4.256+4.054+3.105) -#process.deepntuplizer.lumi_G=cms.double(7.179) -#process.deepntuplizer.lumi_H=cms.double(8.746) + process.deepntuplizer.periods=cms.vstring("2016BtoF","2016GH") process.deepntuplizer.lumis=cms.vdouble(5.404+2.396+4.256+4.054+3.105, 7.179+8.746) - - process.deepntuplizer.sfTrigger_mu=cms.vstring(datapath + "EfficienciesAndSF_RunBtoF.root", datapath + "EfficienciesAndSF_Period4.root") process.deepntuplizer.sfTrigger_mu_Hist=cms.vstring("IsoMu24_OR_IsoTkMu24_PtEtaBins/abseta_pt_ratio", diff --git a/DeepNtuplizer/python/DeepNtuplizer_cfi.py b/DeepNtuplizer/python/DeepNtuplizer_cfi.py index 2b10f5b02af..85cb1bbfe2e 100644 --- a/DeepNtuplizer/python/DeepNtuplizer_cfi.py +++ b/DeepNtuplizer/python/DeepNtuplizer_cfi.py @@ -38,19 +38,25 @@ removeUndefined=cms.bool(True), isData=cms.bool(False), + + #All following is for event weight computation useLHEWeights=cms.bool(True), #leave empty string if you don't want to use pileup weights pileupData=cms.string(""), pileupMC=cms.string(""), + periods=cms.vstring(), + lumis=cms.vdouble(), #weights are weighted with the luminosity of the period + + #to use different triggers for the periods + triggerToken=cms.InputTag("TriggerResults::HLT"), + triggers=cms.vstring(), + #scalefactor information sfMuons = cms.InputTag("slimmedMuons"), sfElectrons=cms.InputTag("slimmedElectrons"), - periods=cms.vstring(), - lumis=cms.vdouble(), - # The scalefactors can be computed on different ways: # - empty vector to not use a specific scalefactor, # - one string to use the same hist for all periods diff --git a/DeepNtuplizer/src/ntuple_eventInfo.cc b/DeepNtuplizer/src/ntuple_eventInfo.cc index cae3d9f3778..17ea565f725 100644 --- a/DeepNtuplizer/src/ntuple_eventInfo.cc +++ b/DeepNtuplizer/src/ntuple_eventInfo.cc @@ -34,6 +34,8 @@ void ntuple_eventInfo::getInput(const edm::ParameterSet& iConfig){ sfMuonTracking_Dir_ = (iConfig.getParameter>("sfMuonTracking")); sfMuonTracking_Name_ = (iConfig.getParameter>("sfMuonTracking_Hist")); + triggers = (iConfig.getParameter>("triggers")); + if(pupDataDir_=="" || pupMCDir_=="") std::cout<<"no pileup histograms, proceed without pileup reweighting. \n"; @@ -70,6 +72,7 @@ void ntuple_eventInfo::initBranches(TTree* tree){ void ntuple_eventInfo::readEvent(const edm::Event& iEvent){ + TriggerInfo triggerInfo(iEvent,triggerToken_); if(!iEvent.isRealData()){ @@ -123,6 +126,7 @@ void ntuple_eventInfo::readEvent(const edm::Event& iEvent){ for(unsigned int i=0; i< periods.size(); i++){ double isf = 1.; + bool itriggered = 1; isf *= getScalefactor(std::abs(leadingMuon_eta), leadingMuon_pt, sfTrigger_mu_Hist, i); isf *= getScalefactor(std::abs(leadingElectron_eta), std::abs(leadingMuon_eta), sfTrigger_emu_Hist, i); @@ -131,6 +135,11 @@ void ntuple_eventInfo::readEvent(const edm::Event& iEvent){ isf *= getScalefactor(std::abs(leadingElectron_sueta), leadingElectron_pt, sfElIdAndIso_Hist, i); isf *= getScalefactor(std::abs(leadingMuon_eta), sfMuonTracking_Hist, i); + if(triggers.size() != 0){ + itriggered = triggerInfo.IsAnyTriggered(triggers[i]); + //std::cout<<"istriggered "<& triggerBitsToken + ){ + + edm::Handle h_triggerBits; + iEvent.getByToken(triggerBitsToken, h_triggerBits); + // todo : use trigger objects + // edm::Handle h_triggerObjects; + // iEvent.getByToken(triggerObjectsToken, h_triggerObjects); + + const edm::TriggerNames &names = iEvent.triggerNames(*h_triggerBits); + + for (unsigned int i = 0; i < h_triggerBits->size(); ++i) { + string name=names.triggerName(i); +// cout << "Trigger #" << i << " " << name << endl; + triggernames.push_back(name); + triggers[name]=h_triggerBits->accept(i); + } +} + +bool TriggerInfo::Exists(std::string triggername) const { + if(triggers.count(triggername)==0){ + return false; + } + return true; +} + + +bool TriggerInfo::IsTriggered(std::string triggername) const { + if(triggername=="any"||triggername=="Any"||triggername=="none"||triggername=="None") return true; + int asterix = triggername.find("*"); + if(asterix==int(std::string::npos)){ + return Exists(triggername)&&triggers.at(triggername); + } + else{ + if(asterix==int(triggername.length()-1)){ + triggername.pop_back(); + auto it=triggers.lower_bound(triggername); + while(it!=triggers.end()&&it->first.find(triggername) == 0){ + if(it->second) return true; + it++; + } + return false; + } + else{ + cerr << "* wildcard only allowed at the end" << endl; + return false; + } + } + return false; + +} + +bool TriggerInfo::IsAnyTriggered(std::vector< std::string > triggerNames) const { + for(auto name=triggerNames.begin(); name!=triggerNames.end();name++){ + if(IsTriggered(*name)) return true; + } + return false; +} + +bool TriggerInfo::IsAnyTriggered(std::string triggerstring) const{ + std::vector triggernames; + + int posOr; + while(true){ + posOr = triggerstring.find("||"); + if(posOr==int(std::string::npos)){ + triggernames.push_back(triggerstring); + return IsAnyTriggered(triggernames); + } + triggernames.push_back(triggerstring.substr(0,posOr)); + triggerstring=triggerstring.substr(posOr+2,triggerstring.length()); + //std::cout<<"triggerstring = "< TriggerInfo::GetTriggers() const{ + return triggers; +} + + +void TriggerInfo::ListTriggers() { + int counter=0; + for(unsigned int i=0; i Date: Thu, 17 May 2018 14:42:46 +0200 Subject: [PATCH 15/17] updates for the plotting scripts --- DeepNtuplizer/plots/plot_event_ttdilep.py | 170 ++++-- DeepNtuplizer/plots/plot_event_ttsemilep.py | 613 ++++++++++++++++++++ DeepNtuplizer/plots/plot_features.py | 90 ++- 3 files changed, 793 insertions(+), 80 deletions(-) create mode 100644 DeepNtuplizer/plots/plot_event_ttsemilep.py diff --git a/DeepNtuplizer/plots/plot_event_ttdilep.py b/DeepNtuplizer/plots/plot_event_ttdilep.py index 9f203f51a89..e1214f3ae93 100644 --- a/DeepNtuplizer/plots/plot_event_ttdilep.py +++ b/DeepNtuplizer/plots/plot_event_ttdilep.py @@ -16,6 +16,7 @@ #gStyle.SetTextSize(14) + class pileupweight: """ DOC """ @@ -40,7 +41,7 @@ def getPileupWeight(self,nInteractions): class scaleFactor(): """ class for isolation and id scale factors - hist is the 2d histogram with the scale factor with abs(eta) on x and pt on y + hist is the 2d histogram with the scale factor with x and y """ def __init__(self,hist): self.hist = hist @@ -100,8 +101,8 @@ def __init__(self,graph, name): self.axis = self.hist.GetXaxis() self.scalefactor = 1. - def getScalefactor(self,eta): - self.bin = self.axis.FindBin(abs(eta)) + def getScalefactor(self,x): + self.bin = self.axis.FindBin(abs(x)) self.scalefactor = self.hist.GetBinContent(self.bin) return self.scalefactor @@ -113,28 +114,36 @@ class process: TFile(datadir + "MyMCPileupHist.root"), TFile(datadir + "MyDataPileupHist.root") ) - # muon scalefactor hists from https://twiki.cern.ch/twiki/bin/viewauth/CMS/MuonWorkInProgressAndPagResults + # emu trigger scalefactors from + # https://gitlab.cern.ch/ttH/reference/blob/955cff0b09f2c95bc480ae0bf3145aab9ce08fcc/definitions/Moriond17.md#64-trigger-scale-factors + # https://gitlab.cern.ch/ttH/reference/blob/955cff0b09f2c95bc480ae0bf3145aab9ce08fcc/definitions/Moriond17.md#41-triggers file_sf_emu_trigger = TFile(datadir + "triggerSummary_emu_ReReco2016_ttH.root") + h_sf_emu_trigger = file_sf_emu_trigger.Get("scalefactor_eta2d_with_syst") + sf_emu_trigger = scaleFactor(h_sf_emu_trigger) + + # muon scalefactor hists from https://twiki.cern.ch/twiki/bin/viewauth/CMS/MuonWorkInProgressAndPagResults + file_sf_muon_id_BCDEF = TFile(datadir + "EfficienciesAndSF_ID_BCDEF.root") + file_sf_muon_iso_BCDEF = TFile(datadir + "EfficienciesAndSF_ISO_BCDEF.root") file_sf_muon_id_GH = TFile(datadir + "EfficienciesAndSF_ID_GH.root") file_sf_muon_iso_GH = TFile(datadir + "EfficienciesAndSF_ISO_GH.root") file_sf_muon_tracking = TFile(datadir + "Tracking_EfficienciesAndSF_BCDEFGH.root") - # electron scalefactor hists from https://twiki.cern.ch/twiki/bin/view/CMS/EgammaIDRecipesRun2 - # -> Electron cut-based 80XID WPs. Scale factors for 80X -> Tight cut-based ID WP scale factor (root file) - # id and iso is combined in one file, there is no tracking for the electron - file_sf_el_id = TFile(datadir + "egammaEffi.txt_EGM2D.root" - ) - - h_sf_emu_trigger = file_sf_emu_trigger.Get("scalefactor_eta2d_with_syst") + h_sf_muon_id_BCDEF = file_sf_muon_id_BCDEF.Get("MC_NUM_TightID_DEN_genTracks_PAR_pt_eta/abseta_pt_ratio") + h_sf_muon_iso_BCDEF = file_sf_muon_iso_BCDEF.Get("TightISO_TightID_pt_eta/abseta_pt_ratio") h_sf_muon_id_GH = file_sf_muon_id_GH.Get("MC_NUM_TightID_DEN_genTracks_PAR_pt_eta/abseta_pt_ratio") h_sf_muon_iso_GH = file_sf_muon_iso_GH.Get("TightISO_TightID_pt_eta/abseta_pt_ratio") g_sf_muon_tracking = file_sf_muon_tracking.Get("ratio_eff_aeta_dr030e030_corr") - h_sf_el_id = file_sf_el_id.Get("EGamma_SF2D") - sf_emu_trigger = scaleFactor(h_sf_emu_trigger) - sf_muon_id = scaleFactor(h_sf_muon_id_GH) - sf_muon_iso = scaleFactor(h_sf_muon_iso_GH) - sf_muon_tracking = scaleFactor_tracking(g_sf_muon_tracking,"sf_muon_tracking") + sf_muon_id_BCDEF = scaleFactor(h_sf_muon_id_BCDEF) + sf_muon_iso_BCDEF = scaleFactor(h_sf_muon_iso_BCDEF) + sf_muon_id_GH = scaleFactor(h_sf_muon_id_GH) + sf_muon_iso_GH = scaleFactor(h_sf_muon_iso_GH) + sf_muon_tracking = scaleFactor_tracking(g_sf_muon_tracking, "sf_muon_tracking") + # electron scalefactor hists from https://twiki.cern.ch/twiki/bin/view/CMS/EgammaIDRecipesRun2 + # -> Electron cut-based 80XID WPs. Scale factors for 80X -> Tight cut-based ID WP scale factor (root file) + # id and iso is combined in one file, there is no tracking for the electron + file_sf_el_id = TFile(datadir + "egammaEffi.txt_EGM2D.root") + h_sf_el_id = file_sf_el_id.Get("EGamma_SF2D") sf_el_id = scaleFactor(h_sf_el_id) muonhandle = Handle("vector") @@ -146,8 +155,8 @@ class process: electronlabel = ("goodElectrons") #electronlabel = ("GoodElectron") jethandle = Handle('vector') - jetlabel = ('slimmedJets') -#jetlabel = ("GoodJets") + #jetlabel = ('slimmedJets') + jetlabel = ("goodJets") ### LHE weights LHEweighthandle = Handle('LHEEventProduct') LHEweightlabel = ("externalLHEProducer") @@ -156,6 +165,9 @@ class process: puphandle = Handle('vector') puplabel = ("slimmedAddPileupInfo") + triggerhandle = Handle("edm::TriggerResults") + triggerlabel = ("TriggerResults::HLT") + hs_ll_pt = THStack("hs_ll_pt", "ll pt") hs_ll_eta = THStack("hs_ll_eta", "ll eta") hs_tl_pt = THStack("hs_tl_pt", "tl pt") @@ -179,6 +191,12 @@ def __init__(self, name, isData=False, color=1): self.h_tl_eta = TH1F(self.name + "_tl_eta", "eta of the leading leption in " + self.name, 20, -2.4, 2.4) self.h_njets = TH1F(self.name + "_njets", "number of jets in " +self.name, 10, -0.5, 9.5) + #self.h_ll_pt.Sumw2() + #self.h_ll_eta.Sumw2() + #self.h_tl_pt.Sumw2() + #self.h_tl_eta.Sumw2() + #self.h_njets.Sumw2() + self.hists = self.h_ll_pt, self.h_ll_eta, self.h_tl_pt, self.h_tl_eta, self.h_njets self.integral = 0. @@ -202,9 +220,9 @@ def __init__(self, name, isData=False, color=1): self.h_ll_pt.SetYTitle("Events/GeV") self.h_ll_pt.GetYaxis().SetTitleOffset(1.2) - self.h_ll_eta.SetYTitle("Events/0.25") + self.h_ll_eta.SetYTitle("Events") self.h_tl_pt.SetYTitle("Events/GeV") - self.h_tl_eta.SetYTitle("Events/0.25") + self.h_tl_eta.SetYTitle("Events") self.h_njets.SetYTitle("Events") self.h_njets.GetXaxis().SetNdivisions(10,0,0) @@ -248,6 +266,14 @@ def fillHists(self, infile, islist=True, useLHEWeights=False, isData=False, even leadingElEta = 0 leadingElSuEta = 0 weight = 1. + weight_BCDEF = 1. + weight_GH = 1. + + lumi_BCDEF = 5.404+2.396+4.243+4.054+3.105 + lumi_G = 7.544 + lumi_H = 8.453 + + # Fill muon hists event.getByLabel(process.muonlabel, process.muonhandle) @@ -301,11 +327,38 @@ def fillHists(self, infile, islist=True, useLHEWeights=False, isData=False, even weight *= process.pupw.getPileupWeight(int(pupInfo.getTrueNumInteractions())) weight *= process.sf_emu_trigger.getScalefactor(abs(leadingElEta),abs(leadingMuonEta)) - weight *= process.sf_muon_id.getScalefactor(abs(leadingMuonEta), leadingMuonPt) - weight *= process.sf_muon_iso.getScalefactor(abs(leadingMuonEta), leadingMuonPt) weight *= process.sf_muon_tracking.getScalefactor(abs(leadingMuonEta)) + weight_BCDEF *= process.sf_muon_id_BCDEF.getScalefactor(abs(leadingMuonEta), leadingMuonPt) + weight_BCDEF *= process.sf_muon_iso_BCDEF.getScalefactor(abs(leadingMuonEta), leadingMuonPt) + weight_GH *= process.sf_muon_id_GH.getScalefactor(abs(leadingMuonEta), leadingMuonPt) + weight_GH *= process.sf_muon_iso_GH.getScalefactor(abs(leadingMuonEta), leadingMuonPt) weight *= process.sf_el_id.getScalefactor(abs(leadingElSuEta), leadingElPt) + ### For 2016H there was used another emu trigger (DZ version) then for B to G, + # compute weights for events that pass the "2016H trigger" and for those who pass the "B to G trigger" + trigger_BCDEFG = 0 + trigger_H = 0 + event.getByLabel(process.triggerlabel, process.triggerhandle) + trigger = process.triggerhandle.product() + for i in range(trigger.size()): + #print(i, events.object().triggerNames(trigger).triggerName(i), trigger.accept(i)) + if events.object().triggerNames(trigger).triggerName(i)[0:49] == "HLT_Mu23_TrkIsoVVL_Ele12_CaloIdL_TrackIdL_IsoVL_v" or \ + events.object().triggerNames(trigger).triggerName(i)[0:48] == "HLT_Mu8_TrkIsoVVL_Ele23_CaloIdL_TrackIdL_IsoVL_v": + + if trigger.accept(i): + trigger_BCDEFG = 1 + + if events.object().triggerNames(trigger).triggerName(i)[0:52] == "HLT_Mu23_TrkIsoVVL_Ele12_CaloIdL_TrackIdL_IsoVL_DZ_v" or \ + events.object().triggerNames(trigger).triggerName(i)[0:51] == "HLT_Mu8_TrkIsoVVL_Ele23_CaloIdL_TrackIdL_IsoVL_DZ_v": + if trigger.accept(i): + trigger_H = 1 + + weight = weight * (weight_BCDEF * lumi_BCDEF * trigger_BCDEFG + + weight_GH * lumi_G * trigger_BCDEFG + + weight_GH * lumi_H * trigger_H) + + + self.h_ll_pt.Fill(leadingPt, weight) self.h_ll_eta.Fill(leadingEta, weight) @@ -333,8 +386,8 @@ def scale_hists(self,sigma=1.,lumi=1.,eff=1.): self.divideByBinWidth(self.hists[0]) self.divideByBinWidth(self.hists[2]) - self.hists[1].Scale(4) - self.hists[3].Scale(4) + #self.hists[1].Scale(4) + #self.hists[3].Scale(4) def divideByBinWidth(self,hist): for ibin in range(0, len(hist)): @@ -361,7 +414,7 @@ def load_hists(self): f1.Close() else: - print("no file for this process") + print("no file for this process found") def draw_hists(self): canvas = TCanvas(self.name, "", 800, 600) @@ -515,24 +568,23 @@ def print_stacks(cls): tt = process("tt", color=625) data = process("data",isData=True) - -dy10to50.fillHists("dy10to50.txt",useLHEWeights=True) -dy50.fillHists("dy50.txt",useLHEWeights=True) -ww.fillHists("ww.txt") -wz.fillHists("wz.txt") -zz.fillHists("zz.txt") -wjets.fillHists("wjets.txt",useLHEWeights=True) +#dy10to50.fillHists("dy10to50.txt",useLHEWeights=True) +#dy50.fillHists("dy50.txt",useLHEWeights=True) +#ww.fillHists("ww.txt") +#wz.fillHists("wz.txt") +#zz.fillHists("zz.txt") +#wjets.fillHists("wjets.txt",useLHEWeights=True) #wt.fillHists("wt.txt") -wantit.fillHists("wantit.txt") -tt.fillHists("tt.txt") -data.fillHists("data.txt",isData=True) +#wantit.fillHists("wantit.txt") +#tt.fillHists("tt.txt") +#data.fillHists("data.txt",isData=True) -#for ip in process.collection: -# ip.load_hists() -#process.hists_data.load_hists() +for ip in process.collection: + ip.load_hists() +process.hists_data.load_hists() -lumi_total = 35.9 -lumi_data = 8.746 +#lumi_total = 35.9 +#lumi_data = 7.544 # (7.544 + 8.453) sigma_tt = 831760 sigma_dy50 = 6025200 @@ -560,25 +612,29 @@ def print_stacks(cls): eff_wjets = 1./16497031 # effective number of events #eff_wjets = 1./24120319 # true number of events -data.scale_hists( lumi=lumi_total/lumi_data) -tt.scale_hists(sigma = sigma_tt, lumi = lumi_total, eff = eff_tt) -dy50.scale_hists(sigma = sigma_dy50, lumi = lumi_total, eff = eff_dy50) -dy10to50.scale_hists(sigma = sigma_dy10to50,lumi = lumi_total, eff = eff_dy10to50) -ww.scale_hists(sigma = sigma_ww, lumi = lumi_total, eff = eff_ww) -wz.scale_hists(sigma = sigma_wz, lumi = lumi_total, eff = eff_wz) -zz.scale_hists(sigma = sigma_zz, lumi = lumi_total, eff = eff_zz) -wantit.scale_hists(sigma = sigma_wantit, lumi = lumi_total, eff = eff_wantit) -wt.scale_hists(sigma = sigma_wt, lumi = lumi_total, eff = eff_wt) -wjets.scale_hists(sigma = sigma_wjets, lumi = lumi_total, eff = eff_wjets) - -data.setMinMax(0,20000,0,300000,0,18500,0,150000,0,140000) -title='180327' - -directory = os.path.dirname('./plots_'+title+'/') +data.scale_hists() +tt.scale_hists(sigma = sigma_tt, eff = eff_tt) +dy50.scale_hists(sigma = sigma_dy50, eff = eff_dy50) +dy10to50.scale_hists(sigma = sigma_dy10to50, eff = eff_dy10to50) +ww.scale_hists(sigma = sigma_ww, eff = eff_ww) +wz.scale_hists(sigma = sigma_wz, eff = eff_wz) +zz.scale_hists(sigma = sigma_zz, eff = eff_zz) +wantit.scale_hists(sigma = sigma_wantit, eff = eff_wantit) +wt.scale_hists(sigma = sigma_wt, eff = eff_wt) +wjets.scale_hists(sigma = sigma_wjets, eff = eff_wjets) + +data.setMinMax(0,8000,0,40000,0,17000,0,40000,0,140000) + +title='plots_180514_full2016' +directory = os.path.dirname('./'+title+'/') # make a canvas, draw, and save it -if not os.path.exists(directory): +if os.path.exists(directory): + print("ERROR: output directory exists, please choose another name or delite the old one") + import sys + sys.exit() +else: os.makedirs(directory) -os.chdir(directory) + os.chdir(directory) integral_mc = 0. integral_data = process.hists_data.integral diff --git a/DeepNtuplizer/plots/plot_event_ttsemilep.py b/DeepNtuplizer/plots/plot_event_ttsemilep.py new file mode 100644 index 00000000000..db531c729f6 --- /dev/null +++ b/DeepNtuplizer/plots/plot_event_ttsemilep.py @@ -0,0 +1,613 @@ +from __future__ import print_function +from __future__ import division + + +import pdb +from ROOT import TH1F, TFile, TCanvas, gROOT, gStyle, THStack, TLegend, TGaxis, gPad, TPad, TGraph, TLine +import numpy as np +import os +from array import array +import datetime +from DataFormats.FWLite import Events, Handle + +gROOT.SetBatch() # don't pop up canvases +gROOT.SetStyle('Plain') # white background +gStyle.SetFillStyle(0) +TGaxis.SetMaxDigits(4) # Force scientific notation for numbers with more than 4 digits +#gStyle.SetBorderSize(0) +#gStyle.SetTextFont(43) +#gStyle.SetTextSize(14) + + +class pileupweight: + """ DOC """ + + def __init__(self, file_pileup_MC, file_pileup_Data): + hist_mc = file_pileup_MC.Get("pileup") + hist_data = file_pileup_Data.Get("pileup") + self.pupWeights = [0] + hist_mc.Scale(1. / hist_mc.Integral()) + hist_data.Scale(1. / hist_data.Integral()) + for bin in range(1, hist_data.GetNbinsX() + 2): + if hist_mc.GetBinContent(bin) != 0: + w = hist_data.GetBinContent(bin) / hist_mc.GetBinContent(bin) + self.pupWeights.append(w) + else: + self.pupWeights.append(1) + + def getPileupWeight(self,nInteractions): + if nInteractions >= len(self.pupWeights): + return 0 + return self.pupWeights[nInteractions] + +class scaleFactor(): + """ + class for isolation and id scale factors + hist is the 2d histogram with the scale factor with abs(eta) on x and pt on y + """ + def __init__(self,hist): + self.hist = hist + self.xaxis = self.hist.GetXaxis() + self.yaxis = self.hist.GetYaxis() + self.binx = 0 + self.biny = 0 + self.scalefactor = 1. + self.maxBinX = self.xaxis.GetLast() + self.maxBinY = self.yaxis.GetLast() + self.minX = self.xaxis.GetXmin() + self.maxX = self.xaxis.GetXmax() + self.minY = self.yaxis.GetXmin() + self.maxY = self.yaxis.GetXmax() + + def getScalefactor(self,x,y): + + self.binx = self.xaxis.FindBin(x) + self.biny = self.yaxis.FindBin(y) + if x >= self.maxX: self.binx = self.maxBinX + if y >= self.maxY: self.biny = self.maxBinY + self.scalefactor = self.hist.GetBinContent(self.binx, self.biny) + return self.scalefactor + + +class scaleFactor_tracking(): + """ + class for tracking scale factors + the tracking scale factors are saved in a TGraphAsymmErrors object which has to be written in a histogram first + """ + def __init__(self,graph, name): + self.graph = graph + self.npoints = self.graph.GetN() + self.x_centers = self.graph.GetX() + self.y_centers = self.graph.GetY() + self.x_lows = np.zeros(self.npoints) + self.x_highs = np.zeros(self.npoints) + self.y_lows = np.zeros(self.npoints) + self.y_highs = np.zeros(self.npoints) + self.x_edges = np.zeros(self.npoints +1) + + for i in range(0,self.npoints): + self.x_lows[i] = self.graph.GetErrorXlow(i) + self.x_highs[i] = self.graph.GetErrorXhigh(i) + self.y_lows[i] = self.graph.GetErrorYlow(i) + self.y_lows[i] = self.graph.GetErrorYhigh(i) + + self.x_edges[i] = self.x_centers[i] - self.x_lows[i] + self.x_edges[self.npoints] = self.x_centers[self.npoints - 1] + self.x_highs[self.npoints-1] + self.hist = TH1F(name, name,self.npoints,self.x_edges) + + for i in range(0,self.npoints): + self.hist.SetBinContent(i+1, self.y_centers[i]) + self.hist.SetBinError(i+1, max(self.y_lows[i], self.y_highs[i])) + + self.bin = 0 + self.axis = self.hist.GetXaxis() + self.scalefactor = 1. + + def getScalefactor(self,x): + self.bin = self.axis.FindBin(abs(x)) + self.scalefactor = self.hist.GetBinContent(self.bin) + return self.scalefactor + + +class process: + """ DOC """ + datadir = "/afs/desy.de/user/d/dwalter/CMSSW_8_0_29/src/DeepNTuples/DeepNtuplizer/data/" + pupw = pileupweight( + TFile(datadir + "MyMCPileupHist.root"), + TFile(datadir + "MyDataPileupHist.root") + ) + + lumi_BCDEF = 5.404 + 2.396 + 4.256 + 4.054 + 3.105 + lumi_GH = 7.179 + 8.746 + + # muon scalefactor hists from https://twiki.cern.ch/twiki/bin/viewauth/CMS/MuonWorkInProgressAndPagResults + file_sf_muon_trigger_GH = TFile(datadir + "EfficienciesAndSF_Period4.root") + file_sf_muon_id_GH = TFile(datadir + "EfficienciesAndSF_ID_GH.root") + file_sf_muon_iso_GH = TFile(datadir + "EfficienciesAndSF_ISO_GH.root") + file_sf_muon_trigger_BCDEF = TFile(datadir + "EfficienciesAndSF_RunBtoF.root") + file_sf_muon_id_BCDEF = TFile(datadir + "EfficienciesAndSF_ID_BCDEF.root") + file_sf_muon_iso_BCDEF = TFile(datadir + "EfficienciesAndSF_ISO_BCDEF.root") + file_sf_muon_tracking = TFile(datadir + "Tracking_EfficienciesAndSF_BCDEFGH.root") + + h_sf_muon_trigger_BCDEF = file_sf_muon_trigger_BCDEF.Get("IsoMu24_OR_IsoTkMu24_PtEtaBins/abseta_pt_ratio") + h_sf_muon_id_BCDEF = file_sf_muon_id_BCDEF.Get("MC_NUM_TightID_DEN_genTracks_PAR_pt_eta/abseta_pt_ratio") + h_sf_muon_iso_BCDEF = file_sf_muon_iso_BCDEF.Get("TightISO_TightID_pt_eta/abseta_pt_ratio") + h_sf_muon_trigger_GH = file_sf_muon_trigger_GH.Get("IsoMu24_OR_IsoTkMu24_PtEtaBins/abseta_pt_ratio") + h_sf_muon_id_GH = file_sf_muon_id_GH.Get("MC_NUM_TightID_DEN_genTracks_PAR_pt_eta/abseta_pt_ratio") + h_sf_muon_iso_GH = file_sf_muon_iso_GH.Get("TightISO_TightID_pt_eta/abseta_pt_ratio") + g_sf_muon_tracking = file_sf_muon_tracking.Get("ratio_eff_aeta_dr030e030_corr") + + sf_muon_trigger_BCDEF = scaleFactor(h_sf_muon_trigger_BCDEF) + sf_muon_id_BCDEF = scaleFactor(h_sf_muon_id_BCDEF) + sf_muon_iso_BCDEF = scaleFactor(h_sf_muon_iso_BCDEF) + sf_muon_trigger_GH = scaleFactor(h_sf_muon_trigger_GH) + sf_muon_id_GH = scaleFactor(h_sf_muon_id_GH) + sf_muon_iso_GH = scaleFactor(h_sf_muon_iso_GH) + sf_muon_tracking = scaleFactor_tracking(g_sf_muon_tracking,"sf_muon_tracking") + + muonhandle = Handle("vector") + muonlabel = ("goodMuons") + + methandle = Handle("vector") + metlabel = ("slimmedMETs") + jethandle = Handle('vector') + jetlabel = ('slimmedJets') +#jetlabel = ("GoodJets") + ### LHE weights + LHEweighthandle = Handle('LHEEventProduct') + LHEweightlabel = ("externalLHEProducer") + + ## Pileup reweighting + puphandle = Handle('vector') + puplabel = ("slimmedAddPileupInfo") + + hs_muon_pt = THStack("hs_muon_pt", "muon pt") + hs_muon_eta = THStack("hs_muon_eta", "muon eta") + hs_mtW = THStack("hs_mtW", "mtW") + hs_ptmiss = THStack("hs_ptmiss", "missing pt") + hs_j_n = THStack("hs_njets", "jet number") + + hs_list = hs_muon_pt, hs_muon_eta, hs_mtW, hs_ptmiss, hs_j_n + + collection = [] + hists_data = None + + tsize = 20 + tfont = 43 + + def __init__(self, name, isData=False, color=1): + self.name = name + self.isData = isData + self.h_muon_pt = TH1F(self.name + "_muon_pt", "pt of muon in " + self.name, 9, array('d', [0, 30, 35, 40, 45, 50, 60, 70, 100, 200])) + self.h_muon_eta = TH1F(self.name + "_muon_eta", "eta of the muon in " + self.name, 20, -2.4, 2.4) + self.h_mtW = TH1F(self.name + "_mtW", "reconstructed transverse mass of W " + self.name, 10, array('d', [0, 50, 60, 70, 80, 90, 100, 110, 120, 150, 200])) + self.h_ptmiss = TH1F(self.name + "_ptmiss", "missing transverse momentum in " + self.name, 11, array('d', [0, 10, 20, 30, 40, 50, 60, 70, 100, 120, 150, 200])) + self.h_njets = TH1F(self.name + "_njets", "number of jets in " +self.name, 20, -0.5, 19.5) + + self.hists = self.h_muon_pt, self.h_muon_eta, self.h_mtW, self.h_ptmiss, self.h_njets + + self.integral = 0. + + #remove status boxes + for hist in self.hists: + hist.SetStats(False) + + if self.isData==False: + process.collection.append(self) + for hist in self.hists: + hist.SetFillColor(color) + else: + process.hists_data = self + + self.h_muon_pt.SetXTitle("muon p_{T} (GeV)") + self.h_muon_eta.SetXTitle("muon eta") + self.h_mtW.SetXTitle("m_{T}^{W} (GeV)") + self.h_ptmiss.SetXTitle("p_{t}^{miss} (GeV)") + self.h_njets.SetXTitle("N_{Jet}") + + self.h_muon_pt.SetYTitle("Events/GeV") + self.h_muon_pt.GetYaxis().SetTitleOffset(1.2) + self.h_muon_eta.SetYTitle("Events/0.25") + self.h_mtW.SetYTitle("Events/GeV") + self.h_ptmiss.SetYTitle("Events/GeV") + self.h_njets.SetYTitle("Events") + + self.h_njets.GetXaxis().SetNdivisions(10,0,0) + + def fillHists(self, infile, islist=True, useLHEWeights=False, isData=False, eventIDs=[]): + print("start to fill hist: " + str(datetime.datetime.now())) + nevents = 0 + njets = 0 + directory = '' + + if islist is True: + print("loop over filelist " + str(infile)) + filelist = open(infile, 'r') + ifile = filelist.readline() + ifile = ifile[:-1] + directory = infile[:-len(infile.split('/')[-1])] + else: + ifile = infile + + while ifile != '': + print("process file ", ifile) + events = Events(directory + ifile) + + ### EVENT LOOP + for event in events: + eventID = event.eventAuxiliary().event() + + #if isData: # avoid double counting + # if eventID in eventIDs: + # # print("this event was already processed") + # continue + # eventIDs = np.append(eventIDs, eventID) + + nevents += 1 + njets += 4 + + + weight = 1. + weight_BCDEF = 1. + weight_GH = 1. + + # Fill muon hists + event.getByLabel(process.muonlabel, process.muonhandle) + muons = process.muonhandle.product() # get the product + muon = muons[0] + + muonPt = muon.pt() + muonEta = muon.eta() + + + # Fill mtw hists + event.getByLabel(process.metlabel, process.methandle) + mets = process.methandle.product() + met = mets[0] + + mtW = np.sqrt(2*(muon.pt()*met.pt() - muon.px()*met.px() - muon.py()*met.py())) + + # Fill jet hists + event.getByLabel(process.jetlabel, process.jethandle) + jets = process.jethandle.product() + + numJets = len(jets) + + # Compute Event weights + if useLHEWeights == True: + event.getByLabel(process.LHEweightlabel, process.LHEweighthandle) + weights = process.LHEweighthandle.product() + weight = weights.weights()[0].wgt / abs(weights.weights()[0].wgt) + + if isData == False: + event.getByLabel(process.puplabel, process.puphandle) + pupInfos = process.puphandle.product() + for pupInfo in pupInfos: + if (pupInfo.getBunchCrossing() == 0): + weight *= process.pupw.getPileupWeight(int(pupInfo.getTrueNumInteractions())) + + weight_BCDEF *= process.sf_muon_trigger_BCDEF.getScalefactor(abs(muonEta), muonPt) + weight_BCDEF *= process.sf_muon_id_BCDEF.getScalefactor(abs(muonEta), muonPt) + weight_BCDEF *= process.sf_muon_iso_BCDEF.getScalefactor(abs(muonEta), muonPt) + weight_GH *= process.sf_muon_trigger_GH.getScalefactor(abs(muonEta), muonPt) + weight_GH *= process.sf_muon_id_GH.getScalefactor(abs(muonEta), muonPt) + weight_GH *= process.sf_muon_iso_GH.getScalefactor(abs(muonEta), muonPt) + weight *= process.sf_muon_tracking.getScalefactor(abs(muonEta)) + + weight = weight * (weight_BCDEF * process.lumi_BCDEF + weight_GH * process.lumi_GH) + + + self.h_muon_pt.Fill(muonPt, weight) + self.h_muon_eta.Fill(muonEta, weight) + self.h_mtW.Fill(mtW, weight) + self.h_ptmiss.Fill(met.pt(), weight) + self.h_njets.Fill(numJets, weight) + + if islist is True: + ifile = filelist.readline() + ifile = ifile[:-1] + else: + break + + if islist is True: + print("close filelist") + filelist.close() + + print("processed events: ", nevents) + print("number of good jets: ", njets) + self.save_hists() + + def scale_hists(self,sigma=1.,lumi=1.,eff=1.): + for hist in self.hists: + hist.Scale(sigma*lumi*eff) + self.integral = self.hists[0].Integral() + + self.divideByBinWidth(self.hists[0]) + self.divideByBinWidth(self.hists[2]) + self.divideByBinWidth(self.hists[3]) + self.hists[1].Scale(4) + + def divideByBinWidth(self,hist): + for ibin in range(0, len(hist)): + content = hist.GetBinContent(ibin) + content /= hist.GetBinWidth(ibin) + hist.SetBinContent(ibin, content) + + def save_hists(self): + f1 = TFile(self.name + ".root", "RECREATE") + for hist in self.hists: + hist.Write() + f1.Close() + + def load_hists(self): + print("load " + self.name) + + if(os.path.isfile(self.name + ".root")): + f1 = TFile(self.name + ".root", "READ") + self.h_muon_pt.Add(f1.Get(self.name + "_muon_pt")) + self.h_muon_eta.Add(f1.Get(self.name + "_muon_eta")) + self.h_mtW.Add(f1.Get(self.name + "_mtW")) + self.h_ptmiss.Add(f1.Get(self.name + "_ptmiss")) + self.h_njets.Add(f1.Get(self.name + "_njets")) + + f1.Close() + else: + print("no file for this process") + + def draw_hists(self): + canvas = TCanvas(self.name, "", 800, 600) + for hist in self.hists: + canvas.Clear() + hist.Draw("HIST") + canvas.Print(hist.GetName()+".png") + + def setMinMax(self, y_min_muon_pt, y_max_muon_pt, y_min_muon_eta, y_max_muon_eta, y_min_mtW, y_max_mtW, y_min_ptmiss, y_max_ptmiss, y_min_njets, y_max_njets): + self.hists[0].SetMinimum(y_min_muon_pt) + self.hists[0].SetMaximum(y_max_muon_pt) + self.hists[1].SetMinimum(y_min_muon_eta) + self.hists[1].SetMaximum(y_max_muon_eta) + self.hists[2].SetMinimum(y_min_mtW) + self.hists[2].SetMaximum(y_max_mtW) + self.hists[3].SetMinimum(y_min_ptmiss) + self.hists[3].SetMaximum(y_max_ptmiss) + self.hists[4].SetMinimum(y_min_njets) + self.hists[4].SetMaximum(y_max_njets) + + @classmethod + def make_stacks(cls): + for proc in cls.collection: + for i,hist in enumerate(proc.hists): + cls.hs_list[i].Add(hist) + + + @classmethod + def print_stacks(cls): + cls.make_stacks() + + leg = TLegend(0.59, 0.54, 0.89, 0.84) + leg.SetBorderSize(0) + leg.SetTextFont(cls.tfont) + leg.AddEntry(cls.hists_data.hists[0], "data", "ep") + leg.AddEntry(cls.collection[8].hists[0], "t#bar{t}", "f") + leg.AddEntry(cls.collection[4].hists[0], "single t", "f") + leg.AddEntry(cls.collection[2].hists[0], "W+Jets", "f") + #leg.AddEntry(cls.collection[2].hists[0], "VV", "f") + leg.AddEntry(cls.collection[0].hists[0], "DY", "f") + + leg21 = TLegend(0.19, 0.69, 0.39, 0.84) + leg21.SetBorderSize(0) + leg21.SetTextFont(cls.tfont) + leg21.AddEntry(cls.hists_data.hists[0], "data", "ep") + leg21.AddEntry(cls.collection[8].hists[0], "t#bar{t}", "f") + leg21.AddEntry(cls.collection[4].hists[0], "single t", "f") + + leg22 = TLegend(0.69, 0.69, 0.89, 0.84) + leg22.SetBorderSize(0) + leg22.SetTextFont(cls.tfont) + leg22.AddEntry(cls.collection[2].hists[0], "W+Jets", "f") + #leg22.AddEntry(cls.collection[2].hists[0], "VV", "f") + leg22.AddEntry(cls.collection[0].hists[0], "DY", "f") + + leg.SetFillStyle(0) # make transparent + leg21.SetFillStyle(0) + leg22.SetFillStyle(0) + + canvas = TCanvas("c1","Example 2 pads (20,80)",200,10,800,600) + #canvas.SetBottomMargin(0.25) + pad1 = TPad("pad1", "The pad 80% of the height", 0, 0.2, 1, 1.0) + pad2 = TPad("pad2", "The pad 20% of the height", 0, 0.05, 1, 0.2) + + pad1.SetLeftMargin(0.15) + pad1.SetRightMargin(0.1) + pad2.SetLeftMargin(0.15) + pad2.SetRightMargin(0.1) + + pad1.SetBottomMargin(0.02) + pad2.SetTopMargin(0.02) + pad2.SetBottomMargin(0.25) + + pad1.Draw() + pad2.Draw() + for i, h_data in enumerate(cls.hists_data.hists): + + h_data.SetTitle("") + h_data.GetXaxis().SetLabelFont(cls.tfont) + h_data.GetXaxis().SetLabelSize(0) + h_data.GetXaxis().SetTitleSize(0) + h_data.GetYaxis().SetLabelFont(cls.tfont) + h_data.GetYaxis().SetLabelSize(cls.tsize) + h_data.GetYaxis().SetTitleFont(cls.tfont) + h_data.GetYaxis().SetTitleSize(cls.tsize) + h_data.GetYaxis().SetTitleOffset(1.5) + + h_data.SetMarkerStyle(20) + #pad1.Clear() + #pad2.Clear() + pad1.cd() + + h_data.Draw("E1") + cls.hs_list[i].Draw("HIST same") + h_data.Draw("E1 same") + gPad.RedrawAxis() # draw axis in foreground + + if i != 1: + leg.Draw("same") + else: + leg21.Draw("same") + leg22.Draw("same") + + pad2.cd() + h_ratio = TH1F(cls.hs_list[i].GetStack().Last()) + + h_ratio.SetTitle("") + h_ratio.GetXaxis().SetLabelFont(cls.tfont) + h_ratio.GetXaxis().SetLabelSize(cls.tsize) + h_ratio.GetYaxis().SetLabelFont(cls.tfont) + h_ratio.GetYaxis().SetLabelSize(cls.tsize) + h_ratio.GetXaxis().SetTitleFont(cls.tfont) + h_ratio.GetXaxis().SetTitleSize(cls.tsize) + h_ratio.GetYaxis().SetTitleFont(cls.tfont) + h_ratio.GetYaxis().SetTitleSize(cls.tsize) + h_ratio.GetXaxis().SetTitleOffset(7.) + h_ratio.GetYaxis().SetTitleOffset(1.5) + h_ratio.GetYaxis().SetNdivisions(403) + h_ratio.GetXaxis().SetTickLength(0.15) + + if i ==4: + h_ratio.GetXaxis().SetNdivisions(10, 0, 0) + + h_ratio.SetMarkerStyle(20) + h_ratio.SetXTitle(h_data.GetXaxis().GetTitle()) + + h_ratio.Divide(h_data) + h_ratio.GetYaxis().SetTitle("mc/data") + + h_ratio.SetMinimum(0.75) + h_ratio.SetMaximum(1.25) + + + middleLine = TLine(h_ratio.GetXaxis().GetXmin(),1. ,h_ratio.GetXaxis().GetXmax(), 1.) + + h_ratio.Draw("e1") + middleLine.Draw("same") + gStyle.SetErrorX(0.) + canvas.Print("stacks_" + str(i) + ".png") + + + +dy10to50 = process("dy10to50", color=593) +dy50 = process("dy50", color=593) +#ww = process("ww", color=393) +#wz = process("wz", color=393) +#zz = process("zz", color=393) +#wjets = process("wjets", color=409) +#w1jets = process("w1jets",color=409) +#w2jets = process("w2jets",color=409) +w3jets = process("w3jets",color=409) +w4jets = process("w4jets",color=409) +wt = process("wt", color=609) +wantit = process("wantit", color=609) +t_tchannel = process("t_tchannel", color=609) +antit_tchannel = process("antit_tchannel", color=609) +tt = process("tt", color=625) +data = process("data",isData=True) + +#for ip in process.collection: +# ip.load_hists() +#process.hists_data.load_hists() + +dy10to50.fillHists("dy10to50.txt",useLHEWeights=True) +dy50.fillHists("dy50.txt",useLHEWeights=True) +#ww.fillHists("ww.txt") +#wz.fillHists("wz.txt") +#zz.fillHists("zz.txt") +#wjets.fillHists("wjets.txt",useLHEWeights=True) +#w1jets.fillHists("w1jets.txt") +#w2jets.fillHists("w2jets.txt") +w3jets.fillHists("w3jets.txt") +w4jets.fillHists("w4jets.txt") +wt.fillHists("wt.txt") +wantit.fillHists("wantit.txt") +t_tchannel.fillHists("t_tchannel.txt") +antit_tchannel.fillHists("antit_tchannel.txt") +tt.fillHists("tt.txt") +data.fillHists("data.txt",isData=True) + + + +sigma_tt = 831760 +sigma_dy50 = 6025200 +sigma_dy10to50 = 22635100 +sigma_ww = 118700 +sigma_wz = 44900 +sigma_zz = 15400 +sigma_wantit = 35600 +sigma_wt = 35600 +sigma_t_tchannel = 136020 +sigma_antit_tchannel = 80950 +sigma_wjets = 61526700 +sigma_w1jets = 9625000 +sigma_w2jets = 3161000 +sigma_w3jets = 948200 #+-423 computed with https://twiki.cern.ch/twiki/bin/view/CMS/HowToGenXSecAnalyzer#Automated_scripts_to_compute_the +sigma_w4jets = 494600 + +# Efficiency = 1/(number of events before cuts), in case of lheweights its the +# effective number of events (in this case: number of events with positive weights - number of events with negative weights) +eff_tt = 1./(77081156 + 77867738) +eff_dy50 = 1./81781052 # effective number of events +#eff_dy50 = 1./122055388 # true number of events +eff_dy10to50 = 1./47946519 # effective number of events +#eff_dy10to50 = 1./65888233 # true number of events +eff_ww = 1./994012 +eff_wz = 1./1000000 +eff_zz = 1./998034 +eff_wantit = 1./6933094 +eff_wt = 1./6952830 +eff_t_tchannel = 1./67240808 +eff_antit_tchannel = 1./38811017 +eff_wjets = 1./16497031 # effective number of events +eff_w1jets = 1./45367044 +eff_w2jets = 1./29878415 +eff_w3jets = 1./19798117 +eff_w4jets = 1./9170576 +#eff_wjets = 1./24120319 # true number of events + +data.scale_hists() +tt.scale_hists(sigma = sigma_tt, eff = eff_tt) +dy50.scale_hists(sigma = sigma_dy50, eff = eff_dy50) +dy10to50.scale_hists(sigma = sigma_dy10to50, eff = eff_dy10to50) +#ww.scale_hists(sigma = sigma_ww, eff = eff_ww) +#wz.scale_hists(sigma = sigma_wz, eff = eff_wz) +#zz.scale_hists(sigma = sigma_zz, eff = eff_zz) +wantit.scale_hists(sigma = sigma_wantit, eff = eff_wantit) +wt.scale_hists(sigma = sigma_wt, eff = eff_wt) +t_tchannel.scale_hists(sigma = sigma_t_tchannel, eff = eff_t_tchannel) +antit_tchannel.scale_hists(sigma = sigma_antit_tchannel, eff = eff_antit_tchannel) +#wjets.scale_hists(sigma = sigma_wjets, eff = eff_wjets) +#w1jets.scale_hists(sigma = sigma_w1jets, eff = eff_w1jets) +#w2jets.scale_hists(sigma = sigma_w2jets, eff = eff_w2jets) +w3jets.scale_hists(sigma = sigma_w3jets, eff = eff_w3jets) +w4jets.scale_hists(sigma = sigma_w4jets, eff = eff_w4jets) + +data.setMinMax(0,20000,0,300000,0,18500,0,15000,0,140000) +title='plots_180515_mainContributions' + +directory = os.path.dirname('./'+title+'/') +# make a canvas, draw, and save it +if not os.path.exists(directory): + os.makedirs(directory) +os.chdir(directory) + +integral_mc = 0. +integral_data = process.hists_data.integral +for ip in process.collection: + integral_mc += ip.integral +print("integral of mc events is " + str(integral_mc)) +print("integral of data events is " + str(integral_data)) +print("data/mc = " +str(integral_data/integral_mc)) + +#for ip in process.collection: +# ip.draw_hists() +#process.hists_data.draw_hists() + +process.print_stacks() \ No newline at end of file diff --git a/DeepNtuplizer/plots/plot_features.py b/DeepNtuplizer/plots/plot_features.py index 77e263a64d0..1a77acb38e4 100644 --- a/DeepNtuplizer/plots/plot_features.py +++ b/DeepNtuplizer/plots/plot_features.py @@ -20,6 +20,13 @@ ROOT.gROOT.SetStyle('Plain') # white background ROOT.gStyle.SetFillStyle(0) +def isInt(a): + try: + int(a) + return True + except: + return False + def hist_bin_uncertainty(data, weights, bin_edges): """ The statistical uncertainity per bin of the binned data. @@ -146,6 +153,26 @@ def plot_features(self): err_mc = hist_bin_uncertainty(max_col_mc, self.weight_mc, binEdges) err_data = hist_bin_uncertainty(max_col_data, self.weight_data, binEdges) + if isInt(ifeature.fillopt): + ientry = int(ifeature.fillopt) + col_mc = np.empty((self.collection_mc[ifeature.name].shape)) + col_data = np.empty((self.collection_data[ifeature.name].shape)) + for j, arr in enumerate(self.collection_mc[ifeature.name]): + if len(arr) > ientry: + col_mc[j] = arr[ientry] + else: + col_mc[j] = -100 + + for j, arr in enumerate(self.collection_data[ifeature.name]): + if len(arr) > ientry: + col_data[j] = arr[ientry] + else: + col_data[j] = -100 + entries_mc, binEdges = np.histogram(col_mc, ifeature.bins, weights=self.weight_mc) + entries_data, _ = np.histogram(col_data, ifeature.bins, weights=self.weight_data) + err_mc = hist_bin_uncertainty(col_mc, self.weight_mc, binEdges) + err_data = hist_bin_uncertainty(col_data, self.weight_data, binEdges) + if ifeature.fillopt == '': entries_mc, binEdges = np.histogram(self.collection_mc[ifeature.name], ifeature.bins, weights=self.weight_mc) entries_data, _ = np.histogram(self.collection_data[ifeature.name], ifeature.bins, weights=self.weight_data) @@ -159,11 +186,11 @@ def plot_features(self): binWidth = binEdges[1:] - binEdges[:-1] ax.bar(bincenters, entries_mc, yerr = err_mc, width = binWidth, align='center', color='w', edgecolor='k',ecolor='k', label='mc') ax.errorbar(bincenters,entries_data*self.scalefactor_data, yerr=err_data*self.scalefactor_data, fmt='k.',ecolor='k', label='data') - ax.legend() + ax.legend(loc='best',numpoints=1, fontsize=20) ax.set_xlim(binEdges[0], binEdges[-1]) - ax.set_ylabel('weighted frequency') - ax.set_xlabel(ifeature.xlabel) - #ax.set_title(ifeature.fillopt+' entries of '+ifeature.name+' in GoodJets') + ax.set_ylabel('weighted frequency', fontsize=20) + ax.set_xlabel(ifeature.xlabel, fontsize=20) + ax.set_title(ifeature.description) ax.set_ylim(bottom=0) if ifeature.ymax != None: ax.set_ylim(top=ifeature.ymax) @@ -172,43 +199,60 @@ def plot_features(self): #ax.text(x_min + 0.01*(x_max-x_min),y_max*0.95,ifeature.description) ax.ticklabel_format(style='sci', scilimits=(-3, 4), axis='both') + plt.gcf().subplots_adjust(bottom=0.15) plt.savefig(ifeature.name+"_"+ifeature.fillopt+".png") -files_mc = ["tt_1_0.root","tt_2_0.root","tt_3_0.root","tt_4_0.root","tt_5_0.root", - "dy50_1_0.root","dy10to50_1_0.root","wantit_1_0.root","wt_1_0.root", - "ww_1_0.root","wz_1_0.root","zz_1_0.root","wjets_1_0.root"] +#files_mc = ["tt_1_0.root","tt_2_0.root","tt_3_0.root","tt_4_0.root","tt_5_0.root", +# "dy50_1_0.root","dy10to50_1_0.root","wantit_1_0.root","wt_1_0.root", +# "ww_1_0.root","wz_1_0.root","zz_1_0.root","wjets_1_0.root"] +files_mc = ["tt.root","tt_backup.root","tt_backup_2.root", + "dy50.root","dy10to50.root","wantit.root","wt.root", + "ww.root","wz.root","zz.root","wjets.root"] files_data = "muonEG_H_0.root" dc = datacollection(files_mc,files_data) -dc.add_feature("jet_pt", np.arange(0,390,15), xlabel='$p_\mathrm{T}(j)$ (GeV)', description='jet') -dc.add_feature("jet_eta", np.arange(-2.4,2.6,0.2), xlabel='$\eta(j)$', description='jet') -dc.add_feature("nCpfcand", np.arange(-0.5,30.5,1), xlabel='$N_\mathrm{cPF}$', description='charged particle flow candidate') -dc.add_feature("nNpfcand", np.arange(-0.5,30.5,1), xlabel='$N_\mathrm{nPF}$', description='neutral particle flow candidate') -dc.add_feature("npv", np.arange(-0.5,50.5,1), xlabel='$N_\mathrm{SV}$', description='primary vertices') -dc.add_feature("nsv", np.arange(-0.5,5.5,1), xlabel='$N_\mathrm{PV}$', description='secondary vertices') -dc.add_feature("TagVarCSV_trackSumJetEtRatio", np.arange(0.,1.04,0.04), xlabel='trackSumJetEtRatio', description='des') -dc.add_feature("TagVarCSV_trackSumJetDeltaR", np.arange(0.,0.26,0.01), xlabel='trackSumJetDeltaR', description='des') -dc.add_feature("TagVarCSV_vertexCategory", np.arange(-0.5,4.5,1), xlabel='vertexCategory', description='des') -dc.add_feature("TagVarCSV_trackSip2dValAboveCharm", np.array((-1.1,-0.9,-0.1,-0.08,-0.06,-0.04,-0.02,0.,0.02,0.04,0.06,0.08,0.1,0.12,0.14,0.16,0.18,0.2,0.22)), xlabel='trackSip2dValAboveCharm', description='des') -dc.add_feature("TagVarCSV_trackSip2dSigAboveCharm", np.arange(-1,21,1), xlabel='trackSip2dSigAboveCharm', description='des') -dc.add_feature("TagVarCSV_trackSip3dValAboveCharm", np.array((-1.1,-0.9,-0.1,-0.08,-0.06,-0.04,-0.02,0.,0.02,0.04,0.06,0.08,0.1,0.12,0.14,0.16,0.18,0.2,0.22)), xlabel='trackSip3dValAboveCharm', description='des') -dc.add_feature("TagVarCSV_trackSip3dSigAboveCharm", np.arange(-1,21,1), xlabel='trackSip3dSigAboveCharm', description='des') -dc.add_feature("TagVarCSV_jetNSelectedTracks", np.arange(0,21,1), xlabel='jetNSelectedTracks', description='des') -dc.add_feature("TagVarCSV_jetNTracksEtaRel", np.arange(0,16,1), xlabel='jetNTracksEtaRel', description='des') +#dc.add_feature("jet_pt", np.arange(0,390,15), xlabel='$p_\mathrm{T}(j)$ (GeV)', description='') +#dc.add_feature("jet_eta", np.arange(-2.4,2.6,0.2), xlabel='$\eta(j)$', description='') +#dc.add_feature("nCpfcand", np.arange(-0.5,30.5,1), xlabel='$N_\mathrm{cPF}$', description='') +#dc.add_feature("nNpfcand", np.arange(-0.5,30.5,1), xlabel='$N_\mathrm{nPF}$', description='') +#dc.add_feature("npv", np.arange(-0.5,50.5,1), xlabel='$N_\mathrm{PV}$', description='') +#dc.add_feature("nsv", np.arange(-0.5,5.5,1), xlabel='$N_\mathrm{SV}$', description='') +#dc.add_feature("TagVarCSV_trackSumJetEtRatio", np.arange(0.,1.04,0.04), xlabel='trackSumJetEtRatio', description='') +#dc.add_feature("TagVarCSV_trackSumJetDeltaR", np.arange(0.,0.26,0.01), xlabel='trackSumJetDeltaR', description='') +#dc.add_feature("TagVarCSV_vertexCategory", np.arange(-0.5,3.5,1), xlabel='vertexCategory', description='') +#dc.add_feature("TagVarCSV_trackSip2dValAboveCharm", np.array((-1.01,-0.99,-0.1,-0.08,-0.06,-0.04,-0.02,0.,0.02,0.04,0.06,0.08,0.1,0.12,0.14,0.16,0.18,0.2,0.22)), xlabel='trackSip2dValAboveCharm', description='') +#dc.add_feature("TagVarCSV_trackSip2dSigAboveCharm", np.arange(-1,21,1), xlabel='trackSip2dSigAboveCharm', description='') +#dc.add_feature("TagVarCSV_trackSip3dValAboveCharm", np.array((-1.01,-0.99,-0.1,-0.08,-0.06,-0.04,-0.02,0.,0.02,0.04,0.06,0.08,0.1,0.12,0.14,0.16,0.18,0.2,0.22)), xlabel='trackSip3dValAboveCharm', description='') +#dc.add_feature("TagVarCSV_trackSip3dSigAboveCharm", np.arange(-1,21,1), xlabel='trackSip3dSigAboveCharm', description='') +#dc.add_feature("TagVarCSV_jetNSelectedTracks", np.arange(-0.5,15.5,1), xlabel='jetNSelectedTracks', description='') +#dc.add_feature("TagVarCSV_jetNTracksEtaRel", np.arange(-0.5,15.5,1), xlabel='jetNTracksEtaRel', description='') + +dc.add_feature("pfDeepCSVJetTags_probb", np.arange(0, 1.05, 0.05), xlabel='pfDeepCSVJetTags_probb', description='') +dc.add_feature("pfDeepCSVJetTags_probbb", np.arange(0, 1.05, 0.05), xlabel='pfDeepCSVJetTags_probbb', description='') +dc.add_feature("pfDeepCSVJetTags_probc", np.arange(0, 1.05, 0.05), xlabel='pfDeepCSVJetTags_probc', description='') +dc.add_feature("pfDeepCSVJetTags_probcc", np.arange(0, 1.05, 0.05), xlabel='pfDeepCSVJetTags_probcc', description='') +dc.add_feature("pfDeepCSVJetTags_probudsg", np.arange(0, 1.05, 0.05), xlabel='pfDeepCSVJetTags_probudsg', description='') + #dc.add_feature("Cpfcan_pt", np.arange(0,105,5),fillopt='max',ymax=225000, xlabel='$p_\mathrm{T}(j)$ (GeV)', description='charged particle flow candidate') #dc.add_feature("Npfcan_pt", np.arange(0,105,5),fillopt='max',xlabel='$p_\mathrm{T}$ (GeV)', description='neutral particle flow candidate') #dc.add_feature("sv_pt", np.arange(0,110,10),fillopt='max', xlabel='$p_\mathrm{T}$ (GeV)', description='secondary vertice') +#dc.add_feature("Cpfcan_ptrel", np.arange(-1,-0.616,0.016),fillopt='0',xlabel=r'$\frac{p_\mathrm{T}(cPF)}{p_\mathrm{T}(j)}$', description='first entry') +#dc.add_feature("Npfcan_deltaR", np.arange(-0.6,0.024,0.024),fillopt='0',xlabel='$\Delta R_m(nPF,SV)$', description='first entry') +#dc.add_feature("Cpfcan_drminsv", np.arange(-0.5,0.02,0.02),fillopt='0',xlabel='$\Delta R_m(cPF,SV)$', description='first entry') +#dc.add_feature("sv_d3dsig", np.arange(0,102,2),fillopt='0',xlabel='$S_{3D}(SV)$', description='first entry') + + #dc.add_feature("Cpfcan_pt", np.arange(0,55,2.5),fillopt='all',ymax=5500000, xlabel='$p_\mathrm{T}$ (GeV)', description='charged particle flow candidate') #dc.add_feature("Npfcan_pt", np.arange(0,55,2.5),fillopt='all',ymax=6500000, xlabel='$p_\mathrm{T}$ (GeV)', description='neutral particle flow candidate') #dc.add_feature("sv_pt", np.arange(0,110,10),fillopt='all',ymax=190000, xlabel='$p_\mathrm{T}$ (GeV)', description='secondary vertice') -#dc.add_feature("sv_deltaR", np.arange(-0.5,0.02,0.02),fillopt='all', xlabel='$\Delta R$', description='secondary vertice') +#dc.add_feature("sv_deltaR", np.arange(-0.5,-0.116,0.016),fillopt='all', xlabel='$\Delta R$', description='secondary vertice') From 90af460a995a13aa4596098e43fa761149f5da14 Mon Sep 17 00:00:00 2001 From: David Walter Date: Thu, 17 May 2018 17:25:02 +0200 Subject: [PATCH 16/17] clean up --- DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py | 6 +++--- DeepNtuplizer/production/DeepNtuplizer_tt_semilep.py | 6 +++--- DeepNtuplizer/python/QGLikelihood_cfi.py | 4 ++-- DeepNtuplizer/src/ntuple_pfCands.cc | 5 ----- 4 files changed, 8 insertions(+), 13 deletions(-) diff --git a/DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py b/DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py index 39304554963..aac5315a5be 100644 --- a/DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py +++ b/DeepNtuplizer/production/DeepNtuplizer_tt_dilep.py @@ -85,7 +85,7 @@ #process.source.fileNames=['file:./00E02A09-853C-E711-93FF-3417EBE644A7.root'] #store/data/Run2016H/SingleMuon/MINIAOD/18Apr2017-v1/00000/00E02A09-853C-E711-93FF-3417EBE644A7.root #process.source.fileNames=['file:./000C6E52-8BEC-E611-B3FF-0025905C42FE.root'] #isData=True #process.source.fileNames=['file:./EE95DEDC-96BE-E611-B45D-A0000420FE80.root'] #isData=False -process.source.fileNames=['file:./0693E0E7-97BE-E611-B32F-0CC47A78A3D8.root'] #/store/mc/RunIISummer16MiniAODv2/TT_TuneCUETP8M2T4_13TeV-powheg-pythia8/MINIAODSIM/PUMoriond17_80X_mcRun2_asymptotic_2016_TrancheIV_v6-v1/80000/ +#process.source.fileNames=['file:./0693E0E7-97BE-E611-B32F-0CC47A78A3D8.root'] #/store/mc/RunIISummer16MiniAODv2/TT_TuneCUETP8M2T4_13TeV-powheg-pythia8/MINIAODSIM/PUMoriond17_80X_mcRun2_asymptotic_2016_TrancheIV_v6-v1/80000/ numberOfFiles = len(process.source.fileNames) @@ -368,8 +368,8 @@ process.looseIVFcandidateVertexArbitrator.secondaryVertices = cms.InputTag("looseIVFcandidateVertexMerger") process.looseIVFcandidateVertexArbitrator.fitterSigmacut = 20 -datapath=os.environ['CMSSW_BASE']+'/src/DeepNTuples/DeepNtuplizer/data/' -#datapath='' +#datapath=os.environ['CMSSW_BASE']+'/src/DeepNTuples/DeepNtuplizer/data/' +datapath='' # DeepNtuplizer configurations process.load("DeepNTuples.DeepNtuplizer.DeepNtuplizer_cfi") diff --git a/DeepNtuplizer/production/DeepNtuplizer_tt_semilep.py b/DeepNtuplizer/production/DeepNtuplizer_tt_semilep.py index def14a47828..44af5ee3443 100644 --- a/DeepNtuplizer/production/DeepNtuplizer_tt_semilep.py +++ b/DeepNtuplizer/production/DeepNtuplizer_tt_semilep.py @@ -84,7 +84,7 @@ #process.source.fileNames=['file:./000C6E52-8BEC-E611-B3FF-0025905C42FE.root'] #isData=True #process.source.fileNames=['file:./0693E0E7-97BE-E611-B32F-0CC47A78A3D8.root'] #isData=False #process.source.fileNames=['file:./EE95DEDC-96BE-E611-B45D-A0000420FE80.root'] #isData=False -process.source.fileNames=['file:./0693E0E7-97BE-E611-B32F-0CC47A78A3D8.root'] #store/mc/RunIISummer16MiniAODv2/TT_TuneCUETP8M2T4_13TeV-powheg-pythia8/MINIAODSIM/PUMoriond17_80X_mcRun2_asymptotic_2016_TrancheIV_v6-v1/50000/ +#process.source.fileNames=['file:./0693E0E7-97BE-E611-B32F-0CC47A78A3D8.root'] #store/mc/RunIISummer16MiniAODv2/TT_TuneCUETP8M2T4_13TeV-powheg-pythia8/MINIAODSIM/PUMoriond17_80X_mcRun2_asymptotic_2016_TrancheIV_v6-v1/50000/ #process.source.fileNames=['file:./00E02A09-853C-E711-93FF-3417EBE644A7.root'] #store/data/Run2016H/SingleMuon/MINIAOD/18Apr2017-v1/00000/ #process.source.fileNames=['file:./F21AE451-7EBA-E611-9399-0025905B858E.root'] #store/mc/RunIISummer16MiniAODv2/TT_TuneCUETP8M2T4_13TeV-powheg-pythia8/MINIAODSIM/PUMoriond17_backup_80X_mcRun2_asymptotic_2016_TrancheIV_v6-v1/00000/ @@ -353,8 +353,8 @@ process.looseIVFcandidateVertexArbitrator.secondaryVertices = cms.InputTag("looseIVFcandidateVertexMerger") process.looseIVFcandidateVertexArbitrator.fitterSigmacut = 20 -datapath=os.environ['CMSSW_BASE']+'/src/DeepNTuples/DeepNtuplizer/data/' -#datapath='' +#datapath=os.environ['CMSSW_BASE']+'/src/DeepNTuples/DeepNtuplizer/data/' +datapath='' # DeepNtuplizer configurations process.load("DeepNTuples.DeepNtuplizer.DeepNtuplizer_cfi") diff --git a/DeepNtuplizer/python/QGLikelihood_cfi.py b/DeepNtuplizer/python/QGLikelihood_cfi.py index ee7c35c2331..ffd7f4f022b 100644 --- a/DeepNtuplizer/python/QGLikelihood_cfi.py +++ b/DeepNtuplizer/python/QGLikelihood_cfi.py @@ -3,8 +3,8 @@ qgDatabaseVersion = 'cmssw8020_v2' -databasepath=os.environ['CMSSW_BASE']+'/src/DeepNTuples/DeepNtuplizer/data/QGL_cmssw8020_v2.db' -#databasepath='QGL_cmssw8020_v2.db' +#databasepath=os.environ['CMSSW_BASE']+'/src/DeepNTuples/DeepNtuplizer/data/QGL_cmssw8020_v2.db' +databasepath='QGL_cmssw8020_v2.db' from CondCore.CondDB.CondDB_cfi import * QGPoolDBESSource = cms.ESSource("PoolDBESSource", diff --git a/DeepNtuplizer/src/ntuple_pfCands.cc b/DeepNtuplizer/src/ntuple_pfCands.cc index 6dfdfffba76..a391e0dbde1 100644 --- a/DeepNtuplizer/src/ntuple_pfCands.cc +++ b/DeepNtuplizer/src/ntuple_pfCands.cc @@ -246,11 +246,6 @@ void ntuple_pfCands::readEvent(const edm::Event& iEvent){ //use either of these functions bool ntuple_pfCands::fillBranches(const pat::Jet & jet, const size_t& jetidx, const edm::View * coll){ - if(jet.pt() > 99.07 && jet.pt()< 99.08){ - std::cout<<" pfCands ..."< Date: Mon, 28 May 2018 12:33:31 +0200 Subject: [PATCH 17/17] new ttbar semileptonic single electron selection; take total eventweight for better workflow; bug fixes --- DeepNtuplizer/interface/ntuple_eventInfo.h | 8 +- DeepNtuplizer/plugins/DeepNtuplizer.cc | 7 +- DeepNtuplizer/plugins/ttsemilepFilter.cc | 37 +- ...milep.py => DeepNtuplizer_tt_semilep_e.py} | 55 ++- .../production/DeepNtuplizer_tt_semilep_mu.py | 428 ++++++++++++++++++ DeepNtuplizer/python/DeepNtuplizer_cfi.py | 8 +- DeepNtuplizer/src/mergeDescriptor.cc | 2 + DeepNtuplizer/src/ntuple_eventInfo.cc | 30 +- 8 files changed, 517 insertions(+), 58 deletions(-) rename DeepNtuplizer/production/{DeepNtuplizer_tt_semilep.py => DeepNtuplizer_tt_semilep_e.py} (88%) create mode 100644 DeepNtuplizer/production/DeepNtuplizer_tt_semilep_mu.py diff --git a/DeepNtuplizer/interface/ntuple_eventInfo.h b/DeepNtuplizer/interface/ntuple_eventInfo.h index 8909828aef7..0a25217eca4 100644 --- a/DeepNtuplizer/interface/ntuple_eventInfo.h +++ b/DeepNtuplizer/interface/ntuple_eventInfo.h @@ -26,7 +26,7 @@ void readHistoFromGraph(TGraphAsymmErrors* graph, TH1D** h, TString name); void initializeScalefactor(std::vector dirs, std::vector names, std::vector* sfHists, std::vector periods); void initializeScalefactor(std::vector dirs, std::vector names, std::vector* sfHists, std::vector periods); -double getScalefactor(double x, double y, std::vector hists, unsigned int period); +double getScalefactor(double x, double y, std::vector hists, unsigned int period, bool takeOverflowX = false); double getScalefactor(double x, std::vector hists, unsigned int period); @@ -80,6 +80,9 @@ class ntuple_eventInfo: public ntuple_content{ std::vector lumis; std::vector periods; + double sigma; + unsigned int nEvents; + std::string pupDataDir_; std::string pupMCDir_; @@ -90,6 +93,8 @@ class ntuple_eventInfo: public ntuple_content{ std::vector sfTrigger_mu_Dir_; std::vector sfTrigger_mu_Name_; + std::vector sfTrigger_e_Dir_; + std::vector sfTrigger_e_Name_; std::vector sfTrigger_emu_Dir_; std::vector sfTrigger_emu_Name_; std::vector sfMuonId_Dir_; @@ -102,6 +107,7 @@ class ntuple_eventInfo: public ntuple_content{ std::vector sfMuonTracking_Name_; std::vector sfTrigger_mu_Hist; + std::vector sfTrigger_e_Hist; std::vector sfTrigger_emu_Hist; std::vector sfMuonId_Hist; std::vector sfMuonIso_Hist; diff --git a/DeepNtuplizer/plugins/DeepNtuplizer.cc b/DeepNtuplizer/plugins/DeepNtuplizer.cc index c1def2b9fba..6890dd87eae 100644 --- a/DeepNtuplizer/plugins/DeepNtuplizer.cc +++ b/DeepNtuplizer/plugins/DeepNtuplizer.cc @@ -193,16 +193,15 @@ DeepNtuplizer::DeepNtuplizer(const edm::ParameterSet& iConfig): ntuple_bTagVars * btagvars = new ntuple_bTagVars(); addModule(btagvars); - if(!isData){ - ntuple_eventInfo *evweight = new ntuple_eventInfo(); + ntuple_eventInfo *evweight = new ntuple_eventInfo(); + if(!isData){ evweight->setLHEToken(consumes(iConfig.getParameter("lheInfo"))); evweight->setMuonsToken(consumes >(iConfig.getParameter("sfMuons"))); evweight->setElectronsToken(consumes >(iConfig.getParameter("sfElectrons"))); evweight->setTriggerToken(consumes(iConfig.getParameter("triggerToken"))); - - addModule(evweight); } + addModule(evweight); if(runFatJets_){ diff --git a/DeepNtuplizer/plugins/ttsemilepFilter.cc b/DeepNtuplizer/plugins/ttsemilepFilter.cc index c86204ccc8b..12e3780b8c1 100644 --- a/DeepNtuplizer/plugins/ttsemilepFilter.cc +++ b/DeepNtuplizer/plugins/ttsemilepFilter.cc @@ -74,7 +74,9 @@ class ttsemilepFilter : public edm::stream::EDFilter<> { edm::Handle > jets; edm::Handle > mets; - double minMT_muonMETpair = 0.; + double minMT_muonMETpair = 0; + unsigned int nElectrons = 0; + unsigned int nMuons = 0; /* double min_chi2 = 0; @@ -111,7 +113,10 @@ ttsemilepFilter::ttsemilepFilter(const edm::ParameterSet& iConfig): //minPt_muon=(iConfig.getParameter("minPt_muon")); //minPt_jet=(iConfig.getParameter("minPt_jet")); - minMT_muonMETpair=(iConfig.getParameter("cut_minMT_muonMETpair")); + minMT_muonMETpair=(iConfig.getParameter("cut_minMT_leptonMETpair")); + nElectrons=(iConfig.getParameter("nElectrons")); + nMuons=(iConfig.getParameter("nMuons")); + } @@ -132,15 +137,17 @@ ttsemilepFilter::~ttsemilepFilter() bool ttsemilepFilter::filter(edm::Event& iEvent, const edm::EventSetup& iSetup) { + iEvent.getByToken(src_muons, muons); iEvent.getByToken(src_electrons, electrons); iEvent.getByToken(src_jets, jets); iEvent.getByToken(src_mets, mets); - if(muons->size()!=1) + + if(muons->size()!=nMuons) return false; - if(electrons->size()!=0) + if(electrons->size()!=nElectrons) return false; if(jets->size()!=4) @@ -152,14 +159,28 @@ ttsemilepFilter::filter(edm::Event& iEvent, const edm::EventSetup& iSetup) } - const auto muon = muons->ptrAt(0); const auto met = mets->ptrAt(0); + double mWt = -1.; + + if(nMuons==1 && nElectrons==0){ + const auto muon = muons->ptrAt(0); + mWt = std::sqrt(2*(muon->pt()*met->pt() - muon->px()*met->px() - muon->py()*met->py())); + } + else if (nElectrons==1 && nMuons==0){ + const auto electron = electrons->ptrAt(0); + mWt = std::sqrt(2*(electron->pt()*met->pt() - electron->px()*met->px() - electron->py()*met->py())); + } - double mWt = std::sqrt(2*(muon->pt()*met->pt() - muon->px()*met->px() - muon->py()*met->py())); - //leptonic decaying W reconstruction - if(mWt < minMT_muonMETpair) + + + if(mWt == -1.){ //no W reconstruction + } + else if(mWt < minMT_muonMETpair){ //leptonic decaying W reconstruction return false; + } + + //hadronically decaying t reconstruction /* diff --git a/DeepNtuplizer/production/DeepNtuplizer_tt_semilep.py b/DeepNtuplizer/production/DeepNtuplizer_tt_semilep_e.py similarity index 88% rename from DeepNtuplizer/production/DeepNtuplizer_tt_semilep.py rename to DeepNtuplizer/production/DeepNtuplizer_tt_semilep_e.py index 44af5ee3443..a19689f3bc5 100644 --- a/DeepNtuplizer/production/DeepNtuplizer_tt_semilep.py +++ b/DeepNtuplizer/production/DeepNtuplizer_tt_semilep_e.py @@ -1,5 +1,5 @@ # this can be run with CMSSW 8_0_29; in CMSSW 8_0_25 the module 'cutBasedElectronID_Summer16_80X_V1_cff' is missing -#basically deepntuplizer with tt semileptonic selection +#basically deepntuplizer with tt semileptonic single electron selection import FWCore.ParameterSet.Config as cms @@ -21,6 +21,9 @@ options.register('isData', False, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.bool, "switch off generator jets") options.register('deepNtuplizer',True, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.bool, "run deepNtuplizer or just the ttbar selection") options.register('lheWeights',False, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.bool, "use LHE weights") +options.register('crossSection', 1., VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.float,"cross section") +options.register('nEvents', 1, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int,"number of events to process") + import os @@ -37,7 +40,7 @@ if hasattr(sys, "argv"): options.parseArguments() -process = cms.Process("semilepSelectedDNNFiller") +process = cms.Process("semilepElectronSelectedDNNFiller") process.load("FWCore.MessageService.MessageLogger_cfi") process.load("Configuration.EventContent.EventContent_cff") @@ -80,8 +83,7 @@ process.load(options.inputScript) -#process.source.fileNames=['file:./00E02A09-853C-E711-93FF-3417EBE644A7.root'] #store/data/Run2016H/SingleMuon/MINIAOD/18Apr2017-v1/00000/00E02A09-853C-E711-93FF-3417EBE644A7.root -#process.source.fileNames=['file:./000C6E52-8BEC-E611-B3FF-0025905C42FE.root'] #isData=True +#process.source.fileNames=['file:./00CC509E-0C3B-E711-98F2-0242AC130004.root'] #isData=True #process.source.fileNames=['file:./0693E0E7-97BE-E611-B32F-0CC47A78A3D8.root'] #isData=False #process.source.fileNames=['file:./EE95DEDC-96BE-E611-B45D-A0000420FE80.root'] #isData=False #process.source.fileNames=['file:./0693E0E7-97BE-E611-B32F-0CC47A78A3D8.root'] #store/mc/RunIISummer16MiniAODv2/TT_TuneCUETP8M2T4_13TeV-powheg-pythia8/MINIAODSIM/PUMoriond17_80X_mcRun2_asymptotic_2016_TrancheIV_v6-v1/50000/ @@ -180,8 +182,7 @@ #HighLevelTrigger -HLTlistSM = cms.vstring("HLT_IsoTkMu24_v*", #Run B-H - "HLT_IsoMu24_v*" #Run B-H +HLTlistSM = cms.vstring("HLT_Ele27_WPTight_Gsf_v*" ) process.TriggerSel = cms.EDFilter("HLTHighLevel", TriggerResultsTag = cms.InputTag("TriggerResults","","HLT"), @@ -245,7 +246,9 @@ src_electrons = cms.InputTag("goodElectrons"), src_jets = cms.InputTag("goodJets"), src_mets = cms.InputTag("slimmedMETs"), - cut_minMT_muonMETpair = cms.double(50.0) + cut_minMT_leptonMETpair = cms.double(50.0), + nElectrons=cms.uint32(1), + nMuons=cms.uint32(0) ) @@ -364,41 +367,35 @@ process.deepntuplizer.LooseSVs = cms.InputTag("looseIVFinclusiveCandidateSecondaryVertices") process.deepntuplizer.applySelection = cms.bool(options.selectJets) -process.deepntuplizer.removeUndefined = cms.bool(False) process.deepntuplizer.isData = cms.bool(options.isData) -process.deepntuplizer.useLHEWeights = cms.bool(options.lheWeights) -process.deepntuplizer.pileupData=cms.string(datapath+"pileup_data_2016.root") -process.deepntuplizer.pileupMC=cms.string(datapath+"pileup_MC_2016.root") -process.deepntuplizer.sfMuons = cms.InputTag("goodMuons") +process.deepntuplizer.removeUndefined = cms.bool(False) + +if not options.isData: + process.deepntuplizer.useLHEWeights = cms.bool(options.lheWeights) -process.deepntuplizer.periods=cms.vstring("2016BtoF","2016GH") -process.deepntuplizer.lumis=cms.vdouble(5.404+2.396+4.256+4.054+3.105, 7.179+8.746) + process.deepntuplizer.pileupData=cms.string(datapath+"pileup_data_2016.root") + process.deepntuplizer.pileupMC=cms.string(datapath+"pileup_MC_2016.root") -process.deepntuplizer.sfTrigger_mu=cms.vstring(datapath + "EfficienciesAndSF_RunBtoF.root", - datapath + "EfficienciesAndSF_Period4.root") -process.deepntuplizer.sfTrigger_mu_Hist=cms.vstring("IsoMu24_OR_IsoTkMu24_PtEtaBins/abseta_pt_ratio", - "IsoMu24_OR_IsoTkMu24_PtEtaBins/abseta_pt_ratio") + process.deepntuplizer.sfElectrons = cms.InputTag("goodElectrons") -process.deepntuplizer.sfMuonId = cms.vstring(datapath+"EfficienciesAndSF_ID_BCDEF.root", - datapath+"EfficienciesAndSF_ID_GH.root") -process.deepntuplizer.sfMuonId_Hist = cms.vstring("MC_NUM_TightID_DEN_genTracks_PAR_pt_eta/abseta_pt_ratio", - "MC_NUM_TightID_DEN_genTracks_PAR_pt_eta/abseta_pt_ratio") + process.deepntuplizer.periods=cms.vstring("2016All",) + process.deepntuplizer.lumis=cms.vdouble(1.,) + process.deepntuplizer.crossSection=cms.double(options.crossSection) + process.deepntuplizer.nEvents=cms.uint32(options.nEvents) -process.deepntuplizer.sfMuonIso=cms.vstring(datapath+"EfficienciesAndSF_ISO_BCDEF.root", - datapath+"EfficienciesAndSF_ISO_GH.root") -process.deepntuplizer.sfMuonIso_Hist=cms.vstring("TightISO_TightID_pt_eta/abseta_pt_ratio", - "TightISO_TightID_pt_eta/abseta_pt_ratio") + process.deepntuplizer.sfTrigger_e=cms.vstring(datapath + "TriggerSF_Run2016All_v1.root",) + process.deepntuplizer.sfTrigger_e_Hist=cms.vstring("Ele27_WPTight_Gsf",) -process.deepntuplizer.sfMuonTracking=cms.vstring(datapath+"Tracking_EfficienciesAndSF_BCDEFGH.root") -process.deepntuplizer.sfMuonTracking_Hist=cms.vstring("ratio_eff_aeta_dr030e030_corr") + process.deepntuplizer.sfElIdAndIso=cms.vstring(datapath+"egammaEffi.txt_EGM2D.root",) + process.deepntuplizer.sfElIdAndIso_Hist=cms.vstring("EGamma_SF2D",) + process.deepntuplizer.gluonReduction = cms.double(options.gluonReduction) if int(release.replace("_", "")) >= 840: process.deepntuplizer.tagInfoName = cms.string('pfDeepCSV') -process.deepntuplizer.gluonReduction = cms.double(options.gluonReduction) # 1631 #process.ProfilerService = cms.Service( diff --git a/DeepNtuplizer/production/DeepNtuplizer_tt_semilep_mu.py b/DeepNtuplizer/production/DeepNtuplizer_tt_semilep_mu.py new file mode 100644 index 00000000000..df624a611fb --- /dev/null +++ b/DeepNtuplizer/production/DeepNtuplizer_tt_semilep_mu.py @@ -0,0 +1,428 @@ +# this can be run with CMSSW 8_0_29; in CMSSW 8_0_25 the module 'cutBasedElectronID_Summer16_80X_V1_cff' is missing +#basically deepntuplizer with tt semileptonic selection + +import FWCore.ParameterSet.Config as cms + +import FWCore.ParameterSet.VarParsing as VarParsing +### parsing job options +import sys + +options = VarParsing.VarParsing() + +options.register('inputScript', '', VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.string,"input Script") +options.register('outputFile', 'output', VarParsing.VarParsing.multiplicity.singleton,VarParsing.VarParsing.varType.string, "output File (w/o .root)") +options.register('maxEvents', -1, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int,"maximum events") +options.register('skipEvents', 0, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int, "skip N events") +options.register('job', 0, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int,"job number") +options.register('nJobs', 1, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int, "total jobs") +options.register('gluonReduction', 0.0, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.float, "gluon reduction") +options.register('selectJets', True, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.bool,"select jets with good gen match") +options.register('globalTag', '', VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.string,"global tag for jet energy correction") +options.register('isData', False, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.bool, "switch off generator jets") +options.register('deepNtuplizer',True, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.bool, "run deepNtuplizer or just the ttbar selection") +options.register('lheWeights',False, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.bool, "use LHE weights") +options.register('crossSection', 1., VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.float,"cross section") +options.register('nEvents', 1, VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.int,"number of events to process") + +import os + +release = os.environ['CMSSW_VERSION'][6:12] +print("Using release " + release) + +options.register( + 'inputFiles', '', + VarParsing.VarParsing.multiplicity.list, + VarParsing.VarParsing.varType.string, + "input files (default is the tt RelVal)" +) + +if hasattr(sys, "argv"): + options.parseArguments() + +process = cms.Process("semilepMuonSelectedDNNFiller") + +process.load("FWCore.MessageService.MessageLogger_cfi") +process.load("Configuration.EventContent.EventContent_cff") +process.load('Configuration.StandardSequences.Services_cff') +process.load('Configuration.StandardSequences.GeometryRecoDB_cff') +process.load('Configuration.StandardSequences.MagneticField_cff') +process.load('Configuration.StandardSequences.FrontierConditions_GlobalTag_cff') + +if options.globalTag == '': + if options.isData == False: + process.GlobalTag.globaltag = '80X_mcRun2_asymptotic_2016_TrancheIV_v8' # For MC Jet Energy correction + if options.isData == True: + process.GlobalTag.globaltag = '80X_dataRun2_2016SeptRepro_v7' # For Data Jet Energy correction +else: + process.GlobalTag.globaltag = options.globalTag + +process.maxEvents = cms.untracked.PSet(input=cms.untracked.int32(-1)) +#process.PoolSource = cms.untracked.PSet( +# firstEvent = cms.untracked.uint32(33285817), +#) + +process.load('FWCore.MessageService.MessageLogger_cfi') +process.MessageLogger.cerr.FwkReport.reportEvery = 10 +if options.inputScript == '': # this is probably for testing + process.MessageLogger.cerr.FwkReport.reportEvery = 100 + +process.options = cms.untracked.PSet( + allowUnscheduled=cms.untracked.bool(True), + wantSummary=cms.untracked.bool(False), + SkipEvent = cms.untracked.vstring('ProductNotFound') +) + + +process.load('DeepNTuples.DeepNtuplizer.samples.TTJetsPhase1_cfg') # default input + +if options.inputFiles: + process.source.fileNames = options.inputFiles + +if options.inputScript != '' and options.inputScript != 'DeepNTuples.DeepNtuplizer.samples.TTJetsPhase1_cfg': + process.load(options.inputScript) + + +#process.source.fileNames=['file:./00E02A09-853C-E711-93FF-3417EBE644A7.root'] #store/data/Run2016H/SingleMuon/MINIAOD/18Apr2017-v1/00000/00E02A09-853C-E711-93FF-3417EBE644A7.root +#process.source.fileNames=['file:./02AAA49F-C83A-E711-B51F-0CC47AA53D82.root'] #isData=True +#process.source.fileNames=['file:./0693E0E7-97BE-E611-B32F-0CC47A78A3D8.root'] #isData=False +#process.source.fileNames=['file:./EE95DEDC-96BE-E611-B45D-A0000420FE80.root'] #isData=False +#process.source.fileNames=['file:./0693E0E7-97BE-E611-B32F-0CC47A78A3D8.root'] #store/mc/RunIISummer16MiniAODv2/TT_TuneCUETP8M2T4_13TeV-powheg-pythia8/MINIAODSIM/PUMoriond17_80X_mcRun2_asymptotic_2016_TrancheIV_v6-v1/50000/ +#process.source.fileNames=['file:./00E02A09-853C-E711-93FF-3417EBE644A7.root'] #store/data/Run2016H/SingleMuon/MINIAOD/18Apr2017-v1/00000/ +#process.source.fileNames=['file:./F21AE451-7EBA-E611-9399-0025905B858E.root'] #store/mc/RunIISummer16MiniAODv2/TT_TuneCUETP8M2T4_13TeV-powheg-pythia8/MINIAODSIM/PUMoriond17_backup_80X_mcRun2_asymptotic_2016_TrancheIV_v6-v1/00000/ + +#process.source.fileNames=['file:./00CC509E-0C3B-E711-98F2-0242AC130004.root'] #Run2016B/SingleMuon/MINIAOD/18Apr2017_ver2-v1/ +numberOfFiles = len(process.source.fileNames) +numberOfJobs = options.nJobs +jobNumber = options.job + +process.source.fileNames = process.source.fileNames[jobNumber:numberOfFiles:numberOfJobs] +#if options.nJobs > 1: +print ("running over these files:") +print (process.source.fileNames) + +process.globalInfo = cms.EDAnalyzer('globalInfo', + lheInfo = cms.InputTag("externalLHEProducer"), + useLHEWeights=cms.bool(options.lheWeights) + ) + +process.source.skipEvents = cms.untracked.uint32(options.skipEvents) +process.maxEvents = cms.untracked.PSet( + input=cms.untracked.int32(options.maxEvents) +) + +if int(release.replace("_", "")) >= 8400 or int(release.replace("_", "")) == 8029: + bTagInfos = [ + 'pfImpactParameterTagInfos', + 'pfInclusiveSecondaryVertexFinderTagInfos', + 'pfDeepCSVTagInfos'] +else: + bTagInfos = [ + 'pfImpactParameterTagInfos', + 'pfInclusiveSecondaryVertexFinderTagInfos', + 'deepNNTagInfos', + ] + +if int(release.replace("_", "")) >= 8400 or int(release.replace("_", "")) == 8029: + bTagDiscriminators = [ + 'softPFMuonBJetTags', + 'softPFElectronBJetTags', + 'pfJetBProbabilityBJetTags', + 'pfJetProbabilityBJetTags', + 'pfCombinedInclusiveSecondaryVertexV2BJetTags', + 'pfDeepCSVJetTags:probudsg', # to be fixed with new names + 'pfDeepCSVJetTags:probb', + 'pfDeepCSVJetTags:probc', + 'pfDeepCSVJetTags:probbb', + 'pfDeepCSVJetTags:probcc', + ] +else: + bTagDiscriminators = [ + 'softPFMuonBJetTags', + 'softPFElectronBJetTags', + 'pfJetBProbabilityBJetTags', + 'pfJetProbabilityBJetTags', + 'pfCombinedInclusiveSecondaryVertexV2BJetTags', + 'deepFlavourJetTags:probudsg', # to be fixed with new names + 'deepFlavourJetTags:probb', + 'deepFlavourJetTags:probc', + 'deepFlavourJetTags:probbb', + 'deepFlavourJetTags:probcc', + ] + +###### semilep selection +outFileName = options.outputFile + '_' + str(options.job) + '.root' +print ('Using output file ' + outFileName) + +if options.deepNtuplizer: + process.TFileService = cms.Service("TFileService", + fileName=cms.string(outFileName)) +else: + process.MINIAODSIMEventContent.outputCommands.extend([ + 'keep *_goodElectrons_*_*', + 'keep *_goodMuons_*_*', + 'keep *_goodJets_*_*', + ]) + + process.outmod = cms.OutputModule("PoolOutputModule", + process.MINIAODSIMEventContent, + SelectEvents = cms.untracked.PSet( + SelectEvents = cms.vstring('p') + ), + fileName = cms.untracked.string(outFileName) + ) + +from PhysicsTools.SelectorUtils.tools.vid_id_tools import * +dataFormat = DataFormat.MiniAOD +switchOnVIDElectronIdProducer(process, dataFormat) +my_id_modules = [ + 'RecoEgamma.ElectronIdentification.Identification.cutBasedElectronID_Summer16_80X_V1_cff' +] +for idmod in my_id_modules: + setupAllVIDIdsInModule(process,idmod,setupVIDElectronSelection) + + +#HighLevelTrigger +HLTlistSM = cms.vstring("HLT_IsoTkMu24_v*", #Run B-H + "HLT_IsoMu24_v*" #Run B-H + ) +process.TriggerSel = cms.EDFilter("HLTHighLevel", + TriggerResultsTag = cms.InputTag("TriggerResults","","HLT"), + HLTPaths = cms.vstring(HLTlistSM), + eventSetupPathsKey = cms.string(''), # not empty => use read paths from AlCaRecoTriggerBitsRcd via this key + andOr = cms.bool(True), # how to deal with multiple triggers: True (OR) accept if ANY is true, False (AND) accept if ALL are true + throw = cms.bool(True) # throw exception on unknown path names +) +### Electron Selection +process.goodElectrons = cms.EDProducer("ElectronIdAdder", + src=cms.InputTag("slimmedElectrons"), + vSrc=cms.InputTag("offlineSlimmedPrimaryVertices"), + idMap=cms.InputTag("egmGsfElectronIDs:cutBasedElectronID-Summer16-80X-V1-tight"), + minPt=cms.double(20.0), + maxAbsEta=cms.double(2.4), + ) + +### Muon Selection +process.goodMuons = cms.EDProducer("MuonIdAdder", + src=cms.InputTag("slimmedMuons"), + vSrc=cms.InputTag("offlineSlimmedPrimaryVertices"), + minPt=cms.double(30.0), + maxAbsEta=cms.double(2.4), + maxRMI=cms.double(0.15) #RMI = relative muon isolation + ) + +### Jet Selection +process.goodJets = cms.EDProducer("PATJetCleaner", + src = cms.InputTag("slimmedJets"), + preselection = cms.string("pt>30 && abs(eta) < 2.4 && neutralHadronEnergyFraction < 0.99 " + "&& neutralEmEnergyFraction < 0.99 && (chargedMultiplicity+neutralMultiplicity) > 1 " + "&& chargedHadronEnergyFraction > 0.0 " + "&& chargedMultiplicity > 0.0 && chargedEmEnergyFraction < 0.99 "), + checkOverlaps = cms.PSet( + muons = cms.PSet( + src = cms.InputTag("goodMuons"), + algorithm = cms.string("byDeltaR"), + preselection = cms.string(""), + deltaR = cms.double(0.4), + checkRecoComponents = cms.bool(False), # don't check if they share some AOD object ref + pairCut = cms.string(""), + requireNoOverlaps = cms.bool(True), # overlaps cause the jet to be discarded + ), + electrons = cms.PSet( + src = cms.InputTag("goodElectrons"), + algorithm = cms.string("byDeltaR"), + preselection = cms.string(""), + deltaR = cms.double(0.4), + checkRecoComponents = cms.bool(False), # don't check if they share some AOD object ref + pairCut = cms.string(""), + requireNoOverlaps = cms.bool(True), # overlaps cause the jet to be discarded + ) + ), + finalCut = cms.string('') + ) + + +### Event Filter +process.ttsemilepFilter = cms.EDFilter("ttsemilepFilter", + src_muons = cms.InputTag("goodMuons"), + src_electrons = cms.InputTag("goodElectrons"), + src_jets = cms.InputTag("goodJets"), + src_mets = cms.InputTag("slimmedMETs"), + cut_minMT_leptonMETpair = cms.double(50.0), + nElectrons=cms.uint32(0), + nMuons=cms.uint32(1) + ) + + +### end selection + +# Jet Energy Corrections +if options.isData: + jetCorrections = cms.vstring(['L1FastJet', 'L2Relative', 'L3Absolute', 'L2L3Residual']) +else: + jetCorrections = cms.vstring(['L1FastJet', 'L2Relative', 'L3Absolute']) + +from PhysicsTools.PatAlgos.tools.jetTools import updateJetCollection +updateJetCollection( + process, + labelName="DeepFlavour", + # jetSource=cms.InputTag('slimmedJetsAK8PFPuppiSoftDropPacked', 'SubJets'), # 'subjets from AK8' + jetSource=cms.InputTag('goodJets'), # 'ak4Jets' + jetCorrections=('AK4PFchs', jetCorrections, 'None'), + pfCandidates=cms.InputTag('packedPFCandidates'), + pvSource=cms.InputTag("offlineSlimmedPrimaryVertices"), + svSource=cms.InputTag('slimmedSecondaryVertices'), + muSource=cms.InputTag('slimmedMuons'), + elSource=cms.InputTag('slimmedElectrons'), + btagInfos=bTagInfos, + btagDiscriminators=bTagDiscriminators, + explicitJTA=False + ) + +if hasattr(process, 'updatedPatJetsTransientCorrectedDeepFlavour'): + process.updatedPatJetsTransientCorrectedDeepFlavour.addTagInfos = cms.bool(True) + process.updatedPatJetsTransientCorrectedDeepFlavour.addBTagInfo = cms.bool(True) +else: + raise ValueError( + 'I could not find updatedPatJetsTransientCorrectedDeepFlavour to embed the tagInfos, please check the cfg') + +# QGLikelihood +process.load("DeepNTuples.DeepNtuplizer.QGLikelihood_cfi") +process.es_prefer_jec = cms.ESPrefer("PoolDBESSource", "QGPoolDBESSource") +process.load('RecoJets.JetProducers.QGTagger_cfi') +process.QGTagger.srcJets = cms.InputTag("selectedUpdatedPatJetsDeepFlavour") +process.QGTagger.jetsLabel = cms.string('QGL_AK4PFchs') + +from RecoJets.JetProducers.ak4GenJets_cfi import ak4GenJets + +process.ak4GenJetsWithNu = ak4GenJets.clone(src='packedGenParticles') + +## Filter out neutrinos from packed GenParticles +process.packedGenParticlesForJetsNoNu = cms.EDFilter("CandPtrSelector", src=cms.InputTag("packedGenParticles"), + cut=cms.string( + "abs(pdgId) != 12 && abs(pdgId) != 14 && abs(pdgId) != 16")) +## Define GenJets +process.ak4GenJetsRecluster = ak4GenJets.clone(src='packedGenParticlesForJetsNoNu') + +process.patGenJetMatchWithNu = cms.EDProducer("GenJetMatcher", # cut on deltaR; pick best by deltaR + src=cms.InputTag("selectedUpdatedPatJetsDeepFlavour"), + # RECO jets (any View is ok) + matched=cms.InputTag("ak4GenJetsWithNu"), + # GEN jets (must be GenJetCollection) + mcPdgId=cms.vint32(), # n/a + mcStatus=cms.vint32(), # n/a + checkCharge=cms.bool(False), # n/a + maxDeltaR=cms.double(0.4), # Minimum deltaR for the match + # maxDPtRel = cms.double(3.0), # Minimum deltaPt/Pt for the match (not used in GenJetMatcher) + resolveAmbiguities=cms.bool(True), + # Forbid two RECO objects to match to the same GEN object + resolveByMatchQuality=cms.bool(False), + # False = just match input in order; True = pick lowest deltaR pair first + ) + +process.patGenJetMatchRecluster = cms.EDProducer("GenJetMatcher", # cut on deltaR; pick best by deltaR + src=cms.InputTag("selectedUpdatedPatJetsDeepFlavour"), + # RECO jets (any View is ok) + matched=cms.InputTag("ak4GenJetsRecluster"), + # GEN jets (must be GenJetCollection) + mcPdgId=cms.vint32(), # n/a + mcStatus=cms.vint32(), # n/a + checkCharge=cms.bool(False), # n/a + maxDeltaR=cms.double(0.4), # Minimum deltaR for the match + # maxDPtRel = cms.double(3.0), # Minimum deltaPt/Pt for the match (not used in GenJetMatcher) + resolveAmbiguities=cms.bool(True), + # Forbid two RECO objects to match to the same GEN object + resolveByMatchQuality=cms.bool(False), + # False = just match input in order; True = pick lowest deltaR pair first + ) + +process.genJetSequence = cms.Sequence(process.packedGenParticlesForJetsNoNu + * process.ak4GenJetsWithNu + * process.ak4GenJetsRecluster + * process.patGenJetMatchWithNu + * process.patGenJetMatchRecluster) + +# Very Loose IVF SV collection +from PhysicsTools.PatAlgos.tools.helpers import loadWithPrefix + +loadWithPrefix(process, 'RecoVertex.AdaptiveVertexFinder.inclusiveVertexing_cff', "looseIVF") +process.looseIVFinclusiveCandidateVertexFinder.primaryVertices = cms.InputTag("offlineSlimmedPrimaryVertices") +process.looseIVFinclusiveCandidateVertexFinder.tracks = cms.InputTag("packedPFCandidates") +process.looseIVFinclusiveCandidateVertexFinder.vertexMinDLen2DSig = cms.double(0.) +process.looseIVFinclusiveCandidateVertexFinder.vertexMinDLenSig = cms.double(0.) +process.looseIVFinclusiveCandidateVertexFinder.fitterSigmacut = 20 + +process.looseIVFcandidateVertexArbitrator.primaryVertices = cms.InputTag("offlineSlimmedPrimaryVertices") +process.looseIVFcandidateVertexArbitrator.tracks = cms.InputTag("packedPFCandidates") +process.looseIVFcandidateVertexArbitrator.secondaryVertices = cms.InputTag("looseIVFcandidateVertexMerger") +process.looseIVFcandidateVertexArbitrator.fitterSigmacut = 20 + +#datapath=os.environ['CMSSW_BASE']+'/src/DeepNTuples/DeepNtuplizer/data/' +datapath='' + +# DeepNtuplizer configurations +process.load("DeepNTuples.DeepNtuplizer.DeepNtuplizer_cfi") +process.deepntuplizer.jets = cms.InputTag('selectedUpdatedPatJetsDeepFlavour') +process.deepntuplizer.bDiscriminators = bTagDiscriminators +process.deepntuplizer.bDiscriminators.append('pfCombinedMVAV2BJetTags') +process.deepntuplizer.LooseSVs = cms.InputTag("looseIVFinclusiveCandidateSecondaryVertices") +process.deepntuplizer.applySelection = cms.bool(options.selectJets) + +process.deepntuplizer.removeUndefined = cms.bool(False) +process.deepntuplizer.isData = cms.bool(options.isData) + + +process.deepntuplizer.sfMuons = cms.InputTag("goodMuons") + +if not options.isData: + process.deepntuplizer.useLHEWeights = cms.bool(options.lheWeights) + process.deepntuplizer.pileupData = cms.string(datapath + "pileup_data_2016.root") + process.deepntuplizer.pileupMC = cms.string(datapath + "pileup_MC_2016.root") + + process.deepntuplizer.periods=cms.vstring("2016BtoF","2016GH") + process.deepntuplizer.lumis=cms.vdouble(5.404+2.396+4.256+4.054+3.105, 7.179+8.746) + process.deepntuplizer.crossSection = cms.double(options.crossSection) + process.deepntuplizer.nEvents = cms.uint32(options.nEvents) + + process.deepntuplizer.sfTrigger_mu=cms.vstring(datapath + "EfficienciesAndSF_RunBtoF.root", + datapath + "EfficienciesAndSF_Period4.root") + process.deepntuplizer.sfTrigger_mu_Hist=cms.vstring("IsoMu24_OR_IsoTkMu24_PtEtaBins/abseta_pt_ratio", + "IsoMu24_OR_IsoTkMu24_PtEtaBins/abseta_pt_ratio") + + process.deepntuplizer.sfMuonId = cms.vstring(datapath+"EfficienciesAndSF_ID_BCDEF.root", + datapath+"EfficienciesAndSF_ID_GH.root") + process.deepntuplizer.sfMuonId_Hist = cms.vstring("MC_NUM_TightID_DEN_genTracks_PAR_pt_eta/abseta_pt_ratio", + "MC_NUM_TightID_DEN_genTracks_PAR_pt_eta/abseta_pt_ratio") + + process.deepntuplizer.sfMuonIso=cms.vstring(datapath+"EfficienciesAndSF_ISO_BCDEF.root", + datapath+"EfficienciesAndSF_ISO_GH.root") + process.deepntuplizer.sfMuonIso_Hist=cms.vstring("TightISO_TightID_pt_eta/abseta_pt_ratio", + "TightISO_TightID_pt_eta/abseta_pt_ratio") + + process.deepntuplizer.sfMuonTracking=cms.vstring(datapath+"Tracking_EfficienciesAndSF_BCDEFGH.root") + process.deepntuplizer.sfMuonTracking_Hist=cms.vstring("ratio_eff_aeta_dr030e030_corr") + + process.deepntuplizer.gluonReduction = cms.double(options.gluonReduction) + +if int(release.replace("_", "")) >= 840: + process.deepntuplizer.tagInfoName = cms.string('pfDeepCSV') + + +# 1631 +#process.ProfilerService = cms.Service( +# "ProfilerService", +# firstEvent=cms.untracked.int32(1631), +# lastEvent=cms.untracked.int32(1641), +# paths=cms.untracked.vstring('p') +#) + + +if options.deepNtuplizer: + if options.isData: + process.p = cms.Path(process.globalInfo + process.TriggerSel + process.ttsemilepFilter + process.QGTagger + process.deepntuplizer) + else: + process.p = cms.Path(process.globalInfo + process.TriggerSel + process.ttsemilepFilter + process.QGTagger + process.genJetSequence * process.deepntuplizer) +else: + process.p = cms.Path(process.TriggerSel + process.ttsemilepFilter) + + process.endp = cms.EndPath(process.outmod) + diff --git a/DeepNtuplizer/python/DeepNtuplizer_cfi.py b/DeepNtuplizer/python/DeepNtuplizer_cfi.py index 85cb1bbfe2e..8a88a7048e1 100644 --- a/DeepNtuplizer/python/DeepNtuplizer_cfi.py +++ b/DeepNtuplizer/python/DeepNtuplizer_cfi.py @@ -48,6 +48,8 @@ periods=cms.vstring(), lumis=cms.vdouble(), #weights are weighted with the luminosity of the period + crossSection=cms.double(1.0), + nEvents=cms.uint32(1), #to use different triggers for the periods triggerToken=cms.InputTag("TriggerResults::HLT"), @@ -63,7 +65,8 @@ # - number of strings equal to number of periods to use a different hist for each period sfTrigger_mu=cms.vstring(), sfTrigger_mu_Hist = cms.vstring(), - + sfTrigger_e=cms.vstring(), + sfTrigger_e_Hist=cms.vstring(), sfTrigger_emu=cms.vstring(), sfTrigger_emu_Hist=cms.vstring(), sfMuonId = cms.vstring(), @@ -74,7 +77,4 @@ sfMuonTracking_Hist=cms.vstring(), sfElIdAndIso=cms.vstring(), sfElIdAndIso_Hist=cms.vstring(), - - - ) diff --git a/DeepNtuplizer/src/mergeDescriptor.cc b/DeepNtuplizer/src/mergeDescriptor.cc index d7a2058e639..c5f0401bafd 100644 --- a/DeepNtuplizer/src/mergeDescriptor.cc +++ b/DeepNtuplizer/src/mergeDescriptor.cc @@ -25,6 +25,7 @@ #include "DeepNTuples/DeepNtuplizer/interface/ntuple_pfCands.h" #include "DeepNTuples/DeepNtuplizer/interface/ntuple_SV.h" #include "DeepNTuples/DeepNtuplizer/interface/ntuple_DeepVertex.h" +#include "DeepNTuples/DeepNtuplizer/interface/ntuple_eventInfo.h" static bool debug=true; @@ -133,6 +134,7 @@ std::vector mergeDescriptor::createChains( branchinfos.push_back(new ntuple_bTagVars()); branchinfos.push_back(new ntuple_pfCands()); // branchinfos.push_back(new ntuple_DeepVertex()); + branchinfos.push_back(new ntuple_eventInfo()); std::vector chains; for(size_t i=0;i>("periods")); lumis = (iConfig.getParameter>("lumis")); + sigma = (iConfig.getParameter("crossSection")); + nEvents = (iConfig.getParameter("nEvents")); pupDataDir_ = (iConfig.getParameter("pileupData")); pupMCDir_ = (iConfig.getParameter("pileupMC")); sfTrigger_mu_Dir_ = (iConfig.getParameter>("sfTrigger_mu")); sfTrigger_mu_Name_ = (iConfig.getParameter>("sfTrigger_mu_Hist")); - + sfTrigger_e_Dir_ = (iConfig.getParameter>("sfTrigger_e")); + sfTrigger_e_Name_ = (iConfig.getParameter>("sfTrigger_e_Hist")); sfTrigger_emu_Dir_ = (iConfig.getParameter>("sfTrigger_emu")); sfTrigger_emu_Name_ = (iConfig.getParameter>("sfTrigger_emu_Hist")); sfMuonId_Dir_ = (iConfig.getParameter>("sfMuonId")); @@ -56,6 +59,7 @@ void ntuple_eventInfo::getInput(const edm::ParameterSet& iConfig){ } initializeScalefactor(sfTrigger_mu_Dir_, sfTrigger_mu_Name_, &sfTrigger_mu_Hist, periods); + initializeScalefactor(sfTrigger_e_Dir_, sfTrigger_e_Name_, &sfTrigger_e_Hist, periods); initializeScalefactor(sfTrigger_emu_Dir_, sfTrigger_emu_Name_, &sfTrigger_emu_Hist, periods); initializeScalefactor(sfMuonId_Dir_, sfMuonId_Name_, &sfMuonId_Hist, periods); initializeScalefactor(sfMuonIso_Dir_, sfMuonIso_Name_, &sfMuonIso_Hist, periods); @@ -72,9 +76,10 @@ void ntuple_eventInfo::initBranches(TTree* tree){ void ntuple_eventInfo::readEvent(const edm::Event& iEvent){ - TriggerInfo triggerInfo(iEvent,triggerToken_); if(!iEvent.isRealData()){ + TriggerInfo triggerInfo(iEvent,triggerToken_); + iEvent.getByToken(lheToken_, lheInfo); iEvent.getByToken(muonToken_, muons); @@ -128,12 +133,13 @@ void ntuple_eventInfo::readEvent(const edm::Event& iEvent){ double isf = 1.; bool itriggered = 1; - isf *= getScalefactor(std::abs(leadingMuon_eta), leadingMuon_pt, sfTrigger_mu_Hist, i); - isf *= getScalefactor(std::abs(leadingElectron_eta), std::abs(leadingMuon_eta), sfTrigger_emu_Hist, i); - isf *= getScalefactor(std::abs(leadingMuon_eta), leadingMuon_pt, sfMuonId_Hist, i); - isf *= getScalefactor(std::abs(leadingMuon_eta), leadingMuon_pt, sfMuonIso_Hist, i); - isf *= getScalefactor(std::abs(leadingElectron_sueta), leadingElectron_pt, sfElIdAndIso_Hist, i); - isf *= getScalefactor(std::abs(leadingMuon_eta), sfMuonTracking_Hist, i); + isf *= getScalefactor(std::abs(leadingMuon_eta), leadingMuon_pt, sfTrigger_mu_Hist, i); + isf *= getScalefactor(leadingElectron_pt, std::abs(leadingElectron_sueta),sfTrigger_e_Hist, i, true); + isf *= getScalefactor(std::abs(leadingElectron_eta), std::abs(leadingMuon_eta), sfTrigger_emu_Hist, i); + isf *= getScalefactor(std::abs(leadingMuon_eta), leadingMuon_pt, sfMuonId_Hist, i); + isf *= getScalefactor(std::abs(leadingMuon_eta), leadingMuon_pt, sfMuonIso_Hist, i); + isf *= getScalefactor(std::abs(leadingElectron_sueta), leadingElectron_pt, sfElIdAndIso_Hist, i); + isf *= getScalefactor(std::abs(leadingMuon_eta), sfMuonTracking_Hist, i); if(triggers.size() != 0){ itriggered = triggerInfo.IsAnyTriggered(triggers[i]); @@ -149,7 +155,7 @@ void ntuple_eventInfo::readEvent(const edm::Event& iEvent){ //std::cout<<"period "<