def __init__(self, globalTag, jesUncertainties=["Total"], jetType="AK4PFchs"): #-------------------------------------------------------------------------------------------- # CV: globalTag and jetType not yet used, as there is no consistent set of txt files for # JES uncertainties and JER scale factors and uncertainties yet #-------------------------------------------------------------------------------------------- self.jesUncertainties = jesUncertainties # smear jet pT to account for measured difference in JER between data and simulation. self.applyJERCorr = True self.jerInputFileName = "Spring16_25nsV10_MC_PtResolution_AK4PFchs.txt" self.jerUncertaintyInputFileName = "Spring16_25nsV10_MC_SF_AK4PFchs.txt" self.jetSmearer = jetSmearer(globalTag, jetType, self.jerInputFileName, self.jerUncertaintyInputFileName) self.jetBranchName = "Jet" self.genJetBranchName = "GenJet" self.metBranchName = "MET" self.rhoBranchName = "fixedGridRhoFastjetAll" # read jet energy scale (JES) uncertainties self.jesInputFilePath = os.environ[ 'CMSSW_BASE'] + "/src/PhysicsTools/NanoAODTools/data/jme/" if len(jesUncertainties) == 1 and jesUncertainties[0] == "Total": self.jesUncertaintyInputFileName = "Summer16_23Sep2016V4_MC_Uncertainty_AK4PFchs.txt" else: self.jesUncertaintyInputFileName = "Summer16_23Sep2016V4_MC_UncertaintySources_AK4PFchs.txt" # define energy threshold below which jets are considered as "unclustered energy" # (cf. JetMETCorrections/Type1MET/python/correctionTermsPfMetType1Type2_cff.py ) self.unclEnThreshold = 15. # load libraries for accessing JES scale factors and uncertainties from txt files for library in [ "libCondFormatsJetMETObjects", "libPhysicsToolsNanoAODTools" ]: if library not in ROOT.gSystem.GetLibraries(): print("Load Library '%s'" % library.replace("lib", "")) ROOT.gSystem.Load(library)
def __init__( self, isMC, isSig, era, muonSelectionTag, electronSelectionTag, CorrMET ): #, HTFilter, LTFilter):#, muonSelection, electronSelection): self.isMC = isMC self.isSig = isSig self.era = era self.muonSelectionTag = muonSelectionTag self.electronSelectionTag = electronSelectionTag self.CorrMET = CorrMET #self.HTFilt = HTFilter #self.LTFilt = LTFilter # smear jet pT to account for measured difference in JER between data and simulation. self.jerInputFileName = "Spring16_25nsV10_MC_PtResolution_AK4PFchs.txt" self.jerUncertaintyInputFileName = "Spring16_25nsV10_MC_SF_AK4PFchs.txt" ###################### LepSF, JECSFs and JERSF for 2017 era ############################################################### if self.era == "2016": self.btag_LooseWP = 0.5426 self.btag_MediumWP = 0.8484 self.btag_TightWP = 0.9535 #https://twiki.cern.ch/twiki/bin/viewauth/CMS/BtagRecommendation80XReReco self.btag_DeepLooseWP = 0.2219 self.btag_DeepMediumWP = 0.6324 self.btag_DeepTightWP = 0.8958 if self.isMC: if self.muonSelectionTag == "LooseWP_2016": mu_f = ["Mu_Trg.root", "Mu_ID.root", "Mu_Iso.root"] mu_h = [ "IsoMu24_OR_IsoTkMu24_PtEtaBins/pt_abseta_ratio", "MC_NUM_LooseID_DEN_genTracks_PAR_pt_eta/pt_abseta_ratio", "LooseISO_LooseID_pt_eta/pt_abseta_ratio" ] if self.electronSelectionTag == "GPMVA90_2016": el_f = ["EGM2D_eleGSF.root", "EGM2D_eleMVA90.root"] el_h = ["EGamma_SF2D", "EGamma_SF2D"] if self.muonSelectionTag == "MediumWP_2016": mu_f = ["Mu_Trg.root", "Mu_ID.root", "Mu_Iso.root"] mu_h = [ "IsoMu24_OR_IsoTkMu24_PtEtaBins/pt_abseta_ratio", "MC_NUM_MediumID_DEN_genTracks_PAR_pt_eta/pt_abseta_ratio", "LooseISO_MediumID_pt_eta/pt_abseta_ratio" ] if self.electronSelectionTag == "Tight_2016": el_f = ["EGM2D_eleGSF.root", "EGM2D_eleMVA90.root"] el_h = ["EGamma_SF2D", "EGamma_SF2D"] #self.jerUncertaintyInputFileName = "Spring16_25nsV10_MC_SF_AK4PFchs.txt" self.jetSmearer = jetSmearer("Summer16_23Sep2016V4_MC", "AK4PFchs", self.jerInputFileName, self.jerUncertaintyInputFileName) ###################### LepSF, JECSFs and JERSF for 2017 era ############################################################### elif self.era == "2017": self.btag_LooseWP = 0.5803 self.btag_MediumWP = 0.8838 self.btag_TightWP = 0.9693 # DeepCSV (new Deep Flavour tagger) #https://twiki.cern.ch/twiki/bin/viewauth/CMS/BtagRecommendation94X self.btag_DeepLooseWP = 0.1522 self.btag_DeepMediumWP = 0.4941 self.btag_DeepTightWP = 0.8001 if self.isMC: if self.muonSelectionTag == "LooseWP_2017": mu_f = ["Mu_Trg17.root", "Mu_ID17.root", "Mu_Iso17.root"] mu_h = [ "IsoMu27_PtEtaBins/pt_abseta_ratio", "NUM_LooseID_DEN_genTracks_pt_abseta", "NUM_LooseRelIso_DEN_LooseID_pt_abseta" ] if self.electronSelectionTag == "GPMVA90_2017": el_f = ["EGM2D_eleGSF17.root", "EGM2D_eleMVA90_17.root"] el_h = ["EGamma_SF2D", "EGamma_SF2D"] if self.muonSelectionTag == "MediumWP_2017": mu_f = ["Mu_Trg17.root", "Mu_ID17.root", "Mu_Iso17.root"] mu_h = [ "IsoMu27_PtEtaBins/pt_abseta_ratio", "NUM_MediumID_DEN_genTracks_pt_abseta", "NUM_LooseRelIso_DEN_MediumID_pt_abseta" ] if self.electronSelectionTag == "Tight_2017": el_f = ["EGM2D_eleGSF17.root", "EGM2D_eleMVA90_17.root"] el_h = ["EGamma_SF2D", "EGamma_SF2D"] # Temporarly use the jetmet uncertainty for 2016 #self.jerUncertaintyInputFileName = "Spring16_25nsV10_MC_SF_AK4PFchs.txt" #self.jetSmearer = jetSmearer("Summer16_23Sep2016V4_MC", "AK4PFchs", self.jerInputFileName, self.jerUncertaintyInputFileName) #self.jerUncertaintyInputFileName = "Fall17_17Nov2017_V6_MC_Uncertainty_AK4PFchs.txt" self.jetSmearer = jetSmearer("Fall17_17Nov2017_V6_MC", "AK4PFchs", self.jerInputFileName, self.jerUncertaintyInputFileName) else: raise ValueError("ERROR: Invalid era = '%s'!" % self.era) if self.isMC: mu_f = [ "%s/src/PhysicsTools/NanoAODTools/python/postprocessing/data/leptonSF/" % os.environ['CMSSW_BASE'] + f for f in mu_f ] el_f = [ "%s/src/PhysicsTools/NanoAODTools/python/postprocessing/data/leptonSF/" % os.environ['CMSSW_BASE'] + f for f in el_f ] self.mu_f = ROOT.std.vector(str)(len(mu_f)) self.mu_h = ROOT.std.vector(str)(len(mu_f)) for i in range(len(mu_f)): self.mu_f[i] = mu_f[i] self.mu_h[i] = mu_h[i] self.el_f = ROOT.std.vector(str)(len(el_f)) self.el_h = ROOT.std.vector(str)(len(el_f)) for i in range(len(el_f)): self.el_f[i] = el_f[i] self.el_h[i] = el_h[i] self.jetReCalibrator = JetReCalibrator( "Fall17_17Nov2017_V6_MC", "AK4PFchs", True, os.environ['CMSSW_BASE'] + "/src/PhysicsTools/NanoAODTools/data/jme/", calculateSeparateCorrections=False, calculateType1METCorrection=False) self.unclEnThreshold = 15. if "/LeptonEfficiencyCorrector_cc.so" not in ROOT.gSystem.GetLibraries( ): print "Load C++ Worker" ROOT.gROOT.ProcessLine( ".L %s/src/PhysicsTools/NanoAODTools/python/postprocessing/helpers/LeptonEfficiencyCorrector.cc+" % os.environ['CMSSW_BASE']) pass
def __init__(self, era, globalTag, jesUncertainties=["Total"], archive=None, jetType="AK8PFPuppi", noGroom=False, jerTag="", jmrVals=[], jmsVals=[], isData=False, applySmearing=True, applyHEMfix=False, splitJER=False): self.era = era self.noGroom = noGroom self.isData = isData self.applySmearing = applySmearing if not isData else False # don't smear for data # --------------------------------------------------------------------- # CV: globalTag and jetType not yet used in the jet smearer, as there # is no consistent set of txt files for JES uncertainties and JER scale # factors and uncertainties yet # --------------------------------------------------------------------- self.splitJER = splitJER if self.splitJER: self.splitJERIDs = list(range(6)) else: self.splitJERIDs = [""] # "empty" ID for the overall JER self.jesUncertainties = jesUncertainties # smear jet pT to account for measured difference in JER between data # and simulation. if jerTag != "": self.jerInputFileName = jerTag + "_PtResolution_" + jetType + ".txt" self.jerUncertaintyInputFileName = jerTag + "_SF_" + jetType + ".txt" else: print("WARNING: jerTag is empty!!! This module will soon be " "deprecated! Please use jetmetHelperRun2 in the future.") if era == "2016": self.jerInputFileName = ''.join( ["Summer16_25nsV1_MC_PtResolution_", jetType, ".txt"]) self.jerUncertaintyInputFileName = ''.join( ["Summer16_25nsV1_MC_SF_", jetType, ".txt"]) elif era == "2017" or era == "2018": # use Fall17 as temporary placeholder until # post-Moriond 2019 JERs are out self.jerInputFileName = ''.join( ["Fall17_V3_MC_PtResolution_", jetType, ".txt"]) self.jerUncertaintyInputFileName = ''.join( ["Fall17_V3_MC_SF_", jetType, ".txt"]) # jet mass resolution: https://twiki.cern.ch/twiki/bin/view/CMS/JetWtagging self.jmrVals = jmrVals if not self.jmrVals: print("WARNING: jmrVals is empty!!! Using default values. This " "module will soon be deprecated! Please use " "jetmetHelperRun2 in the future.") self.jmrVals = [1.0, 1.2, 0.8] # nominal, up, down # Use 2017 values for 2018 until 2018 are released if self.era in ["2017", "2018"]: self.jmrVals = [1.09, 1.14, 1.04] self.jetSmearer = jetSmearer(globalTag, jetType, self.jerInputFileName, self.jerUncertaintyInputFileName, self.jmrVals) if "AK4" in jetType: self.jetBranchName = "Jet" self.genJetBranchName = "GenJet" self.genSubJetBranchName = None self.doGroomed = False elif "AK8" in jetType: self.jetBranchName = "FatJet" self.subJetBranchName = "SubJet" self.genJetBranchName = "GenJetAK8" self.genSubJetBranchName = "SubGenJetAK8" if not self.noGroom: self.doGroomed = True self.puppiCorrFile = ROOT.TFile.Open( os.environ['CMSSW_BASE'] + "/src/PhysicsTools/NanoAODTools/data/jme/puppiCorr.root") self.puppisd_corrGEN = self.puppiCorrFile.Get( "puppiJECcorr_gen") self.puppisd_corrRECO_cen = self.puppiCorrFile.Get( "puppiJECcorr_reco_0eta1v3") self.puppisd_corrRECO_for = self.puppiCorrFile.Get( "puppiJECcorr_reco_1v3eta2v5") else: self.doGroomed = False else: raise ValueError("ERROR: Invalid jet type = '%s'!" % jetType) self.rhoBranchName = "fixedGridRhoFastjetAll" self.lenVar = "n" + self.jetBranchName # jet mass scale self.jmsVals = jmsVals if not self.jmsVals: print("WARNING: jmsVals is empty!!! Using default values! This " + "module will soon be deprecated! Please use " + "jetmetHelperRun2 in the future.") # 2016 values self.jmsVals = [1.00, 0.9906, 1.0094] # nominal, down, up # Use 2017 values for 2018 until 2018 are released if self.era in ["2017", "2018"]: self.jmsVals = [0.982, 0.978, 0.986] # read jet energy scale (JES) uncertainties # (downloaded from https://twiki.cern.ch/twiki/bin/view/CMS/JECDataMC ) self.jesInputArchivePath = os.environ['CMSSW_BASE'] + \ "/src/PhysicsTools/NanoAODTools/data/jme/" # Text files are now tarred so must extract first into temporary # directory (gets deleted during python memory management at script exit) self.jesArchive = tarfile.open( self.jesInputArchivePath + globalTag + ".tgz", "r:gz") if not archive else tarfile.open( self.jesInputArchivePath + archive + ".tgz", "r:gz") self.jesInputFilePath = tempfile.mkdtemp() self.jesArchive.extractall(self.jesInputFilePath) if len(jesUncertainties) == 1 and jesUncertainties[0] == "Total": self.jesUncertaintyInputFileName = globalTag + "_Uncertainty_" + jetType + ".txt" elif jesUncertainties[0] == "Merged" and not self.isData: self.jesUncertaintyInputFileName = "Regrouped_" + \ globalTag + "_UncertaintySources_" + jetType + ".txt" else: self.jesGroupedFilePath = os.environ[ 'CMSSW_BASE'] + "/src/PhysicsTools/NanoAODTools/data/jme/regrouped/" self.jesGroupedUncertaintyFileName = "RegroupedV2_" + globalTag + "_UncertaintySources_" + jetType + ".txt" self.jesGroupedUncertaintyFilePath = pjoin( self.jesGroupedFilePath, self.jesGroupedUncertaintyFileName) # Copy the uncertainty source file to the tmp directory shutil.copy( self.jesGroupedUncertaintyFilePath, pjoin(self.jesInputFilePath, self.jesGroupedUncertaintyFileName)) self.jesUncertaintyInputFileName = self.jesGroupedUncertaintyFileName #self.jesUncertaintyInputFileName = "RegroupedV2_" + globalTag + "_UncertaintySources_" + jetType + ".txt" # read all uncertainty source names from the loaded file if jesUncertainties[0] in ["All", "Merged"]: with open(self.jesInputFilePath + '/' + self.jesUncertaintyInputFileName) as f: lines = f.read().split("\n") sources = [ x for x in lines if x.startswith("[") and x.endswith("]") ] sources = [x[1:-1] for x in sources] self.jesUncertainties = sources if applyHEMfix: self.jesUncertainties.append("HEMIssue") self.jetReCalibrator = JetReCalibrator( globalTag, jetType, True, self.jesInputFilePath, calculateSeparateCorrections=False, calculateType1METCorrection=False) # load libraries for accessing JES scale factors and uncertainties # from txt files for library in [ "libCondFormatsJetMETObjects", "libPhysicsToolsNanoAODTools" ]: if library not in ROOT.gSystem.GetLibraries(): print("Load Library '%s'" % library.replace("lib", "")) ROOT.gSystem.Load(library)
def __init__(self, era, globalTag, jesUncertainties=["Total"], jetType="AK4PFchs", redoJEC=False, noGroom=False): self.era = era self.redoJEC = redoJEC self.noGroom = noGroom #-------------------------------------------------------------------------------------------- # CV: globalTag and jetType not yet used, as there is no consistent set of txt files for # JES uncertainties and JER scale factors and uncertainties yet #-------------------------------------------------------------------------------------------- self.jesUncertainties = jesUncertainties # smear jet pT to account for measured difference in JER between data and simulation. self.jerInputFileName = "Spring16_25nsV10_MC_PtResolution_" + jetType + ".txt" self.jerUncertaintyInputFileName = "Spring16_25nsV10_MC_SF_" + jetType + ".txt" self.jetSmearer = jetSmearer(globalTag, jetType, self.jerInputFileName, self.jerUncertaintyInputFileName) if "AK4" in jetType: self.jetBranchName = "Jet" self.genJetBranchName = "GenJet" self.genSubJetBranchName = None self.doGroomed = False self.corrMET = True elif "AK8" in jetType: self.jetBranchName = "FatJet" self.subJetBranchName = "SubJet" self.genJetBranchName = "GenJetAK8" self.genSubJetBranchName = "SubGenJetAK8" if not self.noGroom: self.doGroomed = True else: self.doGroomed = False self.corrMET = False else: raise ValueError("ERROR: Invalid jet type = '%s'!" % jetType) self.metBranchName = "MET" self.rhoBranchName = "fixedGridRhoFastjetAll" self.lenVar = "n" + self.jetBranchName # To do : change to real values self.jmsVals = [1.00, 0.99, 1.01] # read jet energy scale (JES) uncertainties # (downloaded from https://twiki.cern.ch/twiki/bin/view/CMS/JECDataMC ) self.jesInputFilePath = os.environ[ 'CMSSW_BASE'] + "/src/PhysicsTools/NanoAODTools/data/jme/" if len(jesUncertainties) == 1 and jesUncertainties[0] == "Total": if self.era == "2016": self.jesUncertaintyInputFileName = "Summer16_23Sep2016V4_MC_Uncertainty_" + jetType + ".txt" elif self.era == "2017": self.jesUncertaintyInputFileName = "Fall17_17Nov2017_V6_MC_Uncertainty_" + jetType + ".txt" else: raise ValueError("ERROR: Invalid era = '%s'!" % self.era) else: if self.era == "2016": self.jesUncertaintyInputFileName = "Summer16_23Sep2016V4_MC_UncertaintySources_" + jetType + ".txt" elif self.era == "2017": self.jesUncertaintyInputFileName = "Fall17_17Nov2017_V6_MC_UncertaintySources_" + jetType + ".txt" else: raise ValueError("ERROR: Invalid era = '%s'!" % self.era) # read all uncertainty source names from the loaded file if jesUncertainties[0] == "All": with open(self.jesInputFilePath + self.jesUncertaintyInputFileName) as f: lines = f.read().split("\n") sources = filter( lambda x: x.startswith("[") and x.endswith("]"), lines) sources = map(lambda x: x[1:-1], sources) self.jesUncertainties = sources if self.redoJEC: self.jetReCalibrator = JetReCalibrator( globalTag, jetType, True, self.jesInputFilePath, calculateSeparateCorrections=False, calculateType1METCorrection=False) # define energy threshold below which jets are considered as "unclustered energy" # (cf. JetMETCorrections/Type1MET/python/correctionTermsPfMetType1Type2_cff.py ) self.unclEnThreshold = 15. # load libraries for accessing JES scale factors and uncertainties from txt files for library in [ "libCondFormatsJetMETObjects", "libPhysicsToolsNanoAODTools" ]: if library not in ROOT.gSystem.GetLibraries(): print("Load Library '%s'" % library.replace("lib", "")) ROOT.gSystem.Load(library)
def __init__(self, era, globalTag, jesUncertainties = [ "Total" ], jetType = "AK4PFchs", redoJEC=False, noGroom=False, jerTag="", jmrVals = [], jmsVals = []): self.era = era self.redoJEC = redoJEC self.noGroom = noGroom #-------------------------------------------------------------------------------------------- # CV: globalTag and jetType not yet used in the jet smearer, as there is no consistent set of # txt files for JES uncertainties and JER scale factors and uncertainties yet #-------------------------------------------------------------------------------------------- self.jesUncertainties = jesUncertainties # smear jet pT to account for measured difference in JER between data and simulation. if jerTag != "": self.jerInputFileName = jerTag + "_PtResolution_" + jetType + ".txt" self.jerUncertaintyInputFileName = jerTag + "_SF_" + jetType + ".txt" else: print "WARNING: jerTag is empty!!! This module will soon be deprecated! Please use jetmetHelperRun2 in the future." if era == "2016": self.jerInputFileName = "Summer16_25nsV1_MC_PtResolution_" + jetType + ".txt" self.jerUncertaintyInputFileName = "Summer16_25nsV1_MC_SF_" + jetType + ".txt" elif era == "2017" or era == "2018": # use Fall17 as temporary placeholder until post-Moriond 2019 JERs are out self.jerInputFileName = "Fall17_V3_MC_PtResolution_" + jetType + ".txt" self.jerUncertaintyInputFileName = "Fall17_V3_MC_SF_" + jetType + ".txt" #jet mass resolution: https://twiki.cern.ch/twiki/bin/view/CMS/JetWtagging self.jmrVals = jmrVals if not self.jmrVals: print "WARNING: jmrVals is empty!!! Using default values. This module will soon be deprecated! Please use jetmetHelperRun2 in the future." self.jmrVals = [1.0, 1.2, 0.8] #nominal, up, down # Use 2017 values for 2018 until 2018 are released if self.era in ["2017","2018"]: self.jmrVals = [1.09, 1.14, 1.04] self.jetSmearer = jetSmearer(globalTag, jetType, self.jerInputFileName, self.jerUncertaintyInputFileName, self.jmrVals) if "AK4" in jetType : self.jetBranchName = "Jet" self.genJetBranchName = "GenJet" self.genSubJetBranchName = None self.doGroomed = False self.corrMET = True elif "AK8" in jetType : self.jetBranchName = "FatJet" self.subJetBranchName = "SubJet" self.genJetBranchName = "GenJetAK8" self.genSubJetBranchName = "SubGenJetAK8" if not self.noGroom: self.doGroomed = True self.puppiCorrFile = ROOT.TFile.Open(os.environ['CMSSW_BASE'] + "/src/PhysicsTools/NanoAODTools/data/jme/puppiCorr.root") self.puppisd_corrGEN = self.puppiCorrFile.Get("puppiJECcorr_gen") self.puppisd_corrRECO_cen = self.puppiCorrFile.Get("puppiJECcorr_reco_0eta1v3") self.puppisd_corrRECO_for = self.puppiCorrFile.Get("puppiJECcorr_reco_1v3eta2v5") else: self.doGroomed = False self.corrMET = False else: raise ValueError("ERROR: Invalid jet type = '%s'!" % jetType) self.metBranchName = "MET" self.rhoBranchName = "fixedGridRhoFastjetAll" self.lenVar = "n" + self.jetBranchName #jet mass scale self.jmsVals = jmsVals if not self.jmsVals: print "WARNING: jmsVals is empty!!! Using default values! This module will soon be deprecated! Please use jetmetHelperRun2 in the future." #2016 values self.jmsVals = [1.00, 0.9906, 1.0094] #nominal, down, up # Use 2017 values for 2018 until 2018 are released if self.era in ["2017","2018"]: self.jmsVals = [0.982, 0.978, 0.986] # read jet energy scale (JES) uncertainties # (downloaded from https://twiki.cern.ch/twiki/bin/view/CMS/JECDataMC ) self.jesInputArchivePath = os.environ['CMSSW_BASE'] + "/src/PhysicsTools/NanoAODTools/data/jme/" # Text files are now tarred so must extract first into temporary directory (gets deleted during python memory management at script exit) self.jesArchive = tarfile.open(self.jesInputArchivePath+globalTag+".tgz", "r:gz") self.jesInputFilePath = tempfile.mkdtemp() self.jesArchive.extractall(self.jesInputFilePath) if len(jesUncertainties) == 1 and jesUncertainties[0] == "Total": self.jesUncertaintyInputFileName = globalTag + "_Uncertainty_" + jetType + ".txt" else: self.jesUncertaintyInputFileName = globalTag + "_UncertaintySources_" + jetType + ".txt" # read all uncertainty source names from the loaded file if jesUncertainties[0] == "All": with open(self.jesInputFilePath+'/'+self.jesUncertaintyInputFileName) as f: lines = f.read().split("\n") sources = filter(lambda x: x.startswith("[") and x.endswith("]"), lines) sources = map(lambda x: x[1:-1], sources) self.jesUncertainties = sources if self.redoJEC : self.jetReCalibrator = JetReCalibrator(globalTag, jetType , True, self.jesInputFilePath, calculateSeparateCorrections = False, calculateType1METCorrection = False) # define energy threshold below which jets are considered as "unclustered energy" # (cf. JetMETCorrections/Type1MET/python/correctionTermsPfMetType1Type2_cff.py ) self.unclEnThreshold = 15. # load libraries for accessing JES scale factors and uncertainties from txt files for library in [ "libCondFormatsJetMETObjects", "libPhysicsToolsNanoAODTools" ]: if library not in ROOT.gSystem.GetLibraries(): print("Load Library '%s'" % library.replace("lib", "")) ROOT.gSystem.Load(library)
def __init__(self, era, globalTag, jesUncertainties=["Total"], archive=None, globalTagProd=None, jetType="AK4PFchs", metBranchName="MET", jerTag="", isData=False, applySmearing=True): # globalTagProd only needs to be defined if METFixEE2017 is to be recorrected, and should be the GT that was used for the production of the nanoAOD files self.era = era self.isData = isData self.applySmearing = applySmearing if not isData else False # if set to true, Jet_pt_nom will have JER applied. not to be switched on for data. self.metBranchName = metBranchName self.rhoBranchName = "fixedGridRhoFastjetAll" #-------------------------------------------------------------------------------------------- # CV: globalTag and jetType not yet used in the jet smearer, as there is no consistent set of # txt files for JES uncertainties and JER scale factors and uncertainties yet #-------------------------------------------------------------------------------------------- self.jesUncertainties = jesUncertainties # smear jet pT to account for measured difference in JER between data and simulation. if jerTag != "": self.jerInputFileName = jerTag + "_PtResolution_" + jetType + ".txt" self.jerUncertaintyInputFileName = jerTag + "_SF_" + jetType + ".txt" else: print "WARNING: jerTag is empty!!! This module will soon be deprecated! Please use jetmetHelperRun2 in the future." if era == "2016": self.jerInputFileName = "Summer16_25nsV1_MC_PtResolution_" + jetType + ".txt" self.jerUncertaintyInputFileName = "Summer16_25nsV1_MC_SF_" + jetType + ".txt" elif era == "2017" or era == "2018": ## use 2017 JER for 2018 for the time being self.jerInputFileName = "Fall17_V3_MC_PtResolution_" + jetType + ".txt" self.jerUncertaintyInputFileName = "Fall17_V3_MC_SF_" + jetType + ".txt" elif era == "2018" and False: ## jetSmearer not working with 2018 JERs yet self.jerInputFileName = "Autumn18_V7_MC_PtResolution_" + jetType + ".txt" self.jerUncertaintyInputFileName = "Autumn18_V7_MC_SF_" + jetType + ".txt" self.jetSmearer = jetSmearer(globalTag, jetType, self.jerInputFileName, self.jerUncertaintyInputFileName) if "AK4" in jetType: self.jetBranchName = "Jet" self.genJetBranchName = "GenJet" self.genSubJetBranchName = None else: raise ValueError("ERROR: Invalid jet type = '%s'!" % jetType) self.lenVar = "n" + self.jetBranchName # read jet energy scale (JES) uncertainties # (downloaded from https://twiki.cern.ch/twiki/bin/view/CMS/JECDataMC ) self.jesInputArchivePath = os.environ[ 'CMSSW_BASE'] + "/src/PhysicsTools/NanoAODTools/data/jme/" # Text files are now tarred so must extract first into temporary directory (gets deleted during python memory management at script exit) self.jesArchive = tarfile.open( self.jesInputArchivePath + globalTag + ".tgz", "r:gz") if not archive else tarfile.open( self.jesInputArchivePath + archive + ".tgz", "r:gz") self.jesInputFilePath = tempfile.mkdtemp() self.jesArchive.extractall(self.jesInputFilePath) # to fully re-calculate type-1 MET the JEC that are currently applied are also needed. IS THAT EVEN CORRECT? if len(jesUncertainties) == 1 and jesUncertainties[0] == "Total": self.jesUncertaintyInputFileName = globalTag + "_Uncertainty_" + jetType + ".txt" else: self.jesUncertaintyInputFileName = globalTag + "_UncertaintySources_" + jetType + ".txt" # read all uncertainty source names from the loaded file if jesUncertainties[0] == "All": with open(self.jesInputFilePath + '/' + self.jesUncertaintyInputFileName) as f: lines = f.read().split("\n") sources = filter( lambda x: x.startswith("[") and x.endswith("]"), lines) sources = map(lambda x: x[1:-1], sources) self.jesUncertainties = sources # Define the jet recalibrator self.jetReCalibrator = JetReCalibrator( globalTag, jetType, True, self.jesInputFilePath, calculateSeparateCorrections=False, calculateType1METCorrection=False) # Define the recalibrator for level 1 corrections only self.jetReCalibratorL1 = JetReCalibrator( globalTag, jetType, False, self.jesInputFilePath, calculateSeparateCorrections=True, calculateType1METCorrection=False, upToLevel=1) # Define the recalibrators for GT used in nanoAOD production (only needed to reproduce 2017 v2 MET) if globalTagProd: self.jetReCalibratorProd = JetReCalibrator( globalTagProd, jetType, True, self.jesInputFilePath, calculateSeparateCorrections=False, calculateType1METCorrection=False) self.jetReCalibratorProdL1 = JetReCalibrator( globalTagProd, jetType, False, self.jesInputFilePath, calculateSeparateCorrections=True, calculateType1METCorrection=False, upToLevel=1) else: self.jetReCalibratorProd = False self.jetReCalibratorProdL1 = False # define energy threshold below which jets are considered as "unclustered energy" # (cf. JetMETCorrections/Type1MET/python/correctionTermsPfMetType1Type2_cff.py ) self.unclEnThreshold = 15. # load libraries for accessing JES scale factors and uncertainties from txt files for library in [ "libCondFormatsJetMETObjects", "libPhysicsToolsNanoAODTools" ]: if library not in ROOT.gSystem.GetLibraries(): print("Load Library '%s'" % library.replace("lib", "")) ROOT.gSystem.Load(library)
def __init__(self, era, globalTag, jesUncertainties=["Total"], jetType="AK4PFchs", redoJEC=False, noGroom=False, reducedJECsystematics=False): self.era = era self.redoJEC = redoJEC self.noGroom = noGroom #-------------------------------------------------------------------------------------------- # CV: globalTag and jetType not yet used in the jet smearer, as there is no consistent set of # txt files for JES uncertainties and JER scale factors and uncertainties yet #-------------------------------------------------------------------------------------------- self.jesUncertainties = jesUncertainties # smear jet pT to account for measured difference in JER between data and simulation. if era == "2016": self.jerInputFileName = "Summer16_25nsV1b_MC/Summer16_25nsV1b_MC_PtResolution_" + jetType + ".txt" self.jerUncertaintyInputFileName = "Summer16_25nsV1b_MC/Summer16_25nsV1b_MC_SF_" + jetType + ".txt" elif era == "2017": # use Fall17 as temporary placeholder until post-Moriond 2019 JERs are out self.jerInputFileName = "Fall17_V3b_MC/Fall17_V3b_MC_PtResolution_" + jetType + ".txt" self.jerUncertaintyInputFileName = "Fall17_V3b_MC/Fall17_V3b_MC_SF_" + jetType + ".txt" elif era == "2018": ## (see https://hypernews.cern.ch/HyperNews/CMS/get/JetMET/1994.html) self.jerInputFileName = "Autumn18_V7b_MC/Autumn18_V7b_MC_PtResolution_" + jetType + ".txt" self.jerUncertaintyInputFileName = "Autumn18_V7b_MC/Autumn18_V7b_MC_SF_" + jetType + ".txt" #jet mass resolution: https://twiki.cern.ch/twiki/bin/view/CMS/JetWtagging if self.era == "2016" or self.era == "2018": #update when 2018 values available self.jmrVals = [1.0, 1.2, 0.8] #nominal, up, down else: self.jmrVals = [1.09, 1.14, 1.04] self.jetSmearer = jetSmearer(globalTag, jetType, self.jerInputFileName, self.jerUncertaintyInputFileName, self.jmrVals) if "AK4" in jetType: self.jetBranchName = "Jet" self.genJetBranchName = "GenJet" self.genSubJetBranchName = None self.doGroomed = False self.corrMET = True elif "AK8" in jetType: self.jetBranchName = "FatJet" self.subJetBranchName = "SubJet" self.genJetBranchName = "GenJetAK8" self.genSubJetBranchName = "SubGenJetAK8" if not self.noGroom: self.doGroomed = True else: self.doGroomed = False self.corrMET = False else: raise ValueError("ERROR: Invalid jet type = '%s'!" % jetType) self.metBranchName = "MET" self.rhoBranchName = "fixedGridRhoFastjetAll" self.lenVar = "n" + self.jetBranchName #jet mass scale #W-tagging PUPPI softdrop JMS values: https://twiki.cern.ch/twiki/bin/view/CMS/JetWtagging #2016 values - use for 2018 until new values available self.jmsVals = [1.00, 0.9906, 1.0094] #nominal, down, up if self.era == "2017": self.jmsVals = [0.982, 0.978, 0.986] # read jet energy scale (JES) uncertainties # (downloaded from https://twiki.cern.ch/twiki/bin/view/CMS/JECDataMC ) self.jesInputArchivePath = os.environ[ 'CMSSW_BASE'] + "/src/PhysicsTools/NanoAODTools/data/jme/" # Text files are now tarred so must extract first into temporary directory (gets deleted during python memory management at script exit) self.jesArchive = tarfile.open( self.jesInputArchivePath + globalTag + ".tgz", "r:gz") self.jesInputFilePath = tempfile.mkdtemp() self.jesArchive.extractall(self.jesInputFilePath) if len(jesUncertainties) == 1 and jesUncertainties[0] == "Total": if self.era == "2016": self.jesUncertaintyInputFileName = "Summer16_07Aug2017_V11_MC_Uncertainty_" + jetType + ".txt" elif self.era == "2017": self.jesUncertaintyInputFileName = "Fall17_17Nov2017_V32_MC_Uncertainty_" + jetType + ".txt" elif self.era == "2018": self.jesUncertaintyInputFileName = "Autumn18_V19_MC_Uncertainty_" + jetType + ".txt" else: raise ValueError("ERROR: Invalid era = '%s'!" % self.era) else: if self.era == "2016": self.jesUncertaintyInputFileName = "Summer16_07Aug2017_V11_MC_UncertaintySources_" + jetType + ".txt" elif self.era == "2017": self.jesUncertaintyInputFileName = "Fall17_17Nov2017_V32_MC_UncertaintySources_" + jetType + ".txt" elif self.era == "2018": self.jesUncertaintyInputFileName = "Autumn18_V19_MC_UncertaintySources_" + jetType + ".txt" else: raise ValueError("ERROR: Invalid era = '%s'!" % self.era) if reducedJECsystematics: ## Use https://twiki.cern.ch/twiki/bin/viewauth/CMS/JECUncertaintySources#Run_2_reduced_set_of_uncertainty ## self.jesUncertaintyInputFileName = "Regrouped_" + self.jesUncertaintyInputFileName # read all uncertainty source names from the loaded file if jesUncertainties[0] == "All": with open(self.jesInputFilePath + '/' + self.jesUncertaintyInputFileName) as f: lines = f.read().split("\n") sources = filter( lambda x: x.startswith("[") and x.endswith("]"), lines) sources = map(lambda x: x[1:-1], sources) self.jesUncertainties = sources if self.redoJEC: self.jetReCalibrator = JetReCalibrator( globalTag, jetType, True, self.jesInputFilePath, calculateSeparateCorrections=False, calculateType1METCorrection=False) # define energy threshold below which jets are considered as "unclustered energy" # (cf. JetMETCorrections/Type1MET/python/correctionTermsPfMetType1Type2_cff.py ) self.unclEnThreshold = 15. # load libraries for accessing JES scale factors and uncertainties from txt files for library in [ "libCondFormatsJetMETObjects", "libPhysicsToolsNanoAODTools" ]: if library not in ROOT.gSystem.GetLibraries(): print("Load Library '%s'" % library.replace("lib", "")) ROOT.gSystem.Load(library)