diff --git a/.gitmodules b/.gitmodules index 9ef7cf8c..e69de29b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "PileupWeights"] - path = PileupWeights - url = ssh://git@gitlab.cern.ch:7999/ncsmith/PileupWeights.git diff --git a/ConfigureJobs.py b/ConfigureJobs.py new file mode 100644 index 00000000..faf38728 --- /dev/null +++ b/ConfigureJobs.py @@ -0,0 +1,286 @@ +import datetime +import UserInput +import fnmatch +import glob +import os +import json +import array +import string +import configparser + +def get2DBinning(xvar="mjj", yvar="etajj", analysis='WZ'): + #return (array.array('d', [500, 1000,1500, 2000, 2500]), + # [0, 150, 300, 450] # for MT(WZ) +# return (array.array('d', [500, 1000, 1350, 1750, 2000, 2500]), + xbinning = [] + ybinning = [] + if xvar == "mjj": + xbinning = array.array('d', [500, 1000,1500, 2000, 2500]) + #xbinning = array.array('d', [500, 1000, 1350, 1750, 2500]) + + if yvar == 'etajj': + ybinning = [2.5, 4, 5, 20] + #if yvar == 'etajj': + # ybinning = [2.5, 4, 5.5, 20] + elif yvar == 'dRjj': + ybinning = [0, 5, 6, 20] + return (xbinning, ybinning) + +def getChannels(analysis='ZZ'): + if analysis == 'ZZ': + return ["eeee", "eemm", "mmee", "mmmm"] +def getManagerPath(): + config = configparser.ConfigParser() + config.read_file(open("Templates/config.%s" % os.environ["USER"])) + if "dataset_manager_path" not in config['Setup']: + raise ValueError("dataset_manager_path not specified in config file Template/config.%s" + % os.environ["USER"]) + return config['Setup']['dataset_manager_path'] + "/" +def getCombinePath(): + config = configparser.ConfigParser() + config.read_file(open("Templates/config.%s" % os.environ["USER"])) + if "combine_path" not in config['Setup']: + raise ValueError("dataset_manager_path not specified in config file Template/config.%s" + % os.environ["USER"]) + return config['Setup']['combine_path'] + "/" +def getListOfEWKFilenames(): + return [ + #"wz3lnu-amcnlo",#old 2018 ntuples + "wz3lnu-powheg",#New 2018 ntuples + # Use jet binned WZ samples for subtraction by default + #"wz3lnu-mgmlm-0j", + #"wz3lnu-mgmlm-1j", + #"wz3lnu-mgmlm-2j", + #"wz3lnu-mgmlm-3j", + #"wlljj-ewk", + "zz4l-powheg", + #"zz4ljj-ewk", + #"zz2l2vjj-ewk", + #"tzq", + #"ttz", + #"ttw", + #"zzz", + #"wwz", + #"www", + #"ww", + #"zg", + "ggZZ4e", + "ggZZ4m", + "ggZZ4t", + "ggZZ2e2mu", + "ggZZ2e2tau", + "ggZZ2mu2tau", + ] + +def getListOfEWK(): + return [ + "zz4l-powheg", + "ggZZ4e", + "ggZZ4m", + "ggZZ4t", + "ggZZ2e2mu", + "ggZZ2e2tau", + "ggZZ2mu2tau", + ] +def getListOfDYFilenames(): + return[ + "DYJetsToLL_M10to50", + "DYJetsToLLM-50", + ] +def getListOfNonpromptFilenames(): + return ["tt-lep", + "tt-jets", + #"st-schan", + #"st-tchan-t", + #"st-tchan-tbar", + #"st-tw", + #"st-tbarw", + ##"DYm50", + #"DYm50-1j", + #"DYm50-2j", + #"DYm50-3j", + #"DYm50-4j", + ] +def getListOfHZZFilenames(): + return ["ggHZZ", + "vbfHZZ", + "ttH_HToZZ_4L", + "WminusHToZZ", + "WplusHToZZ", + "ZHToZZ_4L" + ] +def getListOfggZZFilenames(): + return ["ggZZ4e", + "ggZZ4m", + "ggZZ4t", + "ggZZ2e2mu", + "ggZZ2e2tau", + "ggZZ2mu2tau" + ] +def getJobName(sample_name, analysis, selection, version): + date = '{:%Y-%m-%d}'.format(datetime.date.today()) + selection = selection.replace(";",",") + selections = selection.split(",") + selection_name = "To".join([selections[0],selections[-1]]) \ + if len(selections) > 1 else selections[0] + return '-'.join([date, sample_name, analysis, selection_name, + ("v%s" % version) if version.isdigit() else version]) +def getNumberAndSizeOfLocalFiles(path_to_files): + file_list = glob.glob(path_to_files) + return (len(file_list), sum([os.path.getsize(f)/1000000 for f in file_list])) +def getNumberAndSizeOfHDFSFiles(file_path): + file_info = [] + for line in out.splitlines(): + split = line.split() + if len(split) != 9: + continue + file_info.append(float(split[4].rstrip("mkg"))) + return (0,0) if len(file_info) == 0 else (len(file_info), sum(file_info)) +def getListOfHDFSFiles(file_path): + try: + out = subprocess.check_output(["hdfs", "dfs", "-ls", file_path.replace("/hdfs", "")]) + except subprocess.CalledProcessError as error: + logging.warning(error) + return [] + files = [] + for line in out.splitlines(): + split = line.split(" ", 1) + if len(split) != 2: + continue + elif "root" in split[1]: + files.append("/"+split[1]) + return files +def getListOfFiles(filelist, selection, manager_path=""): + if manager_path is "": + manager_path = getManagerPath() + data_path = "%s/ZZ4lRun2DatasetManager/FileInfo" % manager_path + data_info = UserInput.readAllJson("/".join([data_path, "%s.json" % "data/*"])) + mc_info = UserInput.readAllJson("/".join([data_path, "%s.json" % "montecarlo/*"])) + valid_names = data_info.keys() + mc_info.keys() + names = [] + for name in filelist: + if "ZZ4l2016" in name: + dataset_file = manager_path + \ + "ZZ4lRun2DatasetManager/FileInfo/ZZ4l2016/%s.json" % selection + allnames = json.load(open(dataset_file)).keys() + print allnames + if "nodata" in name: + nodata = [x for x in allnames if "data" not in x] + names += nodata + elif "data" in name: + names += [x for x in allnames if "data" in x] + else: + names += allnames + elif "ZZ4l2017" in name: + dataset_file = manager_path + \ + "ZZ4lRun2DatasetManager/FileInfo/ZZ4l2017/%s.json" % selection + allnames = json.load(open(dataset_file)).keys() + print allnames + if "nodata" in name: + nodata = [x for x in allnames if "data" not in x] + names += nodata + elif "data" in name: + names += [x for x in allnames if "data" in x] + else: + names += allnames + elif "ZZ4l2018" in name: + dataset_file = manager_path + \ + "ZZ4lRun2DatasetManager/FileInfo/ZZ4l2018/%s.json" % selection + allnames = json.load(open(dataset_file)).keys() + print allnames + if "nodata" in name: + nodata = [x for x in allnames if "data" not in x] + names += nodata + elif "data" in name: + names += [x for x in allnames if "data" in x] + else: + names += allnames + elif "*" in name: + names += fnmatch.filter(valid_names, name) + else: + if name.split("__")[0] not in valid_names: + print "%s is not a valid name" % name + continue + names += [name] + return [str(i) for i in names] +def fillTemplatedFile(template_file_name, out_file_name, template_dict): + with open(template_file_name, "r") as templateFile: + source = string.Template(templateFile.read()) + result = source.substitute(template_dict) + with open(out_file_name, "w") as outFile: + outFile.write(result) +def getListOfFilesWithXSec(filelist, manager_path=""): + if manager_path is "": + manager_path = getManagerPath() + data_path = "%s/ZZ4lRun2DatasetManager/FileInfo" % manager_path + files = getListOfFiles(filelist, "ntuples", manager_path) + #files = getListOfFiles(filelist, "2018Data", manager_path) + mc_info = UserInput.readAllJson("/".join([data_path, "%s.json" % "montecarlo/*"])) + info = {} + for file_name in files: + if "data" in file_name: + info.update({file_name : 1}) + else: + file_info = mc_info[file_name.split("__")[0]] + kfac = file_info["kfactor"] if "kfactor" in file_info.keys() else 1 + info.update({file_name : file_info["cross_section"]*kfac}) + return info +def getPreviousStep(selection, analysis): + selection_map = {} + if analysis == "ZZ4l2016": + selection_map = { "ntuples" : "ntuples", + "preselection" : "ntuples", + "4lCRBase" : "ntuples" + } + elif analysis == "ZplusL2016": + selection_map = { "ntuples": "ntuples", + "ZplusLBase" : "ntuples" + } + elif analysis == "ZZ4l2017": + selection_map = { "ntuples" : "ntuples", + "preselection" : "ntuples", + "4lCRBase" : "ntuples" + } + elif analysis == "ZplusL2017": + selection_map = { "ntuples": "ntuples", + "ZplusLBase" : "ntuples" + } + elif analysis == "ZZ4l2018": + selection_map = { "ntuples" : "ntuples", + "preselection" : "ntuples", + "4lCRBase" : "ntuples" + } + elif analysis == "ZplusL2018": + selection_map = { "ntuples": "ntuples", + "ZplusLBase" : "ntuples" + } + selection = selection.replace(";",",") + first_selection = selection.split(",")[0].strip() + if first_selection not in selection_map.keys(): + if "preselection" in first_selection: + first_selection = "preselection" + else: + raise ValueError("Invalid selection '%s'. Valid selections are:" + "%s" % (first_selection, selection_map.keys())) + return selection_map[first_selection] +def getInputFilesPath(sample_name, selection, analysis, manager_path=""): + if manager_path is "": + manager_path = getManagerPath() + data_path = "%s/ZZ4lRun2DatasetManager/FileInfo" % manager_path + input_file_name = "/".join([data_path, analysis, "%s.json" % + selection]) + input_files = UserInput.readJson(input_file_name) + if sample_name not in input_files.keys(): + raise ValueError("Invalid input file %s. Input file must correspond" + " to a definition in %s" % (sample_name, input_file_name)) + filename = input_files[sample_name]['file_path'] + return filename +def getCutsJsonName(selection, analysis): + return "/".join(["Cuts", analysis, selection + ".json"]) +def getTriggerName(sample_name, analysis, selection): + trigger_names = ["MuonEG", "DoubleMuon", "DoubleEG", "SingleMuon", "SingleElectron"] + if "data" in sample_name and getPreviousStep(selection, analysis) == "ntuples": + for name in trigger_names: + if name in sample_name: + return "-t " + name + return "-t MonteCarlo" diff --git a/PileupWeights b/PileupWeights deleted file mode 160000 index 5edbb498..00000000 --- a/PileupWeights +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5edbb49861ac655e5b9401fa5856b3f751aecb36 diff --git a/PileupWeights16/PU_Central.root b/PileupWeights16/PU_Central.root new file mode 100644 index 00000000..eeaf6bcb Binary files /dev/null and b/PileupWeights16/PU_Central.root differ diff --git a/PileupWeights16/PU_minBiasDOWN.root b/PileupWeights16/PU_minBiasDOWN.root new file mode 100644 index 00000000..423d60b4 Binary files /dev/null and b/PileupWeights16/PU_minBiasDOWN.root differ diff --git a/PileupWeights16/PU_minBiasUP.root b/PileupWeights16/PU_minBiasUP.root new file mode 100644 index 00000000..c52879ca Binary files /dev/null and b/PileupWeights16/PU_minBiasUP.root differ diff --git a/PileupWeights17/PU_Central.root b/PileupWeights17/PU_Central.root new file mode 100644 index 00000000..68676f9b Binary files /dev/null and b/PileupWeights17/PU_Central.root differ diff --git a/PileupWeights17/PU_minBiasDOWN.root b/PileupWeights17/PU_minBiasDOWN.root new file mode 100644 index 00000000..63809570 Binary files /dev/null and b/PileupWeights17/PU_minBiasDOWN.root differ diff --git a/PileupWeights17/PU_minBiasUP.root b/PileupWeights17/PU_minBiasUP.root new file mode 100644 index 00000000..38c83663 Binary files /dev/null and b/PileupWeights17/PU_minBiasUP.root differ diff --git a/PileupWeights18/PU_Central.root b/PileupWeights18/PU_Central.root new file mode 100644 index 00000000..ffa45177 Binary files /dev/null and b/PileupWeights18/PU_Central.root differ diff --git a/PileupWeights18/PU_minBiasDOWN.root b/PileupWeights18/PU_minBiasDOWN.root new file mode 100644 index 00000000..ae55aaa4 Binary files /dev/null and b/PileupWeights18/PU_minBiasDOWN.root differ diff --git a/PileupWeights18/PU_minBiasUP.root b/PileupWeights18/PU_minBiasUP.root new file mode 100644 index 00000000..0cab0cfe Binary files /dev/null and b/PileupWeights18/PU_minBiasUP.root differ diff --git a/ScaleFactors/setupScaleFactors.py b/ScaleFactors/setupScaleFactors.py index 5cb58a5b..752d8518 100755 --- a/ScaleFactors/setupScaleFactors.py +++ b/ScaleFactors/setupScaleFactors.py @@ -9,6 +9,7 @@ import ROOT import argparse import os +import sys ROOT.gROOT.SetBatch(True) ROOT.PyConfig.IgnoreCommandLineOptions = True @@ -37,118 +38,153 @@ def invert2DHist(hist): return new_hist parser = argparse.ArgumentParser() -parser.add_argument("-t", "--tightfr_file", type=str, - default='data/fakeRate18Apr2017-3LooseLeptons-TightMuons.root') -parser.add_argument("-m", "--medfr_file", type=str, - default='data/fakeRate18Apr2017-3LooseLeptons-MediumMuons.root') -args = parser.parse_args() -output_file = 'data/scaleFactors.root' -fScales = ROOT.TFile(output_file, 'recreate') + +def getComLineArgs(): + parser.add_argument("--year", type=str,default="default", help="Year of Analysis") + parser.add_argument("-t", "--tightfr_file", type=str, + default="") + parser.add_argument("--output_file", "-o", type=str, + default="test.root", help="Output file name") + + return vars(parser.parse_args()) + +args = getComLineArgs() + +year = args["year"] +frfile = args["tightfr_file"] +fScales = ROOT.TFile(args['output_file'], 'recreate') + + # For nTruePU reweighting -pileupSF = ROOT.ScaleFactor("pileupSF", "Run2016B-H 36.8/fb Pileup profile over RunIISpring16 MC Scale Factor, x=NTruePU") -pileupFile = ROOT.TFile.Open('PileupWeights/PU_Central.root') -pileupFileUp = ROOT.TFile.Open('PileupWeights/PU_minBiasUP.root') -pileupFileDown = ROOT.TFile.Open('PileupWeights/PU_minBiasDOWN.root') +if year=="2016": + print "2016 PU reweighting" + pileupSF = ROOT.ScaleFactor("pileupSF", "Run2016B-H 35.9/fb Pileup profile over RunIISummer16 MC Scale Factor, x=NTruePU") + pileupFile = ROOT.TFile.Open('PileupWeights16/PU_Central.root') + pileupFileUp = ROOT.TFile.Open('PileupWeights16/PU_minBiasUP.root') + pileupFileDown = ROOT.TFile.Open('PileupWeights16/PU_minBiasDOWN.root') +elif year=="2017": + pileupSF = ROOT.ScaleFactor("pileupSF", "Run2017B-F 41.5/fb Pileup profile over RunIIFall17 MC Scale Factor, x=NTruePU") + pileupFile = ROOT.TFile.Open('PileupWeights17/PU_Central.root') + pileupFileUp = ROOT.TFile.Open('PileupWeights17/PU_minBiasUP.root') + pileupFileDown = ROOT.TFile.Open('PileupWeights17/PU_minBiasDOWN.root') +elif year=="2018": + pileupSF = ROOT.ScaleFactor("pileupSF", "Run2018A-D 59.95/fb Pileup profile over RunIIFall18 MC Scale Factor, x=NTruePU") + pileupFile = ROOT.TFile.Open('PileupWeights18/PU_Central.root') + pileupFileUp = ROOT.TFile.Open('PileupWeights18/PU_minBiasUP.root') + pileupFileDown = ROOT.TFile.Open('PileupWeights18/PU_minBiasDOWN.root') +else: + print "You forgot to specify the year for which you want scale factors" + sys.exit() pileupSF.Set1DHist(pileupFile.Get('pileup'), pileupFileUp.Get('pileup'), pileupFileDown.Get('pileup')) fScales.cd() pileupSF.Write() -electronTightIdSF = ROOT.ScaleFactor("electronTightIdSF", "Moriond '17 Electron Tight WP ID SF, x=Eta, y=Pt") -eidFile = ROOT.TFile.Open('data/moriond17ElectronTightSF.root') -electronTightIdSF.Set2DHist(float2double(eidFile.Get('EGamma_SF2D'))) -fScales.cd() -electronTightIdSF.Write() -electronGsfSF = ROOT.ScaleFactor("electronGsfSF", "Moriond '17 Electron GSF track reco SF, x=Eta, y=Pt") -eleGsfFile = ROOT.TFile.Open('data/moriond17ElectronRecoSF.root') -electronGsfSF.Set2DHist(float2double(eleGsfFile.Get('EGamma_SF2D'))) -fScales.cd() -electronGsfSF.Write() -muonIdSF = ROOT.ScaleFactor("muonTightIdSF", "Moriond '17 Muon Tight WP ID SF, x=abs(Eta), y=Pt, z=run number") -midFile1 = ROOT.TFile.Open('data/moriond17MuonID_BCDEF.root') -midFile2 = ROOT.TFile.Open('data/moriond17MuonID_GH.root') -muon_ptetaratio1 = midFile1.Get('MC_NUM_TightID_DEN_genTracks_PAR_pt_eta/abseta_pt_ratio') -muon_ptetaratio2 = midFile2.Get('MC_NUM_TightID_DEN_genTracks_PAR_pt_eta/abseta_pt_ratio') -muon_allratio = float2double(muon_ptetaratio1.Clone("muon_allratio")) -for xbin in range(muon_ptetaratio1.GetNbinsX()+2): - for ybin in range(muon_ptetaratio1.GetNbinsY()+2): - runBFmean, runBFerr = muon_ptetaratio1.GetBinContent(xbin, ybin), muon_ptetaratio1.GetBinError(xbin, ybin) - runGHmean, runGHerr = muon_ptetaratio2.GetBinContent(xbin, ybin), muon_ptetaratio2.GetBinError(xbin, ybin) - allmean = (20.5*runBFmean + 16.3*runGHmean) / 36.8 - allerr = (20.5*runBFerr + 16.3*runGHerr) / 36.8 - muon_allratio.SetBinContent(xbin, ybin, allmean) - muon_allratio.SetBinError(xbin, ybin, allerr) -muonIdSF.Set2DHist(muon_allratio) -fScales.cd() -muonIdSF.Write() -muonIsoSF = ROOT.ScaleFactor("muonIsoSF", "Moriond '17 Muon Tight Iso (0.15) WP ID SF, x=abs(Eta), y=Pt, z=run number") -misoFile1 = ROOT.TFile.Open('data/moriond17MuonIso_BCDEF.root') -misoFile2 = ROOT.TFile.Open('data/moriond17MuonIso_GH.root') -muIso_ptetaratio1 = misoFile1.Get('TightISO_TightID_pt_eta/abseta_pt_ratio') -muIso_ptetaratio2 = misoFile2.Get('TightISO_TightID_pt_eta/abseta_pt_ratio') -muIso_allratio = float2double(muon_ptetaratio1.Clone("muIso_allratio")) -for xbin in range(muIso_ptetaratio1.GetNbinsX()+2): - for ybin in range(muIso_ptetaratio1.GetNbinsY()+2): - runBFmean, runBFerr = muIso_ptetaratio1.GetBinContent(xbin, ybin), muIso_ptetaratio1.GetBinError(xbin, ybin) - runGHmean, runGHerr = muIso_ptetaratio2.GetBinContent(xbin, ybin), muIso_ptetaratio2.GetBinError(xbin, ybin) - allmean = (20.5*runBFmean + 16.3*runGHmean) / 36.8 - allerr = (20.5*runBFerr + 16.3*runGHerr) / 36.8 - muIso_allratio.SetBinContent(xbin, ybin, allmean) - muIso_allratio.SetBinError(xbin, ybin, allerr) -muonIsoSF.Set2DHist(muIso_allratio) -fScales.cd() -muonIsoSF.Write() - -# Used for tests on fake rate files from Jakob and Svenja -#efakeRateFile = ROOT.TFile.Open('/eos/user/k/kelong/WZAnalysisData/FakeRates/fromJakob/eFakeRates.root') -#jakob_etight = efakeRateFile.Get('eFakeRates') -#jakob_etight = invert2DHist(jakob_etight) -#mfakeRateFile = ROOT.TFile.Open('/eos/user/k/kelong/WZAnalysisData/FakeRates/fromJakob/muFakeRates.root') -#jakob_mtight = mfakeRateFile.Get('muFakeRates') -#jakob_mtight = invert2DHist(jakob_mtight) -# -#eCBTightFakeRate = ROOT.ScaleFactor("eCBTightFakeRate_Jakob", "Fake rate from dijet control, via Jakob") -#eCBTightFakeRate.Set2DHist(jakob_etight, 0, 0, ROOT.ScaleFactor.AsInHist) -#mCBTightFakeRate = ROOT.ScaleFactor("mCBTightFakeRate_Jakob", "Fake rate from dijet control, via Jakob") -#mCBTightFakeRate.Set2DHist(jakob_mtight, 0, 0, ROOT.ScaleFactor.AsInHist) -#fScales.cd() -#mCBTightFakeRate.Write() -#eCBTightFakeRate.Write() - -#fakeRateFile = ROOT.TFile.Open('/eos/user/k/kelong/WZAnalysisData/FakeRates/CutBasedFakeRate_fromSvenja_final.root') -#eCBMedFakeRate = ROOT.ScaleFactor("eCBMedFakeRate_Svenja", "Fake rate from dijet control, by Svenja") -#eCBMedFakeRate.Set2DHist(float2double(fakeRateFile.Get('e/medium/fakeratePtEta')), 0, 0, ROOT.ScaleFactor.AsInHist) -#eCBTightFakeRate = ROOT.ScaleFactor("eCBTightFakeRate_Svenja", "Fake rate from dijet control, by Svenja") -#eCBTightFakeRate.Set2DHist(float2double(fakeRateFile.Get('e/tight/fakeratePtEta')), 0, 0, ROOT.ScaleFactor.AsInHist) -#mCBMedFakeRate = ROOT.ScaleFactor("mCBMedFakeRate_Svenja", "Fake rate from dijet control, by Svenja") -#mCBMedFakeRate.Set2DHist(float2double(fakeRateFile.Get('m/medium/fakeratePtEta')), 0, 0, ROOT.ScaleFactor.AsInHist) -#mCBTightFakeRate = ROOT.ScaleFactor("mCBTightFakeRate_Svenja", "Fake rate from dijet control, by Svenja") -#mCBTightFakeRate.Set2DHist(float2double(fakeRateFile.Get('m/tight/fakeratePtEta')), 0, 0, ROOT.ScaleFactor.AsInHist) -#fScales.cd() -#mCBMedFakeRate.Write() -#mCBTightFakeRate.Write() -#eCBMedFakeRate.Write() -#eCBTightFakeRate.Write() - -if os.path.isfile(args.medfr_file): - print "INFO: Adding medium fake rates to %s" % output_file - fakeRateFile = ROOT.TFile.Open(args.medfr_file) - eCBMedFakeRateZjets = ROOT.ScaleFactor("eCBMedFakeRate", "Fake rate from Z+jet") - eCBMedFakeRateZjets.Set2DHist(fakeRateFile.Get('DataEWKCorrected/ratio2D_allE'), 0, 0, ROOT.ScaleFactor.AsInHist) - mCBMedFakeRateZjets = ROOT.ScaleFactor("mCBMedFakeRate", "Fake rate from Z+jet") - mCBMedFakeRateZjets.Set2DHist(fakeRateFile.Get('DataEWKCorrected/ratio2D_allMu'), 0, 0, ROOT.ScaleFactor.AsInHist) - fScales.cd() - mCBMedFakeRateZjets.Write() - eCBMedFakeRateZjets.Write() +if year=="2016": + print "Doing 2016 Lepton SF" + electronLowReco16SF = ROOT.ScaleFactor("electronLowReco16SF", "Run '16 Electron Low Reco SF, x=Eta, y=Pt") + eLowRecoFile = ROOT.TFile.Open('data/Ele_Reco_LowEt_2016.root') + electronLowReco16SF.Set2DHist(float2double(eLowRecoFile.Get('EGamma_SF2D'))) + fScales.cd() + electronLowReco16SF.Write() + + #Electron (Pt>20 Reco SF from POG https://twiki.cern.ch/twiki/bin/viewauth/CMS/Egamma2016DataRecommendations + electronReco16SF = ROOT.ScaleFactor("electronReco16SF", "Run '16 Electron Reco SF, x=Eta, y=Pt") + eRecoFile = ROOT.TFile.Open('data/Ele_Reco_2016.root') + electronReco16SF.Set2DHist(float2double(eRecoFile.Get('EGamma_SF2D'))) + fScales.cd() + electronReco16SF.Write() + + electronRun16SF = ROOT.ScaleFactor("electronRun16SF", "Run '16 Electron HZZ ID SF, x=Eta, y=Pt") + eidFile = ROOT.TFile.Open('data/ElectronSF_Legacy_2016_NoGap.root') + electronRun16SF.Set2DHist(float2double(eidFile.Get('EGamma_SF2D'))) + fScales.cd() + electronRun16SF.Write() + + electronRun16GapSF = ROOT.ScaleFactor("electronRun16GapSF", "Run '16 GapElectron HZZ ID SF, x=Eta, y=Pt") + eleGsfFile = ROOT.TFile.Open('data/ElectronSF_Legacy_2016_Gap.root') + electronRun16GapSF.Set2DHist(float2double(eleGsfFile.Get('EGamma_SF2D'))) + fScales.cd() + electronRun16GapSF.Write() + + muonRun16SF = ROOT.ScaleFactor("muonRun16SF", "Muon Run '16 Trk+ID+ISO SF, x=abs(Eta), y=Pt") + mid16File = ROOT.TFile.Open('data/MoriondSFs/final_HZZ_SF_2016_legacy_mupogsysts_newLoose_noTracking_1610.root') + muonRun16SF.Set2DHist(float2double(mid16File.Get('FINAL')),float2double(mid16File.Get('ERROR')),float2double(mid16File.Get('ERROR'))) + fScales.cd() + muonRun16SF.Write() +elif year=="2017": + electronLowReco17SF = ROOT.ScaleFactor("electronLowReco17SF", "Run '17 Electron Low Reco SF, x=Eta, y=Pt") + eLowRecoFile = ROOT.TFile.Open('data/Ele_Reco_LowEt_2017.root') + electronLowReco17SF.Set2DHist(float2double(eLowRecoFile.Get('EGamma_SF2D'))) + fScales.cd() + electronLowReco17SF.Write() + + #Electron (Pt>20 Reco SF from POG https://twiki.cern.ch/twiki/bin/viewauth/CMS/Egamma2017DataRecommendations + electronReco17SF = ROOT.ScaleFactor("electronReco17SF", "Run '17 Electron Reco SF, x=Eta, y=Pt") + eRecoFile = ROOT.TFile.Open('data/Ele_Reco_2017.root') + electronReco17SF.Set2DHist(float2double(eRecoFile.Get('EGamma_SF2D'))) + fScales.cd() + electronReco17SF.Write() + + electronRun17SF = ROOT.ScaleFactor("electronRun17SF", "Run '17 Electron HZZ ID SF, x=Eta, y=Pt") + eidFile = ROOT.TFile.Open('data/ElectronSF_Legacy_2017_NoGap.root') + electronRun17SF.Set2DHist(float2double(eidFile.Get('EGamma_SF2D'))) + fScales.cd() + electronRun17SF.Write() + + electronRun17GapSF = ROOT.ScaleFactor("electronRun17GapSF", "Run '17 GapElectron HZZ ID SF, x=Eta, y=Pt") + eleGsfFile = ROOT.TFile.Open('data/ElectronSF_Legacy_2017_Gap.root') + electronRun17GapSF.Set2DHist(float2double(eleGsfFile.Get('EGamma_SF2D'))) + fScales.cd() + electronRun17GapSF.Write() + + muonRun17SF = ROOT.ScaleFactor("muonRun17SF", "Muon Run '17 Trk+ID+ISO SF, x=abs(Eta), y=Pt") + midFile = ROOT.TFile.Open('data/MoriondSFs/ScaleFactors_mu_Moriond2018_final.root') + muonRun17SF.Set2DHist(float2double(midFile.Get('FINAL')),float2double(midFile.Get('ERROR')),float2double(midFile.Get('ERROR'))) + fScales.cd() + muonRun17SF.Write() +elif year=="2018": + #Electron (Pt<20 Reco SF from POG https://twiki.cern.ch/twiki/bin/viewauth/CMS/Egamma2018DataRecommendations + electronLowReco18SF = ROOT.ScaleFactor("electronLowReco18SF", "Run '18 Electron Low Reco SF, x=Eta, y=Pt") + eLowRecoFile = ROOT.TFile.Open('data/Ele_Reco_LowEt_2018.root') + electronLowReco18SF.Set2DHist(float2double(eLowRecoFile.Get('EGamma_SF2D'))) + fScales.cd() + electronLowReco18SF.Write() + + #Electron (Pt>20 Reco SF from POG https://twiki.cern.ch/twiki/bin/viewauth/CMS/Egamma2018DataRecommendations + electronReco18SF = ROOT.ScaleFactor("electronReco18SF", "Run '18 Electron Reco SF, x=Eta, y=Pt") + eRecoFile = ROOT.TFile.Open('data/Ele_Reco_2018.root') + electronReco18SF.Set2DHist(float2double(eRecoFile.Get('EGamma_SF2D'))) + fScales.cd() + electronReco18SF.Write() + + electronRun18SF = ROOT.ScaleFactor("electronRun18SF", "Run '18 Electron HZZ ID SF, x=Eta, y=Pt") + eidFile = ROOT.TFile.Open('data/ElectronSF_Legacy_2018_NoGap.root') + electronRun18SF.Set2DHist(float2double(eidFile.Get('EGamma_SF2D'))) + fScales.cd() + electronRun18SF.Write() + + electronRun18GapSF = ROOT.ScaleFactor("electronRun18GapSF", "Run '18 GapElectron HZZ ID SF, x=Eta, y=Pt") + eleGsfFile = ROOT.TFile.Open('data/ElectronSF_Legacy_2018_Gap.root') + electronRun18GapSF.Set2DHist(float2double(eleGsfFile.Get('EGamma_SF2D'))) + fScales.cd() + electronRun18GapSF.Write() + + muonRun18SF = ROOT.ScaleFactor("muonRun18SF", "Muon Run '18 Trk+ID+ISO SF, x=abs(Eta), y=Pt") + mid18File = ROOT.TFile.Open('data/final_HZZ_muon_SF_2018_IsBDT_0610.root') + muonRun18SF.Set2DHist(float2double(mid18File.Get('FINAL')),float2double(mid18File.Get('ERROR')),float2double(mid18File.Get('ERROR'))) + fScales.cd() + muonRun18SF.Write() -if os.path.isfile(args.tightfr_file): - print "INFO: Adding tight fake rates to %s" % output_file - fakeRateFile = ROOT.TFile.Open(args.tightfr_file) - eCBTightFakeRateZjets = ROOT.ScaleFactor("eCBTightFakeRate", "Fake rate from Z+jet") - eCBTightFakeRateZjets.Set2DHist(fakeRateFile.Get('DataEWKCorrected/ratio2D_allE'), 0, 0, ROOT.ScaleFactor.AsInHist) - mCBTightFakeRateZjets = ROOT.ScaleFactor("mCBTightFakeRate", "Fake rate from Z+jet") - mCBTightFakeRateZjets.Set2DHist(fakeRateFile.Get('DataEWKCorrected/ratio2D_allMu'), 0, 0, ROOT.ScaleFactor.AsInHist) - fScales.cd() - mCBTightFakeRateZjets.Write() - eCBTightFakeRateZjets.Write() +#For every year there is a separate fakeRate file +if os.path.isfile(frfile): + print "INFO: Adding tight fake rates to %s" % args["output_file"] + fakeRateFile = ROOT.TFile.Open(frfile) + eZZTightFakeRate = ROOT.ScaleFactor("eZZTightFakeRate", "Fake rate from Z+jet") + eZZTightFakeRate.Set2DHist(fakeRateFile.Get('DataEWKCorrected/ratioE2D_allE'), 0, 0, ROOT.ScaleFactor.AsInHist) + mZZTightFakeRate = ROOT.ScaleFactor("mZZTightFakeRate", "Fake rate from Z+jet") + mZZTightFakeRate.Set2DHist(fakeRateFile.Get('DataEWKCorrected/ratioMu2D_allMu'), 0, 0, ROOT.ScaleFactor.AsInHist) + fScales.cd() + mZZTightFakeRate.Write() + eZZTightFakeRate.Write() diff --git a/ScaleFactors/testScales.py b/ScaleFactors/testScales.py index 3283b419..d4536106 100755 --- a/ScaleFactors/testScales.py +++ b/ScaleFactors/testScales.py @@ -25,41 +25,47 @@ # Generate with setupScaleFactors.py # Will need appropriate files in ../data/ -fScales = ROOT.TFile('../data/scaleFactors.root') +fScales = ROOT.TFile('../data/scaleFactorsZZ4l2017.root') pu = fScales.Get('pileupSF') -muonIso = fScales.Get('muonIsoSF') -muonId = fScales.Get('muonTightIdSF') -electronTightId = fScales.Get('electronTightIdSF') -electronMediumId = fScales.Get('electronMediumIdSF') +#muonIso = fScales.Get('muonIsoSF') +#muonId = fScales.Get('electronLowRecoSF') +#electronTightId = fScales.Get('electronTightIdSF') +#electronMediumId = fScales.Get('electronMediumIdSF') -#mCBTightFakeRate = fScales.Get("mCBTightFakeRate_Svenja") -#mCBMedFakeRate = fScales.Get("mCBMedFakeRate_Svenja") -#eCBTightFakeRate = fScales.Get("eCBTightFakeRate_Svenja") -#eCBMedFakeRate = fScales.Get("eCBMedFakeRate_Svenja") -mCBTightFakeRate = fScales.Get("mCBTightFakeRate") -eCBTightFakeRate = fScales.Get("eCBTightFakeRate") +mZZTightFakeRate = fScales.Get("mZZTightFakeRate") +eZZTightFakeRate = fScales.Get("eZZTightFakeRate") + +muonMoriondSF= fScales.Get('muonMoriond18SF') +electronLowRecoSF = fScales.Get('electronLowReco18SF') +electronRecoSF = fScales.Get('electronReco18SF') +electronMoriondSF = fScales.Get('electronMoriond18SF') +electronMoriondGapSF = fScales.Get('electronMoriond18GapSF') + + +#mCBTightFakeRate = fScales.Get("mCBTightFakeRate") +#eCBTightFakeRate = fScales.Get("eCBTightFakeRate") del fScales # Make sure we don't rely on file being open pu.RegisterGlobalFunction() print "pileupSF(3) = ", ROOT.pileupSF(3) dummyTree.Scan('10+10*randVal : pileupSF(10+10*randVal)', '', '', 10) -muonIso.RegisterGlobalFunction(2) # 2D function -muonId.RegisterGlobalFunction(2) # 2D function -print "muonIsoSF(1.1, 30) = ", ROOT.muonIsoSF(1.1, 30) -print "muonTightIdSF(1.1, 30) = ", ROOT.muonTightIdSF(1.1, 30) -dummyTree.Scan('abs(randVal*2) : randVal2*5+30 : muonIsoSF(abs(randVal*2), randVal2*5+30)', '', '', 10) -dummyTree.Scan('abs(randVal*2) : randVal2*5+30 : muonTightIdSF(abs(randVal*2), randVal2*5+30)', '', '', 10) - -electronMediumId.RegisterGlobalFunction(2) # 2D function -electronTightId.RegisterGlobalFunction(2) # 2D function -dummyTree.Scan('abs(randVal*2) : randVal2*5+30 : electronMediumIdSF(abs(randVal*2), randVal2*5+30)', '', '', 10) -dummyTree.Scan('abs(randVal*2) : randVal2*5+30 : electronTightIdSF(abs(randVal*2), randVal2*5+30)', '', '', 10) - -mCBTightFakeRate.RegisterGlobalFunction(2) # 2D function -print "mCBTightFakeRate(1.1, 30) = ", ROOT.mCBTightFakeRate(30, 1.1) -dummyTree.Scan('abs(randVal*2) : randVal2*10+30 : mCBTightFakeRate(randVal2*10+30, abs(randVal*2))', '', '', 10) +muonMoriondSF.RegisterGlobalFunction(2) # 2D function +electronLowRecoSF.RegisterGlobalFunction(2) # 2D function +print "muonMoriondSF(1.1, 30) = ", ROOT.muonMoriond18SF(1.1, 30) +print "electronLowRecoSF(1.1, 30) = ", ROOT.electronLowReco18SF(1.1, 30) +dummyTree.Scan('abs(randVal*2) : randVal2*5+30 : muonMoriond18SF(abs(randVal*2), randVal2*5+30)', '', '', 10) +dummyTree.Scan('abs(randVal*2) : randVal2*5+30 : electronLowReco18SF(abs(randVal*2), randVal2*5+30)', '', '', 10) -eCBTightFakeRate.RegisterGlobalFunction(2) # 2D function -print "eCBTightFakeRate(1.1, 30) = ", ROOT.eCBTightFakeRate(30, 1.1) -dummyTree.Scan('abs(randVal*2) : randVal2*10+30 : eCBTightFakeRate(randVal2*10+30, abs(randVal*2))', '', '', 10) +#electronMediumId.RegisterGlobalFunction(2) # 2D function +#electronTightId.RegisterGlobalFunction(2) # 2D function +#dummyTree.Scan('abs(randVal*2) : randVal2*5+30 : electronMediumIdSF(abs(randVal*2), randVal2*5+30)', '', '', 10) +#dummyTree.Scan('abs(randVal*2) : randVal2*5+30 : electronTightIdSF(abs(randVal*2), randVal2*5+30)', '', '', 10) +# +#mCBTightFakeRate.RegisterGlobalFunction(2) # 2D function +#print "mCBTightFakeRate(1.1, 30) = ", ROOT.mCBTightFakeRate(30, 1.1) +#dummyTree.Scan('abs(randVal*2) : randVal2*10+30 : mCBTightFakeRate(randVal2*10+30, abs(randVal*2))', '', '', 10) +# +#eCBTightFakeRate.RegisterGlobalFunction(2) # 2D function +#print "eCBTightFakeRate(1.1, 30) = ", ROOT.eCBTightFakeRate(30, 1.1) +#dummyTree.Scan('abs(randVal*2) : randVal2*10+30 : eCBTightFakeRate(randVal2*10+30, abs(randVal*2))', '', '', 10) diff --git a/Templates/CombineCards/VGen/ZGen_template_ee.txt b/Templates/CombineCards/VGen/ZGen_template_ee.txt new file mode 100644 index 00000000..96e4b4c3 --- /dev/null +++ b/Templates/CombineCards/VGen/ZGen_template_ee.txt @@ -0,0 +1,23 @@ +imax 1 number of channels +jmax 1 number of processes - 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes ${dy_sample} * ${output_file} ${dy_sample}/${fit_variable}_$$CHANNEL ${dy_sample}/${fit_variable}_$$CHANNEL_$$SYSTEMATIC +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_$$CHANNEL nonprompt/${fit_variable}_$$CHANNEL_$$SYSTEMATIC +shapes data_obs * ${output_file} ${data_name}/${fit_variable}_$$CHANNEL + +bin ee +observation -1 + +------------ +bin ee ee +process ${dy_sample} nonprompt +process -1 1 +rate ${dy_lo_2018} ${nonprompt} +------------ +lumi2016_13TeV lnN 1.025 1.025 +dummyErr_ee lnN 1.02 - +QCDscale_${dy_sample} shape 1 - + + diff --git a/Templates/CombineCards/VGen/ZGen_template_mm.txt b/Templates/CombineCards/VGen/ZGen_template_mm.txt new file mode 100644 index 00000000..f4571726 --- /dev/null +++ b/Templates/CombineCards/VGen/ZGen_template_mm.txt @@ -0,0 +1,24 @@ +imax 1 number of channels +jmax 1 number of processes - 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes ${dy_sample} * ${output_file} ${dy_sample}/${fit_variable}_$$CHANNEL ${dy_sample}/${fit_variable}_$$CHANNEL_$$SYSTEMATIC +shapes nonprompt * ${output_file} ${nonprompt}/${fit_variable}_$$CHANNEL ${nonprompt}/${fit_variable}_$$CHANNEL_$$SYSTEMATIC +shapes data_obs * ${output_file} ${data_name}/${fit_variable}_$$CHANNEL + +bin mm +observation -1 + +------------ +bin mm mm +process ${dy_sample} nonprompt +process -1 1 +rate ${dy_lo_2018} ${nonprompt} +------------ +lumi2016_13TeV lnN 1.025 1.025 +dummyErr_mm lnN 1.02 - +QCDscale_${dy_sample} shape 1 - + + + diff --git a/Templates/CombineCards/ZZSelection/ZZ_template2016_all.txt b/Templates/CombineCards/ZZSelection/ZZ_template2016_all.txt new file mode 100644 index 00000000..f1d8d737 --- /dev/null +++ b/Templates/CombineCards/ZZSelection/ZZ_template2016_all.txt @@ -0,0 +1,42 @@ +imax 1 number of channels +jmax 5 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin all +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin all all all all all all +process zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process 4 3 -1 0 1 2 +rate ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +--------------------------------------------------------------------------------------------------------------------------- +bkgStat lnN - - - - - 1.4 +trigger lnN 1.020 1.020 1.020 1.020 1.020 - +CMS_eff_e shape 1 1 1 1 1 0 +CMS_RecoEff_e shape 1 1 1 1 1 0 +CMS_eff_m shape 1 1 1 1 1 0 +CMS_pileup shape 1 1 1 1 1 0 +QCDscale_HZZ_signal shape 0 1 0 0 0 0 +QCDscale_VVV shape 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 1 0 0 0 0 +pdf_VVV shape 0 0 0 0 1 0 +theoAcc lnN - - 1.02 1.02 - - + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/ZZ_template2016_eeee.txt b/Templates/CombineCards/ZZSelection/ZZ_template2016_eeee.txt new file mode 100644 index 00000000..a85bed1c --- /dev/null +++ b/Templates/CombineCards/ZZSelection/ZZ_template2016_eeee.txt @@ -0,0 +1,45 @@ +imax 1 number of channels +jmax 5 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin eeee +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin eeee eeee eeee eeee eeee eeee +process zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process 4 3 -1 0 1 2 +rate ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +---------------------------------------------------------------------------------------------------------------------------------- +bkg_eeee_16 lnN - - - - - 1.2 +bkg_ee_16 lnN - - - - - 1.2 +trigger_eeee_16 lnN 1.01 1.01 1.01 1.01 1.01 - +trigger_ee_16 lnN 1.01 1.01 1.01 1.01 1.01 - +CMS_eff_e shape 1 1 1 1 1 0 +CMS_RecoEff_e shape 1 1 1 1 1 0 +CMS_pileup shape 1 1 1 1 1 0 +CMS_lumi lnN 1.01 1.01 1.01 1.01 1.01 1.01 +lumi_16 lnN 1.023 1.023 1.023 1.023 1.023 1.023 +QCDscale_HZZ_signal shape 0 1 0 0 0 0 +QCDscale_VVV shape 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 1 0 0 0 0 +pdf_VVV shape 0 0 0 0 1 0 +theoAcc lnN - - 1.02 1.02 - - + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/ZZ_template2016_eemm.txt b/Templates/CombineCards/ZZSelection/ZZ_template2016_eemm.txt new file mode 100644 index 00000000..c048a41d --- /dev/null +++ b/Templates/CombineCards/ZZSelection/ZZ_template2016_eemm.txt @@ -0,0 +1,46 @@ +imax 1 number of channels +jmax 5 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin eemm +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin eemm eemm eemm eemm eemm eemm +process zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process 4 3 -1 0 1 2 +rate ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +------------------------------------------------------------------------------------------------------------------------------ +bkg_mm_16 lnN - - - - - 1.1 +bkg_ee_16 lnN - - - - - 1.1 +trigger_ee_16 lnN 1.01 1.01 1.01 1.01 1.01 - +trigger_mm_16 lnN 1.01 1.01 1.01 1.01 1.01 - +CMS_eff_e shape 1 1 1 1 1 0 +CMS_RecoEff_e shape 1 1 1 1 1 0 +CMS_eff_m shape 1 1 1 1 1 0 +#CMS_pileup shape 1 1 1 1 1 0 +CMS_lumi lnN 1.01 1.01 1.01 1.01 1.01 1.01 +lumi_16 lnN 1.023 1.023 1.023 1.023 1.023 1.023 +QCDscale_HZZ_signal shape 0 1 0 0 0 0 +QCDscale_VVV shape 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 1 0 0 0 0 +pdf_VVV shape 0 0 0 0 1 0 +theoAcc lnN - - 1.02 1.02 - - + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/ZZ_template2016_mmee.txt b/Templates/CombineCards/ZZSelection/ZZ_template2016_mmee.txt new file mode 100644 index 00000000..979100b1 --- /dev/null +++ b/Templates/CombineCards/ZZSelection/ZZ_template2016_mmee.txt @@ -0,0 +1,46 @@ +imax 1 number of channels +jmax 5 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin mmee +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin mmee mmee mmee mmee mmee mmee +process zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process 4 3 -1 0 1 2 +rate ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +-------------------------------------------------------------------------------------------- ------------------------------- +bkg_mm_16 lnN - - - - - 1.1 +bkg_ee_16 lnN - - - - - 1.1 +trigger_ee_16 lnN 1.01 1.01 1.01 1.01 1.01 - +trigger_mm_16 lnN 1.01 1.01 1.01 1.01 1.01 - +CMS_eff_e shape 1 1 1 1 1 0 +CMS_RecoEff_e shape 1 1 1 1 1 0 +CMS_eff_m shape 1 1 1 1 1 0 +CMS_pileup shape 1 1 1 1 1 0 +CMS_lumi lnN 1.01 1.01 1.01 1.01 1.01 1.01 +lumi_16 lnN 1.023 1.023 1.023 1.023 1.023 1.023 +QCDscale_HZZ_signal shape 0 1 0 0 0 0 +QCDscale_VVV shape 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 1 0 0 0 0 +pdf_VVV shape 0 0 0 0 1 0 +theoAcc lnN - - 1.02 1.02 - - + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/ZZ_template2016_mmmm.txt b/Templates/CombineCards/ZZSelection/ZZ_template2016_mmmm.txt new file mode 100644 index 00000000..8d6b9f08 --- /dev/null +++ b/Templates/CombineCards/ZZSelection/ZZ_template2016_mmmm.txt @@ -0,0 +1,44 @@ +imax 1 number of channels +jmax 5 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin mmmm +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin mmmm mmmm mmmm mmmm mmmm mmmm +process zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process 4 3 -1 0 1 2 +rate ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +--------------------------------------------------------------------------------------------------------------------------------- +bkg_mmmm_16 lnN - - - - - 1.2 +bkg_mm_16 lnN - - - - - 1.2 +trigger_mmmm_16 lnN 1.01 1.01 1.01 1.01 1.01 - +trigger_mm_16 lnN 1.01 1.01 1.01 1.01 1.01 - +CMS_eff_m shape 1 1 1 1 1 0 +CMS_pileup shape 1 1 1 1 1 0 +CMS_lumi lnN 1.01 1.01 1.01 1.01 1.01 1.01 +lumi_16 lnN 1.023 1.023 1.023 1.023 1.023 1.023 +QCDscale_HZZ_signal shape 0 1 0 0 0 0 +QCDscale_VVV shape 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 1 0 0 0 0 +pdf_VVV shape 0 0 0 0 1 0 +theoAcc lnN - - 1.02 1.02 - - + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/ZZ_template2017_all.txt b/Templates/CombineCards/ZZSelection/ZZ_template2017_all.txt new file mode 100644 index 00000000..f4affd74 --- /dev/null +++ b/Templates/CombineCards/ZZSelection/ZZ_template2017_all.txt @@ -0,0 +1,42 @@ +imax 1 number of channels +jmax 5 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin all +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin all all all all all all +process zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process 4 3 -1 0 1 2 +rate ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +---------------------------------------------------------------------------------------------------------------------- +bkgStat lnN - - - - - 1.4 +trigger lnN 1.020 1.020 1.020 1.020 1.020 - +CMS_eff_e shape 1 1 1 1 1 0 +CMS_RecoEff_e shape 1 1 1 1 1 0 +CMS_eff_m shape 1 1 1 1 1 0 +CMS_pileup shape 1 1 1 1 1 0 +QCDscale_HZZ_signal shape 0 1 0 0 0 0 +QCDscale_VVV shape 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 1 0 0 0 0 +pdf_VVV shape 0 0 0 0 1 0 +theoAcc lnN - - 1.02 1.02 - - + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/ZZ_template2017_eeee.txt b/Templates/CombineCards/ZZSelection/ZZ_template2017_eeee.txt new file mode 100644 index 00000000..a1be4cf1 --- /dev/null +++ b/Templates/CombineCards/ZZSelection/ZZ_template2017_eeee.txt @@ -0,0 +1,45 @@ +imax 1 number of channels +jmax 5 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin eeee +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin eeee eeee eeee eeee eeee eeee +process zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process 4 3 -1 0 1 2 +rate ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +------------------------------------------------------------------------------------------------------------------------------ +bkg_eeee_17 lnN - - - - - 1.2 +bkg_ee_17 lnN - - - - - 1.2 +trigger_eeee_17 lnN 1.01 1.01 1.01 1.01 1.01 - +trigger_ee_17 lnN 1.01 1.01 1.01 1.01 1.01 - +CMS_eff_e shape 1 1 1 1 1 0 +CMS_RecoEff_e shape 1 1 1 1 1 0 +CMS_pileup shape 1 1 1 1 1 0 +CMS_lumi lnN 1.01 1.01 1.01 1.01 1.01 1.01 +lumi_17 lnN 1.021 1.021 1.021 1.021 1.021 1.021 +QCDscale_HZZ_signal shape 0 1 0 0 0 0 +QCDscale_VVV shape 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 1 0 0 0 0 +pdf_VVV shape 0 0 0 0 1 0 +theoAcc lnN - - 1.02 1.02 - - + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/ZZ_template2017_eemm.txt b/Templates/CombineCards/ZZSelection/ZZ_template2017_eemm.txt new file mode 100644 index 00000000..14ddbb4e --- /dev/null +++ b/Templates/CombineCards/ZZSelection/ZZ_template2017_eemm.txt @@ -0,0 +1,46 @@ +imax 1 number of channels +jmax 5 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin eemm +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin eemm eemm eemm eemm eemm eemm +process zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process 4 3 -1 0 1 2 +rate ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +------------------------------------------------------------------------------------------------------------------------------- +bkg_mm_17 lnN - - - - - 1.1 +bkg_ee_17 lnN - - - - - 1.1 +trigger_ee_17 lnN 1.01 1.01 1.01 1.01 1.01 - +trigger_mm_17 lnN 1.01 1.01 1.01 1.01 1.01 - +CMS_eff_e shape 1 1 1 1 1 0 +CMS_RecoEff_e shape 1 1 1 1 1 0 +CMS_eff_m shape 1 1 1 1 1 0 +CMS_pileup shape 1 1 1 1 1 0 +CMS_lumi lnN 1.01 1.01 1.01 1.01 1.01 1.01 +lumi_17 lnN 1.021 1.021 1.021 1.021 1.021 1.021 +QCDscale_HZZ_signal shape 0 1 0 0 0 0 +QCDscale_VVV shape 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 1 0 0 0 0 +pdf_VVV shape 0 0 0 0 1 0 +theoAcc lnN - - 1.02 1.02 - - + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/ZZ_template2017_mmee.txt b/Templates/CombineCards/ZZSelection/ZZ_template2017_mmee.txt new file mode 100644 index 00000000..6abe06f0 --- /dev/null +++ b/Templates/CombineCards/ZZSelection/ZZ_template2017_mmee.txt @@ -0,0 +1,46 @@ +imax 1 number of channels +jmax 5 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin mmee +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin mmee mmee mmee mmee mmee mmee +process zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process 4 3 -1 0 1 2 +rate ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +------------------------------------------------------------------------------------------------------------------------------ +bkg_mm_17 lnN - - - - - 1.1 +bkg_ee_17 lnN - - - - - 1.1 +trigger_ee_17 lnN 1.01 1.01 1.01 1.01 1.01 - +trigger_mm_17 lnN 1.01 1.01 1.01 1.01 1.01 - +CMS_eff_e shape 1 1 1 1 1 0 +CMS_RecoEff_e shape 1 1 1 1 1 0 +CMS_eff_m shape 1 1 1 1 1 0 +CMS_pileup shape 1 1 1 1 1 0 +CMS_lumi lnN 1.01 1.01 1.01 1.01 1.01 1.01 +lumi_17 lnN 1.021 1.021 1.021 1.021 1.021 1.021 +QCDscale_HZZ_signal shape 0 1 0 0 0 0 +QCDscale_VVV shape 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 1 0 0 0 0 +pdf_VVV shape 0 0 0 0 1 0 +theoAcc lnN - - 1.02 1.02 - - + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/ZZ_template2017_mmmm.txt b/Templates/CombineCards/ZZSelection/ZZ_template2017_mmmm.txt new file mode 100644 index 00000000..c318db14 --- /dev/null +++ b/Templates/CombineCards/ZZSelection/ZZ_template2017_mmmm.txt @@ -0,0 +1,44 @@ +imax 1 number of channels +jmax 5 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin mmmm +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin mmmm mmmm mmmm mmmm mmmm mmmm +process zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process 4 3 -1 0 1 2 +rate ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +------------------------------------------------------------------------------------------------------------------------------ +bkg_mmmm_17 lnN - - - - - 1.2 +bkg_mm_17 lnN - - - - - 1.2 +trigger_mmmm_17 lnN 1.01 1.01 1.01 1.01 1.01 - +trigger_mm_17 lnN 1.01 1.01 1.01 1.01 1.01 - +CMS_eff_m shape 1 1 1 1 1 0 +CMS_pileup shape 1 1 1 1 1 0 +CMS_lumi lnN 1.01 1.01 1.01 1.01 1.01 1.01 +lumi_17 lnN 1.021 1.021 1.021 1.021 1.021 1.021 +QCDscale_HZZ_signal shape 0 1 0 0 0 0 +QCDscale_VVV shape 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 1 0 0 0 0 +pdf_VVV shape 0 0 0 0 1 0 +theoAcc lnN - - 1.02 1.02 - - + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/ZZ_template2018_all.txt b/Templates/CombineCards/ZZSelection/ZZ_template2018_all.txt new file mode 100644 index 00000000..753e9d54 --- /dev/null +++ b/Templates/CombineCards/ZZSelection/ZZ_template2018_all.txt @@ -0,0 +1,42 @@ +imax 1 number of channels +jmax 5 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable} HZZ_signal/${fit_variable}_$$SYSTEMATIC +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable} qqZZ_powheg/${fit_variable}_$$SYSTEMATIC +shapes ggZZ * ${output_file} ggZZ/${fit_variable} ggZZ/${fit_variable}_$$SYSTEMATIC +shapes VVV * ${output_file} VVV/${fit_variable} VVV/${fit_variable}_$$SYSTEMATIC + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC +shapes data_obs * ${output_file} data/${fit_variable} + +bin all +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin all all all all all all +process zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process 4 3 -1 0 1 2 +rate ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +---------------------------------------------------------------------------------------------------------------------- +bkgStat lnN - - - - - 1.4 +trigger lnN 1.020 1.020 1.020 1.020 1.020 - +CMS_eff_e shape 1 1 1 1 1 0 +CMS_RecoEff_e shape 1 1 1 1 1 0 +CMS_eff_m shape 1 1 1 1 1 0 +CMS_pileup shape 1 1 1 1 1 0 +QCDscale_HZZ_signal shape 0 1 0 0 0 0 +QCDscale_VVV shape 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 1 0 0 0 0 +pdf_VVV shape 0 0 0 0 1 0 +theoAcc lnN - - 1.02 1.02 - - + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/ZZ_template2018_eeee.txt b/Templates/CombineCards/ZZSelection/ZZ_template2018_eeee.txt new file mode 100644 index 00000000..13f96af8 --- /dev/null +++ b/Templates/CombineCards/ZZSelection/ZZ_template2018_eeee.txt @@ -0,0 +1,45 @@ +imax 1 number of channels +jmax 5 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin eeee +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin eeee eeee eeee eeee eeee eeee +process zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process 4 3 -1 0 1 2 +rate ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +-------------------------------------------------------------------------------------------------------------------------------- +bkg_eeee_18 lnN - - - - - 1.2 +bkg_ee_18 lnN - - - - - 1.2 +trigger_eeee_18 lnN 1.01 1.01 1.01 1.01 1.01 - +trigger_ee_18 lnN 1.01 1.01 1.01 1.01 1.01 - +CMS_eff_e shape 1 1 1 1 1 0 +CMS_RecoEff_e shape 1 1 1 1 1 0 +CMS_pileup shape 1 1 1 1 1 0 +CMS_lumi lnN 1.01 1.01 1.01 1.01 1.01 1.01 +lumi_18 lnN 1.023 1.023 1.023 1.023 1.023 1.023 +QCDscale_HZZ_signal shape 0 1 0 0 0 0 +QCDscale_VVV shape 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 1 0 0 0 0 +pdf_VVV shape 0 0 0 0 1 0 +theoAcc lnN - - 1.02 1.02 - - + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/ZZ_template2018_eemm.txt b/Templates/CombineCards/ZZSelection/ZZ_template2018_eemm.txt new file mode 100644 index 00000000..0837d7f8 --- /dev/null +++ b/Templates/CombineCards/ZZSelection/ZZ_template2018_eemm.txt @@ -0,0 +1,46 @@ +imax 1 number of channels +jmax 5 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin eemm +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin eemm eemm eemm eemm eemm eemm +process zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process 4 3 -1 0 1 2 +rate ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +------------------------------------------------------------------------------------------------------------------------------- +bkg_mm_18 lnN - - - - - 1.1 +bkg_ee_18 lnN - - - - - 1.1 +trigger_ee_18 lnN 1.01 1.01 1.01 1.01 1.01 - +trigger_mm_18 lnN 1.01 1.01 1.01 1.01 1.01 - +CMS_eff_e shape 1 1 1 1 1 0 +CMS_RecoEff_e shape 1 1 1 1 1 0 +CMS_eff_m shape 1 1 1 1 1 0 +CMS_pileup shape 1 1 1 1 1 0 +CMS_lumi lnN 1.01 1.01 1.01 1.01 1.01 1.01 +lumi_18 lnN 1.023 1.023 1.023 1.023 1.023 1.023 +QCDscale_HZZ_signal shape 0 1 0 0 0 0 +QCDscale_VVV shape 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 1 0 0 0 0 +pdf_VVV shape 0 0 0 0 1 0 +theoAcc lnN - - 1.02 1.02 - - + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/ZZ_template2018_mmee.txt b/Templates/CombineCards/ZZSelection/ZZ_template2018_mmee.txt new file mode 100644 index 00000000..e8bddb0f --- /dev/null +++ b/Templates/CombineCards/ZZSelection/ZZ_template2018_mmee.txt @@ -0,0 +1,46 @@ +imax 1 number of channels +jmax 5 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin mmee +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin mmee mmee mmee mmee mmee mmee +process zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process 4 3 -1 0 1 2 +rate ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +--------------------------------------------------------------------------------------------- ------------------------------- +bkg_mm_18 lnN - - - - - 1.1 +bkg_ee_18 lnN - - - - - 1.1 +trigger_ee_18 lnN 1.01 1.01 1.01 1.01 1.01 - +trigger_mm_18 lnN 1.01 1.01 1.01 1.01 1.01 - +CMS_eff_e shape 1 1 1 1 1 0 +CMS_RecoEff_e shape 1 1 1 1 1 0 +CMS_eff_m shape 1 1 1 1 1 0 +CMS_pileup shape 1 1 1 1 1 0 +CMS_lumi lnN 1.01 1.01 1.01 1.01 1.01 1.01 +lumi_18 lnN 1.023 1.023 1.023 1.023 1.023 1.023 +QCDscale_HZZ_signal shape 0 1 0 0 0 0 +QCDscale_VVV shape 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 1 0 0 0 0 +pdf_VVV shape 0 0 0 0 1 0 +theoAcc lnN - - 1.02 1.02 - - + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/ZZ_template2018_mmmm.txt b/Templates/CombineCards/ZZSelection/ZZ_template2018_mmmm.txt new file mode 100644 index 00000000..e5aadc57 --- /dev/null +++ b/Templates/CombineCards/ZZSelection/ZZ_template2018_mmmm.txt @@ -0,0 +1,44 @@ +imax 1 number of channels +jmax 5 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin mmmm +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin mmmm mmmm mmmm mmmm mmmm mmmm +process zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process 4 3 -1 0 1 2 +rate ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +-------------------------------------------------------------------------------------------------------------------------------- +bkg_mmmm_18 lnN - - - - - 1.2 +bkg_mm_18 lnN - - - - - 1.2 +trigger_mmmm_18 lnN 1.01 1.01 1.01 1.01 1.01 - +trigger_mm_18 lnN 1.01 1.01 1.01 1.01 1.01 - +CMS_eff_m shape 1 1 1 1 1 0 +CMS_pileup shape 1 1 1 1 1 0 +CMS_lumi lnN 1.01 1.01 1.01 1.01 1.01 1.01 +lumi_18 lnN 1.023 1.023 1.023 1.023 1.023 1.023 +QCDscale_HZZ_signal shape 0 1 0 0 0 0 +QCDscale_VVV shape 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 1 0 0 0 0 +pdf_VVV shape 0 0 0 0 1 0 +theoAcc lnN - - 1.02 1.02 - - + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/runCombine_Template2017.sh b/Templates/CombineCards/ZZSelection/runCombine_Template2017.sh new file mode 100755 index 00000000..3920b0ce --- /dev/null +++ b/Templates/CombineCards/ZZSelection/runCombine_Template2017.sh @@ -0,0 +1,17 @@ +combineCards.py eeee=ZZ2017_eeee.txt eemm=ZZ2017_eemm.txt mmee=ZZ2017_mmee.txt mmmm=ZZ2017_mmmm.txt > ZZ2017.txt +text2workspace.py ZZ2017.txt -m 999 -o ZZ2017.root + +if [[ $$1 == "impacts" ]]; then + rm -rf impact + mkdir impact + pushd impact + card="../ZZ2017.root" + combineTool.py -M Impacts -m 125 -d $$card --doInitialFit + combineTool.py -M Impacts -m 125 -d $$card --allPars --doFits --parallel 12 + combineTool.py -M Impacts -m 125 -d $$card --allPars -o impacts.json + plotImpacts.py -i impacts.json -o impacts + popd +else + combine -M MaxLikelihoodFit -d ZZ2017.root $$1 +fi + diff --git a/Templates/CombineCards/ZZSelection/runCombine_Template2018.sh b/Templates/CombineCards/ZZSelection/runCombine_Template2018.sh new file mode 100755 index 00000000..a2fde5f7 --- /dev/null +++ b/Templates/CombineCards/ZZSelection/runCombine_Template2018.sh @@ -0,0 +1,17 @@ +combineCards.py eeee=ZZ2018_eeee.txt eemm=ZZ2018_eemm.txt mmee=ZZ2018_mmee.txt mmmm=ZZ2018_mmmm.txt > ZZ2018.txt +text2workspace.py ZZ2018.txt -m 999 -o ZZ2018.root + +if [[ $$1 == "impacts" ]]; then + rm -rf impact + mkdir impact + pushd impact + card="../ZZ2018.root" + combineTool.py -M Impacts -m 125 -d $$card --doInitialFit + combineTool.py -M Impacts -m 125 -d $$card --allPars --doFits --parallel 12 + combineTool.py -M Impacts -m 125 -d $$card --allPars -o impacts.json + plotImpacts.py -i impacts.json -o impacts + popd +else + combine -M MaxLikelihoodFit -d ZZ2018.root $$1 +fi + diff --git a/Templates/CombineCards/ZZSelection/templateWSherpa/ZZ_template2016_all.txt b/Templates/CombineCards/ZZSelection/templateWSherpa/ZZ_template2016_all.txt new file mode 100644 index 00000000..28067e04 --- /dev/null +++ b/Templates/CombineCards/ZZSelection/templateWSherpa/ZZ_template2016_all.txt @@ -0,0 +1,47 @@ +imax 1 number of channels +jmax 6 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes qqZZ_sherpa * ${output_file} qqZZ_sherpa/${fit_variable}_$$CHANNEL qqZZ_sherpa/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin all +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin all all all all all all all +process qqZZ_sherpa zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process 3 -3 -2 -1 0 1 2 +rate ${qqZZ_sherpa} ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +----------------------------------------------------------------------------------------------------------------------------------------- +bkgStat lnN - - - - - - 1.4 +trigger lnN 1.020 1.020 1.020 1.020 1.020 1.020 - +CMS_eff_e shape 1 1 1 1 1 1 0 +CMS_RecoEff_e shape 1 1 1 1 1 1 0 +CMS_eff_m shape 1 1 1 1 1 1 0 +CMS_pileup shape 1 1 1 1 1 1 0 +QCDscale_HZZ_signal shape 0 0 1 0 0 0 0 +QCDscale_qqZZ_powheg shape 0 0 0 1 0 0 0 +QCDscale_ggZZ lnN 0 0 0 0 1.2 0 0 +QCDscale_VVV shape 0 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 0 1 0 0 0 0 +pdf_qqZZ_powheg shape 0 0 0 1 0 0 0 +pdf_ggZZ lnN 0 0 0 0 1.05 0 0 +pdf_VVV shape 0 0 0 0 0 1 0 + + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/templateWSherpa/ZZ_template2016_eeee.txt b/Templates/CombineCards/ZZSelection/templateWSherpa/ZZ_template2016_eeee.txt new file mode 100644 index 00000000..6c11b75b --- /dev/null +++ b/Templates/CombineCards/ZZSelection/templateWSherpa/ZZ_template2016_eeee.txt @@ -0,0 +1,50 @@ +imax 1 number of channels +jmax 6 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes qqZZ_sherpa * ${output_file} qqZZ_sherpa/${fit_variable}_$$CHANNEL qqZZ_sherpa/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin eeee +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin eeee eeee eeee eeee eeee eeee eeee +process qqZZ_sherpa zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process 3 -3 -2 -1 0 1 2 +rate ${qqZZ_sherpa} ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +------------------------------------------------------------------------------------------------------------------------------------------------- +bkg_eeee_16 lnN - - - - - - 1.2 +bkg_ee_16 lnN - - - - - - 1.2 +trigger_eeee_16 lnN 1.01 1.01 1.01 1.01 1.01 1.01 - +trigger_ee_16 lnN 1.01 1.01 1.01 1.01 1.01 1.01 - +CMS_eff_e shape 1 1 1 1 1 1 0 +CMS_RecoEff_e shape 1 1 1 1 1 1 0 +#CMS_pileup shape 1 1 1 1 1 1 0 +CMS_lumi lnN 1.01 1.01 1.01 1.01 1.01 1.01 1.01 +lumi_16 lnN 1.023 1.023 1.023 1.023 1.023 1.023 1.023 +QCDscale_HZZ_signal shape 0 0 1 0 0 0 0 +QCDscale_qqZZ_powheg shape 0 0 0 1 0 0 0 +QCDscale_ggZZ lnN 0 0 0 0 1.2 0 0 +QCDscale_VVV shape 0 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 0 1 0 0 0 0 +pdf_qqZZ_powheg shape 0 0 1 0 0 0 +pdf_ggZZ lnN 0 0 0 1.05 0 0 +pdf_VVV shape 0 0 0 0 1 0 + + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/templateWSherpa/ZZ_template2016_eemm.txt b/Templates/CombineCards/ZZSelection/templateWSherpa/ZZ_template2016_eemm.txt new file mode 100644 index 00000000..632bbbc1 --- /dev/null +++ b/Templates/CombineCards/ZZSelection/templateWSherpa/ZZ_template2016_eemm.txt @@ -0,0 +1,51 @@ +imax 1 number of channels +jmax 6 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes qqZZ_sherpa * ${output_file} qqZZ_sherpa/${fit_variable}_$$CHANNEL qqZZ_sherpa/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin eemm +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin eemm eemm eemm eemm eemm eemm eemm +process qqZZ_sherpa zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process 3 -3 -2 -1 0 1 2 +rate ${qqZZ_sherpa} ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +--------------------------------------------------------------------------------------------------------------------------------------------- +bkg_mm_16 lnN - - - - - - 1.1 +bkg_ee_16 lnN - - - - - - 1.1 +trigger_ee_16 lnN 1.01 1.01 1.01 1.01 1.01 1.01 - +trigger_mm_16 lnN 1.01 1.01 1.01 1.01 1.01 1.01 - +CMS_eff_e shape 1 1 1 1 1 1 0 +CMS_RecoEff_e shape 1 1 1 1 1 1 0 +CMS_eff_m shape 1 1 1 1 1 1 0 +#CMS_pileup shape 1 1 1 1 1 1 0 +CMS_lumi lnN 1.01 1.01 1.01 1.01 1.01 1.01 1.01 +lumi_16 lnN 1.023 1.023 1.023 1.023 1.023 1.023 1.023 +QCDscale_HZZ_signal shape 0 0 1 0 0 0 0 +QCDscale_qqZZ_powheg shape 0 0 0 1 0 0 0 +QCDscale_ggZZ lnN 0 0 0 0 1.2 0 0 +QCDscale_VVV shape 0 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 0 1 0 0 0 0 +pdf_qqZZ_powheg shape 0 0 0 1 0 0 0 +pdf_ggZZ lnN 0 0 0 0 1.05 0 0 +pdf_VVV shape 0 0 0 0 1 0 + + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/templateWSherpa/ZZ_template2016_mmee.txt b/Templates/CombineCards/ZZSelection/templateWSherpa/ZZ_template2016_mmee.txt new file mode 100644 index 00000000..8e6101e3 --- /dev/null +++ b/Templates/CombineCards/ZZSelection/templateWSherpa/ZZ_template2016_mmee.txt @@ -0,0 +1,51 @@ +imax 1 number of channels +jmax 6 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes qqZZ_sherpa * ${output_file} qqZZ_sherpa/${fit_variable}_$$CHANNEL qqZZ_sherpa/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin mmee +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin mmee mmee mmee mmee mmee mmee mmee +process qqZZ_sherpa zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process 3 -3 -2 -1 0 1 2 +rate ${qqZZ_sherpa} ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +----------------------------------------------------------------------------------------------------------- ------------------------------- +bkg_mm_16 lnN - - - - - - 1.1 +bkg_ee_16 lnN - - - - - - 1.1 +trigger_ee_16 lnN 1.01 1.01 1.01 1.01 1.01 1.01 - +trigger_mm_16 lnN 1.01 1.01 1.01 1.01 1.01 1.01 - +CMS_eff_e shape 1 1 1 1 1 1 0 +CMS_RecoEff_e shape 1 1 1 1 1 1 0 +CMS_eff_m shape 1 1 1 1 1 1 0 +#CMS_pileup shape 1 1 1 1 1 1 0 +CMS_lumi lnN 1.01 1.01 1.01 1.01 1.01 1.01 1.01 +lumi_16 lnN 1.023 1.023 1.023 1.023 1.023 1.023 1.023 +QCDscale_HZZ_signal shape 0 0 1 0 0 0 0 +QCDscale_qqZZ_powheg shape 0 0 0 1 0 0 0 +QCDscale_ggZZ lnN 0 0 0 0 1.2 0 0 +QCDscale_VVV shape 0 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 0 1 0 0 0 0 +pdf_qqZZ_powheg shape 0 0 0 1 0 0 0 +pdf_ggZZ lnN 0 0 0 0 1.05 0 0 +pdf_VVV shape 0 0 0 0 0 1 0 + + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/templateWSherpa/ZZ_template2016_mmmm.txt b/Templates/CombineCards/ZZSelection/templateWSherpa/ZZ_template2016_mmmm.txt new file mode 100644 index 00000000..a5546dc8 --- /dev/null +++ b/Templates/CombineCards/ZZSelection/templateWSherpa/ZZ_template2016_mmmm.txt @@ -0,0 +1,49 @@ +imax 1 number of channels +jmax 6 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes qqZZ_sherpa * ${output_file} qqZZ_sherpa/${fit_variable}_$$CHANNEL qqZZ_sherpa/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin mmmm +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin mmmm mmmm mmmm mmmm mmmm mmmm mmmm +process qqZZ_sherpa zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process 3 -3 -2 -1 0 1 2 +rate ${qqZZ_sherpa} ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +------------------------------------------------------------------------------------------------------------------------------------------------- +bkg_mmmm_16 lnN - - - - - - 1.2 +bkg_mm_16 lnN - - - - - - 1.2 +trigger_mmmm_16 lnN 1.01 1.01 1.01 1.01 1.01 1.01 - +trigger_mm_16 lnN 1.01 1.01 1.01 1.01 1.01 1.01 - +CMS_eff_m shape 1 1 1 1 1 1 0 +#CMS_pileup shape 1 1 1 1 1 1 0 +CMS_lumi lnN 1.01 1.01 1.01 1.01 1.01 1.01 1.01 +lumi_16 lnN 1.023 1.023 1.023 1.023 1.023 1.023 1.023 +QCDscale_HZZ_signal shape 0 0 1 0 0 0 0 +QCDscale_qqZZ_powheg shape 0 0 0 1 0 0 0 +QCDscale_ggZZ lnN 0 0 0 0 1.2 0 0 +QCDscale_VVV shape 0 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 0 1 0 0 0 0 +pdf_qqZZ_powheg shape 0 0 0 1 0 0 0 +pdf_ggZZ lnN 0 0 0 0 1.05 0 0 +pdf_VVV shape 0 0 0 0 0 1 0 + + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2016_all.txt b/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2016_all.txt new file mode 100644 index 00000000..3467b98c --- /dev/null +++ b/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2016_all.txt @@ -0,0 +1,46 @@ +imax 1 number of channels +jmax 5 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin all +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin all all all all all all +process zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process -3 -2 -1 0 1 2 +rate ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +--------------------------------------------------------------------------------------------------------------------------- +bkgStat lnN - - - - - 1.4 +trigger lnN 1.020 1.020 1.020 1.020 1.020 - +CMS_eff_e shape 1 1 1 1 1 0 +CMS_RecoEff_e shape 1 1 1 1 1 0 +CMS_eff_m shape 1 1 1 1 1 0 +CMS_pileup shape 1 1 1 1 1 0 +QCDscale_HZZ_signal shape 0 1 0 0 0 0 +QCDscale_qqZZ_powheg shape 0 0 1 0 0 0 +QCDscale_ggZZ lnN 0 0 0 1.2 0 0 +QCDscale_VVV shape 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 1 0 0 0 0 +pdf_qqZZ_powheg shape 0 0 1 0 0 0 +pdf_ggZZ lnN 0 0 0 1.05 0 0 +pdf_VVV shape 0 0 0 0 1 0 + + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2016_eeee.txt b/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2016_eeee.txt new file mode 100644 index 00000000..d9de9a03 --- /dev/null +++ b/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2016_eeee.txt @@ -0,0 +1,49 @@ +imax 1 number of channels +jmax 5 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin eeee +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin eeee eeee eeee eeee eeee eeee +process zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process -3 -2 -1 0 1 2 +rate ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +---------------------------------------------------------------------------------------------------------------------------------- +bkg_eeee_16 lnN - - - - - 1.2 +bkg_ee_16 lnN - - - - - 1.2 +trigger_eeee_16 lnN 1.01 1.01 1.01 1.01 1.01 - +trigger_ee_16 lnN 1.01 1.01 1.01 1.01 1.01 - +CMS_eff_e shape 1 1 1 1 1 0 +CMS_RecoEff_e shape 1 1 1 1 1 0 +#CMS_pileup shape 1 1 1 1 1 0 +CMS_lumi lnN 1.01 1.01 1.01 1.01 1.01 1.01 +lumi_16 lnN 1.023 1.023 1.023 1.023 1.023 1.023 +QCDscale_HZZ_signal shape 0 1 0 0 0 0 +QCDscale_qqZZ_powheg shape 0 0 1 0 0 0 +QCDscale_ggZZ lnN 0 0 0 1.2 0 0 +QCDscale_VVV shape 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 1 0 0 0 0 +pdf_qqZZ_powheg shape 0 0 1 0 0 0 +pdf_ggZZ lnN 0 0 0 1.05 0 0 +pdf_VVV shape 0 0 0 0 1 0 + + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2016_eemm.txt b/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2016_eemm.txt new file mode 100644 index 00000000..31dfd8ba --- /dev/null +++ b/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2016_eemm.txt @@ -0,0 +1,50 @@ +imax 1 number of channels +jmax 5 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin eemm +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin eemm eemm eemm eemm eemm eemm +process zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process -3 -2 -1 0 1 2 +rate ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +------------------------------------------------------------------------------------------------------------------------------ +bkg_mm_16 lnN - - - - - 1.1 +bkg_ee_16 lnN - - - - - 1.1 +trigger_ee_16 lnN 1.01 1.01 1.01 1.01 1.01 - +trigger_mm_16 lnN 1.01 1.01 1.01 1.01 1.01 - +CMS_eff_e shape 1 1 1 1 1 0 +CMS_RecoEff_e shape 1 1 1 1 1 0 +CMS_eff_m shape 1 1 1 1 1 0 +#CMS_pileup shape 1 1 1 1 1 0 +CMS_lumi lnN 1.01 1.01 1.01 1.01 1.01 1.01 +lumi_16 lnN 1.023 1.023 1.023 1.023 1.023 1.023 +QCDscale_HZZ_signal shape 0 1 0 0 0 0 +QCDscale_qqZZ_powheg shape 0 0 1 0 0 0 +QCDscale_ggZZ lnN 0 0 0 1.2 0 0 +QCDscale_VVV shape 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 1 0 0 0 0 +pdf_qqZZ_powheg shape 0 0 1 0 0 0 +pdf_ggZZ lnN 0 0 0 1.05 0 0 +pdf_VVV shape 0 0 0 0 1 0 + + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2016_mmee.txt b/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2016_mmee.txt new file mode 100644 index 00000000..50bc537f --- /dev/null +++ b/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2016_mmee.txt @@ -0,0 +1,50 @@ +imax 1 number of channels +jmax 5 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin mmee +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin mmee mmee mmee mmee mmee mmee +process zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process -3 -2 -1 0 1 2 +rate ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +-------------------------------------------------------------------------------------------- ------------------------------- +bkg_mm_16 lnN - - - - - 1.1 +bkg_ee_16 lnN - - - - - 1.1 +trigger_ee_16 lnN 1.01 1.01 1.01 1.01 1.01 - +trigger_mm_16 lnN 1.01 1.01 1.01 1.01 1.01 - +CMS_eff_e shape 1 1 1 1 1 0 +CMS_RecoEff_e shape 1 1 1 1 1 0 +CMS_eff_m shape 1 1 1 1 1 0 +#CMS_pileup shape 1 1 1 1 1 0 +CMS_lumi lnN 1.01 1.01 1.01 1.01 1.01 1.01 +lumi_16 lnN 1.023 1.023 1.023 1.023 1.023 1.023 +QCDscale_HZZ_signal shape 0 1 0 0 0 0 +QCDscale_qqZZ_powheg shape 0 0 1 0 0 0 +QCDscale_ggZZ lnN 0 0 0 1.2 0 0 +QCDscale_VVV shape 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 1 0 0 0 0 +pdf_qqZZ_powheg shape 0 0 1 0 0 0 +pdf_ggZZ lnN 0 0 0 1.05 0 0 +pdf_VVV shape 0 0 0 0 1 0 + + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2016_mmmm.txt b/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2016_mmmm.txt new file mode 100644 index 00000000..e6bbf877 --- /dev/null +++ b/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2016_mmmm.txt @@ -0,0 +1,48 @@ +imax 1 number of channels +jmax 5 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin mmmm +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin mmmm mmmm mmmm mmmm mmmm mmmm +process zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process -3 -2 -1 0 1 2 +rate ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +--------------------------------------------------------------------------------------------------------------------------------- +bkg_mmmm_16 lnN - - - - - 1.2 +bkg_mm_16 lnN - - - - - 1.2 +trigger_mmmm_16 lnN 1.01 1.01 1.01 1.01 1.01 - +trigger_mm_16 lnN 1.01 1.01 1.01 1.01 1.01 - +CMS_eff_m shape 1 1 1 1 1 0 +#CMS_pileup shape 1 1 1 1 1 0 +CMS_lumi lnN 1.01 1.01 1.01 1.01 1.01 1.01 +lumi_16 lnN 1.023 1.023 1.023 1.023 1.023 1.023 +QCDscale_HZZ_signal shape 0 1 0 0 0 0 +QCDscale_qqZZ_powheg shape 0 0 1 0 0 0 +QCDscale_ggZZ lnN 0 0 0 1.2 0 0 +QCDscale_VVV shape 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 1 0 0 0 0 +pdf_qqZZ_powheg shape 0 0 1 0 0 0 +pdf_ggZZ lnN 0 0 0 1.05 0 0 +pdf_VVV shape 0 0 0 0 1 0 + + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2017_all.txt b/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2017_all.txt new file mode 100644 index 00000000..b27a5fb6 --- /dev/null +++ b/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2017_all.txt @@ -0,0 +1,46 @@ +imax 1 number of channels +jmax 5 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin all +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin all all all all all all +process zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process -3 -2 -1 0 1 2 +rate ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +---------------------------------------------------------------------------------------------------------------------- +bkgStat lnN - - - - - 1.4 +trigger lnN 1.020 1.020 1.020 1.020 1.020 - +CMS_eff_e shape 1 1 1 1 1 0 +CMS_RecoEff_e shape 1 1 1 1 1 0 +CMS_eff_m shape 1 1 1 1 1 0 +#CMS_pileup shape 1 1 1 1 1 0 +QCDscale_HZZ_signal shape 0 1 0 0 0 0 +QCDscale_qqZZ_powheg shape 0 0 1 0 0 0 +QCDscale_ggZZ lnN 0 0 0 1.2 0 0 +QCDscale_VVV shape 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 1 0 0 0 0 +pdf_qqZZ_powheg shape 0 0 1 0 0 0 +pdf_ggZZ lnN 0 0 0 1.05 0 0 +pdf_VVV shape 0 0 0 0 1 0 + + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2017_eeee.txt b/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2017_eeee.txt new file mode 100644 index 00000000..41287956 --- /dev/null +++ b/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2017_eeee.txt @@ -0,0 +1,48 @@ +imax 1 number of channels +jmax 5 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin eeee +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin eeee eeee eeee eeee eeee eeee +process zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process -3 -2 -1 0 1 2 +rate ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +------------------------------------------------------------------------------------------------------------------------------ +bkg_eeee_17 lnN - - - - - 1.2 +bkg_ee_17 lnN - - - - - 1.2 +trigger_eeee_17 lnN 1.01 1.01 1.01 1.01 1.01 - +trigger_ee_17 lnN 1.01 1.01 1.01 1.01 1.01 - +CMS_eff_e shape 1 1 1 1 1 0 +CMS_RecoEff_e shape 1 1 1 1 1 0 +#CMS_pileup shape 1 1 1 1 1 0 +CMS_lumi lnN 1.01 1.01 1.01 1.01 1.01 1.01 +lumi_17 lnN 1.021 1.021 1.021 1.021 1.021 1.021 +QCDscale_HZZ_signal shape 0 1 0 0 0 0 +QCDscale_qqZZ_powheg shape 0 0 1 0 0 0 +QCDscale_ggZZ lnN 0 0 0 1.2 0 0 +QCDscale_VVV shape 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 1 0 0 0 0 +pdf_qqZZ_powheg shape 0 0 1 0 0 0 +pdf_ggZZ lnN 0 0 0 1.05 0 0 +pdf_VVV shape 0 0 0 0 1 0 + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2017_eemm.txt b/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2017_eemm.txt new file mode 100644 index 00000000..9019f1db --- /dev/null +++ b/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2017_eemm.txt @@ -0,0 +1,50 @@ +imax 1 number of channels +jmax 5 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin eemm +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin eemm eemm eemm eemm eemm eemm +process zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process -3 -2 -1 0 1 2 +rate ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +------------------------------------------------------------------------------------------------------------------------------- +bkg_mm_17 lnN - - - - - 1.1 +bkg_ee_17 lnN - - - - - 1.1 +trigger_ee_17 lnN 1.01 1.01 1.01 1.01 1.01 - +trigger_mm_17 lnN 1.01 1.01 1.01 1.01 1.01 - +CMS_eff_e shape 1 1 1 1 1 0 +CMS_RecoEff_e shape 1 1 1 1 1 0 +CMS_eff_m shape 1 1 1 1 1 0 +#CMS_pileup shape 1 1 1 1 1 0 +CMS_lumi lnN 1.01 1.01 1.01 1.01 1.01 1.01 +lumi_17 lnN 1.021 1.021 1.021 1.021 1.021 1.021 +QCDscale_HZZ_signal shape 0 1 0 0 0 0 +QCDscale_qqZZ_powheg shape 0 0 1 0 0 0 +QCDscale_ggZZ lnN 0 0 0 1.2 0 0 +QCDscale_VVV shape 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 1 0 0 0 0 +pdf_qqZZ_powheg shape 0 0 1 0 0 0 +pdf_ggZZ lnN 0 0 0 1.05 0 0 +pdf_VVV shape 0 0 0 0 1 0 + + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2017_mmee.txt b/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2017_mmee.txt new file mode 100644 index 00000000..aed705d5 --- /dev/null +++ b/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2017_mmee.txt @@ -0,0 +1,49 @@ +imax 1 number of channels +jmax 5 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin mmee +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin mmee mmee mmee mmee mmee mmee +process zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process -3 -2 -1 0 1 2 +rate ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +------------------------------------------------------------------------------------------------------------------------------ +bkg_mm_17 lnN - - - - - 1.1 +bkg_ee_17 lnN - - - - - 1.1 +trigger_ee_17 lnN 1.01 1.01 1.01 1.01 1.01 - +trigger_mm_17 lnN 1.01 1.01 1.01 1.01 1.01 - +CMS_eff_e shape 1 1 1 1 1 0 +CMS_RecoEff_e shape 1 1 1 1 1 0 +CMS_eff_m shape 1 1 1 1 1 0 +#CMS_pileup shape 1 1 1 1 1 0 +CMS_lumi lnN 1.01 1.01 1.01 1.01 1.01 1.01 +lumi_17 lnN 1.021 1.021 1.021 1.021 1.021 1.021 +QCDscale_HZZ_signal shape 0 1 0 0 0 0 +QCDscale_qqZZ_powheg shape 0 0 1 0 0 0 +QCDscale_ggZZ lnN 0 0 0 1.2 0 0 +QCDscale_VVV shape 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 1 0 0 0 0 +pdf_qqZZ_powheg shape 0 0 1 0 0 0 +pdf_ggZZ lnN 0 0 0 1.05 0 0 +pdf_VVV shape 0 0 0 0 1 0 + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2017_mmmm.txt b/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2017_mmmm.txt new file mode 100644 index 00000000..e2ae7125 --- /dev/null +++ b/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2017_mmmm.txt @@ -0,0 +1,47 @@ +imax 1 number of channels +jmax 5 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin mmmm +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin mmmm mmmm mmmm mmmm mmmm mmmm +process zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process -3 -2 -1 0 1 2 +rate ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +------------------------------------------------------------------------------------------------------------------------------ +bkg_mmmm_17 lnN - - - - - 1.2 +bkg_mm_17 lnN - - - - - 1.2 +trigger_mmmm_17 lnN 1.01 1.01 1.01 1.01 1.01 - +trigger_mm_17 lnN 1.01 1.01 1.01 1.01 1.01 - +CMS_eff_m shape 1 1 1 1 1 0 +#CMS_pileup shape 1 1 1 1 1 0 +CMS_lumi lnN 1.01 1.01 1.01 1.01 1.01 1.01 +lumi_17 lnN 1.021 1.021 1.021 1.021 1.021 1.021 +QCDscale_HZZ_signal shape 0 1 0 0 0 0 +QCDscale_qqZZ_powheg shape 0 0 1 0 0 0 +QCDscale_ggZZ lnN 0 0 0 1.2 0 0 +QCDscale_VVV shape 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 1 0 0 0 0 +pdf_qqZZ_powheg shape 0 0 1 0 0 0 +pdf_ggZZ lnN 0 0 0 1.05 0 0 +pdf_VVV shape 0 0 0 0 1 0 + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2018_all.txt b/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2018_all.txt new file mode 100644 index 00000000..056b8827 --- /dev/null +++ b/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2018_all.txt @@ -0,0 +1,46 @@ +imax 1 number of channels +jmax 5 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable} HZZ_signal/${fit_variable}_$$SYSTEMATIC +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable} qqZZ_powheg/${fit_variable}_$$SYSTEMATIC +shapes ggZZ * ${output_file} ggZZ/${fit_variable} ggZZ/${fit_variable}_$$SYSTEMATIC +shapes VVV * ${output_file} VVV/${fit_variable} VVV/${fit_variable}_$$SYSTEMATIC + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC +shapes data_obs * ${output_file} data/${fit_variable} + +bin all +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin all all all all all all +process zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process -3 -2 -1 0 1 2 +rate ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +---------------------------------------------------------------------------------------------------------------------- +bkgStat lnN - - - - - 1.4 +trigger lnN 1.020 1.020 1.020 1.020 1.020 - +CMS_eff_e shape 1 1 1 1 1 0 +CMS_RecoEff_e shape 1 1 1 1 1 0 +CMS_eff_m shape 1 1 1 1 1 0 +#CMS_pileup shape 1 1 1 1 1 0 +QCDscale_HZZ_signal shape 0 1 0 0 0 0 +QCDscale_qqZZ_powheg shape 0 0 1 0 0 0 +QCDscale_ggZZ lnN 0 0 0 1.2 0 0 +QCDscale_VVV shape 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 1 0 0 0 0 +pdf_qqZZ_powheg shape 0 0 1 0 0 0 +pdf_ggZZ lnN 0 0 0 1.05 0 0 +pdf_VVV shape 0 0 0 0 1 0 + + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2018_eeee.txt b/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2018_eeee.txt new file mode 100644 index 00000000..7860cc85 --- /dev/null +++ b/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2018_eeee.txt @@ -0,0 +1,48 @@ +imax 1 number of channels +jmax 5 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin eeee +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin eeee eeee eeee eeee eeee eeee +process zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process -3 -2 -1 0 1 2 +rate ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +-------------------------------------------------------------------------------------------------------------------------------- +bkg_eeee_18 lnN - - - - - 1.2 +bkg_ee_18 lnN - - - - - 1.2 +trigger_eeee_18 lnN 1.01 1.01 1.01 1.01 1.01 - +trigger_ee_18 lnN 1.01 1.01 1.01 1.01 1.01 - +CMS_eff_e shape 1 1 1 1 1 0 +CMS_RecoEff_e shape 1 1 1 1 1 0 +#CMS_pileup shape 1 1 1 1 1 0 +CMS_lumi lnN 1.01 1.01 1.01 1.01 1.01 1.01 +lumi_18 lnN 1.023 1.023 1.023 1.023 1.023 1.023 +QCDscale_HZZ_signal shape 0 1 0 0 0 0 +QCDscale_qqZZ_powheg shape 0 0 1 0 0 0 +QCDscale_ggZZ lnN 0 0 0 1.2 0 0 +QCDscale_VVV shape 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 1 0 0 0 0 +pdf_qqZZ_powheg shape 0 0 1 0 0 0 +pdf_ggZZ lnN 0 0 0 1.05 0 0 +pdf_VVV shape 0 0 0 0 1 0 + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2018_eemm.txt b/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2018_eemm.txt new file mode 100644 index 00000000..965fe6a2 --- /dev/null +++ b/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2018_eemm.txt @@ -0,0 +1,50 @@ +imax 1 number of channels +jmax 5 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin eemm +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin eemm eemm eemm eemm eemm eemm +process zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process -3 -2 -1 0 1 2 +rate ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +------------------------------------------------------------------------------------------------------------------------------- +bkg_mm_18 lnN - - - - - 1.1 +bkg_ee_18 lnN - - - - - 1.1 +trigger_ee_18 lnN 1.01 1.01 1.01 1.01 1.01 - +trigger_mm_18 lnN 1.01 1.01 1.01 1.01 1.01 - +CMS_eff_e shape 1 1 1 1 1 0 +CMS_RecoEff_e shape 1 1 1 1 1 0 +CMS_eff_m shape 1 1 1 1 1 0 +#CMS_pileup shape 1 1 1 1 1 0 +CMS_lumi lnN 1.01 1.01 1.01 1.01 1.01 1.01 +lumi_18 lnN 1.023 1.023 1.023 1.023 1.023 1.023 +QCDscale_HZZ_signal shape 0 1 0 0 0 0 +QCDscale_qqZZ_powheg shape 0 0 1 0 0 0 +QCDscale_ggZZ lnN 0 0 0 1.2 0 0 +QCDscale_VVV shape 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 1 0 0 0 0 +pdf_qqZZ_powheg shape 0 0 1 0 0 0 +pdf_ggZZ lnN 0 0 0 1.05 0 0 +pdf_VVV shape 0 0 0 0 1 0 + + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2018_mmee.txt b/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2018_mmee.txt new file mode 100644 index 00000000..6de75044 --- /dev/null +++ b/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2018_mmee.txt @@ -0,0 +1,49 @@ +imax 1 number of channels +jmax 5 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin mmee +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin mmee mmee mmee mmee mmee mmee +process zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process -3 -2 -1 0 1 2 +rate ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +--------------------------------------------------------------------------------------------- ------------------------------- +bkg_mm_18 lnN - - - - - 1.1 +bkg_ee_18 lnN - - - - - 1.1 +trigger_ee_18 lnN 1.01 1.01 1.01 1.01 1.01 - +trigger_mm_18 lnN 1.01 1.01 1.01 1.01 1.01 - +CMS_eff_e shape 1 1 1 1 1 0 +CMS_RecoEff_e shape 1 1 1 1 1 0 +CMS_eff_m shape 1 1 1 1 1 0 +#CMS_pileup shape 1 1 1 1 1 0 +CMS_lumi lnN 1.01 1.01 1.01 1.01 1.01 1.01 +lumi_18 lnN 1.023 1.023 1.023 1.023 1.023 1.023 +QCDscale_HZZ_signal shape 0 1 0 0 0 0 +QCDscale_qqZZ_powheg shape 0 0 1 0 0 0 +QCDscale_ggZZ lnN 0 0 0 1.2 0 0 +QCDscale_VVV shape 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 1 0 0 0 0 +pdf_qqZZ_powheg shape 0 0 1 0 0 0 +pdf_ggZZ lnN 0 0 0 1.05 0 0 +pdf_VVV shape 0 0 0 0 1 0 + +* autoMCStats 1 diff --git a/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2018_mmmm.txt b/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2018_mmmm.txt new file mode 100644 index 00000000..70ab5401 --- /dev/null +++ b/Templates/CombineCards/ZZSelection/templateWithTheory/ZZ_template2018_mmmm.txt @@ -0,0 +1,47 @@ +imax 1 number of channels +jmax 5 number of backgrounds plus signals minus 1 +kmax ${nuisances} number of nuisance parameters (sources of systematical uncertainties) +------------ + +shapes zzjj4l_ewk * ${output_file} zzjj4l_ewk/${fit_variable}_$$CHANNEL zzjj4l_ewk/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes HZZ_signal * ${output_file} HZZ_signal/${fit_variable}_$$CHANNEL HZZ_signal/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes qqZZ_powheg * ${output_file} qqZZ_powheg/${fit_variable}_$$CHANNEL qqZZ_powheg/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes ggZZ * ${output_file} ggZZ/${fit_variable}_$$CHANNEL ggZZ/${fit_variable}_$$SYSTEMATIC_$$CHANNEL +shapes VVV * ${output_file} VVV/${fit_variable}_$$CHANNEL VVV/${fit_variable}_$$SYSTEMATIC_$$CHANNEL + +shapes nonprompt * ${output_file} nonprompt/${fit_variable}_Fakes_$$CHANNEL nonprompt/${fit_variable}_Fakes_$$SYSTEMATIC_$$CHANNEL +shapes data_obs * ${output_file} data/${fit_variable}_$$CHANNEL + +bin mmmm +observation ${data} + +------------ +#nonprompt is data-driven Z+X background +# now we list the expected events for signal and all backgrounds in that bin +# the second 'process' line must have a positive number for backgrounds, and 0 for signal +# then we list the independent sources of uncertainties, and give their effect (syst. error) +# on each process and bin + +bin mmmm mmmm mmmm mmmm mmmm mmmm +process zzjj4l_ewk HZZ_signal qqZZ_powheg ggZZ VVV nonprompt +process -3 -2 -1 0 1 2 +rate ${zzjj4l_ewk} ${HZZ_signal} ${qqZZ_powheg} ${ggZZ} ${VVV} ${nonprompt} +-------------------------------------------------------------------------------------------------------------------------------- +bkg_mmmm_18 lnN - - - - - 1.2 +bkg_mm_18 lnN - - - - - 1.2 +trigger_mmmm_18 lnN 1.01 1.01 1.01 1.01 1.01 - +trigger_mm_18 lnN 1.01 1.01 1.01 1.01 1.01 - +CMS_eff_m shape 1 1 1 1 1 0 +#CMS_pileup shape 1 1 1 1 1 0 +CMS_lumi lnN 1.01 1.01 1.01 1.01 1.01 1.01 +lumi_18 lnN 1.023 1.023 1.023 1.023 1.023 1.023 +QCDscale_HZZ_signal shape 0 1 0 0 0 0 +QCDscale_qqZZ_powheg shape 0 0 1 0 0 0 +QCDscale_ggZZ lnN 0 0 0 1.2 0 0 +QCDscale_VVV shape 0 0 0 0 1 0 +pdf_HZZ_signal shape 0 1 0 0 0 0 +pdf_qqZZ_powheg shape 0 0 1 0 0 0 +pdf_ggZZ lnN 0 0 0 1.05 0 0 +pdf_VVV shape 0 0 0 0 1 0 + +* autoMCStats 1 diff --git a/Templates/config.kelong b/Templates/config.kelong index d3790450..afd857d5 100644 --- a/Templates/config.kelong +++ b/Templates/config.kelong @@ -2,6 +2,7 @@ user = kelong analysis = WZ dataset_manager_path = /afs/cern.ch/user/k/%(user)s/work +dataset_manager_name = AnalysisDatasetManager combine_path = %(dataset_manager_path)s/HiggsCombine/CMSSW_8_1_0/src/HiggsAnalysis/CombinedLimit output_path = /eos/user/k/%(user)s/%(analysis)sAnalysisData fakeRate_output = %(output_path)s/FakeRates diff --git a/Templates/config.uhussain b/Templates/config.uhussain new file mode 100644 index 00000000..915b46f1 --- /dev/null +++ b/Templates/config.uhussain @@ -0,0 +1,10 @@ +[Setup] +user = uhussain +analysis = ZZ +dataset_manager_path = /afs/cern.ch/user/u/%(user)s/work +dataset_manager_name = ZZ4lRun2DatasetManager +combine_path = %(dataset_manager_path)s/%(dataset_manager_name)s/HiggsCombine/CMSSW_10_2_3/src/HiggsAnalysis/CombinedLimit +output_path = /eos/user/u/%(user)s/%(analysis)sAnalysisData +fakeRate_output = %(output_path)s/FakesRates +hist_output = %(output_path)s/HistFiles +combine_output = %(output_path)s/CombineData diff --git a/Utilities/python/CombineCardTools.py b/Utilities/python/CombineCardTools.py new file mode 100644 index 00000000..cb98fa5f --- /dev/null +++ b/Utilities/python/CombineCardTools.py @@ -0,0 +1,228 @@ +import logging +import ConfigureJobs +import HistTools +import OutputTools +from prettytable import PrettyTable +import os +import ROOT + +class CombineCardTools(object): + def __init__(self): + self.fitVariable = "" + self.fitVariableAppend = {} + self.processes = [] + self.yields = {} + self.histData = {} + self.crossSectionMap = {} + self.outputFile = "" + self.templateName = "" + self.channels = [] + self.variations = {} + self.rebin = None + self.isMC = True + self.isUnrolledFit = False + self.lumi = 1 + self.outputFolder = "." + self.theoryVariations = {} + + def setPlotGroups(self, xsecMap): + self.crossSectionMap = xsecMap + + def setRebin(self, rebin): + self.rebin = rebin + + def setCrosSectionMap(self, xsecMap): + self.crossSectionMap = xsecMap + + # Map of plot groups and members (individual processes) + def setProcesses(self, processes): + self.processes = processes + + def setFitVariableAppend(self, process, append): + self.fitVariableAppend[process] = append + + def setFitVariable(self, variable): + self.fitVariable = variable + + def setVariations(self, variations, exclude=[]): + if not self.processes: + raise ValueError("No processes defined, can't set variations") + for process in self.processes.keys(): + if process in exclude: + self.setVariationsByProcess(process, []) + continue + self.setVariationsByProcess(process, variations) + + def getVariations(self): + return self.variations + + def getVariationsForProcess(self, process): + if process not in self.variations.keys(): + raise ValueError("Variations not defined for process %s" % process) + return self.variations[process] + + def setVariationsByProcess(self, process, variations): + if "Up" not in variations and "Down" not in variations: + variations = [x+y for x in variations for y in ["Up", "Down"]] + self.variations[process] = variations + + def weightHistName(self, channel, process): + fitVariable = self.getFitVariable(process) + variable = fitVariable.replace("unrolled", "2D") if self.isUnrolledFit else fitVariable + return "_".join([variable, "lheWeights", channel]) + + def setLumi(self, lumi): + self.lumi = lumi + + def setOutputFolder(self, outputFolder): + self.outputFolder = outputFolder + if not os.path.isdir(outputFolder): + os.makedirs(outputFolder) + + def addTheoryVar(self, processName, varName, entries, central=0, exclude=[]): + if "scale" not in varName.lower() and "pdf" not in varName.lower(): + raise ValueError("Invalid theory uncertainty %s. Must be type 'scale' or 'pdf'" % varName) + name = "scale" if "scale" in varName.lower() else "pdf" + + if not processName in self.theoryVariations: + self.theoryVariations[processName] = {} + + self.theoryVariations[processName].update({ name : { + "entries" : entries, + "central" : central, + "exclude" : exclude, + "combine" : "envelope" if name == "scale" else ("hessian" if "hessian" in varName else "mc"), + } + }) + + def getRootFile(self, rtfile, mode=None): + if type(rtfile) == str: + if mode: + return ROOT.TFile.Open(rtfile, mode) + else: + return ROOT.TFile.Open(rtfile) + return rtfile + + def setTemplateFileName(self, templateName): + self.templateName = templateName + + def setOutputFile(self, outputFile): + #self.outputFile = self.getRootFile("/".join([self.outputFolder, outputFile]), "RECREATE") + self.outputFile = self.getRootFile(outputFile, "RECREATE") + + def setInputFile(self, inputFile): + self.inputFile = self.getRootFile(inputFile) + + def setChannels(self, channels): + self.channels = channels + for chan in self.channels + ["all"]: + self.yields[chan] = {} + + def processHists(self, processName): + return self.histData[processName] + + def getFitVariable(self, process): + if process not in self.fitVariableAppend: + return self.fitVariable + return "_".join([self.fitVariable, self.fitVariableAppend[process]]) + + def combineChannels(self, group, central=True): + variations = self.variations[group.GetName()][:] + fitVariable = self.getFitVariable(group.GetName()) + if central: + variations.append("") + for var in variations: + # TODO: Remove these two replace statements, it's WZ/ZZ specific + name = fitVariable if var is "" else "_".join([fitVariable, var]) + hist_name = name + "_" + self.channels[0] + hist = group.FindObject(hist_name) + if not hist: + logging.warning("Failed to find hist %s in group %s. Skipping" % (hist_name, group.GetName())) + continue + hist = hist.Clone(name) + ROOT.SetOwnership(hist, False) + group.Add(hist) + for chan in self.channels[1:]: + chan_hist = group.FindObject(name + "_" + chan) + hist.Add(chan_hist) + + def listOfHistsByProcess(self, processName): + if self.fitVariable == "": + raise ValueError("Must declare fit variable before defining plots") + fitVariable = self.getFitVariable(processName) + plots = ["_".join([fitVariable, chan]) for chan in self.channels] + variations = self.getVariationsForProcess(processName) + plots += ["_".join([fitVariable, var, c]) for var in variations for c in self.channels] + if processName in self.theoryVariations.keys(): + plots += [self.weightHistName(c, processName) for c in self.channels] + return plots + + # processName needs to match a PlotGroup + def loadHistsForProcess(self, processName, scaleNorm=1): + plotsToRead = self.listOfHistsByProcess(processName) + + group = HistTools.makeCompositeHists(self.inputFile, processName, + {proc : self.crossSectionMap[proc] for proc in self.processes[processName]}, + self.lumi, plotsToRead, rebin=self.rebin, overflow=False) + + fitVariable = self.getFitVariable(processName) + #TODO:Make optional + processedHists = [] + for chan in self.channels: + histName = "_".join([fitVariable, chan]) if chan != "all" else fitVariable + hist = group.FindObject(histName) + #TODO: Make optional + if "data" not in processName.lower(): + HistTools.removeZeros(hist) + HistTools.addOverflow(hist) + processedHists.append(histName) + self.yields[chan].update({processName : round(hist.Integral(), 4) if hist.Integral() > 0 else 0.0001}) + + if chan == self.channels[0]: + self.yields["all"][processName] = self.yields[chan][processName] + else: + self.yields["all"][processName] += self.yields[chan][processName] + + if processName in self.theoryVariations: + weightHist = group.FindObject(self.weightHistName(chan, processName)) + if not weightHist: + logging.warning("Failed to find %s. Skipping" % self.weightHistName(chan, processName)) + continue + theoryVars = self.theoryVariations[processName] + scaleHists = HistTools.getScaleHists(weightHist, processName, self.rebin, + entries=theoryVars['scale']['entries'], central=theoryVars['scale']['central']) + pdfFunction = getattr(HistTools, "get%sPDFVariationHists" % ("Hessian" if "hessian" in theoryVars['pdf']['combine'] else "MC")) + pdfHists = pdfFunction(weightHist, theoryVars['pdf']['entries'], processName, + self.rebin, central=theoryVars['pdf']['central']) + group.extend(scaleHists+pdfHists) + #TODO: You may want to combine channels before removing zeros + self.combineChannels(group) + #TODO: Make optional + map(HistTools.addOverflow, filter(lambda x: (x.GetName() not in processedHists), group)) + if "data" not in group.GetName().lower(): + map(HistTools.removeZeros, filter(lambda x: (x.GetName() not in processedHists), group)) + self.histData[processName] = group + + # It's best to call this function for process, otherwise you can end up + # storing many large histograms in memory + def writeProcessHistsToOutput(self, processName): + if processName not in self.histData.keys() or not self.histData[processName]: + raise ValueError("Hists for process %s not found" % processName) + processHists = self.histData[processName] + OutputTools.writeOutputListItem(processHists, self.outputFile) + processHists.Delete() + + def writeCards(self, chan, nuisances, year="", extraArgs={}): + chan_dict = self.yields[chan].copy() + chan_dict.update(extraArgs) + chan_dict["nuisances"] = nuisances + chan_dict["fit_variable"] = self.fitVariable + chan_dict["output_file"] = self.outputFile.GetName() + outputCard = self.templateName.split("/")[-1].format(channel=chan, year=year) + outputCard = outputCard.replace("template", "") + outputCard = outputCard.replace("__", "_") + ConfigureJobs.fillTemplatedFile(self.templateName.format(channel=chan, year=year), + "/".join([self.outputFolder, outputCard]), + chan_dict + ) + diff --git a/Utilities/python/ConfigureJobs.py b/Utilities/python/ConfigureJobs.py index 66a9d627..e89dedf2 100644 --- a/Utilities/python/ConfigureJobs.py +++ b/Utilities/python/ConfigureJobs.py @@ -7,6 +7,8 @@ import json import array import string +import socket +import logging #try: import configparser #except: @@ -43,19 +45,37 @@ def getBinning(variable='MTWZ', isVBS=True, isHiggs=False): def getChannels(analysis='WZ'): if analysis == 'WZ': return ["eee", "eem", "emm", "mmm"] -def getManagerPath(): + +def getManagerName(): + config_name = "Templates/config.%s" % os.getlogin() + default_name = "AnalysisDatasetManager" + if not os.path.isfile(config_name): + logging.warning("dataset_manager_name not specified in config file %s" % config_name) + logging.warning("Using default '%s'" % default_name) + return default_name config = configparser.ConfigParser() - try: - config.read_file(open("Templates/config.%s" % os.environ["USER"])) - if "dataset_manager_path" not in config['Setup']: - raise ValueError("dataset_manager_path not specified in config file Template/config.%s" - % os.environ["USER"]) - except ValueError as e: - if os.path.isdir('AnalysisDatasetManager'): - return '.' - raise e + config.read_file(open(config_name)) + if "dataset_manager_name" not in config['Setup']: + logging.warning("dataset_manager_name not specified in config file %s" % config_name) + logging.warning("Using default '%s'" % default_name) + return default_name + return config['Setup']['dataset_manager_name'] +def getManagerPath(): + config_name = "Templates/config.%s" % os.getlogin() + if not os.path.isfile(config_name): + if os.path.isdir(getManagerName()): + return '.' + else: + raise IOError("Failed to find valid config file. Looking for %s" + % config_name) + config = configparser.ConfigParser() + config.read_file(open(config_name)) + if "dataset_manager_path" not in config['Setup']: + raise ValueError("dataset_manager_path not specified in config file %s" + % config_name) return config['Setup']['dataset_manager_path'] + "/" + def getCombinePath(): config = configparser.ConfigParser() config.read_file(open("Templates/config.%s" % os.environ["USER"])) @@ -63,7 +83,39 @@ def getCombinePath(): raise ValueError("dataset_manager_path not specified in config file Template/config.%s" % os.environ["USER"]) return config['Setup']['combine_path'] + "/" -def getListOfEWKFilenames(): +def getListOfGenFilenames(analysis='ZZ'): + if 'ZZ' in analysis: + return [ + "zz4l-amcatnlo", + "zz4l-powheg", + #"zzjj4l-ewk", + "ggZZ4e", + "ggZZ4m", + "ggZZ4t", + "ggZZ2e2mu", + "ggZZ2e2tau", + "ggZZ2mu2tau", + "ggHZZ", + "ttH_HToZZ_4L", + "WminusHToZZ", + "WplusHToZZ", + "ZHToZZ_4L", + "vbfHZZ", + ] + return [] +def getListOfEWKFilenames(analysis=""): + if "ZZ4l" in analysis: + return [ + "zz4l-powheg", + #"zzjj4l-ewk", + "ggZZ4e", + "ggZZ4m", + "ggZZ4t", + "ggZZ2e2mu", + "ggZZ2e2tau", + "ggZZ2mu2tau", + ] + # TODO: This is obviously WZ specific and should be updated return [ # "wz3lnu-powheg", # Use jet binned WZ samples for subtraction by default @@ -87,6 +139,11 @@ def getListOfEWKFilenames(): "ggZZ4m", "ggZZ2e2mu", ] +def getListOfDYFilenames(): + return[ + "DYJetsToLL_M10to50", + "DYJetsToLLM-50", + ] def getListOfNonpromptFilenames(): return ["tt-lep", "st-schan", @@ -138,20 +195,58 @@ def getListOfHDFSFiles(file_path): elif "root" in split[1]: files.append(split[1]) return files -def getListOfFiles(filelist, selection, manager_path=""): + +# TODO: Would be good to switch the order of the last two arguments +# completely deprecate manager_path without breaking things +def getListOfFiles(filelist, selection, manager_path="", analysis=""): if manager_path is "": manager_path = getManagerPath() - data_path = "%s/AnalysisDatasetManager/FileInfo" % manager_path + data_path = "%s/%s/FileInfo" % (manager_path, getManagerName()) data_info = UserInput.readAllInfo("/".join([data_path, "data/*"])) mc_info = UserInput.readAllInfo("/".join([data_path, "montecarlo/*"])) - valid_names = data_info.keys() + mc_info.keys() + analysis_info = UserInput.readInfo("/".join([data_path, analysis, selection])) \ + if analysis != "" else [] + valid_names = (data_info.keys() + mc_info.keys()) if not analysis_info else analysis_info.keys() names = [] for name in filelist: if ".root" in name: names.append(name) elif "WZxsec2016" in name: dataset_file = manager_path + \ - "AnalysisDatasetManager/FileInfo/WZxsec2016/%s.json" % selection + "%s/FileInfo/WZxsec2016/%s.json" % (getManagerPath(), selection) + allnames = json.load(open(dataset_file)).keys() + if "nodata" in name: + nodata = [x for x in allnames if "data" not in x] + names += nodata + elif "data" in name: + names += [x for x in allnames if "data" in x] + else: + names += allnames + elif "ZZ4l2016" in name: + dataset_file = manager_path + \ + "ZZ4lRun2DatasetManager/FileInfo/ZZ4l2016/%s.json" % selection + allnames = json.load(open(dataset_file)).keys() + if "nodata" in name: + nodata = [x for x in allnames if "data" not in x] + names += nodata + elif "data" in name: + names += [x for x in allnames if "data" in x] + else: + names += allnames + elif "ZZ4l2017" in name: + dataset_file = manager_path + \ + "ZZ4lRun2DatasetManager/FileInfo/ZZ4l2017/%s.json" % selection + allnames = json.load(open(dataset_file)).keys() + if "nodata" in name: + nodata = [x for x in allnames if "data" not in x] + names += nodata + elif "data" in name: + names += [x for x in allnames if "data" in x] + else: + names += allnames + elif "ZZ4l2018" in name: + dataset_file = manager_path + \ + "ZZ4lRun2DatasetManager/FileInfo/ZZ4l2018/%s.json" % selection allnames = json.load(open(dataset_file)).keys() if "nodata" in name: nodata = [x for x in allnames if "data" not in x] @@ -165,16 +260,19 @@ def getListOfFiles(filelist, selection, manager_path=""): else: if name.split("__")[0] not in valid_names: print "%s is not a valid name" % name - print "Valid names are", valid_names + print "Valid names must be defined in AnalysisDatasetManager/FileInfo/(data/montecarlo)*" continue names += [name] return [str(i) for i in names] def getXrdRedirector(): - usbased = ["hep.wisc.edu"] - if any(i in os.environ["HOSTNAME"] for i in usbased): - return 'cmsxrootd.fnal.gov' - return 'cms-xrd-global.cern.ch' + usbased = ["wisc.edu"] + usredir = 'cmsxrootd.fnal.gov' + globalredir = 'cms-xrd-global.cern.ch' + # Cluster machines may not have this env variable + if any(i in socket.gethostname() for i in usbased): + return usredir + return globalredir def fillTemplatedFile(template_file_name, out_file_name, template_dict): with open(template_file_name, "r") as templateFile: @@ -182,21 +280,37 @@ def fillTemplatedFile(template_file_name, out_file_name, template_dict): result = source.substitute(template_dict) with open(out_file_name, "w") as outFile: outFile.write(result) -def getListOfFilesWithXSec(filelist, manager_path=""): + +def getListOfFilesWithXSec(filelist, manager_path="", selection="ntuples"): if manager_path is "": manager_path = getManagerPath() - data_path = "%s/AnalysisDatasetManager/FileInfo" % manager_path - files = getListOfFiles(filelist, "ntuples", manager_path) + data_path = "%s/%s/FileInfo" % (manager_path, getManagerName()) + files = getListOfFiles(filelist, selection, manager_path) mc_info = UserInput.readAllInfo("/".join([data_path, "montecarlo/*"])) info = {} for file_name in files: - if "data" in file_name: + if "data" in file_name.lower() or "nonprompt" in file_name.lower(): info.update({file_name : 1}) else: file_info = mc_info[file_name.split("__")[0]] kfac = file_info["kfactor"] if "kfactor" in file_info.keys() else 1 info.update({file_name : file_info["cross_section"]*kfac}) return info + +def getListOfFilesWithDASPath(filelist, analysis, selection, manager_path=""): + if manager_path is "": + manager_path = getManagerPath() + data_path = "%s/%s/FileInfo" % (manager_path, getManagerName()) + files = getListOfFiles(filelist, selection, manager_path, analysis) + selection_info = UserInput.readInfo("/".join([data_path, analysis, selection])) + info = {} + for file_name in files: + if "DAS" not in selection_info[file_name].keys(): + print "ERROR: DAS path not defined for file %s in analysis %s/%s" % (file_name, analysis, selection) + continue + info.update({file_name : selection_info[file_name]["DAS"]}) + return info + def getPreviousStep(selection, analysis): selection_map = {} if analysis == "WZxsec2016": @@ -239,7 +353,7 @@ def getConfigFileName(config_file_name): for extension in ["json", "py"]: if os.path.isfile(".".join([config_file_name, extension])): return ".".join([config_file_name, extension]) - raise IOError("Invalid configuration file. Tried to read %s which does not exist" % \ + raise ValueError("Invalid configuration file. Tried to read %s which does not exist" % \ config_file_name) def getInputFilesPath(sample_name, selection, analysis, manager_path=""): @@ -248,7 +362,7 @@ def getInputFilesPath(sample_name, selection, analysis, manager_path=""): if ".root" in sample_name: print "INFO: using simple file %s" % sample_name return sample_name - data_path = "%s/AnalysisDatasetManager/FileInfo" % manager_path + data_path = "%s/%s/FileInfo" % (manager_path, getManagerName()) input_file_base_name = "/".join([data_path, analysis, selection]) input_file_name = getConfigFileName(input_file_base_name) input_files = UserInput.readInfo(input_file_name) diff --git a/Utilities/python/HistTools.py b/Utilities/python/HistTools.py index 00c6408e..ddffabdf 100644 --- a/Utilities/python/HistTools.py +++ b/Utilities/python/HistTools.py @@ -1,5 +1,7 @@ import array import ROOT +import logging +import math def getDifference(fOut, name, dir1, dir2, ratioFunc=None): differences = ROOT.TList() @@ -12,11 +14,11 @@ def getDifference(fOut, name, dir1, dir2, ratioFunc=None): diff = hist1.Clone() diff.Add(hist2, -1) elif not hist1: - print "WARNING: Hist %s was not produced for " \ - "dataset(s) %s" % (histname, dir1) + logging.warning("Hist %s was not produced for " \ + "dataset(s) %s" % (histname, dir1)) elif not hist2: - print "WARNING: Hist %s was not produced for " \ - "dataset(s) %s" % (histname, dir2) + logging.warning("Hist %s was not produced for " \ + "dataset(s) %s" % (histname, dir2)) differences.Add(diff) if ratioFunc: ratios = ratioFunc(differences) @@ -126,61 +128,83 @@ def getLHEWeightHists(init2D_hist, entries, name, variation_name, rebin=None): hist_name = init2D_hist.GetName().replace("lheWeights", "%s_%sUp" % (variation_name, name)) return hists, hist_name -def getPDFHists(init2D_hist, entries, name, rebin=None): +def getMCPDFVariationHists(init2D_hist, entries, name, rebin=None, central=0): hists, hist_name = getLHEWeightHists(init2D_hist, entries, name, "pdf", rebin) - #return hists + if central == -1: + upaction = lambda x: x[int(0.84*len(entries))] + downaction = lambda x: x[int(0.16*len(entries))] + else: + upaction = lambda x : x[central]*(1+getPDFPercentVariation(x)) + downaction = lambda x: x[central]*(1-getPDFPercentVariation(x)) + return getVariationHists(hists, name, hist_name, - lambda x: x[0]*(1+getPDFPercentVariation(x)), - lambda x: x[0]*(1-getPDFPercentVariation(x)) + upaction, downaction, central ) +def getHessianPDFVariationHists(init2D_hist, entries, name, rebin=None, central=0): + hists, hist_name = getLHEWeightHists(init2D_hist, entries, name, "pdf", rebin) + #centralIndex = central if central != -1 else int(len(entries)/2) + sumsq = lambda x: math.sqrt(sum([0 if y < 0.01 else ((x[central] - y)**2) for y in x])) + upaction = lambda x: x[central] + sumsq(x) + downaction = lambda x: x[central] - sumsq(x) + return getVariationHists(hists, name, hist_name, + upaction, downaction, central, #downaction, central + ) + +def getAllHessianPDFHists(): + hists, hist_name = getLHEWeightHists(init2D_hist, entries, name, "pdf", rebin) + return hists + def getPDFPercentVariation(values): denom = values[84] + values[16] if denom == 0: return 0 return abs(values[84] - values[16])/denom -def getScaleHists(scale_hist2D, name, rebin=None): - entries = [i for i in range(1,10) if i not in [7, 9]] +def getScaleHists(scale_hist2D, name, rebin=None, entries=[i for i in range(1,10)], central=0, exclude=[7,9]): hists, hist_name = getLHEWeightHists(scale_hist2D, entries, name, "QCDscale", rebin) - return getVariationHists(hists, name, hist_name, lambda x: x[-1], lambda x: x[1]) + return getVariationHists(hists, name, hist_name, lambda x: x[-1], lambda x: x[1], central) -def getVariationHists(hists, process_name, histUp_name, up_action, down_action): - histUp = hists[0].Clone(histUp_name) +def getVariationHists(hists, process_name, histUp_name, up_action, down_action, central=0): + histUp = hists[central].Clone(histUp_name) histDown = histUp.Clone(histUp_name.replace("Up", "Down")) - histCentral = hists[0] + histCentral = hists.pop(central) if central != -1 else None # Include overflow - for i in range(0, hists[0].GetNbinsX()+2): + for i in range(0, histUp.GetNbinsX()+2): vals = [] - for hist in hists[1:]: + for hist in hists: vals.append(hist.GetBinContent(i)) vals.sort() - vals.insert(0, histCentral.GetBinContent(i)) + vals.insert(0, histCentral.GetBinContent(i) if histCentral else 0) histUp.SetBinContent(i, up_action(vals)) histDown.SetBinContent(i, down_action(vals)) # For now, skip this check on aQGC for now, since they're screwed up if "aqgc" in process_name: continue - isValidVariation(process_name, histCentral, histUp, histDown) + logging.debug("For process %s: Central, down, up: %s, %s, %s" % (process_name, histCentral.Integral() if histCentral else 0, histDown.Integral(), histUp.Integral())) + if histCentral and False: # Off for now, it can happen that groups have some hists with no weights which screws this up + isValidVariation(process_name, histCentral, histUp, histDown) return [histUp, histDown] def isValidVariation(process_name, histCentral, histUp, histDown): for i in range(0, histCentral.GetNbinsX()+2): - if histDown.GetBinContent(i) >= histCentral.GetBinContent(i) and histCentral.GetBinContent(i) > 0: + if histDown.GetBinContent(i) > histCentral.GetBinContent(i) and histCentral.GetBinContent(i) > 0.01: raise RuntimeError("Down variation >= central value for %s, hist %s" " This shouldn't be possible.\n" + "up_hist: %0.4f\n" "down_hist: %0.4f\n" "central_hist: %0.4f\n" "bin: %i\n" - % (process_name, histDown.GetName(), histDown.GetBinContent(i), histCentral.GetBinContent(i), i) + % (process_name, histDown.GetName(), histUp.GetBinContent(i), histDown.GetBinContent(i), histCentral.GetBinContent(i), i) ) - if histUp.GetBinContent(i) <= histCentral.GetBinContent(i) and histCentral.GetBinContent(i) > 0: + if histUp.GetBinContent(i) < histCentral.GetBinContent(i) and histCentral.GetBinContent(i) > 0.01: raise RuntimeError("Up variation <= central value for %s, hist %s." " This shouldn't be possible.\n" - "up_hist: %0.2f\n" - "central_hist: %0.2f\n" + "up_hist: %0.4f\n" + "down_hist: %0.4f\n" + "central_hist: %0.4f\n" "bin: %i\n" - % (process_name, histUp.GetName(), histUp.GetBinContent(i), histCentral.GetBinContent(i), i) + % (process_name, histUp.GetName(), histUp.GetBinContent(i), histDown.GetBinContent(i), histCentral.GetBinContent(i), i) ) def getTransformed3DScaleHists(scale_hist3D, transformation, transform_args, name): @@ -229,6 +253,9 @@ def addControlRegionToFitHist(control_hist, input_hist, base_name="unrolled"): ROOT.SetOwnership(hist, False) return hist +def addOverflow(hist): + addOverflowAndUnderflow(hist, underflow=False, overflow=True) + def addOverflowAndUnderflow(hist, underflow=True, overflow=True): if not "TH1" in hist.ClassName(): return @@ -241,7 +268,7 @@ def addOverflowAndUnderflow(hist, underflow=True, overflow=True): add_underflow = hist.GetBinContent(0) + hist.GetBinContent(1) hist.SetBinContent(1, add_underflow) -def makeCompositeHists(hist_file, name, members, lumi, hists=[], underflow=False, overflow=True, rebin=None): +def makeCompositeHists(hist_file, name, members, lumi, hists=[], hist_filter=0, underflow=False, overflow=True, rebin=None): composite = ROOT.TList() composite.SetName(name) for directory in [str(i) for i in members.keys()]: @@ -249,16 +276,18 @@ def makeCompositeHists(hist_file, name, members, lumi, hists=[], underflow=False if "aqgc" in directory: directory = name if not hist_file.Get(directory): - print "Skipping invalid filename %s" % directory + logging.warning("Skipping invalid filename %s" % directory) continue if hists == []: hists = [i.GetName() for i in hist_file.Get(directory).GetListOfKeys()] + if hist_filter: + hists = filter(hist_filter, hists) sumweights = 0 - if "data" not in directory.lower(): - sumweights_hist = hist_file.Get("/".join([directory.split("__")[0], "sumweights"])) + if "data" not in directory.lower() and "nonprompt" not in directory.lower(): + sumweights_hist = hist_file.Get("/".join([directory, "sumweights"])) if not sumweights_hist: raise RuntimeError("Failed to find sumWeights for dataset %s" % directory) - sumweights = sumweights_hist.Integral() + sumweights = sumweights_hist.Integral(1, sumweights_hist.GetNbinsX()+2) sumweights_hist.Delete() for histname in hists: if histname == "sumweights": continue @@ -271,7 +300,8 @@ def makeCompositeHists(hist_file, name, members, lumi, hists=[], underflow=False if hist: sumhist = composite.FindObject(hist.GetName()) if sumweights: - hist.Scale(members[directory.split("__")[0]]*1000*lumi/sumweights) + xsec = members[directory if directory in members.keys() else directory.split("__")[0]] + hist.Scale(xsec*1000*lumi/sumweights) addOverflowAndUnderflow(hist, underflow, overflow) else: raise RuntimeError("hist %s was not produced for " diff --git a/Utilities/python/SelectorTools.py b/Utilities/python/SelectorTools.py index 918bb2dc..a672f1d9 100755 --- a/Utilities/python/SelectorTools.py +++ b/Utilities/python/SelectorTools.py @@ -20,7 +20,9 @@ def __init__(self, analysis, selection, input_tier, year): "Zstudy" : "ZSelector", "Zstudy_2016" : "ZSelector", "Zstudy_2017" : "ZSelector", - "ZZGen" : "ZZGenSelector", + "ZZ4l2016" : "ZZSelector", + "ZZ4l2017" : "ZZSelector", + "ZZ4l2018" : "ZZSelector", "WGen" : "WGenSelector", "ZGen" : "ZGenSelector", "ThreeLep" : "ThreeLepSelector", @@ -40,6 +42,7 @@ def __init__(self, analysis, selection, input_tier, year): self.numCores = 1 self.channels = ["Inclusive"] self.outfile_name = "temp.root" + self.outfile = 0 self.datasets = {} # Needed to parallelize class member function, see @@ -53,11 +56,25 @@ def tempfileName(self, dataset): def setChannels(self, channels): self.channels = channels + def isBackground(self): + self.selector_name = self.selector_name.replace("Selector", "BackgroundSelector") + + def isGen(self): + self.selector_name = self.selector_name.replace("BackgroundSelector", "GenSelector") + + def isFake(self): + self.selector_name = self.selector_name.replace("ZZ", "FakeRate") + + def outputFile(self): + return self.outfile + def setOutputfile(self, outfile_name): + if self.outfile: + self.outfile.Close() self.outfile_name = outfile_name self.outfile = ROOT.gROOT.FindObject(outfile_name) if not self.outfile: - self.outfile = ROOT.TFile.Open(outfile_name) + self.outfile = ROOT.TFile.Open(outfile_name, "recreate") self.current_file = self.outfile def addTNamed(self, name, title): @@ -85,6 +102,9 @@ def setNtupeType(self, ntupleType): def setNumCores(self, numCores): self.numCores = numCores + def setSumWeights(self, addSumweights): + self.addSumweights = addSumweights + def setFileList(self, list_of_files, nPerJob, jobNum): if not os.path.isfile(list_of_files): raise ValueError("%s is not a valid file." % list_of_files) @@ -115,6 +135,7 @@ def setFileList(self, list_of_files, nPerJob, jobNum): self.datasets[dataset].append(file_path) def setDatasets(self, datalist): + self.clearDatasets() datasets = ConfigureJobs.getListOfFiles(datalist, self.input_tier) for dataset in datasets: if "@" in dataset: @@ -128,6 +149,9 @@ def setDatasets(self, datalist): continue self.datasets[dataset] = [file_path] + def clearDatasets(self): + self.datasets.clear() + def applySelector(self): for chan in self.channels: self.addTNamed("channel", chan) @@ -147,8 +171,9 @@ def processDataset(self, dataset, file_path, chan): select.SetInputList(self.inputs) self.addTNamed("name", dataset) # Only add for one channel - addSumweights = self.addSumweights and self.channels.index(chan) == 0 and "data" not in dataset + addSumweights = self.addSumweights and self.channels.index(chan) == 0 and "data" not in dataset and "Background" not in self.selector_name and "Gen" not in self.selector_name if addSumweights: + #print "Should only go here once!" sumweights_hist = ROOT.gROOT.FindObject("sumweights") # Avoid accidentally combining sumweights across datasets if sumweights_hist: @@ -157,7 +182,7 @@ def processDataset(self, dataset, file_path, chan): self.outfile = ROOT.TFile.Open(self.outfile_name) sumweights_hist = self.outfile.Get("%s/sumweights" % dataset) if not sumweights_hist: - sumweights_hist = ROOT.TH1D("sumweights", "sumweights", 100, 0, 100) + sumweights_hist = ROOT.TH1D("sumweights", "sumweights", 1000, 0, 1000) sumweights_hist.SetDirectory(ROOT.gROOT) self.processLocalFiles(select, file_path, addSumweights, chan) output_list = select.GetOutputList() @@ -210,7 +235,7 @@ def getTreeName(self, chan): def combineParallelFiles(self, tempfiles, chan): tempfiles = filter(os.path.isfile, tempfiles) outfile = self.outfile_name - if chan != "Inclusive": + if chan != "Inclusive" and len(self.channels) != 1: outfile = self.outfile_name.replace(".root", "_%s.root" % chan) rval = subprocess.call(["hadd", "-f", outfile] + tempfiles) if rval == 0: diff --git a/Utilities/python/UserInput.py b/Utilities/python/UserInput.py index d7f4b835..edebfe2a 100644 --- a/Utilities/python/UserInput.py +++ b/Utilities/python/UserInput.py @@ -25,7 +25,7 @@ def getDefaultParser(): input_group.add_argument("-f", "--filenames", type=lambda x : [i.strip() for i in x.split(',')], help="List of input file names, " - "as defined in AnalysisDatasetManager, separated " + "as defined in ZZ4lRun2DatasetManager, separated " "by commas") input_group.add_argument("--inputs_from_file", nargs=3, metavar=('filelist', 'nPerJob', 'jobNum'), @@ -82,7 +82,7 @@ def readJson(json_file_name): print(err) return json_info -# Depends on AnalysisDatasetManagerModule +# Depends on ZZ4lRun2DatasetManagerModule def getHistInfo(analysis, input_hists, noConfig=False): if noConfig: print "INFO: assuming histogram information is specified in selector" @@ -90,7 +90,7 @@ def getHistInfo(analysis, input_hists, noConfig=False): manager_path = ConfigureJobs.getManagerPath() ConfigHistTools = imp.load_source("ConfigHistTools", - "/".join([manager_path, "AnalysisDatasetManager/Utilities/python/ConfigHistTools.py"])) + "/".join([manager_path, "ZZ4lRun2DatasetManager/Utilities/python/ConfigHistTools.py"])) # For histograms produced with some postprocessing on the hist file excludedHistPatterns = ["wCR", "unrolled", "YieldByChannel"] config_hists = ConfigHistTools.getAllHistNames(manager_path, analysis) \ @@ -104,7 +104,7 @@ def getHistInfo(analysis, input_hists, noConfig=False): def getHistExpr(hist_names, selection): manager_path = ConfigureJobs.getManagerPath() ConfigHistTools = imp.load_source("ConfigHistTools", - "/".join([manager_path, "AnalysisDatasetManager/Utilities/python/ConfigHistTools.py"])) + "/".join([manager_path, "ZZ4lRun2DatasetManager/Utilities/python/ConfigHistTools.py"])) info = ROOT.TList() info.SetName("histinfo") diff --git a/Utilities/scripts/makeAtgcForSenka.py b/Utilities/scripts/makeAtgcForSenka.py new file mode 100644 index 00000000..226239b7 --- /dev/null +++ b/Utilities/scripts/makeAtgcForSenka.py @@ -0,0 +1,118 @@ +import sys +import ROOT +import os +import logging +import json +import array +from python import ConfigureJobs + +def addOverflow(hist): + addOverflowAndUnderflow(hist, underflow=False, overflow=True) + +def addOverflowAndUnderflow(hist, underflow=True, overflow=True): + if not "TH1" in hist.ClassName(): + return + if overflow: + # Returns num bins + overflow + underflow + num_bins = hist.GetNbinsX() + add_overflow = hist.GetBinContent(num_bins) + hist.GetBinContent(num_bins + 1) + hist.SetBinContent(num_bins, add_overflow) + if underflow: + add_underflow = hist.GetBinContent(0) + hist.GetBinContent(1) + hist.SetBinContent(1, add_underflow) + +manager_path = ConfigureJobs.getManagerPath() +manager_name = ConfigureJobs.getManagerName() +#print "manager_path: ", manager_path +if manager_path not in sys.path: + sys.path.insert(0, "/".join([manager_path,"ZZ4lRun2DatasetManager", "Utilities/python"])) + +fileMap = { "2016" : "/afs/cern.ch/user/u/uhussain/ZZ4lRun2HistFiles/Hists17Oct2019-ZZ4l2016_Moriond.root", + "2017" : "", + "2018" : "/afs/cern.ch/user/u/uhussain/ZZ4lRun2HistFiles/Hists29Oct2019-ZZ4l2018_MVA.root", + } +channels = ["eeee", "eemm", "mmmm"] +#channels = ["eemm"] +eVariations = ["CMS_eff_eUp", "CMS_eff_eDown","CMS_RecoEff_eUp", "CMS_RecoEff_eDown"] +mVariations = ["CMS_eff_mUp","CMS_eff_mDown"] +#systVariations=[] +fitvar = "Mass" +rebin = array.array('d', [100.0,200.0,250.0,300.0,350.0,400.0,500.0,600.0,800.0,1000.0,1200.0]) +outputFolder = "ForSenka/%sFullRunII" % fitvar +if not os.path.isdir(outputFolder): + os.makedirs(outputFolder) + +#for year in fileMap.keys(): +for year in ["2018"]: + dataset_file = "%s/ZZ4lRun2DatasetManager/FileInfo/ZZ4l%s/%s.json" % (manager_path,year, "LooseLeptons") + allnames = json.load(open(dataset_file)) + atgcSamples={} + for name in allnames.keys(): + if "atgc" in name or "sherpa" in name: + atgcSamples[str(name)]= str(allnames[name]['plot_group']) + print atgcSamples + fileName=fileMap[year] + print "fileName: ",fileName + if type(fileName) == str: hist_file = ROOT.TFile.Open(fileName) + for chan in channels: + savehists=[] + outputFile = "ZZatgcInput_%s_%s.root" % (chan,year) + for process in [str(i) for i in atgcSamples.keys()]: + histNames=[] + if process=="nonprompt": + histNames.append("Mass_Fakes_{channel}".format(channel=chan)) + else: + histNames.append("Mass_{channel}".format(channel=chan)) + if not hist_file.Get(process): + logging.warning("Skipping invalid filename %s" % process) + continue + if process not in ["data","nonprompt"]: + if chan=="eeee": + for var in eVariations: + histNames.append("Mass_%s_%s" % (var,chan)) + elif chan=="mmmm": + for var in mVariations: + histNames.append("Mass_%s_%s" % (var,chan)) + elif chan=="eemm": + for var in eVariations+mVariations: + histNames.append("Mass_%s_%s" % (var,chan)) + #print "plot_group: ",process + #print "histNames: ",histNames + for name in histNames: + tmphist = hist_file.Get("/".join([process, name])) + if not tmphist: + raise RuntimeError("Failed to produce histogram %s" % "/".join([process, name])) + if "eemm" in name: + ##combine eemm and mmee channels + secname = name.replace("eemm","mmee") + tmphist2 = hist_file.Get("/".join([process, secname])) + #print tmphist.GetName(),": ",tmphist.Integral() + #print tmphist2.GetName(),": ",tmphist2.Integral() + tmphist.Add(tmphist2) + hist = tmphist.Clone() + #print "total: ",hist.Integral() + histnew = hist.Rebin(len(rebin)-1,"histnew",rebin) + addOverflow(histnew) + tmphist.Delete() + if process=="zz4l-sherpa": + print "this process happens in 2016" + histnew.Scale(0.455985*1000*35.9*1.239/histnew.Integral()) + if process=="zz4l-atgc_1" and year=="2018": + print "this process happens in 2018" + histnew.Scale(0.455985*1000*41.5*1.239/histnew.Integral()) + newName = name.replace("Mass",str(atgcSamples[process])) + newName = newName.replace("_"+chan,"") + hist.Delete() + histnew.SetName(newName) + savehists.append(histnew) + + fOut = ROOT.TFile.Open("/".join([outputFolder, outputFile]), "RECREATE") + fOut.cd() + for newhists in savehists: + newhists.Write() + fOut.Close() + hist_file.Close() + + + + diff --git a/Utilities/scripts/makeFakeRates.py b/Utilities/scripts/makeFakeRates.py index 54d2b6ee..56948204 100755 --- a/Utilities/scripts/makeFakeRates.py +++ b/Utilities/scripts/makeFakeRates.py @@ -5,38 +5,66 @@ from python import UserInput,OutputTools from python import ConfigureJobs from python import SelectorTools,HistTools +import logging +import sys ROOT.gROOT.SetBatch(True) -channels = ["eee", "eem", "emm", "mmm"] def getComLineArgs(): parser = UserInput.getDefaultParser() - parser.add_argument("--proof", "-p", - action='store_true', help="Don't use proof") parser.add_argument("--lumi", "-l", type=float, - default=35.87, help="luminosity value (in fb-1)") + default=41.5, help="luminosity value (in fb-1)") + parser.add_argument("--test", action='store_true', + help="Run test job (no background estimate)") + parser.add_argument("--uwvv", action='store_true', + help="Use UWVV format ntuples in stead of NanoAOD") + parser.add_argument("--noHistConfig", action='store_true', + help="Don't rely on config file to specify hist info") + parser.add_argument("--input_tier", type=str, + default="", help="Selection stage of input files") + parser.add_argument("--year", type=str, + default="default", help="Year of Analysis") + parser.add_argument("-j", "--numCores", type=int, default=1, + help="Number of cores to use (parallelize by dataset)") + parser.add_argument("--scalefactors_file", "-sf", type=str, + default="", help="ScaleFactors file name") parser.add_argument("--output_file", "-o", type=str, default="", help="Output file name") + parser.add_argument("-c", "--channels", + type=lambda x : [i.strip() for i in x.split(',')], + default=["eee","eem","emm","mmm"], help="List of channels" + "separated by commas. NOTE: set to Inclusive for NanoAOD") + parser.add_argument("-b", "--hist_names", + type=lambda x : [i.strip() for i in x.split(',')], + default=["all"], help="List of histograms, " + "as defined in ZZ4lRun2DatasetManager, separated " + "by commas") return vars(parser.parse_args()) def getHistNames(channels): - base_hists = [x+y for x in ["passingLoose", "passingTight"] \ - for y in "1DEta", "1DPt", "2D"] + base_hists = [x+y for x in ["passingLooseE", "passingTightE","passingLooseMu", "passingTightMu"] \ + for y in "1DEta", "1DPt_barrel","1DPt_endcap", "2D"] if len(channels) == 0: return base_hists return [x+"_"+y for x in base_hists for y in channels] # Turn off overflow for FR hists (> 50 is pretty much all EWK anyway) -def makeCompositeHists(name, members, addRatios=True, overflow=False): +def makeCompositeHists(hist_file,name, members, addRatios=True, overflow=False): composite = ROOT.TList() composite.SetName(name) + if name=="AllEWK": + print "EWK members: ",members for directory in [str(i) for i in members.keys()]: for histname in getHistNames(["eee", "eem", "emm", "mmm"]): - hist = fOut.Get("/".join([directory, histname])) + print "histname:", histname + print "hist_file:", hist_file + print "directory:",directory + hist = hist_file.Get("/".join([directory, str(histname)])) + print "hist:", hist if hist: sumhist = composite.FindObject(hist.GetName()) if "data" not in directory and hist.GetEntries() > 0: - sumweights_hist = fOut.Get("/".join([directory, "sumweights"])) + sumweights_hist = hist_file.Get("/".join([directory, "sumweights"])) sumweights = sumweights_hist.Integral() hist.Scale(members[directory]*1000*args['lumi']/sumweights) if overflow and isinstance(hist, ROOT.TH1): @@ -93,35 +121,69 @@ def getRatios(hists): return ratios args = getComLineArgs() -proof = 0 -if args['proof']: - ROOT.TProof.Open("workers=12") - proof = ROOT.gProof -today = datetime.date.today().strftime("%d%b%Y") -fileName = "data/fakeRate%s-%s.root" % (today, args['selection']) if args['output_file'] == "" \ - else args['output_file'] -fOut = ROOT.TFile(fileName, "recreate") - -fScales = ROOT.TFile('data/scaleFactors.root') -muonIsoSF = fScales.Get('muonIsoSF') -muonIdSF = fScales.Get('muonTightIdSF') -electronTightIdSF = fScales.Get('electronTightIdSF') -electronGsfSF = fScales.Get('electronGsfSF') -pileupSF = fScales.Get('pileupSF') -sf_inputs = [electronTightIdSF, electronGsfSF, muonIsoSF, muonIdSF, pileupSF] -SelectorTools.applySelector(args["filenames"], - "FakeRateSelector", args['selection'], fOut, - extra_inputs=sf_inputs, proof=args['proof'], - addSumweights=True) - -alldata = makeCompositeHists("AllData", ConfigureJobs.getListOfFilesWithXSec(["WZxsec2016data"])) -OutputTools.writeOutputListItem(alldata, fOut) -allewk = makeCompositeHists("AllEWK", ConfigureJobs.getListOfFilesWithXSec( - ConfigureJobs.getListOfEWKFilenames()), False) -OutputTools.writeOutputListItem(allewk, fOut) -allnonprompt = makeCompositeHists("NonpromptMC", ConfigureJobs.getListOfFilesWithXSec( - ConfigureJobs.getListOfNonpromptFilenames())) -OutputTools.writeOutputListItem(allnonprompt, fOut) -final = HistTools.getDifference(fOut, "DataEWKCorrected", "AllData", "AllEWK", getRatios) -OutputTools.writeOutputListItem(final, fOut) +today = datetime.date.today().strftime("%d%b%Y") +#fileName = "data/fakeRate%s-%s.root" % (today,args['analysis']) if args['output_file'] == "" \ +# else args['output_file'] +fileName="data/fakeRate15Sep2019-ZZ4l2016.root" +if not args['test']: + fOut = ROOT.TFile(fileName, "recreate") + + + addScaleFacs = False + if args['analysis'] == "WZxsec2016" or args['analysis'] == 'Zstudy_2016' or args['scalefactors_file']: + addScaleFacs = True + sf_inputs = [ROOT.TParameter(bool)("applyScaleFacs", False)] + + if args['input_tier'] == '': + args['input_tier'] = args['selection'] + selection = args['selection'].split("_")[0] + + if selection == "Inclusive2Jet": + selection = "Wselection" + print "Info: Using Wselection for hist defintions" + analysis = "/".join([args['analysis'], selection]) + hists, hist_inputs = UserInput.getHistInfo(analysis, args['hist_names'], args['noHistConfig']) + print "hists: ",hists + print "hist_inputs: ", hist_inputs + selector = SelectorTools.SelectorDriver(args['analysis'], args['selection'], args['input_tier'], args['year']) + selector.setOutputfile(fOut.GetName()) + selector.setInputs(sf_inputs+hist_inputs) + selector.isFake() + + selector.setNtupeType("UWVV" if args['uwvv'] else "NanoAOD") + if args['uwvv']: + logging.debug("Processing channels " % args['channels']) + selector.setChannels(args['channels']) + + selector.setNumCores(args['numCores']) + + if args['filenames']: + selector.setDatasets(args['filenames']) + else: + selector.setFileList(*args['inputs_from_file']) + mc = selector.applySelector() + + #if args['test']: + # sys.exit(0) + + #fOut.Close() +if args['test']: + fOut = ROOT.TFile.Open(fileName, "update") + alldata = makeCompositeHists(fOut,"AllData", ConfigureJobs.getListOfFilesWithXSec([args['analysis']+"data"])) + OutputTools.writeOutputListItem(alldata, fOut) + alldata.Delete() + allewk = makeCompositeHists(fOut,"AllEWK", ConfigureJobs.getListOfFilesWithXSec( + ConfigureJobs.getListOfEWKFilenames()), True) + OutputTools.writeOutputListItem(allewk, fOut) + allewk.Delete() + allDYJets = makeCompositeHists(fOut,"DYMC", ConfigureJobs.getListOfFilesWithXSec( + ConfigureJobs.getListOfDYFilenames()),True) + OutputTools.writeOutputListItem(allDYJets, fOut) + allDYJets.Delete() + #allnonprompt = makeCompositeHists("NonpromptMC", ConfigureJobs.getListOfFilesWithXSec( + # ConfigureJobs.getListOfNonpromptFilenames())) + #OutputTools.writeOutputListItem(allnonprompt, fOut) + final = HistTools.getDifference(fOut, "DataEWKCorrected", "AllData", "AllEWK", getRatios) + OutputTools.writeOutputListItem(final, fOut) + final.Delete() diff --git a/Utilities/scripts/makeFileForSenka.py b/Utilities/scripts/makeFileForSenka.py new file mode 100644 index 00000000..bac2316a --- /dev/null +++ b/Utilities/scripts/makeFileForSenka.py @@ -0,0 +1,93 @@ +import sys +import ROOT +import os +import logging +#Putting qqZZ_sherpa in the atgc files +#plot_groups = ["HZZ_signal","qqZZ_powheg","qqZZ_sherpa","zzjj4l_ewk","ggZZ", "VVV", "data", "nonprompt",] +plot_groups = ["HZZ_signal","qqZZ_powheg","zzjj4l_ewk","ggZZ", "VVV", "data", "nonprompt",] +#plot_groups = ["HZZ_signal"] +fileMap = { "2016" : "/data/uhussain/ZZTo4l/FullRun2/VVAnalyzer/CMSSW_10_3_1/src/Analysis/VVAnalysis/ZZCombineInput_2016.root", + "2017" : "/data/uhussain/ZZTo4l/FullRun2/VVAnalyzer/CMSSW_10_3_1/src/Analysis/VVAnalysis/ZZCombineInput_2017.root", + "2018" : "/data/uhussain/ZZTo4l/FullRun2/VVAnalyzer/CMSSW_10_3_1/src/Analysis/VVAnalysis/ZZCombineInput_2018.root", + } +channels = ["eeee", "eemm", "mmmm"] +#channels = ["eemm"] +eVariations = ["CMS_eff_eUp", "CMS_eff_eDown","CMS_RecoEff_eUp", "CMS_RecoEff_eDown"] +mVariations = ["CMS_eff_mUp","CMS_eff_mDown"] +#systVariations=[] +#"CMS_pileup"], +#theorVariations=[] +theorVariations = ["pdf","QCDscale"] +fitvar = "Mass" + +outputFolder = "ForSenka/%sFullRunII" % fitvar +if not os.path.isdir(outputFolder): + os.makedirs(outputFolder) + +for year in fileMap.keys(): +#for year in ["2016"]: + fileName=fileMap[year] + if type(fileName) == str: hist_file = ROOT.TFile.Open(fileName) + for chan in channels: + savehists=[] + outputFile = "ZZSMInput_%s_%s.root" % (chan,year) + for process in plot_groups: + histNames=[] + if process=="nonprompt": + histNames.append("Mass_Fakes_{channel}".format(channel=chan)) + else: + histNames.append("Mass_{channel}".format(channel=chan)) + if not hist_file.Get(process): + logging.warning("Skipping invalid filename %s" % process) + continue + if process not in ["data","nonprompt"]: + if chan=="eeee": + for var in eVariations: + histNames.append("Mass_%s_%s" % (var,chan)) + elif chan=="mmmm": + for var in mVariations: + histNames.append("Mass_%s_%s" % (var,chan)) + elif chan=="eemm": + for var in eVariations+mVariations: + histNames.append("Mass_%s_%s" % (var,chan)) + if process in ["qqZZ_powheg","HZZ_signal","ggZZ","VVV"]: + for var in theorVariations: + histNames.append("Mass_%s_%sUp_%s" % (var,process,chan)) + histNames.append("Mass_%s_%sDown_%s" % (var,process,chan)) + print "plot_group: ",process + print "histNames: ",histNames + for name in histNames: + tmphist = hist_file.Get("/".join([process, name])) + if not tmphist: + raise RuntimeError("Failed to produce histogram %s" % "/".join([process, name])) + if "eemm" in name: + ##combine eemm and mmee channels + secname = name.replace("eemm","mmee") + tmphist2 = hist_file.Get("/".join([process, secname])) + #print tmphist.GetName(),": ",tmphist.Integral() + #print tmphist2.GetName(),": ",tmphist2.Integral() + tmphist.Add(tmphist2) + hist = tmphist.Clone() + #print "total: ",hist.Integral() + tmphist.Delete() + newName = name.replace("Mass",process) + newName = newName.replace("_"+chan,"") + if "pdf" or "QCD" in newName: + newName = newName.replace("_"+process,"") + if "Fakes" in newName: + newName = newName.replace("_Fakes","") + if "data" in newName: + newName = newName.replace("data","data_obs") + hist.SetName(newName) + savehists.append(hist) + + fOut = ROOT.TFile.Open("/".join([outputFolder, outputFile]), "RECREATE") + fOut.cd() + for newhists in savehists: + newhists.Write() + fOut.Close() + hist_file.Close() + + + + diff --git a/Utilities/scripts/makeHistFile.py b/Utilities/scripts/makeHistFile.py index 034c0622..09d6e008 100755 --- a/Utilities/scripts/makeHistFile.py +++ b/Utilities/scripts/makeHistFile.py @@ -8,6 +8,10 @@ import os import logging import sys +import datetime +import subprocess + +#logging.basicConfig(level=logging.DEBUG) def getComLineArgs(): parser = UserInput.getDefaultParser() @@ -15,10 +19,16 @@ def getComLineArgs(): default=35.87, help="luminosity value (in fb-1)") parser.add_argument("--output_file", "-o", type=str, default="test.root", help="Output file name") + parser.add_argument("--muIDType", type=str, + default="", help="Moriond Muon ID or MVA ID") parser.add_argument("--test", action='store_true', help="Run test job (no background estimate)") parser.add_argument("--uwvv", action='store_true', help="Use UWVV format ntuples in stead of NanoAOD") + parser.add_argument("--with_background", action='store_true', + help="Don't run background selector") + parser.add_argument("--with_Gen", action='store_true', + help="Don't run ZZGen selector") parser.add_argument("--noHistConfig", action='store_true', help="Don't rely on config file to specify hist info") parser.add_argument("-j", "--numCores", type=int, default=1, @@ -27,6 +37,8 @@ def getComLineArgs(): default="", help="Selection stage of input files") parser.add_argument("--year", type=str, default="default", help="Year of Analysis") + parser.add_argument("--scalefactors_file", "-sf", type=str, + default="", help="ScaleFactors file name") parser.add_argument("-c", "--channels", type=lambda x : [i.strip() for i in x.split(',')], default=["eee","eem","emm","mmm"], help="List of channels" @@ -34,7 +46,7 @@ def getComLineArgs(): parser.add_argument("-b", "--hist_names", type=lambda x : [i.strip() for i in x.split(',')], default=["all"], help="List of histograms, " - "as defined in AnalysisDatasetManager, separated " + "as defined in ZZ4lRun2DatasetManager, separated " "by commas") return vars(parser.parse_args()) @@ -44,48 +56,106 @@ def makeHistFile(args): manager_path = ConfigureJobs.getManagerPath() if manager_path not in sys.path: sys.path.insert(0, "/".join([manager_path, - "AnalysisDatasetManager", "Utilities/python"])) + "ZZ4lRun2DatasetManager", "Utilities/python"])) - tmpFileName = args['output_file'] - fOut = ROOT.TFile(tmpFileName, "recreate") + today = datetime.date.today().strftime("%d%b%Y") + + if args['test']: + tmpFileName = "Hists%s-%s.root" % (today, args['output_file']) + else: + tmpFileName = "Hists%s-%s.root" % (today, args['output_file']) if args['selection'] == "SignalSync" \ + else "Hists%s-%s_%s.root" % (today, args['analysis'],args['muIDType']) + toCombine = args['with_background'] or args['with_Gen'] + fOut = ROOT.TFile(tmpFileName if not toCombine else tmpFileName.replace(".root", "sel.root"), "recreate") + combinedNames = [fOut.GetName()] addScaleFacs = False - if args['analysis'] == "WZxsec2016" or args['analysis'] == 'Zstudy_2016': + if args['analysis'] == "WZxsec2016" or args['analysis'] == 'Zstudy_2016' or args['scalefactors_file']: addScaleFacs = True - addScaleFacs=False + sf_inputs = [ROOT.TParameter(bool)("applyScaleFacs", False)] - + fr_inputs = [] if addScaleFacs: - fScales = ROOT.TFile('data/scaleFactors.root') - mCBTightFakeRate = fScales.Get("mCBTightFakeRate") - eCBTightFakeRate = fScales.Get("eCBTightFakeRate") - useSvenjasFRs = False - useJakobsFRs = False - if useSvenjasFRs: - mCBTightFakeRate = fScales.Get("mCBTightFakeRate_Svenja") - eCBTightFakeRate = fScales.Get("eCBTightFakeRate_Svenja") - elif useJakobsFRs: - mCBTightFakeRate = fScales.Get("mCBTightFakeRate_Jakob") - eCBTightFakeRate = fScales.Get("eCBTightFakeRate_Jakob") - # For medium muons - #mCBMedFakeRate.SetName("fakeRate_allMu") - if mCBTightFakeRate: - mCBTightFakeRate.SetName("fakeRate_allMu") - if eCBTightFakeRate: - eCBTightFakeRate.SetName("fakeRate_allE") - - muonIsoSF = fScales.Get('muonIsoSF') - muonIdSF = fScales.Get('muonTightIdSF') - electronTightIdSF = fScales.Get('electronTightIdSF') - electronGsfSF = fScales.Get('electronGsfSF') - pileupSF = fScales.Get('pileupSF') - - #fPrefireEfficiency = ROOT.TFile('data/Map_Jet_L1FinOReff_bxm1_looseJet_JetHT_Run2016B-H.root') - fPrefireEfficiency = ROOT.TFile('data/Map_Jet_L1FinOReff_bxm1_looseJet_SingleMuon_Run2016B-H.root') - prefireEff = fPrefireEfficiency.Get('prefireEfficiencyMap') - - fr_inputs = [eCBTightFakeRate, mCBTightFakeRate,] - sf_inputs = [electronTightIdSF, electronGsfSF, muonIsoSF, muonIdSF, pileupSF, prefireEff] + fScales = ROOT.TFile(args['scalefactors_file']) + if "ZZ4l" in args['analysis']: + mZZTightFakeRate = fScales.Get("mZZTightFakeRate") + eZZTightFakeRate = fScales.Get("eZZTightFakeRate") + if mZZTightFakeRate: + mZZTightFakeRate.SetName("fakeRate_allMu") + if eZZTightFakeRate: + eZZTightFakeRate.SetName("fakeRate_allE") + if "2018" in args['scalefactors_file']: + muonRunSF= fScales.Get('muonRun18SF') + muonRunSF.SetName("muonRunSF") + electronLowRecoSF = fScales.Get('electronLowReco18SF') + electronLowRecoSF.SetName("electronLowRecoSF") + electronRecoSF = fScales.Get('electronReco18SF') + electronRecoSF.SetName("electronRecoSF") + electronRunSF = fScales.Get('electronRun18SF') + electronRunSF.SetName("electronRunSF") + electronRunGapSF = fScales.Get('electronRun18GapSF') + electronRunGapSF.SetName("electronRunGapSF") + elif "2016" in args['scalefactors_file']: + muonRunSF= fScales.Get('muonRun16SF') + muonRunSF.SetName("muonRunSF") + electronLowRecoSF = fScales.Get('electronLowReco16SF') + electronLowRecoSF.SetName("electronLowRecoSF") + electronRecoSF = fScales.Get('electronReco16SF') + electronRecoSF.SetName("electronRecoSF") + electronRunSF = fScales.Get('electronRun16SF') + electronRunSF.SetName("electronRunSF") + electronRunGapSF = fScales.Get('electronRun16GapSF') + electronRunGapSF.SetName("electronRunGapSF") + elif "2017" in args['scalefactors_file']: + muonRunSF= fScales.Get('muonRun17SF') + muonRunSF.SetName("muonRunSF") + electronLowRecoSF = fScales.Get('electronLowReco17SF') + electronLowRecoSF.SetName("electronLowRecoSF") + electronRecoSF = fScales.Get('electronReco17SF') + electronRecoSF.SetName("electronRecoSF") + electronRunSF = fScales.Get('electronRun17SF') + electronRunSF.SetName("electronRunSF") + electronRunGapSF = fScales.Get('electronRun17GapSF') + electronRunGapSF.SetName("electronRunGapSF") + else: + print "what scale factors you want?" + sys.exit() + pileupSF = fScales.Get('pileupSF') + + fr_inputs = [eZZTightFakeRate, mZZTightFakeRate,] + sf_inputs = [electronLowRecoSF,electronRecoSF,electronRunSF, electronRunGapSF,muonRunSF,pileupSF] + else: + fScales = ROOT.TFile('data/scaleFactors.root') + mCBTightFakeRate = fScales.Get("mCBTightFakeRate") + eCBTightFakeRate = fScales.Get("eCBTightFakeRate") + useSvenjasFRs = False + useJakobsFRs = False + if useSvenjasFRs: + mCBTightFakeRate = fScales.Get("mCBTightFakeRate_Svenja") + eCBTightFakeRate = fScales.Get("eCBTightFakeRate_Svenja") + elif useJakobsFRs: + mCBTightFakeRate = fScales.Get("mCBTightFakeRate_Jakob") + eCBTightFakeRate = fScales.Get("eCBTightFakeRate_Jakob") + # For medium muons + #mCBMedFakeRate.SetName("fakeRate_allMu") + if mCBTightFakeRate: + mCBTightFakeRate.SetName("fakeRate_allMu") + if eCBTightFakeRate: + eCBTightFakeRate.SetName("fakeRate_allE") + + muonIsoSF = fScales.Get('muonIsoSF') + muonIdSF = fScales.Get('muonTightIdSF') + electronTightIdSF = fScales.Get('electronTightIdSF') + electronGsfSF = fScales.Get('electronGsfSF') + pileupSF = fScales.Get('pileupSF') + + #fPrefireEfficiency = ROOT.TFile('data/Map_Jet_L1FinOReff_bxm1_looseJet_JetHT_Run2016B-H.root') + fPrefireEfficiency = ROOT.TFile('data/Map_Jet_L1FinOReff_bxm1_looseJet_SingleMuon_Run2016B-H.root') + prefireEff = fPrefireEfficiency.Get('prefireEfficiencyMap') + + fr_inputs = [eCBTightFakeRate, mCBTightFakeRate,] + sf_inputs = [electronTightIdSF, electronGsfSF, muonIsoSF, muonIdSF, pileupSF, prefireEff] + sf_inputs.append(ROOT.TParameter(bool)("applyScaleFacs", True)) if args['input_tier'] == '': @@ -98,18 +168,6 @@ def makeHistFile(args): analysis = "/".join([args['analysis'], selection]) hists, hist_inputs = UserInput.getHistInfo(analysis, args['hist_names'], args['noHistConfig']) - #if "WZxsec2016" in analysis and "FakeRate" not in args['output_selection'] and not args['test']: - # background = SelectorTools.applySelector(["WZxsec2016data"] + - # ConfigureJobs.getListOfEWKFilenames() + ["wz3lnu-powheg"] + - # ConfigureJobs.getListOfNonpromptFilenames(), - # "WZBackgroundSelector", args['selection'], fOut, - # extra_inputs=sf_inputs+fr_inputs+hist_inputs+tselection, - # channels=channels, - # addSumweights=False, - # nanoAOD=nanoAOD, - # parallel=args['parallel'], - # ) - selector = SelectorTools.SelectorDriver(args['analysis'], args['selection'], args['input_tier'], args['year']) selector.setOutputfile(fOut.GetName()) selector.setInputs(sf_inputs+hist_inputs) @@ -126,24 +184,60 @@ def makeHistFile(args): selector.setFileList(*args['inputs_from_file']) mc = selector.applySelector() + + if args['with_background']: + selector.isBackground() + selector.setInputs(sf_inputs+hist_inputs+fr_inputs) + output_name = tmpFileName.replace(".root", "bkgd.root") + selector.setOutputfile(output_name) + bkgd = selector.applySelector() + combinedNames.append(output_name) + + if args['with_Gen']: + selector.isGen() + selector.setChannels([c+"Gen" for c in args['channels']]) + # Make sure to remove data from the dataset lists + selector.setInputs(hist_inputs) + output_name = tmpFileName.replace(".root", "gen.root") + selector.setOutputfile(output_name) + combinedNames.append(output_name) + if args['filenames']: + #selector.setDatasets(args['filenames']) + selector.setDatasets(ConfigureJobs.getListOfGenFilenames(args['analysis'])) + else: + selector.setFileList(*args['inputs_from_file']) + gen = selector.applySelector() + selector.setChannels(args['channels']) + selector.outputFile().Close() + + if len(combinedNames) > 1: + rval = subprocess.call(["hadd", "-f", tmpFileName] + combinedNames) + if rval == 0: + map(os.remove, combinedNames) + if args['test']: fOut.Close() sys.exit(0) + fOut.Close() + fOut = ROOT.TFile.Open(tmpFileName, "update") + alldata = HistTools.makeCompositeHists(fOut,"AllData", - ConfigureJobs.getListOfFilesWithXSec(["WZxsec2016data"], manager_path), args['lumi'], + ConfigureJobs.getListOfFilesWithXSec([args['analysis']+"data"], manager_path), args['lumi'], underflow=False, overflow=False) OutputTools.writeOutputListItem(alldata, fOut) alldata.Delete() - nonpromptmc = HistTools.makeCompositeHists(fOut, "NonpromptMC", ConfigureJobs.getListOfFilesWithXSec( - ConfigureJobs.getListOfNonpromptFilenames(), manager_path), args['lumi'], - underflow=False, overflow=False) - nonpromptmc.Delete() + if "ZZ4l" not in args['analysis']: + nonpromptmc = HistTools.makeCompositeHists(fOut, "NonpromptMC", ConfigureJobs.getListOfFilesWithXSec( + ConfigureJobs.getListOfNonpromptFilenames(), manager_path), args['lumi'], + underflow=False, overflow=False) + nonpromptmc.Delete() + + OutputTools.writeOutputListItem(nonpromptmc, fOut) - OutputTools.writeOutputListItem(nonpromptmc, fOut) ewkmc = HistTools.makeCompositeHists(fOut,"AllEWK", ConfigureJobs.getListOfFilesWithXSec( - ConfigureJobs.getListOfEWKFilenames(), manager_path), args['lumi'], + ConfigureJobs.getListOfEWKFilenames(args['analysis']), manager_path), args['lumi'], underflow=False, overflow=False) OutputTools.writeOutputListItem(ewkmc, fOut) ewkmc.Delete() diff --git a/Utilities/scripts/makeSimpleHtml.py b/Utilities/scripts/makeSimpleHtml.py new file mode 100755 index 00000000..9d9316eb --- /dev/null +++ b/Utilities/scripts/makeSimpleHtml.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python +""" + Modified from T. Ruggles and D. Taylor, U. Wisconsin + Changes by K.Long, https://github.com/kdlong/WZConfigPlotting/commit/14d492fe266f87991395aaf188cb25c9116e9cf1 +""" +import glob +import imghdr +import argparse + +def writeHTML(path, name): + image_files = [x for x in glob.glob(path + "/plots/*.*") if imghdr.what(x)] + with open('%s/index.html' % path, 'w') as index: + index = open('%s/index.html' % path, 'w') + index.write('\n' + '\n' + ' {title}\n' + ' \n' + '\n' + '\n'.format(title=name) + ) + index.write('
{title}
\n' + ' \n'.format(title=name) + ) + if "Nonprompt" in path: + relative_path = path.split("/")[-1].replace("Nonprompt", "MC") + index.write('
Monte Carlo based plots: \n' + ' [MC plots]' % relative_path + + '
\n' + '
\n' + ) + elif "MC" in path: + relative_path = path.split("/")[-1].replace("MC", "Nonprompt") + index.write('
Plots with data driven background: \n' + ' [Nonprompt plots]' % relative_path + + '
\n' + '
\n' + ) + if path.split("/")[-1] not in ["eeee", "eemm","mmee","mmmm"]: + index.write('
Plots by channel: \n' + ' [eeee] - ' + ' [eemm] - ' + ' [mmee] - ' + ' [mmmm]' + '
\n' + '
\n' + ) + else: + index.write('
Plots by channel: \n' + ' [eeee] - ' + ' [eemm] - ' + ' [mmee] - ' + ' [mmmm]' + '
\n' + '
\n' + ) + for i, image_file in enumerate(image_files): + file_name = image_file.strip().split('/')[-1].strip() + if i % 3 == 0: + index.write(' \n') + index.write(getTableRow(image_file.split("/")[-1])) + if (i+1) % 3 == 0: + index.write(' \n') + index.write( '\n' + '' ) +def getTableRow(image_file): + return ''' \n'''.format(image=image_file, name=image_file.split(".")[-2]) + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('-p', '--path_to_files', type=str, required=True) + parser.add_argument('-n', '--name', type=str, required=True) + args = parser.parse_args() + + writeHTML(args.path_to_files.rstrip("/*"), args.name) + +if __name__ == "__main__": + main() diff --git a/Utilities/scripts/plotFakeRates.py b/Utilities/scripts/plotFakeRates.py index c67119a0..a4b0d5d0 100755 --- a/Utilities/scripts/plotFakeRates.py +++ b/Utilities/scripts/plotFakeRates.py @@ -9,16 +9,48 @@ canvas = ROOT.TCanvas("canvas", "canvas") def getTGraphAsymmErrors(frfile, folder, param, obj): - tight_hist = frfile.Get("%s/passingTight%s_all%s" % (folder, param, obj)) - loose_hist = frfile.Get("%s/passingLoose%s_all%s" % (folder, param, obj)) + tight_hist = frfile.Get("%s/passingTight%s%s_all%s" % (folder, obj ,param, obj)) + loose_hist = frfile.Get("%s/passingLoose%s%s_all%s" % (folder, obj ,param, obj)) + tight_hist.SetTitle("") + loose_hist.SetTitle("") graph = ROOT.TGraphAsymmErrors(tight_hist, loose_hist) graph.SetMarkerStyle(6) - graph.SetMinimum(0) - graph.SetMaximum(0.8) + if obj=="E": + graph.SetMinimum(0.01) + graph.SetMaximum(0.35) if "Pt" in param else graph.SetMaximum(0.1) + else: + graph.SetMinimum(0.04) + graph.SetMaximum(0.35) if "Pt" in param else graph.SetMaximum(0.3) return graph +def getTGraphAsymmErrorsPt(frfile, folder, param, obj): + tight_hist_barrel = frfile.Get("%s/passingTight%s%s_barrel_all%s" % (folder, obj, param, obj)) + loose_hist_barrel = frfile.Get("%s/passingLoose%s%s_barrel_all%s" % (folder, obj, param, obj)) + tight_hist_barrel.SetTitle("") + loose_hist_barrel.SetTitle("") + barrel = ROOT.TGraphAsymmErrors(tight_hist_barrel, loose_hist_barrel) + barrel.SetMarkerStyle(6) + barrel.SetLineColor(ROOT.kBlue) + tight_hist_endcap = frfile.Get("%s/passingTight%s%s_endcap_all%s" % (folder, obj, param, obj)) + loose_hist_endcap = frfile.Get("%s/passingLoose%s%s_endcap_all%s" % (folder,obj, param, obj)) + tight_hist_endcap.SetTitle("") + loose_hist_endcap.SetTitle("") + endcap = ROOT.TGraphAsymmErrors(tight_hist_endcap, loose_hist_endcap) + endcap.SetMarkerStyle(6) + endcap.SetLineColor(ROOT.kRed) + if obj=="E": + barrel.SetMinimum(0.01) + barrel.SetMaximum(0.35) if "Pt" in param else barrel.SetMaximum(0.1) + endcap.SetMinimum(0.01) + endcap.SetMaximum(0.35) if "Pt" in param else endcap.SetMaximum(0.1) + else: + barrel.SetMinimum(0.04) + barrel.SetMaximum(0.35) if "Pt" in param else barrel.SetMaximum(0.3) + endcap.SetMinimum(0.04) + endcap.SetMaximum(0.35) if "Pt" in param else endcap.SetMaximum(0.3) + return barrel,endcap def getTextBox(obj, extra_text=""): - text_box = ROOT.TPaveText(0.2, 0.92, 0.4+0.02*len(extra_text), 0.86, "blNDC") + text_box = ROOT.TPaveText(0.2, 0.88, 0.4+0.02*len(extra_text), 0.81, "blNDC") text_box.SetFillColor(0) text_box.SetLineColor(ROOT.kBlack) text_box.SetTextFont(42) @@ -27,81 +59,178 @@ def getTextBox(obj, extra_text=""): ROOT.SetOwnership(text_box, False) return text_box -def invert2DHist(hist): - new_hist = ROOT.TH2D(hist.GetName(), hist.GetTitle(), - 3, 0, 2.5, - 3, array.array('d', [10,20,30,50])) - ROOT.SetOwnership(new_hist, False) - for x in range(hist.GetNbinsX()+1): - for y in range(hist.GetNbinsY()+1): - value = hist.GetBinContent(x, y) - new_hist.SetBinContent(y, x, value) - new_hist.GetXaxis().SetTitle(hist.GetXaxis().GetTitle()) - new_hist.GetYaxis().SetTitle(hist.GetYaxis().GetTitle()) +def getLumiTextBox(): + texS = ROOT.TLatex(0.615,0.95,"#sqrt{s} = 13 TeV, 35.9 fb^{-1}") + texS.SetNDC() + texS.SetTextFont(42) + texS.SetTextSize(0.040) + texS.Draw() + texS1 = ROOT.TLatex(0.15,0.95,"#bf{CMS} #it{Preliminary}") + texS1.SetNDC() + texS1.SetTextFont(42) + texS1.SetTextSize(0.040) + texS1.Draw() + return texS,texS1 + +def invert2DHist(hist,obj): + if (obj=="E"): + new_hist = ROOT.TH2D(hist.GetName(), hist.GetTitle(), + 4, array.array('d',[0.,0.7395,1.479,2.0,2.5]), + 6, array.array('d', [5,10,20,30,40,50,80])) + ROOT.SetOwnership(new_hist, False) + for x in range(hist.GetNbinsX()+1): + for y in range(hist.GetNbinsY()+1): + value = hist.GetBinContent(x, y) + new_hist.SetBinContent(y, x, value) + new_hist.GetXaxis().SetTitle(hist.GetXaxis().GetTitle()) + new_hist.GetYaxis().SetTitle(hist.GetYaxis().GetTitle()) + elif (obj=="Mu"): + new_hist = ROOT.TH2D(hist.GetName(), hist.GetTitle(), + 2, array.array('d',[0.,1.2,2.4]), + 6, array.array('d', [5,10,20,30,40,50,80])) + ROOT.SetOwnership(new_hist, False) + for x in range(hist.GetNbinsX()+1): + for y in range(hist.GetNbinsY()+1): + value = hist.GetBinContent(x, y) + new_hist.SetBinContent(y, x, value) + new_hist.GetXaxis().SetTitle(hist.GetXaxis().GetTitle()) + new_hist.GetYaxis().SetTitle(hist.GetYaxis().GetTitle()) return new_hist def makeDataPlots(param, obj, outdir): - data_ewkcorr_graph = frfile.Get("DataEWKCorrected/ratio%s_all%s" % (param, obj)) \ - if "2D" in param else getTGraphAsymmErrors(frfile, "DataEWKCorrected", param, obj) - data_ewkcorr_graph.SetLineColor(ROOT.kRed) + if "Pt" in param: + data_ewkcorr_barrel,data_ewkcorr_endcap = getTGraphAsymmErrorsPt(frfile, "DataEWKCorrected", param, obj) + elif "2D" in param: + data_ewkcorr_graph = frfile.Get("DataEWKCorrected/ratio%s%s_all%s" % (obj,param, obj)) + else: + data_ewkcorr_graph = getTGraphAsymmErrors(frfile, "DataEWKCorrected", param, obj) + data_ewkcorr_graph.SetLineColor(ROOT.kRed) draw_opt = "PA" if "2D" not in param else "colz text" if "2D" in param: - data_ewkcorr_graph = invert2DHist(data_ewkcorr_graph) + data_ewkcorr_graph.SetTitle("") + ROOT.gStyle.SetOptStat(0) + data_ewkcorr_graph = invert2DHist(data_ewkcorr_graph,obj) #data_ewkcorr_graph.GetYaxis().SetTitle("#eta") data_ewkcorr_graph.GetYaxis().SetTitle("p_{T} [GeV]") - data_ewkcorr_graph.GetXaxis().SetTitle("#eta") - else: + data_ewkcorr_graph.GetXaxis().SetTitle("|#eta|") + data_ewkcorr_graph.Draw(draw_opt) + elif "Eta" in param: + data_ewkcorr_graph.SetTitle("") data_ewkcorr_graph.GetYaxis().SetTitle("Passing Tight / Passing Loose") - xlabel = "p_{T} [GeV]" if "Pt" in param else "#eta" + xlabel = "|#eta|" data_ewkcorr_graph.GetXaxis().SetTitle(xlabel) - data_ewkcorr_graph.Draw(draw_opt) + data_ewkcorr_graph.Draw(draw_opt) + else: + data_ewkcorr_barrel.SetTitle("") + data_ewkcorr_barrel.SetLineStyle(2) + data_ewkcorr_barrel.GetYaxis().SetTitle("Passing Tight / Passing Loose") + xlabel = "p_{T} [GeV]" + data_ewkcorr_barrel.GetXaxis().SetTitle(xlabel) + data_ewkcorr_barrel.Draw("PA") + data_ewkcorr_endcap.SetLineStyle(2) + data_ewkcorr_endcap.SetTitle("") + data_ewkcorr_endcap.Draw("P") text_box = getTextBox(obj) text_box.Draw() - - if not "2D" in param: + texS,texS1=getLumiTextBox() + + if (not "2D" in param) and ("Eta" in param): data_uncorr_graph = getTGraphAsymmErrors(frfile, "AllData", param, obj) + data_uncorr_graph.SetTitle("") data_uncorr_graph.Draw("P") - legend = ROOT.TLegend(0.2,.85,.55,.70) + legend = ROOT.TLegend(0.2,.80,.40,.70) legend.AddEntry(data_uncorr_graph, "Data", "l") legend.AddEntry(data_ewkcorr_graph, "Data - EWK", "l") legend.Draw() - + elif ("Pt" in param): + data_uncorr_barrel,data_uncorr_endcap = getTGraphAsymmErrorsPt(frfile, "AllData", param, obj) + data_uncorr_barrel.SetTitle("") + data_uncorr_barrel.Draw("P") + data_uncorr_endcap.SetTitle("") + data_uncorr_endcap.Draw("P") + + legend = ROOT.TLegend(0.2,.80,.40,.70) + legend.AddEntry(data_uncorr_barrel, "barrel uncorrected", "l") + legend.AddEntry(data_ewkcorr_barrel, "barrel corrected", "l") + legend.AddEntry(data_uncorr_endcap, "endcap uncorrected", "l") + legend.AddEntry(data_ewkcorr_endcap, "endcap corrected", "l") + legend.Draw() canvas.Print("%s/ratio%s_all%s.png" % (outdir, param, obj)) canvas.Print("%s/ratio%s_all%s.pdf" % (outdir, param, obj)) def makeMCPlots(param, obj, outdir): - graph = frfile.Get("NonpromptMC/ratio%s_all%s" % (param, obj)) \ - if "2D" in param else getTGraphAsymmErrors(frfile, "NonpromptMC", param, obj) - graph.SetLineColor(ROOT.kRed) + if "Pt" in param: + data_ewkcorr_barrel,data_ewkcorr_endcap = getTGraphAsymmErrorsPt(frfile, "DataEWKCorrected", param, obj) + elif "2D" in param: + data_ewkcorr_graph = frfile.Get("DataEWKCorrected/ratio%s%s_all%s" % (obj,param, obj)) + else: + data_ewkcorr_graph = getTGraphAsymmErrors(frfile, "DataEWKCorrected", param, obj) + data_ewkcorr_graph.SetLineColor(ROOT.kRed) draw_opt = "PA" if "2D" not in param else "colz text" if "2D" in param: - graph.GetYaxis().SetTitle("#eta") + data_ewkcorr_graph.SetTitle("") + ROOT.gStyle.SetOptStat(0) + data_ewkcorr_graph = invert2DHist(data_ewkcorr_graph,obj) + #data_ewkcorr_graph.GetYaxis().SetTitle("#eta") + data_ewkcorr_graph.GetYaxis().SetTitle("p_{T} [GeV]") + data_ewkcorr_graph.GetXaxis().SetTitle("|#eta|") + data_ewkcorr_graph.Draw(draw_opt) + elif "Eta" in param: + data_ewkcorr_graph.SetTitle("") + data_ewkcorr_graph.GetYaxis().SetTitle("Passing Tight / Passing Loose") + xlabel = "|#eta|" + data_ewkcorr_graph.GetXaxis().SetTitle(xlabel) + data_ewkcorr_graph.Draw(draw_opt) else: - graph.GetYaxis().SetTitle("Passing Tight / Passing Loose") - xlabel = "p_{T} [GeV]" if "Pt" in param else "#eta" - graph.GetXaxis().SetTitle(xlabel) - graph.Draw(draw_opt) + data_ewkcorr_barrel.SetTitle("") + data_ewkcorr_barrel.SetLineStyle(2) + data_ewkcorr_barrel.GetYaxis().SetTitle("Passing Tight / Passing Loose") + xlabel = "p_{T} [GeV]" + data_ewkcorr_barrel.GetXaxis().SetTitle(xlabel) + data_ewkcorr_barrel.Draw("PA") + data_ewkcorr_endcap.SetLineStyle(2) + data_ewkcorr_endcap.SetTitle("") + data_ewkcorr_endcap.Draw("P") - text_box = getTextBox(obj, "(MC)") + text_box = getTextBox(obj) text_box.Draw() + texS,texS1=getLumiTextBox() - if not "2D" in param: - legend = ROOT.TLegend(0.2,.85,.55,.70) - legend.AddEntry(graph, "Nonprompt MC", "l") + if (not "2D" in param) and ("Eta" in param): + data_uncorr_graph = getTGraphAsymmErrors(frfile, "DYMC", param, obj) + data_uncorr_graph.SetTitle("") + data_uncorr_graph.Draw("P") + + legend = ROOT.TLegend(0.2,.80,.40,.70) + legend.AddEntry(data_ewkcorr_graph, "Data - EWK", "l") + legend.AddEntry(data_uncorr_graph, "DYJets(MC)", "l") + legend.Draw() + elif ("Pt" in param): + data_uncorr_barrel,data_uncorr_endcap = getTGraphAsymmErrorsPt(frfile, "DYMC", param, obj) + data_uncorr_barrel.SetTitle("") + data_uncorr_barrel.Draw("P SAME") + data_uncorr_endcap.SetTitle("") + data_uncorr_endcap.Draw("P SAME") + + legend = ROOT.TLegend(0.2,.80,.40,.70) + legend.AddEntry(data_ewkcorr_barrel, "barrel Data-EWK", "l") + legend.AddEntry(data_uncorr_barrel, "barrel DYJets MC", "l") + legend.AddEntry(data_ewkcorr_endcap, "endcap Data-EWK", "l") + legend.AddEntry(data_uncorr_endcap, "endcap DYJets MC", "l") legend.Draw() canvas.Print("%s/ratio%s_all%s.png" % (outdir, param, obj)) canvas.Print("%s/ratio%s_all%s.pdf" % (outdir, param, obj)) -frfile = ROOT.TFile("/eos/user/k/kelong/WZAnalysisData/FakeRates/fakeRateMar2018-TightLepsFrom3MediumLeptons.root") +frfile = ROOT.TFile("/data/uhussain/ZZTo4l/FullRun2/VVAnalyzer/CMSSW_10_3_1/src/Analysis/VVAnalysis/data/fakeRate15Sep2019-ZZ4l2016.root") -data_folder_name = datetime.date.today().strftime("%Y%b"+"_ScaleFacs") -data_outdir = "~/www/DibosonAnalysisData/PlottingResults/WZxsec2016/FakeRates/" + data_folder_name + "/plots" -mc_outdir = "~/www/DibosonAnalysisData/PlottingResults/WZxsec2016/FakeRates/" + data_folder_name + "-MC/plots" +data_folder_name = datetime.date.today().strftime("%Y%b%d"+"_ZZ4l") +data_outdir = "~/www/ZZFullRun2/PlottingResults/ZZ4l2016/FakeRatesFromData/" + data_folder_name + "/plots" +mc_outdir = "~/www/ZZFullRun2/PlottingResults/ZZ4l2016/FakeRates/" + data_folder_name + "-MC/plots" for outdir in [data_outdir, mc_outdir]: try: @@ -111,6 +240,7 @@ def makeMCPlots(param, obj, outdir): pass for param in ["1DPt", "1DEta", "2D"]: +#for param in ["1DPt", "1DEta"]: for obj in ["Mu", "E"]: makeDataPlots(param, obj, data_outdir) makeMCPlots(param, obj, mc_outdir) diff --git a/Utilities/scripts/setupZGenCombine.py b/Utilities/scripts/setupZGenCombine.py new file mode 100644 index 00000000..2871c7dc --- /dev/null +++ b/Utilities/scripts/setupZGenCombine.py @@ -0,0 +1,57 @@ +from python import CombineCardTools +from python import ConfigureJobs +import sys +import ROOT +import logging +import array + +ROOT.gROOT.SetBatch(True) +logging.basicConfig(level=logging.DEBUG) + +cardtool = CombineCardTools.CombineCardTools() + +manager_path = ConfigureJobs.getManagerPath() +sys.path.append("/".join([manager_path, "AnalysisDatasetManager", + "Utilities/python"])) + +from ConfigHistFactory import ConfigHistFactory +config_factory = ConfigHistFactory( + "%s/AnalysisDatasetManager" % manager_path, + "ZGen/NanoAOD", +) + +#plot_groups = ["nonprompt", "dy_lo", "dy_htbinned", "dy_htbinned_cp5", "dy_lo_2018"] +plot_groups = ["nonprompt", "dy_htbinned_cp5", "dy_lo_2018"] +plotGroupsMap = {name : config_factory.getPlotGroupMembers(name) for name in plot_groups} + +xsecs = ConfigureJobs.getListOfFilesWithXSec([f for files in plotGroupsMap.values() for f in files]) + +channels = ["ee", "mm"] +fitvar = "ptZ" +#rebin = array.array('d', [0.0,50.0,100.0,150.0,200.0,250.0,300.0,350.0,400.0]) +cardtool.setFitVariable(fitvar) +#cardtool.setRebin(rebin) +cardtool.setProcesses(plotGroupsMap) +cardtool.setChannels(channels) +cardtool.setCrosSectionMap(xsecs) +cardtool.setVariations([]) +cardtool.setOutputFolder("/eos/user/k/kelong/CombineStudies/ZGen/%s" % fitvar) + +cardtool.setLumi(35.9) +cardtool.setInputFile("/eos/user/k/kelong/HistFiles/ZGen/combined_withNonprompt.root") +cardtool.setOutputFile("ZGenCombineInput.root") +for process in plot_groups: + #Turn this back on when the theory uncertainties are added + if process not in ["nonprompt", "data"]: #and False + cardtool.addTheoryVar(process, 'scale', range(0, 8), exclude=[5, 7], central=-1) + cardtool.addTheoryVar(process, 'pdf_hessian', range(9, 109), central=-1) + cardtool.loadHistsForProcess(process) + cardtool.writeProcessHistsToOutput(process) + +nuissance_map = {"ee" : 3, "mm" : 3 } +for chan in channels: #+ ["all"]: + cardtool.setTemplateFileName("Templates/CombineCards/VGen/ZGen_template_{channel}.txt") + logging.info("Writting cards for channel %s" % chan) + cardtool.writeCards(chan, nuissance_map[chan], + #extraArgs={"data_name" : "dy_lo", "dy_sample" : "dy_lo"}) + extraArgs={"data_name" : "dy_lo_2018", "dy_sample" : "dy_lo_2018"}) diff --git a/Utilities/scripts/setupZZCombine.py b/Utilities/scripts/setupZZCombine.py new file mode 100644 index 00000000..b59d5c98 --- /dev/null +++ b/Utilities/scripts/setupZZCombine.py @@ -0,0 +1,107 @@ +from python import CombineCardTools +from python import ConfigureJobs +import sys +import ROOT +import logging +import array +import os +import shutil + +#logging.basicConfig(level=logging.DEBUG) + +cardtool = CombineCardTools.CombineCardTools() + + +manager_path = ConfigureJobs.getManagerPath() +manager_name = ConfigureJobs.getManagerName() +#print "manager_path: ", manager_path +#print "manager_name: ", manager_name +sys.path.append("/".join([manager_path, manager_name, + "Utilities/python"])) +#print sys.path +from ConfigHistFactory import ConfigHistFactory +config_factory = ConfigHistFactory( + "%s/%s" % (manager_path, manager_name), + "ZZ4l2016/LooseLeptons", +) +#manager_path = ConfigureJobs.getManagerPath() +#manager_name = ConfigureJobs.getManagerName() +##print "manager_path: ", manager_path +#if manager_path not in sys.path: +# sys.path.insert(0, "/".join([manager_path,"ZZ4lRun2DatasetManager", "Utilities/python"])) +#dataset_file = "%s/ZZ4lRun2DatasetManager/FileInfo/ZZ4l2016/%s.json" % (manager_path, "LooseLeptons") +#allnames = json.load(open(dataset_file)) +#atgcSamples={} +#for name in allnames.keys(): +# if "atgc" in name or "sherpa" in name: +# atgcSamples[str(name)]= str(allnames[name]['plot_group']) +#print atgcSamples + +plot_groups = ["HZZ_signal","qqZZ_powheg","zzjj4l_ewk","ggZZ", "VVV", "data", "nonprompt",] +plotGroupsMap = {name : config_factory.getPlotGroupMembers(name) for name in plot_groups} +xsecs = ConfigureJobs.getListOfFilesWithXSec([f for files in plotGroupsMap.values() for f in files]) + + +lumiMap = {"2016" : 35.9, "2017" : 41.5, "2018" : 59.67,"FullRun2":137.1} +fileMap = { "2016" : "/afs/cern.ch/user/u/uhussain/ZZ4lRun2HistFiles/Hists17Oct2019-ZZ4l2016_Moriond.root", + "2017" : "/afs/cern.ch/user/u/uhussain/ZZ4lRun2HistFiles/Hists14Oct2019-ZZ4l2017_Moriond.root", + "2018" : "/afs/cern.ch/user/u/uhussain/ZZ4lRun2HistFiles/Hists15Oct2019-ZZ4l2018_MVA.root", + "FullRun2":"/afs/cern.ch/user/u/uhussain/ZZ4lRun2HistFiles/Hists17Oct2019-ZZFullRun2.root", + } +channels = ["eeee", "eemm", "mmee", "mmmm"] +nuissance_map = {"eeee" : 16, "eemm" : 17, "mmee" : 17, "mmmm" : 15, "all" : 13} +#fitvar = "ZZPt" +#rebin = array.array('d', [0.0,50.0,100.0,150.0,200.0,250.0,300.0,350.0,400.0]) +fitvar = "Mass" +rebin = array.array('d', [100.0,200.0,250.0,300.0,350.0,400.0,500.0,600.0,800.0,1000.0,1200.0]) +#fitvar = "yield" +#cardtool.setRebin(rebin) +cardtool.setFitVariable(fitvar) +cardtool.setFitVariableAppend("nonprompt", "Fakes") +cardtool.setProcesses(plotGroupsMap) +cardtool.setChannels(channels) +cardtool.setCrosSectionMap(xsecs) +cardtool.setVariations(["CMS_eff_e", "CMS_RecoEff_e", "CMS_eff_m","CMS_pileup"], + exclude=["nonprompt", "data"]) +#cardtool.setOutputFolder("/eos/user/k/kelong/CombineStudies/ZZ/%s2016Fit" % fitvar) + +combine_dir = ConfigureJobs.getCombinePath() +folder_name="%sFitFullRunII" % fitvar + +output_dir = '/'.join([combine_dir,"ZZ", folder_name]) + +try: + os.makedirs(output_dir) +except OSError as e: + logging.warning(e) + pass +output_folder = "CombineStudies/ZZ/%sFitFullRunII_Oct29" % fitvar +cardtool.setOutputFolder(output_folder) + +for year in ["2016","2017","2018"]: +#One has to make templates for full Run 2 which i haven't done yet. +#for year in ["FullRun2"]: + cardtool.setLumi(lumiMap[year]) + cardtool.setInputFile(fileMap[year]) + print fileMap[year], lumiMap[year] + cardtool.setOutputFile("ZZCombineInput_{year}.root".format(year=year)) + #cardtool.setOutputFolder("/eos/user/k/kelong/CombineStudies/ZZ/%s%sFit" % (fitvar, year)) + for process in plot_groups: + #Turn this back on when the theory uncertainties are added + if process not in ["zzjj4l_ewk","qqZZ_sherpa","zzqjj4l_ewk","nonprompt", "data"]: #and False + cardtool.addTheoryVar(process, 'scale', range(1, 10), exclude=[7, 9], central=0) + cardtool.addTheoryVar(process, 'pdf_hessian' if year != "2016" else 'pdf_mc', [1]+[i for i in range(10, 111)], central=0) + cardtool.loadHistsForProcess(process) + cardtool.writeProcessHistsToOutput(process) + + for chan in channels + ["all"]: + cardtool.setTemplateFileName("Templates/CombineCards/ZZSelection/ZZ_template{year}_{channel}.txt") + logging.info("Writting cards for channel %s" % chan) + cardtool.writeCards(chan, nuissance_map[chan], year=year) + + +copyFiles=os.listdir(output_folder) +for f in copyFiles: + full_file_name=os.path.join(output_folder,f) + if os.path.isfile(full_file_name): + shutil.copy(full_file_name,output_dir) diff --git a/createSignal16.sh b/createSignal16.sh new file mode 100755 index 00000000..2cd96f81 --- /dev/null +++ b/createSignal16.sh @@ -0,0 +1 @@ +./Utilities/scripts/makeHistFile.py -a ZZ4l2016 -s SignalSync -l 35.9 -f 2016SignalSync -sf data/scaleFactorsZZ4l2018.root -ls Signal16 --test > eventlistSignal16_Usama_full.txt diff --git a/interface/FakeRateSelector.h b/interface/FakeRateSelector.h index d25cadf9..06ab35a4 100644 --- a/interface/FakeRateSelector.h +++ b/interface/FakeRateSelector.h @@ -10,35 +10,59 @@ #include // Headers needed by this particular selector -#include "Analysis/VVAnalysis/interface/WZSelectorBase.h" +#include "Analysis/VVAnalysis/interface/ZZSelectorBase.h" #include -class FakeRateSelector : public WZSelectorBase { +class FakeRateSelector : public ZZSelectorBase { public : + TH2D* passingTightE2D_; + TH1D* passingTightE1DPt_barrel_; + TH1D* passingTightE1DPt_endcap_; + TH1D* passingTightE1DEta_; + TH2D* passingLooseE2D_; + TH1D* passingLooseE1DPt_barrel_; + TH1D* passingLooseE1DPt_endcap_; + TH1D* passingLooseE1DEta_; + TH2D* ratioE2D_; + TH1D* ratioE1DPt_barrel_; + TH1D* ratioE1DPt_endcap_; + TH1D* ratioE1DEta_; + + TH2D* passingTightMu2D_; + TH1D* passingTightMu1DPt_barrel_; + TH1D* passingTightMu1DPt_endcap_; + TH1D* passingTightMu1DEta_; + TH2D* passingLooseMu2D_; + TH1D* passingLooseMu1DPt_barrel_; + TH1D* passingLooseMu1DPt_endcap_; + TH1D* passingLooseMu1DEta_; + TH2D* ratioMu2D_; + TH1D* ratioMu1DPt_barrel_; + TH1D* ratioMu1DPt_endcap_; + TH1D* ratioMu1DEta_; TH2D* passingTight2D_; - TH1D* passingTight1DPt_; + TH1D* passingTight1DPt_barrel_; + TH1D* passingTight1DPt_endcap_; TH1D* passingTight1DEta_; TH2D* passingLoose2D_; - TH1D* passingLoose1DPt_; + TH1D* passingLoose1DPt_barrel_; + TH1D* passingLoose1DPt_endcap_; TH1D* passingLoose1DEta_; TH2D* ratio2D_; - TH1D* ratio1DPt_; + TH1D* ratio1DPt_barrel_; + TH1D* ratio1DPt_endcap_; TH1D* ratio1DEta_; - Float_t type1_pfMETEt; - UInt_t nCBVIDVetoElec; - UInt_t nWZLooseMuon; - - TBranch* b_type1_pfMETEt; - TBranch* b_nCBVIDVetoElec; - TBranch* b_nWZLooseMuon; - - // Readers to access the data (delete the ones you do not need). + virtual void Init(TTree *tree) override; virtual void SetupNewDirectory() override; - virtual void FillHistograms(Long64_t entry, std::pair variation) override; - + //virtual void FillHistograms(Long64_t entry, std::pair variation) override; ClassDefOverride(FakeRateSelector,0); + +private: + void LoadBranchesUWVV(Long64_t entry, std::pair variation) override; + + }; #endif diff --git a/interface/SelectorBase.h b/interface/SelectorBase.h index e2818b12..9d9f04c5 100644 --- a/interface/SelectorBase.h +++ b/interface/SelectorBase.h @@ -48,6 +48,7 @@ class SelectorBase : public TSelector { enum Selection { tightleptons, ZZGenFiducial, + ZZselection, Wselection, Zselection, Wselection_Full, FakeRateSelectionLoose, FakeRateSelectionTight, VBSselection_Loose, @@ -72,9 +73,11 @@ class SelectorBase : public TSelector { metUnclusteredEnergyUp, metUnclusteredEnergyDown, muonEfficiencyUp, muonEfficiencyDown, muonScaleUp, muonScaleDown, + electronRecoEffUp, electronRecoEffDown, electronEfficiencyUp, electronEfficiencyDown, electronScaleUp, electronScaleDown, pileupUp, pileupDown, + //L1prefiringWeightUp, L1prefiringWeightDown, }; /****************************/ @@ -91,6 +94,12 @@ class SelectorBase : public TSelector { {"ZZGenFiducial", ZZGenFiducial}, {"Wselection", Wselection}, {"Zselection", Zselection}, + {"ZZselection", ZZselection}, + {"SignalSync", ZZselection}, + {"AllData", ZZselection}, + {"LooseLeptons", ZZselection}, + {"TightLeptonsWGen", ZZselection}, + {"ZplusLSkim", ZZselection}, {"Wselection_Full", Wselection_Full}, {"FakeRateSelectionLoose", FakeRateSelectionLoose}, {"FakeRateSelectionTight", FakeRateSelectionTight}, @@ -125,12 +134,12 @@ class SelectorBase : public TSelector { {"ee", ee}, {"em", em}, {"mm", mm}, {"eee", eee}, {"eem", eem}, {"emm", emm}, {"mmm", mmm}, {"eeee", eeee}, {"eemm", eemm}, {"mmee", mmee}, {"mmmm", mmmm}, + {"eeeeGen", eeee}, {"eemmGen", eemm},{"mmeeGen", mmee},{"mmmmGen", mmmm}, {"Inclusive", Inclusive}, {"lll", lll}, }; std::vector allChannels_ = {}; - std::vector hists1D_ = {}; std::map variations_ = {{Central, ""}}; std::map systematics_ = {}; @@ -138,6 +147,7 @@ class SelectorBase : public TSelector { TH1D* sumWeightsHist_; bool doSystematics_; + bool isNonPrompt_ = false; bool addSumweights_; bool applyScaleFactors_; bool applyPrefiringCorr_; @@ -186,9 +196,11 @@ class SelectorBase : public TSelector { std::map histMap1D_ = {}; //TODO change the name to map and don't break things std::map hists2D_ = {}; - std::map weighthists_ = {}; - std::map weighthists2D_ {}; + std::map weighthistMap1D_ = {}; + std::map weighthistMap2D_ {}; + std::vector hists1D_ = {}; + std::vector weighthists1D_ = {}; // The histograms for which you also want systematic variations std::vector systHists_ = {}; std::vector systHists2D_ = {}; @@ -219,6 +231,8 @@ class SelectorBase : public TSelector { std::vector ReadHistDataFromConfig(std::string histDataString); std::string getHistName(std::string histName, std::string variationName, std::string channel); std::string getHistName(std::string histName, std::string variationName); + template + void InitializeHistMap(std::vector& labels, std::map& histMap); // Filling Functions template diff --git a/interface/ZZBackgroundSelector.h b/interface/ZZBackgroundSelector.h new file mode 100644 index 00000000..48810cdb --- /dev/null +++ b/interface/ZZBackgroundSelector.h @@ -0,0 +1,41 @@ +#ifndef ZZBackgroundSelector_h +#define ZZBackgroundSelector_h + +#include +#include "Analysis/VVAnalysis/interface/ScaleFactor.h" +#include "Analysis/VVAnalysis/interface/ZZSelector.h" + +class ZZBackgroundSelector : public ZZSelector { +public : + ScaleFactor * fakeRate_allE_; + ScaleFactor * fakeRate_allMu_; + + //PPPF represents 3P1F CR and PPFF represents 2P1F CR + TH1D* Z1MassHistPPPF_; + TH1D* Z1MassHistPPFF_; + TH1D* Z2MassHistPPPF_; + TH1D* Z2MassHistPPFF_; + //4lMass Histogram + TH1D* MassHistPPPF_; + TH1D* MassHistPPFF_; + + TH1D* WeightsHistmmee_; + TH1D* WeightsHisteemm_; + + virtual void Init(TTree *tree) override; + virtual void SetupNewDirectory() override; + virtual void SlaveBegin(TTree *tree) override; + + ClassDefOverride(ZZBackgroundSelector,0); +private: + float getl3FakeRate(Long64_t entry); + float getl4FakeRate(Long64_t entry); + //In ZZ we only care about 3P1F and 2P2F, contributions are extremely low from other regions like FFFF,PFFF etc + bool IsPPPFRegion(); + bool IsPPFFRegion(); + void SetZ1Z2Masses(); + float getEventWeight(Long64_t entry); + void LoadBranchesUWVV(Long64_t entry, std::pair variation) override; +}; + +#endif diff --git a/interface/ZZGenSelector.h b/interface/ZZGenSelector.h index d5d47653..9f872df9 100644 --- a/interface/ZZGenSelector.h +++ b/interface/ZZGenSelector.h @@ -8,18 +8,22 @@ class ZZGenSelector : public SelectorBase { public : - float GendPhiZZ; //DeltaPhi between Z1 and Z2 + float GendPhiZZ; //DeltaPhi between Z1 and Z2 + float GendRZZ; //DeltaR between Z1 and Z2 Float_t GenMass; Float_t GenPt; Float_t GenEta; Float_t Genweight; + Float_t genWeight; Float_t GenZ1mass; Float_t GenZ2mass; Float_t GenZ1pt; Float_t GenZ2pt; Float_t GenZ1Phi; - Float_t GenZ2Phi; - + Float_t GenZ2Phi; + Float_t GenZ1Eta; + Float_t GenZ2Eta; + Float_t Genl1Pt; Float_t Genl2Pt; Float_t Genl3Pt; @@ -33,10 +37,13 @@ public : Float_t Genl3Phi; Float_t Genl4Phi; + TBranch* b_genWeight; TBranch* b_GenZ1mass; TBranch* b_GenZ2mass; TBranch* b_GenZ1pt; TBranch* b_GenZ2pt; + TBranch* b_GenZ1Eta; + TBranch* b_GenZ2Eta; TBranch* b_GenZ1Phi; TBranch* b_GenZ2Phi; TBranch* b_GenMass; diff --git a/interface/ZZSelector.h b/interface/ZZSelector.h new file mode 100644 index 00000000..e872174b --- /dev/null +++ b/interface/ZZSelector.h @@ -0,0 +1,98 @@ +#ifndef ZZSelector_h +#define ZZSelector_h + +#include +#include "Analysis/VVAnalysis/interface/ZZSelectorBase.h" +#include + +class ZZSelector : public ZZSelectorBase { +public : + bool applyFullSelection_ = true; + bool isaTGC_ = false; + bool doaTGC_ = false; + + std::vector* scaleWeights = NULL; + std::vector* pdfWeights = NULL; + std::vector lheWeights; + unsigned int weight_info_; + + + float dEtajj; + float dEtajj_jesUp; + float dEtajj_jesDown; + float dEtajj_jerUp; + float dEtajj_jerDown; + float dRjj; + float dRjj_jesUp; + float dRjj_jesDown; + float dRjj_jerUp; + float dRjj_jerDown; + float zep3l; + float zep3l_jesUp; + float zep3l_jesDown; + float zep3l_jerUp; + float zep3l_jerDown; + Float_t mjj; + std::vector* jetEta = NULL; + std::vector* jetEta_jesUp = NULL; + std::vector* jetEta_jesDown = NULL; + std::vector* jetEta_jerUp = NULL; + std::vector* jetEta_jerDown = NULL; + std::vector* jetPhi = NULL; + std::vector* jetPhi_jesUp = NULL; + std::vector* jetPhi_jesDown = NULL; + std::vector* jetPhi_jerUp = NULL; + std::vector* jetPhi_jerDown = NULL; + std::vector* jetPt = NULL; + std::vector* jetPt_jesUp = NULL; + std::vector* jetPt_jesDown = NULL; + std::vector* jetPt_jerUp = NULL; + std::vector* jetPt_jerDown = NULL; + std::vector* jetCSVv2 = NULL; + UInt_t nvtx; + Float_t Mass; + Float_t Pt; + Float_t Eta; + float dPhiZZ; //DeltaPhi between Z1 and Z2 + float dRZZ; //DeltaR between Z1 and Z2 + TBranch* b_nvtx; + TBranch* b_Mass; + TBranch* b_Pt; + TBranch* b_Eta; + TBranch* b_jetPt; + TBranch* b_jetEta; + TBranch* b_mjj; + int cen_count = 0; + float count = 0; + + // Readers to access the data (delete the ones you do not need). + virtual void Init(TTree *tree) override; + virtual void SetupNewDirectory() override; + + ClassDefOverride(ZZSelector,0); + +protected: + virtual void SetBranchesUWVV() override; + void LoadBranchesUWVV(Long64_t entry, std::pair variation) override; + void FillHistograms(Long64_t entry, std::pair variation) override; + void ApplyScaleFactors(); + bool PassesZZSelection(bool nonPrompt); + bool PassesZZjjSelection(); + bool PassesHZZSelection(bool nonPrompt); + unsigned int GetLheWeightInfo(); + void SetVariables(Long64_t entry); + //bool DuplicatedEvent(); + bool TightZZLeptons(); + bool ZZSelection(); + bool Z4lSelection(); + bool ZSelection(); + bool HZZSIPSelection(); + //bool SmartCut(); + bool HZZLowMass(); + bool HZZMediumMass(); + bool TestMuons(); + void ShiftEfficiencies(Systematic variation); +}; + +#endif + diff --git a/interface/ZZSelectorBase.h b/interface/ZZSelectorBase.h new file mode 100644 index 00000000..34da4759 --- /dev/null +++ b/interface/ZZSelectorBase.h @@ -0,0 +1,222 @@ +#ifndef ZZSelectorBase_h +#define ZZSelectorBase_h + +#include +#include +#include +#include +#include +#include +#include +#include + +// Headers needed by this particular selector +#include +#include "Analysis/VVAnalysis/interface/ScaleFactor.h" +#include "Analysis/VVAnalysis/interface/SelectorBase.h" +#include "Analysis/VVAnalysis/interface/helpers.h" + +class ZZSelectorBase : public SelectorBase { +public : + ScaleFactor* pileupSF_; + ScaleFactor* eLowRecoSF_; + ScaleFactor* eRecoSF_; + ScaleFactor* eIdSF_; + ScaleFactor* eGapIdSF_; + ScaleFactor* mIdSF_; + //ScaleFactor* mIsoSF_; + + + //bool isVBS_; + //MC variable to check for duplication(this is a flag to differentiate between channels) + UInt_t run; + UInt_t lumi; + ULong64_t evt; + //Int_t duplicated; + Float_t weight; + Float_t genWeight; + Float_t L1prefiringWeight; + Float_t nTruePU; + Float_t Z1mass; + Float_t Z2mass; + //Float_t Zamass; + //Float_t Zbmass; + Float_t Z1pt; + Float_t Z2pt; + Float_t Z1Phi; + Float_t Z2Phi; + Float_t Z1Eta; + Float_t Z2Eta; + Float_t type1_pfMETEt; + Float_t type1_pfMETPhi; + Float_t l1GenPt; + Float_t l2GenPt; + Float_t l3GenPt; + Float_t l4GenPt; + + Bool_t l1IsTight; + Bool_t l2IsTight; + Bool_t l3IsTight; + Bool_t l4IsTight; + Float_t l1IsIso; + Float_t l2IsIso; + Float_t l3IsIso; + Float_t l4IsIso; + + Bool_t l1IsGap; + Bool_t l2IsGap; + Bool_t l3IsGap; + Bool_t l4IsGap; + + Float_t l1Pt; + Float_t l2Pt; + Float_t l3Pt; + Float_t l4Pt; + Float_t l1Eta; + Float_t l2Eta; + Float_t l3Eta; + Float_t l4Eta; + Float_t l1Phi; + Float_t l2Phi; + Float_t l3Phi; + Float_t l4Phi; + Float_t l1SIP3D; + Float_t l2SIP3D; + Float_t l3SIP3D; + Float_t l4SIP3D; + Int_t l1PdgId; + Int_t l2PdgId; + Int_t l3PdgId; + Int_t l4PdgId; + Float_t l1Mass; + Float_t l2Mass; + Float_t l3Mass; + Float_t l4Mass; + + Float_t l1PVDXY; + Float_t l2PVDXY; + Float_t l3PVDXY; + Float_t l4PVDXY; + Float_t l1PVDZ; + Float_t l2PVDZ; + Float_t l3PVDZ; + Float_t l4PVDZ; + + Float_t l3MtToMET; + + TBranch* b_pdfWeights; + TBranch* b_scaleWeights; + //TBranch* b_duplicated; + TBranch* b_genWeight; + TBranch* b_L1prefiringWeight; + TBranch* b_Z1mass; + TBranch* b_Z2mass; + //Smart cut on 4e/4mu + //TBranch* b_Zamass; + //TBranch* b_Zbmass; + TBranch* b_Z1pt; + TBranch* b_Z2pt; + TBranch* b_Z1Phi; + TBranch* b_Z2Phi; + TBranch* b_Z1Eta; + TBranch* b_Z2Eta; + TBranch* b_nTruePU; + TBranch* b_type1_pfMETEt; + TBranch* b_type1_pfMETPhi; + TBranch* b_l1GenPt; + TBranch* b_l2GenPt; + TBranch* b_l3GenPt; + TBranch* b_l4GenPt; + + TBranch* b_run; + TBranch* b_lumi; + TBranch* b_evt; + + TBranch* b_l1IsTight; + TBranch* b_l2IsTight; + TBranch* b_l3IsTight; + TBranch* b_l4IsTight; + TBranch* b_l1IsIso; + TBranch* b_l2IsIso; + TBranch* b_l3IsIso; + TBranch* b_l4IsIso; + + TBranch* b_l1IsGap; + TBranch* b_l2IsGap; + TBranch* b_l3IsGap; + TBranch* b_l4IsGap; + + TBranch* b_l1Pt; + TBranch* b_l2Pt; + TBranch* b_l3Pt; + TBranch* b_l4Pt; + TBranch* b_l1Eta; + TBranch* b_l2Eta; + TBranch* b_l3Eta; + TBranch* b_l4Eta; + TBranch* b_l1Phi; + TBranch* b_l2Phi; + TBranch* b_l3Phi; + TBranch* b_l4Phi; + TBranch* b_l1SIP3D; + TBranch* b_l2SIP3D; + TBranch* b_l3SIP3D; + TBranch* b_l4SIP3D; + TBranch* b_l1Mass; + TBranch* b_l2Mass; + TBranch* b_l3Mass; + TBranch* b_l4Mass; + TBranch* b_l1PdgId; + TBranch* b_l2PdgId; + TBranch* b_l3PdgId; + TBranch* b_l4PdgId; + TBranch* b_l3MtToMET; + + // Readers to access the data (delete the ones you do not need). + virtual void SetScaleFactors() override; + virtual void Init(TTree *tree) override; + + ClassDefOverride(ZZSelectorBase,0); + + +protected: + std::vector nonprompt3l_ = { + "tt-lep", "st-schan", "st-tchan-t", "st-tchan-tbar", + "st-tw", "st-tbarw", "DYm50", "DYm50-1j", + "DYm50-2j","DYm50-3j","DYm50-4j", "DYm50__LO", + }; + + bool isNonpromptEstimate_; + bool isNonpromptMC_; + bool isZgamma_; + const float FR_MAX_PT_ = 80; + const float FR_MAX_ETA_ = 2.5; + const float MuSF_MAX_PT_ = 200; + const float EleSF_MAX_PT_ = 500; + virtual std::string GetNameFromFile() override; + virtual void SetBranchesNanoAOD() override; + virtual void SetBranchesUWVV() override; + void LoadBranchesUWVV(Long64_t entry, std::pair variation) override; + void LoadBranchesNanoAOD(Long64_t entry, std::pair variation) override; + bool e1e2IsZ1(Long64_t entry); + bool lep1IsTight(); + bool lep2IsTight(); + bool lep3IsTight(); + bool lep4IsTight(); + bool lep1IsIso(); + bool lep2IsIso(); + bool lep3IsIso(); + bool lep4IsIso(); + bool Z1PF(); + bool Z1FP(); + bool Z1FF(); + bool Z2PF(); + bool Z2FP(); + bool Z2FF(); + bool tightSIP(); + bool tightZ1Leptons(); + bool tightZ2Leptons(); +}; + +#endif + diff --git a/makeFakeRates2016.sh b/makeFakeRates2016.sh new file mode 100755 index 00000000..b6f07bd5 --- /dev/null +++ b/makeFakeRates2016.sh @@ -0,0 +1 @@ +./Utilities/scripts/makeFakeRates.py -a ZZ4l2016 -s ZplusLSkim -l 35.9 -f ZZ4l2016 --uwvv --noHistConfig -c eee,eem,emm,mmm --test diff --git a/makeFakeRates2017.sh b/makeFakeRates2017.sh new file mode 100755 index 00000000..6b545392 --- /dev/null +++ b/makeFakeRates2017.sh @@ -0,0 +1 @@ +./Utilities/scripts/makeFakeRates.py -a ZZ4l2017 -s ZplusLSkim -l 41.5 -f ZZ4l2017 --uwvv --noHistConfig -c eee,eem,emm,mmm --test diff --git a/makeFakeRates2018.sh b/makeFakeRates2018.sh new file mode 100755 index 00000000..6302c257 --- /dev/null +++ b/makeFakeRates2018.sh @@ -0,0 +1 @@ +./Utilities/scripts/makeFakeRates.py -a ZZ4l2018 -s ZplusLSkim -l 59.7 -f ZZ4l2018 --uwvv --noHistConfig -c eee,eem,emm,mmm --test diff --git a/makeHistFile.py b/makeHistFile.py new file mode 100755 index 00000000..30849309 --- /dev/null +++ b/makeHistFile.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python +import ROOT +from python import SelectorTools +from python import UserInput +from python import OutputTools +from python import ConfigureJobs +from python import HistTools +import os +import sys +import datetime +channels = ["eeee", "eemm","mmee","mmmm"] +#channels = ["eeee"] +def getComLineArgs(): + parser = UserInput.getDefaultParser() + parser.add_argument("--proof", "-p", + action='store_true', help="Don't use proof") + parser.add_argument("--lumi", "-l", type=float, + default=41.5, help="luminosity value (in fb-1)") + parser.add_argument("--output_file", "-o", type=str, + default="", help="Output file name") + parser.add_argument("--scalefactors_file", "-sf", type=str, + default="", help="ScaleFactors file name") + parser.add_argument("--leptonSelections", "-ls", type=str, + default="TightLeptons", help="Either All Loose or Tight") + parser.add_argument("--test", action='store_true', + help="Run test job (no background estimate)") + parser.add_argument("--output_selection", type=str, + default="", help="Selection stage of output file " + "(Same as input if not give)") + parser.add_argument("-b", "--hist_names", + type=lambda x : [i.strip() for i in x.split(',')], + default=["all"], help="List of histograms, " + "as defined in ZZ4lRun2DatasetManager, separated " + "by commas") + return vars(parser.parse_args()) + +def getHistExpr(hist_names, selection): + info = ROOT.TList() + info.SetName("histinfo") + for hist_name in hist_names: + bin_info = ConfigHistTools.getHistBinInfo(manager_path, selection, hist_name) + if "TH1" in ConfigHistTools.getHistType(manager_path, selection, hist_name): + bin_expr = "{nbins}, {xmin}, {xmax}".format(**bin_info) + else: + bin_expr = "{nbinsx}, {xmin}, {xmax}, {nbinsy}, {ymin}, {ymax}".format(**bin_info) + info.Add(ROOT.TNamed(hist_name, " $ ".join([hist_name, bin_expr]))) + return info + +ROOT.gROOT.SetBatch(True) + +args = getComLineArgs() +manager_path = ConfigureJobs.getManagerPath() +sys.path.append("/".join([manager_path, + "ZZ4lRun2DatasetManager", "Utilities/python"])) +import ConfigHistTools + +today = datetime.date.today().strftime("%d%b%Y") +tmpFileName = "HistFiles/Hists%s-%s.root" % (today, args['leptonSelections']) if args['output_file'] == "" \ + else args['output_file'] +fOut = ROOT.TFile(tmpFileName, "recreate") + +fScales = ROOT.TFile(args['scalefactors_file']) +mZZTightFakeRate = fScales.Get("mZZTightFakeRate") +eZZTightFakeRate = fScales.Get("eZZTightFakeRate") +#fakeRateFile=ROOT.TFile('data/fakeRate18Dec2018-ZplusLSkimZZ2018Data.root') +#eZZTightFakeRate=fakeRateFile.Get('DataEWKCorrected/ratioE2D_allE') +#mZZTightFakeRate=fakeRateFile.Get('DataEWKCorrected/ratioMu2D_allMu') +#useSvenjasFRs = False +#useJakobsFRs = False +#if useSvenjasFRs: +# mZZTightFakeRate = fScales.Get("mZZTightFakeRate_Svenja") +# eZZTightFakeRate = fScales.Get("eZZTightFakeRate_Svenja") +#elif useJakobsFRs: +# mZZTightFakeRate = fScales.Get("mZZTightFakeRate_Jakob") +# eZZTightFakeRate = fScales.Get("eZZTightFakeRate_Jakob") +## For medium muons +##mZZMedFakeRate.SetName("fakeRate_allMu") +if mZZTightFakeRate: + #print "Yes muon fake rates" + mZZTightFakeRate.SetName("fakeRate_allMu") +if eZZTightFakeRate: + #print "Yes electron fake rates" + eZZTightFakeRate.SetName("fakeRate_allE") +# +#muonIsoSF = fScales.Get('muonIsoSF') +muonMoriond19SF= fScales.Get('muonMoriond19SF') +#Electron Reco SF (POG) https://twiki.cern.ch/twiki/bin/viewauth/CMS/Egamma2018DataRecommendations +electronLowReco19SF = fScales.Get('electronLowReco19SF') +electronReco19SF = fScales.Get('electronReco19SF') +#Electron ID + SIP HZZ Scale factors +electronMoriond19SF = fScales.Get('electronMoriond19SF') +electronMoriond19GapSF = fScales.Get('electronMoriond19GapSF') +pileupSF = fScales.Get('pileupSF') + +fr_inputs = [eZZTightFakeRate, mZZTightFakeRate,] +sf_inputs = [electronLowReco19SF,electronReco19SF,electronMoriond19SF, electronMoriond19GapSF,muonMoriond19SF,pileupSF] +#sf_inputs=[pileupSF] +selection = args['selection'].replace("LooseLeptons", "") \ + if args['output_selection'] == "" else args['output_selection'].split("_")[0] +if selection == "": + selection = "LooseLeptons" + print "Info: Using BasicZZSelections for hist defintions" +analysis = "/".join([args['analysis'], selection]) +hists = ConfigHistTools.getAllHistNames(manager_path, analysis) \ + if "all" in args['hist_names'] else args['hist_names'] + +hists = [h for h in hists if "unrolled" not in h and "wCR" not in h and h not in ["YieldByChannel", "CutFlow"]] +#print "hists: ", hists +hist_inputs = [getHistExpr(hists, analysis)] +#print "hist_inputs: ",hist_inputs +tselection = [ROOT.TNamed("selection", args['output_selection'])] +#print "tselection: ",tselection +if args['proof']: + ROOT.TProof.Open('workers=12') + +if "FakeRate" not in args['output_selection'] and not args['test']: + # background = SelectorTools.applySelector(["ZZ4l2018data"] + + # ConfigureJobs.getListOfEWK() + ["wz3lnu-powheg"] + + # ConfigureJobs.getListOfNonpromptFilenames(),channels, + # "WZBackgroundSelector", args['selection'], fOut, + # extra_inputs=sf_inputs+fr_inputs+hist_inputs+tselection, + # addSumweights=False, + # proof=args['proof']) + background = SelectorTools.applySelector([args['analysis']+"data"] + + ConfigureJobs.getListOfEWKFilenames()+ConfigureJobs.getListOfDYFilenames()+ConfigureJobs.getListOfNonpromptFilenames()+ConfigureJobs.getListOfHZZFilenames(),channels, + "ZZBackgroundSelector", args['selection'], fOut,args['analysis'], + extra_inputs=sf_inputs+fr_inputs+hist_inputs+tselection, + addSumweights=False, + proof=args['proof']) +mc = SelectorTools.applySelector(args['filenames'],channels, "ZZSelector", args['selection'], fOut,args['analysis'], + extra_inputs=sf_inputs+hist_inputs+tselection, + addSumweights=True, proof=args['proof']) +if args['test']: + exit(0) + +alldata = HistTools.makeCompositeHists(fOut,"AllData", + ConfigureJobs.getListOfFilesWithXSec([args['analysis']+"data"], manager_path), args['lumi'], + underflow=False, overflow=False) +OutputTools.writeOutputListItem(alldata, fOut) +alldata.Delete() + +#nonpromptmc = HistTools.makeCompositeHists(fOut, "NonpromptMC", ConfigureJobs.getListOfFilesWithXSec( +# ConfigureJobs.getListOfNonpromptFilenames(), manager_path), args['lumi'], +# underflow=False, overflow=False) +#nonpromptmc.Delete() +# +#OutputTools.writeOutputListItem(nonpromptmc, fOut) + +#allggZZmc= HistTools.makeCompositeHists(fOut,"ggZZ", ConfigureJobs.getListOfFilesWithXSec( +# ConfigureJobs.getListOfggZZFilenames(), manager_path), args['lumi'], +# underflow=False, overflow=False) +#OutputTools.writeOutputListItem(allggZZmc, fOut) +#allggZZmc.Delete() +# +#allSignal= HistTools.makeCompositeHists(fOut,"HZZ-signal", ConfigureJobs.getListOfFilesWithXSec( +# ConfigureJobs.getListOfHZZFilenames(), manager_path), args['lumi'], +# underflow=False, overflow=False) +#OutputTools.writeOutputListItem(allSignal, fOut) +#allSignal.Delete() + +ewkmc = HistTools.makeCompositeHists(fOut,"AllEWK", ConfigureJobs.getListOfFilesWithXSec( + ConfigureJobs.getListOfEWK(), manager_path), args['lumi'], + underflow=False, overflow=False) +OutputTools.writeOutputListItem(ewkmc, fOut) +ewkmc.Delete() + +ewkcorr = HistTools.getDifference(fOut, "DataEWKCorrected", "AllData", "AllEWK") +OutputTools.writeOutputListItem(ewkcorr, fOut) +ewkcorr.Delete() diff --git a/makeScaleFactors2016.sh b/makeScaleFactors2016.sh new file mode 100755 index 00000000..e0438029 --- /dev/null +++ b/makeScaleFactors2016.sh @@ -0,0 +1 @@ +python ScaleFactors/setupScaleFactors.py --year 2016 -t data/fakeRate15Sep2019-ZZ4l2016.root --output_file data/scaleFactorsZZ4l2016.root diff --git a/makeScaleFactors2017.sh b/makeScaleFactors2017.sh new file mode 100755 index 00000000..3bc601f3 --- /dev/null +++ b/makeScaleFactors2017.sh @@ -0,0 +1 @@ +python ScaleFactors/setupScaleFactors.py --year 2017 -t data/fakeRate14Sep2019-ZZ4l2017.root --output_file data/scaleFactorsZZ4l2017.root diff --git a/makeScaleFactors2018.sh b/makeScaleFactors2018.sh new file mode 100755 index 00000000..b3582b19 --- /dev/null +++ b/makeScaleFactors2018.sh @@ -0,0 +1 @@ +python ScaleFactors/setupScaleFactors.py --year 2018 -t data/fakeRate15Sep2019-ZZ4l2018.root --output_file data/scaleFactorsZZ4l2018.root diff --git a/recipe/setup.sh b/recipe/setup.sh index dbccf094..c934ccce 100644 --- a/recipe/setup.sh +++ b/recipe/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash -dataset_manager=$(./Utilities/scripts/getConfigValue.py dataset_manager_path)/AnalysisDatasetManager +dataset_manager=$(./Utilities/scripts/getConfigValue.py dataset_manager_path)/ZZ4lRun2DatasetManager pushd $CMSSW_BASE/src/Analysis/VVAnalysis/Cuts echo "INFO: Linking alias files" diff --git a/runAllFiles.sh b/runAllFiles.sh new file mode 100755 index 00000000..84f87124 --- /dev/null +++ b/runAllFiles.sh @@ -0,0 +1,8 @@ +echo "creating 2016 hist file" +./runZZ4l2016.sh + +echo "creating 2017 hist file" +./runZZ4l2017.sh + +#echo "creating 2018 hist file" +#./runZZ4l2018.sh diff --git a/runTest.sh b/runTest.sh new file mode 100755 index 00000000..42ae12d4 --- /dev/null +++ b/runTest.sh @@ -0,0 +1 @@ +./Utilities/scripts/makeHistFile.py -a ZZ4l2017 -s LooseLeptons --output_file testSignal2017 --test --uwvv -c eeee,eemm,mmee,mmmm -f zz4l-powheg --with_Gen -sf data/scaleFactorsZZ4l2017.root diff --git a/runZZ4l2016.sh b/runZZ4l2016.sh new file mode 100755 index 00000000..5eba05fb --- /dev/null +++ b/runZZ4l2016.sh @@ -0,0 +1,2 @@ +./Utilities/scripts/makeHistFile.py -a ZZ4l2016 -s LooseLeptons --output_file NoSyst2016 --muIDType Moriond --year 2016 --uwvv -c eeee,eemm,mmee,mmmm -f ZZ4l2016 -j 12 --with_background --with_Gen -sf data/MoriondSFs/scaleFactorsZZ4l2016.root +#./Utilities/scripts/makeHistFile.py -a ZZ4l2016 -s LooseLeptons --output_file test2016 --uwvv -c eeee,eemm,mmee,mmmm -f ZZ4l2016 -j 12 --with_Gen --with_background -sf data/scaleFactorsZZ4l2017.root diff --git a/runZZ4l2016WGen.sh b/runZZ4l2016WGen.sh new file mode 100755 index 00000000..448de919 --- /dev/null +++ b/runZZ4l2016WGen.sh @@ -0,0 +1 @@ +./Utilities/scripts/makeHistFile.py -a ZZ4l2016 -s LooseLeptons --output_file zzGen2016 --year 2016 --uwvv -c eeee,eemm,mmee,mmmm --test -f zz4l-powheg -j 12 --with_Gen --with_background -sf data/scaleFactorsZZ4l2016.root diff --git a/runZZ4l2017.sh b/runZZ4l2017.sh new file mode 100755 index 00000000..7334d787 --- /dev/null +++ b/runZZ4l2017.sh @@ -0,0 +1 @@ +./Utilities/scripts/makeHistFile.py -a ZZ4l2017 -s LooseLeptons --output_file test2017 --muIDType Moriond --year 2017 --uwvv -c eeee,eemm,mmee,mmmm -f ZZ4l2017 -j 12 --with_Gen --with_background -sf data/MoriondSFs/scaleFactorsZZ4l2017.root diff --git a/runZZ4l2018.sh b/runZZ4l2018.sh new file mode 100755 index 00000000..baa035a5 --- /dev/null +++ b/runZZ4l2018.sh @@ -0,0 +1 @@ +./Utilities/scripts/makeHistFile.py -a ZZ4l2018 -s LooseLeptons --output_file test2018 --muIDType MVA --year 2018 --uwvv -c eeee,eemm,mmee,mmmm -f ZZ4l2018 -j 12 --with_Gen --with_background -sf data/latestSFs/scaleFactorsZZ4l2018.root diff --git a/src/FakeRateSelector.cc b/src/FakeRateSelector.cc index 5be36887..bd39579e 100644 --- a/src/FakeRateSelector.cc +++ b/src/FakeRateSelector.cc @@ -1,53 +1,114 @@ #include "Analysis/VVAnalysis/interface/FakeRateSelector.h" #include -void FakeRateSelector::FillHistograms(Long64_t entry, std::pair variation) { - if (!passesLeptonVeto) - return; - if (l1Pt < 25 || l2Pt < 15) - return; - if (ZMass > 101.1876 || ZMass < 81.1876) - return; - if (type1_pfMETEt > 25) - return; - if (l3MtToMET > 30) - return; - if (!tightZLeptons()) - return; - - if (!IsGenMatched3l()) - return; - +void FakeRateSelector::LoadBranchesUWVV(Long64_t entry, std::pair variation) { + ZZSelectorBase::LoadBranchesUWVV(entry, variation); + //In HZZ AN it says: |M_inv(l1,l2)- MZ| < 7 GeV, to reduce the contribution from photon (asymmetric) conversions populating low masses. + if (Z1mass > 98.1876 || Z1mass < 84.1876){ + return;} + if (type1_pfMETEt > 25){ + return;} + if (l3MtToMET > 30){ + return;} + if (!tightZ1Leptons()){ + return;} + float pt_fillval = l3Pt; float eta_fillval = std::abs(l3Eta); - + //std::cout<<"Is it filling?"<Evaluate2D(std::abs(l3Eta), l3Pt); + //if (channel_ == eee || channel_ == emm) { + // loose_weight /= eIdSF_->Evaluate2D(std::abs(l3Eta), l3Pt); + //} + //else if (channel_ == eem || channel_ == mmm) { + // loose_weight /= mIsoSF_->Evaluate2D(std::abs(l3Eta), l3Pt); + //} + //Electron barrel up to |eta| = 1.479 + if((channel_ == eee) || (channel_ == emm)){ + if(eta_fillval < 1.479) + passingLooseE1DPt_barrel_->Fill(pt_fillval, loose_weight); + else + passingLooseE1DPt_endcap_->Fill(pt_fillval, loose_weight); + + passingLooseE2D_->Fill(pt_fillval, eta_fillval, loose_weight); + passingLooseE1DEta_->Fill(eta_fillval, loose_weight); } + //Muon barrel up to |eta| = 1.2 else if (channel_ == eem || channel_ == mmm) { - loose_weight /= mIsoSF_->Evaluate2D(std::abs(l3Eta), l3Pt); + if(eta_fillval < 1.2) + passingLooseMu1DPt_barrel_->Fill(pt_fillval, loose_weight); + else + passingLooseMu1DPt_endcap_->Fill(pt_fillval, loose_weight); + + passingLooseMu2D_->Fill(pt_fillval, eta_fillval, loose_weight); + passingLooseMu1DEta_->Fill(eta_fillval, loose_weight); } - passingLoose2D_->Fill(pt_fillval, eta_fillval, loose_weight); - passingLoose1DPt_->Fill(pt_fillval, loose_weight); - passingLoose1DEta_->Fill(eta_fillval, loose_weight); - if (lepton3IsTight()) { - passingTight2D_->Fill(pt_fillval, eta_fillval, weight); - passingTight1DPt_->Fill(pt_fillval, weight); - passingTight1DEta_->Fill(eta_fillval, weight); + if (lep3IsTight()) { + if((channel_ == eee) || (channel_ == emm)){ + if(eta_fillval < 1.479) + passingTightE1DPt_barrel_->Fill(pt_fillval, loose_weight); + else + passingTightE1DPt_endcap_->Fill(pt_fillval, loose_weight); + + passingTightE2D_->Fill(pt_fillval, eta_fillval, weight); + passingTightE1DEta_->Fill(eta_fillval, weight); + } + //Muon barrel up to |eta| = 1.2 + else if (channel_ == eem || channel_ == mmm) { + if(eta_fillval < 1.2) + passingTightMu1DPt_barrel_->Fill(pt_fillval, loose_weight); + else + passingTightMu1DPt_endcap_->Fill(pt_fillval, loose_weight); + + passingTightMu2D_->Fill(pt_fillval, eta_fillval, weight); + passingTightMu1DEta_->Fill(eta_fillval, weight); + } } } -void FakeRateSelector::SetupNewDirectory() { - WZSelectorBase::SetupNewDirectory(); +void FakeRateSelector::Init(TTree *tree) +{ + //systematics_ = {{Central,""}}; + ZZSelectorBase::Init(tree); + +} + +void FakeRateSelector::SetupNewDirectory() +{ + ZZSelectorBase::SetupNewDirectory(); + + const int MuPtbins = 6; + double Mu_Pt_bins[MuPtbins+1] = {5,10,20,30,40,50,80}; + + const int ElePtbins = 6; + double Ele_Pt_bins[ElePtbins+1] = {5,10,20,30,40,50,80}; + //For electron fakes + + const int nEleEtabins=4; + double Ele_eta_bins[nEleEtabins+1] = {0.,0.7395,1.479,2.0,2.5}; + + //For muons fakes + + const int nMuEtabins=2; + double Mu_eta_bins[nMuEtabins+1] = {0.,1.2,2.4}; - const int nvarbins = 3; - double variable_pt_bins[nvarbins+1] = {10, 20, 30, FR_MAX_PT_}; - AddObject(passingTight2D_, ("passingTight2D_"+channelName_).c_str(), "#eta; p_{T} [GeV]", nvarbins, variable_pt_bins, 3, 0, 2.5); - AddObject(passingTight1DPt_, ("passingTight1DPt_"+channelName_).c_str(), "Tight leptons; p_{T} [GeV]", nvarbins, variable_pt_bins); - AddObject(passingTight1DEta_, ("passingTight1DEta_"+channelName_).c_str(), "Tight leptons; #eta", 3, 0, 2.5); + AddObject(passingTightE2D_, ("passingTightE2D_"+channelName_).c_str(), "|#eta|; p_{T} [GeV]", ElePtbins, Ele_Pt_bins, nEleEtabins,Ele_eta_bins); + AddObject(passingTightE1DEta_, ("passingTightE1DEta_"+channelName_).c_str(), "Tight leptons; |#eta|", nEleEtabins,Ele_eta_bins); + AddObject(passingLooseE2D_, ("passingLooseE2D_"+channelName_).c_str(), "|#eta|; p_{T} [GeV]", ElePtbins, Ele_Pt_bins, nEleEtabins,Ele_eta_bins); + AddObject(passingLooseE1DEta_, ("passingLooseE1DEta_"+channelName_).c_str(), "Loose leptons; |#eta|", nEleEtabins,Ele_eta_bins); + AddObject(passingTightE1DPt_barrel_, ("passingTightE1DPt_barrel_"+channelName_).c_str(), "Tight leptons; p_{T} [GeV]", ElePtbins, Ele_Pt_bins); + AddObject(passingTightE1DPt_endcap_, ("passingTightE1DPt_endcap_"+channelName_).c_str(), "Tight leptons; p_{T} [GeV]", ElePtbins, Ele_Pt_bins); + AddObject(passingLooseE1DPt_barrel_, ("passingLooseE1DPt_barrel_"+channelName_).c_str(), "Loose leptons; p_{T} [GeV]", ElePtbins, Ele_Pt_bins); + AddObject(passingLooseE1DPt_endcap_, ("passingLooseE1DPt_endcap_"+channelName_).c_str(), "Loose leptons; p_{T} [GeV]", ElePtbins, Ele_Pt_bins); - AddObject(passingLoose2D_, ("passingLoose2D_"+channelName_).c_str(), "#eta; p_{T} [GeV]", nvarbins, variable_pt_bins, 3, 0, 2.5); - AddObject(passingLoose1DPt_, ("passingLoose1DPt_"+channelName_).c_str(), "Loose leptons; p_{T} [GeV]", nvarbins, variable_pt_bins); - AddObject(passingLoose1DEta_, ("passingLoose1DEta_"+channelName_).c_str(), "Loose leptons; #eta", 3, 0, 2.5); + AddObject(passingTightMu2D_, ("passingTightMu2D_"+channelName_).c_str(), "|#eta|; p_{T} [GeV]", MuPtbins, Mu_Pt_bins, nMuEtabins,Mu_eta_bins); + AddObject(passingTightMu1DEta_, ("passingTightMu1DEta_"+channelName_).c_str(), "Tight leptons; |#eta|", nMuEtabins,Mu_eta_bins); + AddObject(passingLooseMu2D_, ("passingLooseMu2D_"+channelName_).c_str(), "|#eta|; p_{T} [GeV]", MuPtbins, Mu_Pt_bins, nMuEtabins,Mu_eta_bins); + AddObject(passingLooseMu1DEta_, ("passingLooseMu1DEta_"+channelName_).c_str(), "Loose leptons; |#eta|", nMuEtabins,Mu_eta_bins); + AddObject(passingTightMu1DPt_barrel_, ("passingTightMu1DPt_barrel_"+channelName_).c_str(), "Tight leptons; p_{T} [GeV]", MuPtbins, Mu_Pt_bins); + AddObject(passingTightMu1DPt_endcap_, ("passingTightMu1DPt_endcap_"+channelName_).c_str(), "Tight leptons; p_{T} [GeV]", MuPtbins, Mu_Pt_bins); + AddObject(passingLooseMu1DPt_barrel_, ("passingLooseMu1DPt_barrel_"+channelName_).c_str(), "Loose leptons; p_{T} [GeV]", MuPtbins, Mu_Pt_bins); + AddObject(passingLooseMu1DPt_endcap_, ("passingLooseMu1DPt_endcap_"+channelName_).c_str(), "Loose leptons; p_{T} [GeV]", MuPtbins, Mu_Pt_bins); + } diff --git a/src/ScaleFactor.cc b/src/ScaleFactor.cc index 1542e430..26c5c776 100644 --- a/src/ScaleFactor.cc +++ b/src/ScaleFactor.cc @@ -110,15 +110,20 @@ double ScaleFactor::Evaluate2D(double x, double y, Variation var) const } else if ( var == ShiftUp && histShiftUp2D_ != nullptr ) { auto bin = histShiftUp2D_->FindBin(x, y); - return histShiftUp2D_->GetBinContent(bin); + //Don't forget this is done only to deal with special Muon "ERROR" histogram in 2017,2018 + //If you actually have a ShiftUp histogram then this would be wrong! + return histCentral2D_->GetBinContent(bin) + histShiftUp2D_->GetBinContent(bin); } else if ( var == ShiftUp && histCentral2D_ != nullptr ) { auto bin = histCentral2D_->FindBin(x, y); return histCentral2D_->GetBinContent(bin) + histCentral2D_->GetBinError(bin); } + + //Don't forget this is done only to deal with special Muon "ERROR" histogram in 2017,2018 + //If you actually have a ShiftUp histogram then this would be wrong! else if ( var == ShiftDown && histShiftDown2D_ != nullptr ) { auto bin = histShiftDown2D_->FindBin(x, y); - return histShiftDown2D_->GetBinContent(bin); + return histCentral2D_->GetBinContent(bin) - histShiftDown2D_->GetBinContent(bin); } else if ( var == ShiftDown && histCentral2D_ != nullptr ) { auto bin = histCentral2D_->FindBin(x, y); diff --git a/src/SelectorBase.cc b/src/SelectorBase.cc index 4c81bbc7..16755db8 100644 --- a/src/SelectorBase.cc +++ b/src/SelectorBase.cc @@ -81,7 +81,7 @@ void SelectorBase::Init(TTree *tree) if (name_.find("data") == std::string::npos){ isMC_ = true; } - if (doSystematics_ && isMC_) // isNonpromptEstimate? + if (doSystematics_ && isMC_ && !isNonPrompt_) // isNonpromptEstimate? variations_.insert(systematics_.begin(), systematics_.end()); currentHistDir_ = dynamic_cast(fOutput->FindObject(name_.c_str())); @@ -134,7 +134,9 @@ void SelectorBase::LoadBranches(Long64_t entry, std::pairFindObject("histinfo"); - if (histInfo == nullptr ) - throw std::domain_error("Can't initialize histograms without passing histogram information to TSelector"); - - for (auto& label : hists1D_) { +template +void SelectorBase::InitializeHistMap(std::vector& labels, std::map& histMap) { + for (auto& label : labels) { if (channel_ != Inclusive) { auto histName = getHistName(label, "", channelName_); - histMap1D_[histName] = {}; + histMap[histName] = {}; } else { for (auto& chan : allChannels_) { auto histName = getHistName(label, "", chan); - histMap1D_[histName] = {}; + histMap[histName] = {}; } } } +} + +void SelectorBase::InitializeHistogramsFromConfig() { + TList* histInfo = (TList *) GetInputList()->FindObject("histinfo"); + if (histInfo == nullptr ) + throw std::domain_error("Can't initialize histograms without passing histogram information to TSelector"); + + InitializeHistMap(hists1D_, histMap1D_); + InitializeHistMap(weighthists1D_, weighthistMap1D_); for (auto && entry : *histInfo) { TNamed* currentHistInfo = dynamic_cast(entry); @@ -229,24 +237,31 @@ void SelectorBase::InitializeHistogramFromConfig(std::string name, std::string c if (histData.size() == 4) { AddObject(histMap1D_[histName], histName.c_str(), histData[0].c_str(),nbins, xmin, xmax); - if (doSystematics_ && std::find(systHists_.begin(), systHists_.end(), histName) != systHists_.end()) { + //std::cout<<"doSystematics: "<(histMap1D_[syst_histName], syst_histName.c_str(), histData[0].c_str(),nbins, xmin, xmax); // TODO: Cleaner way to determine if you want to store systematics for weighted entries - //if (isaQGC_ && doaQGC_ && (weighthists_.find(name) != weighthists_.end())) { + //if (isaQGC_ && doaQGC_ && (weighthistMap1D_.find(name) != weighthistMap1D_.end())) { // std::string weightsyst_histName = name+"_lheWeights_"+syst.second; - // AddObject(weighthists_[syst_histName], + // AddObject(weighthistMap1D_[syst_histName], // (weightsyst_histName+"_"+channel).c_str(), histData[0].c_str(), // nbins, xmin, xmax, 1000, 0, 1000); //} } } // Weight hists must be subset of 1D hists! - if (isMC_ && (weighthists_.find(histName) != weighthists_.end())) { - AddObject(weighthists_[histName], + //std::cout<<"size of weighthistMap1D_: "<(weighthistMap1D_[histName], (name+"_lheWeights_"+channel).c_str(), histData[0].c_str(), nbins, xmin, xmax, 1000, 0, 1000); } @@ -257,7 +272,7 @@ void SelectorBase::InitializeHistogramFromConfig(std::string name, std::string c float ymax = std::stof(histData[6]); AddObject(hists2D_[histName], histName.c_str(), histData[0].c_str(),nbins, xmin, xmax, nbinsy, ymin, ymax); - if (doSystematics_ && std::find(systHists2D_.begin(), systHists2D_.end(), histName) != systHists2D_.end()) { + if (doSystematics_ && !isNonPrompt_ && std::find(systHists2D_.begin(), systHists2D_.end(), histName) != systHists2D_.end()) { for (auto& syst : systematics_) { std::string syst_hist_name = name+"_"+syst.second + "_" + channel; hists2D_[syst_hist_name] = {}; @@ -266,8 +281,8 @@ void SelectorBase::InitializeHistogramFromConfig(std::string name, std::string c } } // 3D weight hists must be subset of 2D hists! - if (isMC_ && (weighthists2D_.find(histName) != weighthists2D_.end())) { - AddObject(weighthists2D_[histName], + if (isMC_ && !isNonPrompt_ && (weighthistMap2D_.find(histName) != weighthistMap2D_.end())) { + AddObject(weighthistMap2D_[histName], (name+"_lheWeights_"+channel).c_str(), histData[0].c_str(), nbins, xmin, xmax, nbinsy, ymin, ymax, 1000, 0, 1000); } diff --git a/src/WZSelector.cc b/src/WZSelector.cc index b782728f..4f8a71ce 100644 --- a/src/WZSelector.cc +++ b/src/WZSelector.cc @@ -602,24 +602,24 @@ void WZSelector::FillHistograms(Long64_t entry, std::pair + +void ZZBackgroundSelector::SlaveBegin(TTree * /*tree*/) +{ + //systematics_ = { + // {jetEnergyScaleUp, "CMS_scale_jUp"}, + // {jetEnergyScaleDown, "CMS_scale_jDown"}, + // {jetEnergyResolutionUp, "CMS_res_jUp"}, + // {jetEnergyResolutionDown, "CMS_res_jDown"}, + //}; + //isNonpromptEstimate_ = true; + //doaQGC_ = false; + + ZZSelector::SlaveBegin(0); + fakeRate_allE_ = (ScaleFactor *) GetInputList()->FindObject("fakeRate_allE"); + if (fakeRate_allE_ == nullptr ) Abort("Must pass electron fake rate to input list!"); + fakeRate_allMu_ = (ScaleFactor *) GetInputList()->FindObject("fakeRate_allMu"); + if (fakeRate_allMu_ == nullptr ) Abort("Must pass muon fake rate to input list!"); +} +void ZZBackgroundSelector::Init(TTree *tree) { + isNonPrompt_ = true; + ZZSelector::Init(tree); + systematics_ = {}; +} + +void ZZBackgroundSelector::SetupNewDirectory() +{ + ZZSelector::SetupNewDirectory(); + + // Insure that hist ranges are exactly the same as ZZSelector, just change name + for (const auto && obj : *currentHistDir_) { + std::string name = obj->GetName(); + TNamed* named = dynamic_cast(obj); + named->SetName(name.insert(name.length()-4, "Fakes_").c_str()); + } + AddObject(Z1MassHistPPPF_, ("Z1Mass_PPPF_"+channelName_).c_str(), "Z1Mass; m_{Z_{1}} [GeV]; Events;", 60, 0, 120); + AddObject(Z1MassHistPPFF_, ("Z1Mass_PPFF_"+channelName_).c_str(), "Z1Mass; m_{Z_{1}} [GeV]; Events;", 60, 0, 120); + + AddObject(Z2MassHistPPPF_, ("Z2Mass_PPPF_"+channelName_).c_str(), "Z2Mass; m_{Z_{2}} [GeV]; Events;", 60, 0, 120); + AddObject(Z2MassHistPPFF_, ("Z2Mass_PPFF_"+channelName_).c_str(), "Z2Mass; m_{Z_{2}} [GeV]; Events;", 60, 0, 120); + + AddObject(MassHistPPPF_, ("Mass_PPPF_"+channelName_).c_str(), "Mass; m_{4l} [GeV]; Events;", 40, 70, 870); + AddObject(MassHistPPFF_, ("Mass_PPFF_"+channelName_).c_str(), "Mass; m_{4l} [GeV]; Events;", 40, 70, 870); + + AddObject(WeightsHistmmee_, ("Weights_mmee_"+channelName_).c_str(), "Weight; Event Weight; Events;", 10, -5, 5); + AddObject(WeightsHisteemm_, ("Weights_eemm_"+channelName_).c_str(), "Weight; Event Weight; Events;", 100, -5, 5); +} +float ZZBackgroundSelector::getEventWeight(Long64_t entry) { + float evtwgt = 0; + + if(channel_ == mmee && (e1e2IsZ1(entry))) + WeightsHistmmee_->Fill(1,weight); + + if(channel_ == eemm && !(e1e2IsZ1(entry))) + WeightsHisteemm_->Fill(1,weight); + + //if ((channel_ == eeee) || (channel_ == mmmm)){ + //} + //in eemm the e1e2IsZ1 function already sets the correct Z1,Z2 leptons and even the IDs from LoadBranches + //So only need to take care which is l3 and l4 + // if ((channel_ == eemm) || (channel_ == mmee)){ + // if(Z2FP()){ + // float templ3Pt = l3Pt; + // l3Pt = l4Pt; + // l4Pt = templ3Pt; + // float templ3Eta = l3Eta; + // l3Eta = l4Eta; + // l4Eta = templ3Eta; + // } + // } + //std::cout<<"Weight in Bkg Seletor getEventWeight function: "<Fill(Z1mass, weight); + Z2MassHistPPPF_->Fill(Z2mass, weight); + MassHistPPPF_->Fill(Mass,weight); + } + evtwgt = (getl4FakeRate(entry)*weight); + //WeightsHistPPPF_->Fill(1,evtwgt); + } + if (IsPPFFRegion()) { + if (true) { + //std::cout<<"Weight in PPFF: "<Fill(Z1mass, weight); + Z2MassHistPPFF_->Fill(Z2mass, weight); + MassHistPPFF_->Fill(Mass,weight); + } + evtwgt = ((-1*getl3FakeRate(entry)*getl4FakeRate(entry))*weight); + //evtwgt = ((getl3FakeRate(entry)*getl4FakeRate(entry))*weight); + //WeightsHistPPFF_->Fill(1,evtwgt); + } + //std::cout<<"eventWeight after Fake Rate: "< variation) { + ZZSelector::LoadBranchesUWVV(entry, variation); + SetZ1Z2Masses(); + if (!ZZSelection()){ + return;} + //std::cout<<"isNonPrompt_ from ZZSelector: "<Evaluate2D(pt_fillval, std::abs(l3Eta)); + //fr = 0.03;//avg e fake rate + //std::cout<<"channel: "<Evaluate2D(pt_fillval, std::abs(l3Eta)); + //fr = 0.1;//avg mu fake rate + //std::cout<<"channel: "<Evaluate2D(pt_fillval, std::abs(l4Eta)); + //fr = 0.03;//avg e fake rate + //std::cout<<"channel: "<Evaluate2D(pt_fillval, std::abs(l4Eta)); + //fr = 0.1;//avg mu fake rate + //std::cout<<"channel: "< l3 + float templ1Pt = l1Pt; + l1Pt = l3Pt; + l3Pt = templ1Pt; + float templ1Eta = l1Eta; + l1Eta = l3Eta; + l3Eta = templ1Eta;} + else{ + } + } + else if(Z1PF() && Z2FP()){ + //Make sure I am not making a Z in eemm with an e and mu! + if ((channel_ == eeee) || (channel_ == mmmm)){ + Z1mass = (lepton1+lepton4).M(); + Z2mass = (lepton2+lepton3).M(); + Z1pt = (lepton1+lepton4).Pt(); + Z2pt = (lepton2+lepton3).Pt(); + //Here the two fakes are l2,l3 and we only need to relabel l2 -> l4 since this only matters in PPFF region so l3,l4 are interchangeable + float templ2Pt = l2Pt; + l2Pt = l4Pt; + l4Pt = templ2Pt; + float templ2Eta = l2Eta; + l2Eta = l4Eta; + l4Eta = templ2Eta; + } + else{ + } + } +} + diff --git a/src/ZZGenSelector.cc b/src/ZZGenSelector.cc index 0bbc3137..e6e9612b 100644 --- a/src/ZZGenSelector.cc +++ b/src/ZZGenSelector.cc @@ -6,40 +6,16 @@ void ZZGenSelector::Init(TTree *tree) { allChannels_ = {"ee", "mm", }; hists1D_ = { - "GenZ2lep2_Phi", - "GenZ2lep2_Pt", "GenMass", - "Pt", - "nJets", - "nJetCSVv2T", "Genyield", "GenZMass", - "GenZ1Mass", - "GenZ2Mass", "GenZZPt", "GenZZEta", - "GenZ1Pt", - "GenZ2Pt", "GenZPt", - "GenZ1Phi", - "GenZ2Phi", "GendPhiZ1Z2", + "GendRZ1Z2", "GenLepPt", "GenLepEta", - "GenLep12Pt", - "GenLep12Eta", - "GenLep34Pt", - "GenLep34Eta", - "GenZ1lep1_Eta", - "GenZ1lep1_Phi", - "GenZ1lep1_Pt", - "GenZ1lep2_Eta", - "GenZ1lep2_Phi", - "GenZ1lep2_Pt", - "GenZ2lep1_Eta", - "GenZ2lep1_Phi", - "GenZ2lep1_Pt", - "GenZ2lep2_Eta", }; //hists2D_ = {"GenZ1Mass_GenZ2Mass"}; @@ -49,6 +25,7 @@ void ZZGenSelector::Init(TTree *tree) void ZZGenSelector::LoadBranchesUWVV(Long64_t entry, std::pair variation) { Genweight = 1; + b_genWeight->GetEntry(entry); b_Genl1Pt->GetEntry(entry); b_Genl2Pt->GetEntry(entry); b_Genl3Pt->GetEntry(entry); @@ -66,10 +43,14 @@ void ZZGenSelector::LoadBranchesUWVV(Long64_t entry, std::pairGetEntry(entry); b_GenZ2pt->GetEntry(entry); b_GenZ2Phi->GetEntry(entry); + b_GenZ1Eta->GetEntry(entry); + b_GenZ2Eta->GetEntry(entry); } b_GenZ1mass->GetEntry(entry); b_GenZ1pt->GetEntry(entry); b_GenZ1Phi->GetEntry(entry); + //std::cout<<"Genweight before: "< variation) { @@ -107,6 +94,9 @@ void ZZGenSelector::SetBranchesNanoAOD() { } void ZZGenSelector::SetBranchesUWVV() { + if (isMC_){ + fChain->SetBranchAddress("genWeight", &genWeight, &b_genWeight); + } if (channel_ == eeee) { //std::cout<<"enum channel_: "<SetBranchAddress("e1_e2_Mass", &GenZ1mass, &b_GenZ1mass); @@ -115,6 +105,8 @@ void ZZGenSelector::SetBranchesUWVV() { fChain->SetBranchAddress("e3_e4_Pt", &GenZ2pt, &b_GenZ2pt); fChain->SetBranchAddress("e1_e2_Phi", &GenZ1Phi, &b_GenZ1Phi); fChain->SetBranchAddress("e3_e4_Phi", &GenZ2Phi, &b_GenZ2Phi); + fChain->SetBranchAddress("e1_e2_Eta", &GenZ1Eta, &b_GenZ1Eta); + fChain->SetBranchAddress("e3_e4_Eta", &GenZ2Eta, &b_GenZ2Eta); fChain->SetBranchAddress("e1Pt", &Genl1Pt, &b_Genl1Pt); fChain->SetBranchAddress("e2Pt", &Genl2Pt, &b_Genl2Pt); fChain->SetBranchAddress("e3Pt", &Genl3Pt, &b_Genl3Pt); @@ -137,6 +129,8 @@ void ZZGenSelector::SetBranchesUWVV() { fChain->SetBranchAddress("m1_m2_Pt", &GenZ2pt, &b_GenZ2pt); fChain->SetBranchAddress("e1_e2_Phi", &GenZ1Phi, &b_GenZ1Phi); fChain->SetBranchAddress("m1_m2_Phi", &GenZ2Phi, &b_GenZ2Phi); + fChain->SetBranchAddress("e1_e2_Eta", &GenZ1Eta, &b_GenZ1Eta); + fChain->SetBranchAddress("m1_m2_Eta", &GenZ2Eta, &b_GenZ2Eta); fChain->SetBranchAddress("e1Pt", &Genl1Pt, &b_Genl1Pt); fChain->SetBranchAddress("e2Pt", &Genl2Pt, &b_Genl2Pt); fChain->SetBranchAddress("m1Pt", &Genl3Pt, &b_Genl3Pt); @@ -157,6 +151,8 @@ void ZZGenSelector::SetBranchesUWVV() { fChain->SetBranchAddress("m1_m2_Pt", &GenZ2pt, &b_GenZ2pt); fChain->SetBranchAddress("e1_e2_Phi", &GenZ1Phi, &b_GenZ1Phi); fChain->SetBranchAddress("m1_m2_Phi", &GenZ2Phi, &b_GenZ2Phi); + fChain->SetBranchAddress("e1_e2_Eta", &GenZ1Eta, &b_GenZ1Eta); + fChain->SetBranchAddress("m1_m2_Eta", &GenZ2Eta, &b_GenZ2Eta); fChain->SetBranchAddress("e1Pt", &Genl1Pt, &b_Genl1Pt); fChain->SetBranchAddress("e2Pt", &Genl2Pt, &b_Genl2Pt); fChain->SetBranchAddress("m1Pt", &Genl3Pt, &b_Genl3Pt); @@ -177,6 +173,8 @@ void ZZGenSelector::SetBranchesUWVV() { fChain->SetBranchAddress("m3_m4_Pt", &GenZ2pt, &b_GenZ2pt); fChain->SetBranchAddress("m1_m2_Phi", &GenZ1Phi, &b_GenZ1Phi); fChain->SetBranchAddress("m3_m4_Phi", &GenZ2Phi, &b_GenZ2Phi); + fChain->SetBranchAddress("m1_m2_Eta", &GenZ1Eta, &b_GenZ1Eta); + fChain->SetBranchAddress("m3_m4_Eta", &GenZ2Eta, &b_GenZ2Eta); fChain->SetBranchAddress("m1Pt", &Genl1Pt, &b_Genl1Pt); fChain->SetBranchAddress("m2Pt", &Genl2Pt, &b_Genl2Pt); fChain->SetBranchAddress("m3Pt", &Genl3Pt, &b_Genl3Pt); @@ -257,6 +255,12 @@ void ZZGenSelector::FillHistograms(Long64_t entry, std::pair + +void ZZSelector::Init(TTree *tree) +{ + systematics_ = { + {electronRecoEffUp,"CMS_RecoEff_eUp"}, + {electronRecoEffDown,"CMS_RecoEff_eDown"}, + {electronEfficiencyUp, "CMS_eff_eUp"}, + {electronEfficiencyDown, "CMS_eff_eDown"}, + {muonEfficiencyUp, "CMS_eff_mUp"}, + {muonEfficiencyDown, "CMS_eff_mDown"}, + {pileupUp, "CMS_pileupUp"}, + {pileupDown, "CMS_pileupDown"}, + }; + doSystematics_ = true; + + //This would be set true inside ZZBackground Selector + //isNonPrompt_ = false; + + systHists_ = { + "yield", + "Mass", + "ZMass", + "ZZPt", + "ZZEta", + "dPhiZ1Z2", + "dRZ1Z2", + "ZPt", + "LepPt", + "LepEta" + }; + //hists1D_ = { + // "yield", "backgroundControlYield","nTruePU","nvtx","ZMass","Z1Mass","Z2Mass","ZZPt", + // "Z1Pt","Z2Pt","Z1Phi","Z2Phi","dPhiZ1Z2","ZPt","LepPt","LepEta","Lep12Pt","Lep12Eta", + // "Lep34Pt","Lep34Eta","Z1lep1_Eta","Z1lep1_Phi","Z1lep1_Pt","Z1lep1_PdgId","Z1lep2_Eta", + // "Z1lep2_Phi","Z1lep2_Pt","Z1lep2_PdgId","Z2lep1_Eta","Z2lep1_Phi","Z2lep1_Pt","Z2lep1_PdgId", + // "Z2lep2_Eta","Z2lep2_Phi","Z2lep2_Pt","Z2lep2_PdgId","Mass","nJets", + //}; + + hists1D_ = { + "yield", "ZMass","ZZPt","ZZEta","dPhiZ1Z2","dRZ1Z2","ZPt","LepPt","LepEta", + "Mass","nJets","jetPt[0]","jetPt[1]","jetEta[0]","jetEta[1]","mjj","dEtajj","SIP3D" + }; + + weighthists1D_ = { + "yield", + "Mass", + "ZMass", + "ZZPt", + "ZZEta", + "dPhiZ1Z2", + "dRZ1Z2", + "ZPt", + "LepPt", + "LepEta" + }; + ZZSelectorBase::Init(tree); +} + +void ZZSelector::SetBranchesUWVV() { + ZZSelectorBase::SetBranchesUWVV(); + if (isMC_) { + weight_info_ = GetLheWeightInfo(); + if (weight_info_ > 0) + fChain->SetBranchAddress("scaleWeights", &scaleWeights, &b_scaleWeights); + if ((weight_info_ == 2 || weight_info_ == 3) && doSystematics_ && !isNonPrompt_) + fChain->SetBranchAddress("pdfWeights", &pdfWeights, &b_pdfWeights); + } + fChain->SetBranchAddress("Mass", &Mass, &b_Mass); + fChain->SetBranchAddress("Pt", &Pt, &b_Pt); + fChain->SetBranchAddress("Eta", &Eta, &b_Eta); + fChain->SetBranchAddress("jetPt", &jetPt, &b_jetPt); + fChain->SetBranchAddress("jetEta", &jetEta, &b_jetEta); + fChain->SetBranchAddress("mjj", &mjj, &b_mjj); +} + +unsigned int ZZSelector::GetLheWeightInfo() { + std::vector noLheWeights = { + "ggZZ2e2mu", "ggZZ4e", "ggZZ4m", "ggZZ4t", "ggZZ2e2tau","ggZZ2mu2tau","zz4l-sherpa","ZZJJTo2e2mu-EWK-phantom","ZZJJTo4e-EWK-phantom","ZZJJTo4mu-EWK-phantom" + }; + std::vector scaleAndPdfWeights = { + "wz3lnu-powheg", "wz3lnu-mg5amcnlo", + "ZZZ", "WZZ", "WWZ", + "zz4l-powheg", "zz4l-amcatnlo", + "ZZJJTo4L-EWK" + }; + std::vector allLheWeights = { + //"wzjj-aqgcft", "wzjj-aqgcfm", "wzjj-aqgcfs", + //"wz-atgc_pt0-200", "wz-atgc_pt200-300", + //"wz-atgc_pt300" + }; + + if ((std::find(noLheWeights.begin(), noLheWeights.end(), name_) != noLheWeights.end()) || (isaTGC_)) + return 0; + if (std::find(scaleAndPdfWeights.begin(), scaleAndPdfWeights.end(), name_) != scaleAndPdfWeights.end()) + return 2; + if (std::find(allLheWeights.begin(), allLheWeights.end(), name_) != allLheWeights.end()) + return 3; + return 1; +} +void ZZSelector::LoadBranchesUWVV(Long64_t entry, std::pair variation) { + + ZZSelectorBase::LoadBranchesUWVV(entry, variation); + + //b_MtToMET->GetEntry(entry); + //b_l1Pt->GetEntry(entry); + //b_l2Pt->GetEntry(entry); + //b_l3Pt->GetEntry(entry); + b_Mass->GetEntry(entry); + b_Pt->GetEntry(entry); + b_Eta->GetEntry(entry); + b_jetPt->GetEntry(entry); + b_jetEta->GetEntry(entry); + b_mjj->GetEntry(entry); + //std::cout<<"channel in LoadBranches function: "< 0) { + b_scaleWeights->GetEntry(entry); + lheWeights = *scaleWeights; + if (weight_info_ == 2) { + b_pdfWeights->GetEntry(entry); + // Only keep NNPDF weights + lheWeights.insert(lheWeights.end(), pdfWeights->begin(), + pdfWeights->begin()+std::min(static_cast(103), pdfWeights->size())); + } + else if (weight_info_ == 3) { + b_pdfWeights->GetEntry(entry); + lheWeights.insert(lheWeights.end(), pdfWeights->begin(), pdfWeights->end()); + } + } + } + } + else if (isMC_) { + //Systematic uncertainties and creating shiftUp and shiftDown histograms + //Starting with lepton Efficiencies + if (variation.first == electronEfficiencyUp || variation.first == electronEfficiencyDown || variation.first == electronRecoEffUp || variation.first == electronRecoEffDown || + variation.first == muonEfficiencyUp || variation.first == muonEfficiencyDown) { + ShiftEfficiencies(variation.first); + } + else if (variation.first == pileupUp) { + weight *= pileupSF_->Evaluate1D(nTruePU, ScaleFactor::ShiftUp)/pileupSF_->Evaluate1D(nTruePU); + } + else if (variation.first == pileupDown) { + weight *= pileupSF_->Evaluate1D(nTruePU, ScaleFactor::ShiftDown)/pileupSF_->Evaluate1D(nTruePU); + } + } + + auto deltaPhiZZ = [](float phi1, float phi2) { + float pi = TMath::Pi(); + float dphi = fabs(phi1-phi2); + if(dphi>pi) + dphi = 2.0*pi - dphi; + return dphi; + }; + auto deltaEtajj = [](std::vector* jEta) { + if (jEta->size() < 2) + return -1.; + double etaDiff = jEta->at(0) - jEta->at(1); + return std::abs(etaDiff); + }; + + auto deltaRZZ = [](float eta1, float eta2, float dPhi) { + float dEta = eta1 - eta2; + return std::sqrt(dPhi * dPhi + dEta * dEta); + }; + + dEtajj = deltaEtajj(jetEta); + dPhiZZ = deltaPhiZZ(Z1Phi,Z2Phi); + dRZZ = deltaRZZ(Z1Eta,Z2Eta,dPhiZZ); +} + +void ZZSelector::ApplyScaleFactors() { + //In order to get around the Overflow issue, set the Pt, not ideal. + //std::cout<<"weight before SF: "<Evaluate2D(std::abs(l1Eta), pt_e1); + //std::cout<<"weight for GapE: "<Evaluate2D(std::abs(l1Eta), pt_e1); + } + if(l2IsGap){ + weight *= eGapIdSF_->Evaluate2D(std::abs(l2Eta), pt_e2); + } + else{ + weight *= eIdSF_->Evaluate2D(std::abs(l2Eta), pt_e2); + } + if(l3IsGap){ + weight *= eGapIdSF_->Evaluate2D(std::abs(l3Eta), pt_e3); + } + else{ + weight *= eIdSF_->Evaluate2D(std::abs(l3Eta), pt_e3); + } + if(l4IsGap){ + weight *= eGapIdSF_->Evaluate2D(std::abs(l4Eta), pt_e4); + } + else{ + weight *= eIdSF_->Evaluate2D(std::abs(l4Eta), pt_e4); + } + } + if (eRecoSF_ != nullptr and eLowRecoSF_ != nullptr ) { + //Applying Electron Reco SFs + if(l1Pt < 20){ + weight *= eLowRecoSF_->Evaluate2D(std::abs(l1Eta), l1Pt); + } + else{ + weight *= eRecoSF_->Evaluate2D(std::abs(l1Eta), pt_e1); + } + if(l2Pt < 20){ + weight *= eLowRecoSF_->Evaluate2D(std::abs(l2Eta), l2Pt); + } + else{ + weight *= eRecoSF_->Evaluate2D(std::abs(l2Eta), pt_e2); + } + if(l3Pt < 20){ + weight *= eLowRecoSF_->Evaluate2D(std::abs(l3Eta), l3Pt); + } + else{ + weight *= eRecoSF_->Evaluate2D(std::abs(l3Eta), pt_e3); + } + if(l4Pt < 20){ + weight *= eLowRecoSF_->Evaluate2D(std::abs(l4Eta), l4Pt); + } + else{ + weight *= eRecoSF_->Evaluate2D(std::abs(l4Eta), pt_e4); + } + } + } + else if (channel_ == eemm) { + float pt_e1 = l1Pt < EleSF_MAX_PT_ ? l1Pt : EleSF_MAX_PT_ - 0.01; + float pt_e2 = l2Pt < EleSF_MAX_PT_ ? l2Pt : EleSF_MAX_PT_ - 0.01; + float pt_m3 = l3Pt < MuSF_MAX_PT_ ? l3Pt : MuSF_MAX_PT_ - 0.01; + float pt_m4 = l4Pt < MuSF_MAX_PT_ ? l4Pt : MuSF_MAX_PT_ - 0.01; + if (eIdSF_ != nullptr and eGapIdSF_ != nullptr ) { + //In order to get around the Overflow issue, set the Pt, not ideal. + if(l1IsGap){ + weight *= eGapIdSF_->Evaluate2D(std::abs(l1Eta), pt_e1); + } + else{ + weight *= eIdSF_->Evaluate2D(std::abs(l1Eta), pt_e1); + } + if(l2IsGap){ + weight *= eGapIdSF_->Evaluate2D(std::abs(l2Eta), pt_e2); + } + else{ + weight *= eIdSF_->Evaluate2D(std::abs(l2Eta), pt_e2); + } + } + //Applying Electron Reco SFs + if (eRecoSF_ != nullptr and eLowRecoSF_ != nullptr ) { + if(l1Pt < 20){ + weight *= eLowRecoSF_->Evaluate2D(std::abs(l1Eta), l1Pt); + } + else{ + weight *= eRecoSF_->Evaluate2D(std::abs(l1Eta), pt_e1); + } + if(l2Pt < 20){ + weight *= eLowRecoSF_->Evaluate2D(std::abs(l2Eta), l2Pt); + } + else{ + weight *= eRecoSF_->Evaluate2D(std::abs(l2Eta), pt_e2); + } + } + if (mIdSF_ != nullptr) { + weight *= mIdSF_->Evaluate2D(std::abs(l3Eta), pt_m3); + weight *= mIdSF_->Evaluate2D(std::abs(l4Eta), pt_m4); + } + } + else if (channel_ == mmee) { + float pt_m1 = l1Pt < MuSF_MAX_PT_ ? l1Pt : MuSF_MAX_PT_ - 0.01; + float pt_m2 = l2Pt < MuSF_MAX_PT_ ? l2Pt : MuSF_MAX_PT_ - 0.01; + float pt_e3 = l3Pt < EleSF_MAX_PT_ ? l3Pt : EleSF_MAX_PT_ - 0.01; + float pt_e4 = l4Pt < EleSF_MAX_PT_ ? l4Pt : EleSF_MAX_PT_ - 0.01; + if (mIdSF_ != nullptr) { + weight *= mIdSF_->Evaluate2D(std::abs(l1Eta), pt_m1); + weight *= mIdSF_->Evaluate2D(std::abs(l2Eta), pt_m2); + } + if (eIdSF_ != nullptr and eGapIdSF_ != nullptr ) { + if(l3IsGap){ + weight *= eGapIdSF_->Evaluate2D(std::abs(l3Eta), pt_e3); + } + else{ + weight *= eIdSF_->Evaluate2D(std::abs(l3Eta), pt_e3); + } + if(l4IsGap){ + weight *= eGapIdSF_->Evaluate2D(std::abs(l4Eta), pt_e4); + } + else{ + weight *= eIdSF_->Evaluate2D(std::abs(l4Eta), pt_e4); + } + } + //Applying Electron Reco SFs + if (eRecoSF_ != nullptr and eLowRecoSF_ != nullptr ) { + if(l3Pt < 20){ + weight *= eLowRecoSF_->Evaluate2D(std::abs(l3Eta), l3Pt); + } + else{ + weight *= eRecoSF_->Evaluate2D(std::abs(l3Eta), pt_e3); + } + if(l4Pt < 20){ + weight *= eLowRecoSF_->Evaluate2D(std::abs(l4Eta), l4Pt); + } + else{ + weight *= eRecoSF_->Evaluate2D(std::abs(l4Eta), pt_e4); + } + } + } + else { + float pt_m1 = l1Pt < MuSF_MAX_PT_ ? l1Pt : MuSF_MAX_PT_ - 0.01; + float pt_m2 = l2Pt < MuSF_MAX_PT_ ? l2Pt : MuSF_MAX_PT_ - 0.01; + float pt_m3 = l3Pt < MuSF_MAX_PT_ ? l3Pt : MuSF_MAX_PT_ - 0.01; + float pt_m4 = l4Pt < MuSF_MAX_PT_ ? l4Pt : MuSF_MAX_PT_ - 0.01; + if (mIdSF_ != nullptr) { + weight *= mIdSF_->Evaluate2D(std::abs(l1Eta), pt_m1); + weight *= mIdSF_->Evaluate2D(std::abs(l2Eta), pt_m2); + weight *= mIdSF_->Evaluate2D(std::abs(l3Eta), pt_m3); + weight *= mIdSF_->Evaluate2D(std::abs(l4Eta), pt_m4); + } + } + if (pileupSF_ != nullptr) { + weight *= pileupSF_->Evaluate1D(nTruePU); + } +} +//Similar to Kenneth's SetShiftedMasses function which i will need later as well +void ZZSelector::SetVariables(Long64_t entry) { + if(!(e1e2IsZ1(entry))){ + //std::cout<<"e1e2IsZ1 is working"<Evaluate2D(std::abs(l1Eta), l1Pt,shift)/eLowRecoSF_->Evaluate2D(std::abs(l1Eta), l1Pt); + } + else{ + weight *= eRecoSF_->Evaluate2D(std::abs(l1Eta), pt_e1,shift)/eRecoSF_->Evaluate2D(std::abs(l1Eta), pt_e1); + } + if(l2Pt < 20){ + weight *= eLowRecoSF_->Evaluate2D(std::abs(l2Eta), l2Pt,shift)/eLowRecoSF_->Evaluate2D(std::abs(l2Eta), l2Pt); + } + else{ + weight *= eRecoSF_->Evaluate2D(std::abs(l2Eta), pt_e2,shift)/eRecoSF_->Evaluate2D(std::abs(l2Eta), pt_e2); + } + if(l3Pt < 20){ + weight *= eLowRecoSF_->Evaluate2D(std::abs(l3Eta), l3Pt,shift)/eLowRecoSF_->Evaluate2D(std::abs(l3Eta), l3Pt); + } + else{ + weight *= eRecoSF_->Evaluate2D(std::abs(l3Eta), pt_e3,shift)/eRecoSF_->Evaluate2D(std::abs(l3Eta), pt_e3) ; + } + if(l4Pt < 20){ + weight *= eLowRecoSF_->Evaluate2D(std::abs(l4Eta), l4Pt,shift)/eLowRecoSF_->Evaluate2D(std::abs(l4Eta), l4Pt); + } + else{ + weight *= eRecoSF_->Evaluate2D(std::abs(l4Eta), pt_e4,shift)/eRecoSF_->Evaluate2D(std::abs(l4Eta), pt_e4); + } + } + } + //Applying Electron ID SFs Up/Down for ElectronIDEffSyst + else if (variation == electronEfficiencyUp || variation == electronEfficiencyDown) { + if (eIdSF_ != nullptr and eGapIdSF_ != nullptr ) { + if(l1IsGap){ + weight *= eGapIdSF_->Evaluate2D(std::abs(l1Eta), pt_e1, shift)/eGapIdSF_->Evaluate2D(std::abs(l1Eta), pt_e1); + } + else{ + weight *= eIdSF_->Evaluate2D(std::abs(l1Eta), pt_e1, shift)/eIdSF_->Evaluate2D(std::abs(l1Eta), pt_e1); + } + if(l2IsGap){ + weight *= eGapIdSF_->Evaluate2D(std::abs(l2Eta), pt_e2, shift)/eGapIdSF_->Evaluate2D(std::abs(l2Eta), pt_e2); + } + else{ + weight *= eIdSF_->Evaluate2D(std::abs(l2Eta), pt_e2, shift)/eIdSF_->Evaluate2D(std::abs(l2Eta), pt_e2); + } + if(l3IsGap){ + weight *= eGapIdSF_->Evaluate2D(std::abs(l3Eta), pt_e3, shift)/eGapIdSF_->Evaluate2D(std::abs(l3Eta), pt_e3); + } + else{ + weight *= eIdSF_->Evaluate2D(std::abs(l3Eta), pt_e3, shift)/eIdSF_->Evaluate2D(std::abs(l3Eta), pt_e3); + } + if(l4IsGap){ + weight *= eGapIdSF_->Evaluate2D(std::abs(l4Eta), pt_e4, shift)/eGapIdSF_->Evaluate2D(std::abs(l4Eta), pt_e4); + } + else{ + weight *= eIdSF_->Evaluate2D(std::abs(l4Eta), pt_e4, shift)/eIdSF_->Evaluate2D(std::abs(l4Eta), pt_e4); + } + } + } + }//channel eeee + else if (channel_ == eemm) { + //In order to get around the Overflow issue, set the Pt, not ideal. + float pt_e1 = l1Pt < EleSF_MAX_PT_ ? l1Pt : EleSF_MAX_PT_ - 0.01; + float pt_e2 = l2Pt < EleSF_MAX_PT_ ? l2Pt : EleSF_MAX_PT_ - 0.01; + float pt_m3 = l3Pt < MuSF_MAX_PT_ ? l3Pt : MuSF_MAX_PT_ - 0.01; + float pt_m4 = l4Pt < MuSF_MAX_PT_ ? l4Pt : MuSF_MAX_PT_ - 0.01; + if (variation == electronRecoEffUp || variation == electronRecoEffDown) { + //Applying Electron Reco SFs Up/Down for ElectronRecoEffSyst + if(l1Pt < 20){ + weight *= eLowRecoSF_->Evaluate2D(std::abs(l1Eta), l1Pt,shift)/eLowRecoSF_->Evaluate2D(std::abs(l1Eta), l1Pt); + } + else{ + weight *= eRecoSF_->Evaluate2D(std::abs(l1Eta), pt_e1,shift)/eRecoSF_->Evaluate2D(std::abs(l1Eta), pt_e1); + } + if(l2Pt < 20){ + weight *= eLowRecoSF_->Evaluate2D(std::abs(l2Eta), l2Pt,shift)/eLowRecoSF_->Evaluate2D(std::abs(l2Eta), l2Pt); + } + else{ + weight *= eRecoSF_->Evaluate2D(std::abs(l2Eta), pt_e2,shift)/eRecoSF_->Evaluate2D(std::abs(l2Eta), pt_e2); + } + } + //Applying Electron ID SFs Up/Down for ElectronIDEffSyst + else if (variation == electronEfficiencyUp || variation == electronEfficiencyDown) { + if(l1IsGap){ + weight *= eGapIdSF_->Evaluate2D(std::abs(l1Eta), pt_e1, shift)/eGapIdSF_->Evaluate2D(std::abs(l1Eta), pt_e1); + } + else{ + weight *= eIdSF_->Evaluate2D(std::abs(l1Eta), pt_e1, shift)/eIdSF_->Evaluate2D(std::abs(l1Eta), pt_e1); + } + if(l2IsGap){ + weight *= eGapIdSF_->Evaluate2D(std::abs(l2Eta), pt_e2, shift)/eGapIdSF_->Evaluate2D(std::abs(l2Eta), pt_e2); + } + else{ + weight *= eIdSF_->Evaluate2D(std::abs(l2Eta), pt_e2, shift)/eIdSF_->Evaluate2D(std::abs(l2Eta), pt_e2); + } + } + else if (variation == muonEfficiencyUp || variation == muonEfficiencyDown) { + weight *= mIdSF_->Evaluate2D(std::abs(l3Eta), pt_m3, shift)/mIdSF_->Evaluate2D(std::abs(l3Eta), pt_m3); + weight *= mIdSF_->Evaluate2D(std::abs(l4Eta), pt_m4, shift)/mIdSF_->Evaluate2D(std::abs(l4Eta), pt_m4); + } + } + else if (channel_ == mmee) { + float pt_m1 = l1Pt < MuSF_MAX_PT_ ? l1Pt : MuSF_MAX_PT_ - 0.01; + float pt_m2 = l2Pt < MuSF_MAX_PT_ ? l2Pt : MuSF_MAX_PT_ - 0.01; + float pt_e3 = l3Pt < EleSF_MAX_PT_ ? l3Pt : EleSF_MAX_PT_ - 0.01; + float pt_e4 = l4Pt < EleSF_MAX_PT_ ? l4Pt : EleSF_MAX_PT_ - 0.01; + if (variation == muonEfficiencyUp || variation == muonEfficiencyDown) { + weight *= mIdSF_->Evaluate2D(std::abs(l1Eta), pt_m1, shift)/mIdSF_->Evaluate2D(std::abs(l1Eta), pt_m1); + weight *= mIdSF_->Evaluate2D(std::abs(l2Eta), pt_m2, shift)/mIdSF_->Evaluate2D(std::abs(l2Eta), pt_m2); + } + else if (variation == electronRecoEffUp || variation == electronRecoEffDown) { + //Applying Electron Reco SFs Up/Down for ElectronRecoEffSyst + if(l3Pt < 20){ + weight *= eLowRecoSF_->Evaluate2D(std::abs(l3Eta), l3Pt,shift)/eLowRecoSF_->Evaluate2D(std::abs(l3Eta), l3Pt); + } + else{ + weight *= eRecoSF_->Evaluate2D(std::abs(l3Eta), pt_e3,shift)/eRecoSF_->Evaluate2D(std::abs(l3Eta), pt_e3) ; + } + if(l4Pt < 20){ + weight *= eLowRecoSF_->Evaluate2D(std::abs(l4Eta), l4Pt,shift)/eLowRecoSF_->Evaluate2D(std::abs(l4Eta), l4Pt); + } + else{ + weight *= eRecoSF_->Evaluate2D(std::abs(l4Eta), pt_e4,shift)/eRecoSF_->Evaluate2D(std::abs(l4Eta), pt_e4); + } + } + //Applying Electron ID SFs Up/Down for ElectronIDEffSyst + else if (variation == electronEfficiencyUp || variation == electronEfficiencyDown) { + if(l3IsGap){ + weight *= eGapIdSF_->Evaluate2D(std::abs(l3Eta), pt_e3, shift)/eGapIdSF_->Evaluate2D(std::abs(l3Eta), pt_e3); + } + else{ + weight *= eIdSF_->Evaluate2D(std::abs(l3Eta), pt_e3, shift)/eIdSF_->Evaluate2D(std::abs(l3Eta), pt_e3); + } + if(l4IsGap){ + weight *= eGapIdSF_->Evaluate2D(std::abs(l4Eta), pt_e4, shift)/eGapIdSF_->Evaluate2D(std::abs(l4Eta), pt_e4); + } + else{ + weight *= eIdSF_->Evaluate2D(std::abs(l4Eta), pt_e4, shift)/eIdSF_->Evaluate2D(std::abs(l4Eta), pt_e4); + } + } + } + else if (channel_ == mmmm && (variation == muonEfficiencyUp || variation == muonEfficiencyDown)) { + float pt_m1 = l1Pt < MuSF_MAX_PT_ ? l1Pt : MuSF_MAX_PT_ - 0.01; + float pt_m2 = l2Pt < MuSF_MAX_PT_ ? l2Pt : MuSF_MAX_PT_ - 0.01; + float pt_m3 = l3Pt < MuSF_MAX_PT_ ? l3Pt : MuSF_MAX_PT_ - 0.01; + float pt_m4 = l4Pt < MuSF_MAX_PT_ ? l4Pt : MuSF_MAX_PT_ - 0.01; + weight *= mIdSF_->Evaluate2D(std::abs(l1Eta), pt_m1, shift)/mIdSF_->Evaluate2D(std::abs(l1Eta), pt_m1); + //std::cout<<"l1 Shift: "<< mIdSF_->Evaluate2D(std::abs(l1Eta), pt_m1, shift)<Evaluate2D(std::abs(l1Eta), pt_m1)<Evaluate2D(std::abs(l2Eta), pt_m2, shift)/mIdSF_->Evaluate2D(std::abs(l2Eta), pt_m2); + weight *= mIdSF_->Evaluate2D(std::abs(l3Eta), pt_m3, shift)/mIdSF_->Evaluate2D(std::abs(l3Eta), pt_m3); + //std::cout<<"l3 Shift: "<< mIdSF_->Evaluate2D(std::abs(l3Eta), pt_m3, shift)<Evaluate2D(std::abs(l3Eta), pt_m3)<Evaluate2D(std::abs(l4Eta), pt_m4, shift)/mIdSF_->Evaluate2D(std::abs(l4Eta), pt_m4); + } +} + +bool ZZSelector::PassesZZjjSelection() { + if ((jetPt->size() != jetEta->size() || jetPt->size() < 2) || (mjj < 100)) + return false; + else + return true; +} +bool ZZSelector::PassesZZSelection(bool nonPrompt){ + //This nonPrompt boolean is for ZZBackgroundSelector + //When running ZZBackgroundSelector, FillHistograms should run just with ZZSelection, we cannot require TightZZLeptons by definition + if (nonPrompt){ + //Because we are using Cut Based Moriond ID for Muons, we need SIP cut for 2016,2017 + if (year_ == yr2016 || year_ == yr2017){ + if (ZZSelection() && HZZSIPSelection()) + return true; + else + return false; + } + else{ + if (ZZSelection()) + return true; + else + return false; + } + } + else{ + //std::cout<<"nonPrompt inside function: "< 60.0 && Z1mass < 120.0) && (Z2mass > 60.0 && Z2mass < 120.0)) + return true; + else + return false; +} + +//We already require 4 < Z1,Z2 < 120 in the "Loose Skim" +bool ZZSelector::ZSelection() { + if (Z1mass > 40.0 && Z2mass > 12.0) + return true; + else + return false; +} +bool ZZSelector::Z4lSelection() { + if (Mass > 80.0 && Mass < 100.0) + return true; + else + return false; +} +//This is no longer needed as I apply SIP < 4.0 on electrons while skimming and we don't need SIP cut on muons with latest HZZID +bool ZZSelector::HZZSIPSelection(){ + if ((l1SIP3D < 4.0 && l2SIP3D < 4.0 && l3SIP3D < 4.0 && l4SIP3D < 4.0)) + return true; + else + return false; +} +bool ZZSelector::HZZLowMass() { + if (Mass > 130.0 && Mass < 170.0) + return true; + else + return false; +} +bool ZZSelector::HZZMediumMass() { + if (Mass > 138.0 && Mass < 300.0) + return true; + else + return false; +} +bool ZZSelector::TestMuons(){ + if ((Z1mass > 82.0 && Z1mass < 102.0) && (Z2mass < 40.0)) + return true; + else + return false; +} + +void ZZSelector::FillHistograms(Long64_t entry, std::pair variation) { + //bool noBlind = true; + //Applying the ZZ Selection here + //std::cout<<"Is fillHistograms working?"<size(), weight); + if (jetPt->size() > 0 && jetPt->size() == jetEta->size()) { + SafeHistFill(histMap1D_, getHistName("jetPt[0]", variation.second), jetPt->at(0), weight); + SafeHistFill(histMap1D_, getHistName("jetEta[0]", variation.second), jetEta->at(0), weight); + } + if (jetPt->size() > 1 && jetPt->size() == jetEta->size()) { + SafeHistFill(histMap1D_, getHistName("jetPt[1]", variation.second), jetPt->at(1), weight); + SafeHistFill(histMap1D_, getHistName("jetEta[1]", variation.second), jetEta->at(1), weight); + } + if (!PassesZZjjSelection()){ + return; + } + SafeHistFill(histMap1D_, getHistName("mjj", variation.second), mjj, weight); + SafeHistFill(histMap1D_, getHistName("dEtajj", variation.second), dEtajj, weight); + // Summing 12,34 leptons + //SafeHistFill(histMap1D_, getHistName("Lep12Pt", variation.second), l1Pt, weight); + //SafeHistFill(histMap1D_, getHistName("Lep12Pt", variation.second), l2Pt, weight); + //SafeHistFill(histMap1D_, getHistName("Lep34Pt", variation.second), l3Pt, weight); + //SafeHistFill(histMap1D_, getHistName("Lep34Pt", variation.second), l4Pt, weight); + //SafeHistFill(histMap1D_, getHistName("Lep12Eta", variation.second), l1Eta, weight); + //SafeHistFill(histMap1D_, getHistName("Lep12Eta", variation.second), l2Eta, weight); + //SafeHistFill(histMap1D_, getHistName("Le34Eta", variation.second), l3Eta, weight); + //SafeHistFill(histMap1D_, getHistName("Lep34Eta", variation.second), l4Eta, weight); + //SafeHistFill(histMap1D_, getHistName("Z1Mass", variation.second), Z1mass, weight); + //SafeHistFill(histMap1D_, getHistName("Z2Mass", variation.second), Z2mass, weight); + //SafeHistFill(histMap1D_, getHistName("Z1Pt", variation.second), Z1pt, weight); + //SafeHistFill(histMap1D_, getHistName("Z2Pt", variation.second), Z2pt, weight); + //SafeHistFill(histMap1D_, getHistName("Z1Phi", variation.second), Z1Phi, weight); + //SafeHistFill(histMap1D_, getHistName("Z2Phi", variation.second), Z2Phi, weight); + //SafeHistFill(histMap1D_, getHistName("Z1lep1_Pt", variation.second), l1Pt, weight); + //SafeHistFill(histMap1D_, getHistName("Z1lep1_Eta", variation.second), l1Eta, weight); + //SafeHistFill(histMap1D_, getHistName("Z1lep1_Phi", variation.second), l1Phi, weight); + //SafeHistFill(histMap1D_, getHistName("Z1lep1_PdgId", variation.second), l1PdgId, weight); + //SafeHistFill(histMap1D_, getHistName("Z1lep2_Pt", variation.second), l2Pt, weight); + //SafeHistFill(histMap1D_, getHistName("Z1lep2_Eta", variation.second), l2Eta, weight); + //SafeHistFill(histMap1D_, getHistName("Z1lep2_Phi", variation.second), l2Phi, weight); + //SafeHistFill(histMap1D_, getHistName("Z1lep2_PdgId", variation.second), l2PdgId, weight); + //SafeHistFill(histMap1D_, getHistName("Z2lep1_Pt", variation.second), l3Pt, weight); + //SafeHistFill(histMap1D_, getHistName("Z2lep1_Eta", variation.second), l3Eta, weight); + //SafeHistFill(histMap1D_, getHistName("Z2lep1_Phi", variation.second), l3Phi, weight); + //SafeHistFill(histMap1D_, getHistName("Z2lep1_PdgId", variation.second), l3PdgId, weight); + //SafeHistFill(histMap1D_, getHistName("Z2lep2_Pt", variation.second), l4Pt, weight); + //SafeHistFill(histMap1D_, getHistName("Z2lep2_Eta", variation.second), l4Eta, weight); + //SafeHistFill(histMap1D_, getHistName("Z2lep2_Phi", variation.second), l4Phi, weight); + //SafeHistFill(histMap1D_, getHistName("Z2lep2_PdgId", variation.second), l4PdgId, weight); + //SafeHistFill(hists2D_, getHistName("Z1lep1_Z1lep2_Pt",variation.second),l1Pt,l2Pt,weight); + //SafeHistFill(hists2D_, getHistName("Z1lep1_Z1lep2_Eta",variation.second),l1Eta,l2Eta,weight); + //SafeHistFill(hists2D_, getHistName("Z1lep1_Z1lep2_Phi",variation.second),l1Phi,l2Phi,weight); + //SafeHistFill(hists2D_, getHistName("Z2lep1_Z2lep2_Pt",variation.second),l3Pt,l4Pt,weight); + //SafeHistFill(hists2D_, getHistName("Z2lep1_Z2lep2_Eta",variation.second),l3Eta,l4Eta,weight); + //SafeHistFill(hists2D_, getHistName("Z2lep1_Z2lep2_Phi",variation.second),l3Phi,l4Phi,weight); + ////2D Z1 vs Z2 + //SafeHistFill(hists2D_, getHistName("Z1Mass_Z2Mass",variation.second),Z1mass,Z2mass,weight); + + //if (histMap1D_[getHistName("nvtx", variation.second)] != nullptr) { + // b_nvtx->GetEntry(entry); + // histMap1D_[getHistName("nvtx", variation.second)]->Fill(nvtx, weight); + //} + //if (isMC_) + // SafeHistFill(histMap1D_, getHistName("nTruePU", variation.second), nTruePU, weight); +} + + +void ZZSelector::SetupNewDirectory() +{ + SelectorBase::SetupNewDirectory(); + isaTGC_ = name_.find("atgc") != std::string::npos; + //std::cout<<"selection in ZZSelector: "< +#include +#include "TParameter.h" + +std::string ZZSelectorBase::GetNameFromFile() { + std::regex expr = std::regex("201[0-9]-[0-9][0-9]-[0-9][0-9]-(.*)-ZZ4l2018"); + std::smatch matches; + std::string fileName = fChain->GetTree()->GetDirectory()->GetFile()->GetName(); + + std::regex_search(fileName, matches, expr); + return std::string(matches.str(1)); +} +void ZZSelectorBase::SetScaleFactors() +{ + pileupSF_ = (ScaleFactor *) GetInputList()->FindObject("pileupSF"); + if (pileupSF_ == nullptr ) + std::invalid_argument("Must pass pileup weights SF"); + eLowRecoSF_ = (ScaleFactor *) GetInputList()->FindObject("electronLowRecoSF"); + if (eLowRecoSF_ == nullptr ) + std::invalid_argument("Must pass electron LowReco SF"); + eRecoSF_ = (ScaleFactor *) GetInputList()->FindObject("electronRecoSF"); + if (eRecoSF_ == nullptr ) + std::invalid_argument("Must pass electron Reco SF"); + eIdSF_ = (ScaleFactor *) GetInputList()->FindObject("electronRunSF"); + if (eIdSF_ == nullptr ) + std::invalid_argument("Must pass electron Run SF"); + eGapIdSF_ = (ScaleFactor *) GetInputList()->FindObject("electronRunGapSF"); + if (eGapIdSF_ == nullptr ) + std::invalid_argument("Must pass electronGap Run SF"); + mIdSF_ = (ScaleFactor *) GetInputList()->FindObject("muonRunSF"); + if (mIdSF_ == nullptr ) + std::invalid_argument("Must pass muon Run SF"); + + //There are L1Prefiring weight and uncertainity in the ZZ UWVV ntuples + //prefireEff_ = (TEfficiency*) GetInputList()->FindObject("prefireEfficiencyMap"); + //if (prefireEff_ == nullptr ) + // std::invalid_argument("Must pass prefiring efficiency map"); +} + +void ZZSelectorBase::Init(TTree *tree) +{ + + //allChannels_ = {"eeee","eemm","mmee","mmmm","eee", "eem", "emm", "mmm"}; + + SelectorBase::Init(tree); +} + +void ZZSelectorBase::SetBranchesUWVV() { + if (isMC_){ + fChain->SetBranchAddress("genWeight", &genWeight, &b_genWeight); + fChain->SetBranchAddress("nTruePU", &nTruePU, &b_nTruePU); + if (year_ == yr2016 || year_ == yr2017){ + fChain->SetBranchAddress("L1prefiringWeight", &L1prefiringWeight, &b_L1prefiringWeight); + } + } + else { + //fChain->SetBranchAddress("Flag_duplicateMuonsPass", Flag_duplicateMuonsPass); + //fChain->SetBranchAddress("Flag_badMuonsPass", Flag_badMuonsPass); + } + //std::cout<<"In ZZSelectorBase"<SetBranchAddress("run", &run, &b_run); + fChain->SetBranchAddress("lumi", &lumi, &b_lumi); + fChain->SetBranchAddress("evt", &evt, &b_evt); + //fChain->SetBranchAddress("duplicated", &duplicated, &b_duplicated); + //fChain->SetBranchAddress("e1IsFall17isoV2wpHZZ", &l1IsTight, &b_l1IsTight); + fChain->SetBranchAddress("e1ZZTightIDNoVtx", &l1IsTight, &b_l1IsTight); + fChain->SetBranchAddress("e1ZZIso", &l1IsIso, &b_l1IsIso); + //fChain->SetBranchAddress("e2IsFall17isoV2wpHZZ", &l2IsTight, &b_l2IsTight); + fChain->SetBranchAddress("e2ZZTightIDNoVtx", &l2IsTight, &b_l2IsTight); + fChain->SetBranchAddress("e2ZZIso", &l2IsIso, &b_l2IsIso); + //fChain->SetBranchAddress("e3IsFall17isoV2wpHZZ", &l3IsTight, &b_l3IsTight); + fChain->SetBranchAddress("e3ZZTightIDNoVtx", &l3IsTight, &b_l3IsTight); + fChain->SetBranchAddress("e3ZZIso", &l3IsIso, &b_l3IsIso); + //fChain->SetBranchAddress("e4IsFall17isoV2wpHZZ", &l4IsTight, &b_l4IsTight); + fChain->SetBranchAddress("e4ZZTightIDNoVtx", &l4IsTight, &b_l4IsTight); + fChain->SetBranchAddress("e4ZZIso", &l4IsIso, &b_l4IsIso); + fChain->SetBranchAddress("e1_e2_Mass", &Z1mass, &b_Z1mass); + fChain->SetBranchAddress("e3_e4_Mass", &Z2mass, &b_Z2mass); + //fChain->SetBranchAddress("e1_e3_Mass", &Zamass, &b_Zamass); + //fChain->SetBranchAddress("e2_e4_Mass", &Zbmass, &b_Zbmass); + fChain->SetBranchAddress("e1_e2_Pt", &Z1pt, &b_Z1pt); + fChain->SetBranchAddress("e3_e4_Pt", &Z2pt, &b_Z2pt); + fChain->SetBranchAddress("e1_e2_Phi", &Z1Phi, &b_Z1Phi); + fChain->SetBranchAddress("e3_e4_Phi", &Z2Phi, &b_Z2Phi); + fChain->SetBranchAddress("e1_e2_Eta", &Z1Eta, &b_Z1Eta); + fChain->SetBranchAddress("e3_e4_Eta", &Z2Eta, &b_Z2Eta); + fChain->SetBranchAddress("e1Pt", &l1Pt, &b_l1Pt); + fChain->SetBranchAddress("e2Pt", &l2Pt, &b_l2Pt); + fChain->SetBranchAddress("e3Pt", &l3Pt, &b_l3Pt); + fChain->SetBranchAddress("e4Pt", &l4Pt, &b_l4Pt); + fChain->SetBranchAddress("e1Eta", &l1Eta, &b_l1Eta); + fChain->SetBranchAddress("e2Eta", &l2Eta, &b_l2Eta); + fChain->SetBranchAddress("e3Eta", &l3Eta, &b_l3Eta); + fChain->SetBranchAddress("e4Eta", &l4Eta, &b_l4Eta); + fChain->SetBranchAddress("e1Phi", &l1Phi, &b_l1Phi); + fChain->SetBranchAddress("e2Phi", &l2Phi, &b_l2Phi); + fChain->SetBranchAddress("e3Phi", &l3Phi, &b_l3Phi); + fChain->SetBranchAddress("e4Phi", &l4Phi, &b_l4Phi); + fChain->SetBranchAddress("e1SIP3D", &l1SIP3D, &b_l1SIP3D); + fChain->SetBranchAddress("e2SIP3D", &l2SIP3D, &b_l2SIP3D); + fChain->SetBranchAddress("e3SIP3D", &l3SIP3D, &b_l3SIP3D); + fChain->SetBranchAddress("e4SIP3D", &l4SIP3D, &b_l4SIP3D); + fChain->SetBranchAddress("e1PdgId", &l1PdgId, &b_l1PdgId); + fChain->SetBranchAddress("e2PdgId", &l2PdgId, &b_l2PdgId); + fChain->SetBranchAddress("e3PdgId", &l3PdgId, &b_l3PdgId); + fChain->SetBranchAddress("e4PdgId", &l4PdgId, &b_l4PdgId); + fChain->SetBranchAddress("e1Mass", &l1Mass, &b_l1Mass); + fChain->SetBranchAddress("e2Mass", &l2Mass, &b_l2Mass); + fChain->SetBranchAddress("e3Mass", &l3Mass, &b_l3Mass); + fChain->SetBranchAddress("e4Mass", &l4Mass, &b_l4Mass); + fChain->SetBranchAddress("e1IsGap", &l1IsGap, &b_l1IsGap); + fChain->SetBranchAddress("e2IsGap", &l2IsGap, &b_l2IsGap); + fChain->SetBranchAddress("e3IsGap", &l3IsGap, &b_l3IsGap); + fChain->SetBranchAddress("e4IsGap", &l4IsGap, &b_l4IsGap); + } + //Add 2e2mu channel also but it still needs to differentiate which one is Z1Mass and which one is Z2Mass leptons + //This is done with a flag at the time of Process for each event on the fly + else if (channel_ == eemm) { + //channel_ = eemm; + //fChain->SetBranchAddress("e1ZZTightIDNoVtx", &l1IsTight, &b_l1IsTight); + fChain->SetBranchAddress("run", &run, &b_run); + fChain->SetBranchAddress("lumi", &lumi, &b_lumi); + fChain->SetBranchAddress("evt", &evt, &b_evt); + //fChain->SetBranchAddress("duplicated", &duplicated, &b_duplicated); + //fChain->SetBranchAddress("e1IsFall17isoV2wpHZZ", &l1IsTight, &b_l1IsTight); + fChain->SetBranchAddress("e1ZZTightIDNoVtx", &l1IsTight, &b_l1IsTight); + fChain->SetBranchAddress("e1ZZIso", &l1IsIso, &b_l1IsIso); + //fChain->SetBranchAddress("e2IsFall17isoV2wpHZZ", &l2IsTight, &b_l2IsTight); + fChain->SetBranchAddress("e2ZZTightIDNoVtx", &l2IsTight, &b_l2IsTight); + fChain->SetBranchAddress("e2ZZIso", &l2IsIso, &b_l2IsIso); + fChain->SetBranchAddress("m1ZZIso", &l3IsIso, &b_l3IsIso); + if (year_ == yr2016 || year_ == yr2017){ + fChain->SetBranchAddress("m1PASTightIDNoVtx", &l3IsTight, &b_l3IsTight); + fChain->SetBranchAddress("m2PASTightIDNoVtx", &l4IsTight, &b_l4IsTight);} + else{ + fChain->SetBranchAddress("m1ZZTightIDNoVtx", &l3IsTight, &b_l3IsTight); + fChain->SetBranchAddress("m2ZZTightIDNoVtx", &l4IsTight, &b_l4IsTight); + } + fChain->SetBranchAddress("m2ZZIso", &l4IsIso, &b_l4IsIso); + fChain->SetBranchAddress("e1_e2_Mass", &Z1mass, &b_Z1mass); + fChain->SetBranchAddress("m1_m2_Mass", &Z2mass, &b_Z2mass); + fChain->SetBranchAddress("e1_e2_Pt", &Z1pt, &b_Z1pt); + fChain->SetBranchAddress("m1_m2_Pt", &Z2pt, &b_Z2pt); + fChain->SetBranchAddress("e1_e2_Phi", &Z1Phi, &b_Z1Phi); + fChain->SetBranchAddress("m1_m2_Phi", &Z2Phi, &b_Z2Phi); + fChain->SetBranchAddress("e1_e2_Eta", &Z1Eta, &b_Z1Eta); + fChain->SetBranchAddress("m1_m2_Eta", &Z2Eta, &b_Z2Eta); + fChain->SetBranchAddress("e1Pt", &l1Pt, &b_l1Pt); + fChain->SetBranchAddress("e2Pt", &l2Pt, &b_l2Pt); + fChain->SetBranchAddress("m1Pt", &l3Pt, &b_l3Pt); + fChain->SetBranchAddress("m2Pt", &l4Pt, &b_l4Pt); + fChain->SetBranchAddress("e1Eta", &l1Eta, &b_l1Eta); + fChain->SetBranchAddress("e2Eta", &l2Eta, &b_l2Eta); + fChain->SetBranchAddress("m1Eta", &l3Eta, &b_l3Eta); + fChain->SetBranchAddress("m2Eta", &l4Eta, &b_l4Eta); + fChain->SetBranchAddress("e1Phi", &l1Phi, &b_l1Phi); + fChain->SetBranchAddress("e2Phi", &l2Phi, &b_l2Phi); + fChain->SetBranchAddress("e1SIP3D", &l1SIP3D, &b_l1SIP3D); + fChain->SetBranchAddress("e2SIP3D", &l2SIP3D, &b_l2SIP3D); + fChain->SetBranchAddress("m1Phi", &l3Phi, &b_l3Phi); + fChain->SetBranchAddress("m2Phi", &l4Phi, &b_l4Phi); + fChain->SetBranchAddress("m1SIP3D", &l3SIP3D, &b_l3SIP3D); + fChain->SetBranchAddress("m2SIP3D", &l4SIP3D, &b_l4SIP3D); + fChain->SetBranchAddress("e1PdgId", &l1PdgId, &b_l1PdgId); + fChain->SetBranchAddress("e2PdgId", &l2PdgId, &b_l2PdgId); + fChain->SetBranchAddress("m1PdgId", &l3PdgId, &b_l3PdgId); + fChain->SetBranchAddress("m2PdgId", &l4PdgId, &b_l4PdgId); + fChain->SetBranchAddress("e1Mass", &l1Mass, &b_l1Mass); + fChain->SetBranchAddress("e2Mass", &l2Mass, &b_l2Mass); + fChain->SetBranchAddress("m1Mass", &l3Mass, &b_l3Mass); + fChain->SetBranchAddress("m2Mass", &l4Mass, &b_l4Mass); + fChain->SetBranchAddress("e1IsGap", &l1IsGap, &b_l1IsGap); + fChain->SetBranchAddress("e2IsGap", &l2IsGap, &b_l2IsGap); + //There are 2 different SFs for electrons depending on whether the electron is from the crack + //in ECAL crystals or not but we need a dummy for the muons? Makes life easier later + fChain->SetBranchAddress("m1IsLoose", &l3IsGap, &b_l3IsGap); + fChain->SetBranchAddress("m2IsLoose", &l4IsGap, &b_l4IsGap); + } + else if (channel_ == mmee) { + //channel_ = mmee; + fChain->SetBranchAddress("run", &run, &b_run); + fChain->SetBranchAddress("lumi", &lumi, &b_lumi); + fChain->SetBranchAddress("evt", &evt, &b_evt); + //fChain->SetBranchAddress("duplicated", &duplicated, &b_duplicated); + //fChain->SetBranchAddress("e1IsFall17isoV2wpHZZ", &l1IsTight, &b_l1IsTight); + fChain->SetBranchAddress("e1ZZTightIDNoVtx", &l1IsTight, &b_l1IsTight); + fChain->SetBranchAddress("e1ZZIso", &l1IsIso, &b_l1IsIso); + //fChain->SetBranchAddress("e2IsFall17isoV2wpHZZ", &l2IsTight, &b_l2IsTight); + fChain->SetBranchAddress("e2ZZTightIDNoVtx", &l2IsTight, &b_l2IsTight); + fChain->SetBranchAddress("e2ZZIso", &l2IsIso, &b_l2IsIso); + fChain->SetBranchAddress("m1ZZIso", &l3IsIso, &b_l3IsIso); + if (year_ == yr2016 || year_ == yr2017){ + fChain->SetBranchAddress("m1PASTightIDNoVtx", &l3IsTight, &b_l3IsTight); + fChain->SetBranchAddress("m2PASTightIDNoVtx", &l4IsTight, &b_l4IsTight);} + else{ + fChain->SetBranchAddress("m1ZZTightIDNoVtx", &l3IsTight, &b_l3IsTight); + fChain->SetBranchAddress("m2ZZTightIDNoVtx", &l4IsTight, &b_l4IsTight); + } + fChain->SetBranchAddress("m2ZZIso", &l4IsIso, &b_l4IsIso); + fChain->SetBranchAddress("e1_e2_Mass", &Z1mass, &b_Z1mass); + fChain->SetBranchAddress("m1_m2_Mass", &Z2mass, &b_Z2mass); + fChain->SetBranchAddress("e1_e2_Pt", &Z1pt, &b_Z1pt); + fChain->SetBranchAddress("m1_m2_Pt", &Z2pt, &b_Z2pt); + fChain->SetBranchAddress("e1_e2_Phi", &Z1Phi, &b_Z1Phi); + fChain->SetBranchAddress("m1_m2_Phi", &Z2Phi, &b_Z2Phi); + fChain->SetBranchAddress("e1_e2_Eta", &Z1Eta, &b_Z1Eta); + fChain->SetBranchAddress("m1_m2_Eta", &Z2Eta, &b_Z2Eta); + fChain->SetBranchAddress("e1Pt", &l1Pt, &b_l1Pt); + fChain->SetBranchAddress("e2Pt", &l2Pt, &b_l2Pt); + fChain->SetBranchAddress("m1Pt", &l3Pt, &b_l3Pt); + fChain->SetBranchAddress("m2Pt", &l4Pt, &b_l4Pt); + fChain->SetBranchAddress("e1Eta", &l1Eta, &b_l1Eta); + fChain->SetBranchAddress("e2Eta", &l2Eta, &b_l2Eta); + fChain->SetBranchAddress("m1Eta", &l3Eta, &b_l3Eta); + fChain->SetBranchAddress("m2Eta", &l4Eta, &b_l4Eta); + fChain->SetBranchAddress("e1Phi", &l1Phi, &b_l1Phi); + fChain->SetBranchAddress("e2Phi", &l2Phi, &b_l2Phi); + fChain->SetBranchAddress("e1SIP3D", &l1SIP3D, &b_l1SIP3D); + fChain->SetBranchAddress("e2SIP3D", &l2SIP3D, &b_l2SIP3D); + fChain->SetBranchAddress("m1Phi", &l3Phi, &b_l3Phi); + fChain->SetBranchAddress("m2Phi", &l4Phi, &b_l4Phi); + fChain->SetBranchAddress("m1SIP3D", &l3SIP3D, &b_l3SIP3D); + fChain->SetBranchAddress("m2SIP3D", &l4SIP3D, &b_l4SIP3D); + fChain->SetBranchAddress("e1PdgId", &l1PdgId, &b_l1PdgId); + fChain->SetBranchAddress("e2PdgId", &l2PdgId, &b_l2PdgId); + fChain->SetBranchAddress("m1PdgId", &l3PdgId, &b_l3PdgId); + fChain->SetBranchAddress("m2PdgId", &l4PdgId, &b_l4PdgId); + fChain->SetBranchAddress("e1Mass", &l1Mass, &b_l1Mass); + fChain->SetBranchAddress("e2Mass", &l2Mass, &b_l2Mass); + fChain->SetBranchAddress("m1Mass", &l3Mass, &b_l3Mass); + fChain->SetBranchAddress("m2Mass", &l4Mass, &b_l4Mass); + fChain->SetBranchAddress("e1IsGap", &l1IsGap, &b_l1IsGap); + fChain->SetBranchAddress("e2IsGap", &l2IsGap, &b_l2IsGap); + fChain->SetBranchAddress("m1IsLoose", &l3IsGap, &b_l3IsGap); + fChain->SetBranchAddress("m2IsLoose", &l4IsGap, &b_l4IsGap); + } + else if (channel_ == mmmm) { + //channel_ = mmmm; + fChain->SetBranchAddress("run", &run, &b_run); + fChain->SetBranchAddress("lumi", &lumi, &b_lumi); + fChain->SetBranchAddress("evt", &evt, &b_evt); + //fChain->SetBranchAddress("duplicated", &duplicated, &b_duplicated); + if (year_ == yr2016 || year_ == yr2017){ + fChain->SetBranchAddress("m1PASTightIDNoVtx", &l1IsTight, &b_l1IsTight); + fChain->SetBranchAddress("m2PASTightIDNoVtx", &l2IsTight, &b_l2IsTight); + fChain->SetBranchAddress("m3PASTightIDNoVtx", &l3IsTight, &b_l3IsTight); + fChain->SetBranchAddress("m4PASTightIDNoVtx", &l4IsTight, &b_l4IsTight);} + else{ + fChain->SetBranchAddress("m1ZZTightIDNoVtx", &l1IsTight, &b_l1IsTight); + fChain->SetBranchAddress("m2ZZTightIDNoVtx", &l2IsTight, &b_l2IsTight); + fChain->SetBranchAddress("m3ZZTightIDNoVtx", &l3IsTight, &b_l3IsTight); + fChain->SetBranchAddress("m4ZZTightIDNoVtx", &l4IsTight, &b_l4IsTight); + } + fChain->SetBranchAddress("m1ZZIso", &l1IsIso, &b_l1IsIso); + fChain->SetBranchAddress("m2ZZIso", &l2IsIso, &b_l2IsIso); + fChain->SetBranchAddress("m3ZZIso", &l3IsIso, &b_l3IsIso); + fChain->SetBranchAddress("m4ZZIso", &l4IsIso, &b_l4IsIso); + fChain->SetBranchAddress("m1_m2_Mass", &Z1mass, &b_Z1mass); + fChain->SetBranchAddress("m3_m4_Mass", &Z2mass, &b_Z2mass); + //fChain->SetBranchAddress("m1_m3_Mass", &Zamass, &b_Zamass); + //fChain->SetBranchAddress("m2_m4_Mass", &Zbmass, &b_Zbmass); + fChain->SetBranchAddress("m1_m2_Pt", &Z1pt, &b_Z1pt); + fChain->SetBranchAddress("m3_m4_Pt", &Z2pt, &b_Z2pt); + fChain->SetBranchAddress("m1_m2_Phi", &Z1Phi, &b_Z1Phi); + fChain->SetBranchAddress("m3_m4_Phi", &Z2Phi, &b_Z2Phi); + fChain->SetBranchAddress("m1_m2_Eta", &Z1Eta, &b_Z1Eta); + fChain->SetBranchAddress("m3_m4_Eta", &Z2Eta, &b_Z2Eta); + fChain->SetBranchAddress("m1Pt", &l1Pt, &b_l1Pt); + fChain->SetBranchAddress("m2Pt", &l2Pt, &b_l2Pt); + fChain->SetBranchAddress("m3Pt", &l3Pt, &b_l3Pt); + fChain->SetBranchAddress("m4Pt", &l4Pt, &b_l4Pt); + fChain->SetBranchAddress("m1Eta", &l1Eta, &b_l1Eta); + fChain->SetBranchAddress("m2Eta", &l2Eta, &b_l2Eta); + fChain->SetBranchAddress("m3Eta", &l3Eta, &b_l3Eta); + fChain->SetBranchAddress("m4Eta", &l4Eta, &b_l4Eta); + fChain->SetBranchAddress("m1Phi", &l1Phi, &b_l1Phi); + fChain->SetBranchAddress("m2Phi", &l2Phi, &b_l2Phi); + fChain->SetBranchAddress("m3Phi", &l3Phi, &b_l3Phi); + fChain->SetBranchAddress("m4Phi", &l4Phi, &b_l4Phi); + fChain->SetBranchAddress("m1SIP3D", &l1SIP3D, &b_l1SIP3D); + fChain->SetBranchAddress("m2SIP3D", &l2SIP3D, &b_l2SIP3D); + fChain->SetBranchAddress("m3SIP3D", &l3SIP3D, &b_l3SIP3D); + fChain->SetBranchAddress("m4SIP3D", &l4SIP3D, &b_l4SIP3D); + fChain->SetBranchAddress("m1PdgId", &l1PdgId, &b_l1PdgId); + fChain->SetBranchAddress("m2PdgId", &l2PdgId, &b_l2PdgId); + fChain->SetBranchAddress("m3PdgId", &l3PdgId, &b_l3PdgId); + fChain->SetBranchAddress("m4PdgId", &l4PdgId, &b_l4PdgId); + fChain->SetBranchAddress("m1Mass", &l1Mass, &b_l1Mass); + fChain->SetBranchAddress("m2Mass", &l2Mass, &b_l2Mass); + fChain->SetBranchAddress("m3Mass", &l3Mass, &b_l3Mass); + fChain->SetBranchAddress("m4Mass", &l4Mass, &b_l4Mass); + } + else if (channel_ == eee) { + //channel_ = eee; + fChain->SetBranchAddress("run", &run, &b_run); + fChain->SetBranchAddress("lumi", &lumi, &b_lumi); + fChain->SetBranchAddress("evt", &evt, &b_evt); + //fChain->SetBranchAddress("duplicated", &duplicated, &b_duplicated); + fChain->SetBranchAddress("e1ZZTightIDNoVtx", &l1IsTight, &b_l1IsTight); + fChain->SetBranchAddress("e1ZZIso", &l1IsIso, &b_l1IsIso); + fChain->SetBranchAddress("e2ZZTightIDNoVtx", &l2IsTight, &b_l2IsTight); + fChain->SetBranchAddress("e2ZZIso", &l2IsIso, &b_l2IsIso); + fChain->SetBranchAddress("e3ZZTightIDNoVtx", &l3IsTight, &b_l3IsTight); + fChain->SetBranchAddress("e3ZZIso", &l3IsIso, &b_l3IsIso); + fChain->SetBranchAddress("e1_e2_Mass", &Z1mass, &b_Z1mass); + fChain->SetBranchAddress("e1_e2_Pt", &Z1pt, &b_Z1pt); + fChain->SetBranchAddress("e1_e2_Phi", &Z1Phi, &b_Z1Phi); + fChain->SetBranchAddress("e1Pt", &l1Pt, &b_l1Pt); + fChain->SetBranchAddress("e2Pt", &l2Pt, &b_l2Pt); + fChain->SetBranchAddress("e3Pt", &l3Pt, &b_l3Pt); + fChain->SetBranchAddress("e1Eta", &l1Eta, &b_l1Eta); + fChain->SetBranchAddress("e2Eta", &l2Eta, &b_l2Eta); + fChain->SetBranchAddress("e3Eta", &l3Eta, &b_l3Eta); + fChain->SetBranchAddress("e1Phi", &l1Phi, &b_l1Phi); + fChain->SetBranchAddress("e2Phi", &l2Phi, &b_l2Phi); + fChain->SetBranchAddress("e3Phi", &l3Phi, &b_l3Phi); + fChain->SetBranchAddress("e1SIP3D", &l1SIP3D, &b_l1SIP3D); + fChain->SetBranchAddress("e2SIP3D", &l2SIP3D, &b_l2SIP3D); + fChain->SetBranchAddress("e3SIP3D", &l3SIP3D, &b_l3SIP3D); + fChain->SetBranchAddress("e1PdgId", &l1PdgId, &b_l1PdgId); + fChain->SetBranchAddress("e2PdgId", &l2PdgId, &b_l2PdgId); + fChain->SetBranchAddress("e3PdgId", &l3PdgId, &b_l3PdgId); + fChain->SetBranchAddress("e3MtToMET", &l3MtToMET, &b_l3MtToMET); + } + else if (channel_ == eem) { + //channel_ = eem; + fChain->SetBranchAddress("run", &run, &b_run); + fChain->SetBranchAddress("lumi", &lumi, &b_lumi); + fChain->SetBranchAddress("evt", &evt, &b_evt); + //fChain->SetBranchAddress("duplicated", &duplicated, &b_duplicated); + fChain->SetBranchAddress("e1ZZTightIDNoVtx", &l1IsTight, &b_l1IsTight); + fChain->SetBranchAddress("e1ZZIso", &l1IsIso, &b_l1IsIso); + fChain->SetBranchAddress("e2ZZTightIDNoVtx", &l2IsTight, &b_l2IsTight); + fChain->SetBranchAddress("e2ZZIso", &l2IsIso, &b_l2IsIso); + if (year_ == yr2016 || year_ == yr2017){ + fChain->SetBranchAddress("mPASTightIDNoVtx", &l3IsTight, &b_l3IsTight);} + else{ + fChain->SetBranchAddress("mZZTightIDNoVtx", &l3IsTight, &b_l3IsTight); + } + fChain->SetBranchAddress("mZZIso", &l3IsIso, &b_l3IsIso); + fChain->SetBranchAddress("e1_e2_Mass", &Z1mass, &b_Z1mass); + fChain->SetBranchAddress("e1_e2_Pt", &Z1pt, &b_Z1pt); + fChain->SetBranchAddress("e1_e2_Phi", &Z1Phi, &b_Z1Phi); + fChain->SetBranchAddress("e1_e2_Pt", &Z1pt, &b_Z1pt); + fChain->SetBranchAddress("e1Pt", &l1Pt, &b_l1Pt); + fChain->SetBranchAddress("e2Pt", &l2Pt, &b_l2Pt); + fChain->SetBranchAddress("e1Eta", &l1Eta, &b_l1Eta); + fChain->SetBranchAddress("e2Eta", &l2Eta, &b_l2Eta); + fChain->SetBranchAddress("e1Phi", &l1Phi, &b_l1Phi); + fChain->SetBranchAddress("e2Phi", &l2Phi, &b_l2Phi); + fChain->SetBranchAddress("mPt", &l3Pt, &b_l3Pt); + fChain->SetBranchAddress("mEta", &l3Eta, &b_l3Eta); + fChain->SetBranchAddress("mPhi", &l3Phi, &b_l3Phi); + fChain->SetBranchAddress("e1SIP3D", &l1SIP3D, &b_l1SIP3D); + fChain->SetBranchAddress("e2SIP3D", &l2SIP3D, &b_l2SIP3D); + fChain->SetBranchAddress("mSIP3D", &l3SIP3D, &b_l3SIP3D); + fChain->SetBranchAddress("e1PdgId", &l1PdgId, &b_l1PdgId); + fChain->SetBranchAddress("e2PdgId", &l2PdgId, &b_l2PdgId); + fChain->SetBranchAddress("mPdgId", &l3PdgId, &b_l3PdgId); + fChain->SetBranchAddress("mMtToMET", &l3MtToMET, &b_l3MtToMET); + } + else if (channel_ == emm) { + //channel_ = emm; + fChain->SetBranchAddress("run", &run, &b_run); + fChain->SetBranchAddress("lumi", &lumi, &b_lumi); + fChain->SetBranchAddress("evt", &evt, &b_evt); + //fChain->SetBranchAddress("duplicated", &duplicated, &b_duplicated); + fChain->SetBranchAddress("eZZTightIDNoVtx", &l3IsTight, &b_l3IsTight); + fChain->SetBranchAddress("eZZIso", &l3IsIso, &b_l3IsIso); + if (year_ == yr2016 || year_ == yr2017){ + fChain->SetBranchAddress("m1PASTightIDNoVtx", &l1IsTight, &b_l1IsTight); + fChain->SetBranchAddress("m2PASTightIDNoVtx", &l2IsTight, &b_l2IsTight);} + else{ + fChain->SetBranchAddress("m1ZZTightIDNoVtx", &l1IsTight, &b_l1IsTight); + fChain->SetBranchAddress("m2ZZTightIDNoVtx", &l2IsTight, &b_l2IsTight); + } + fChain->SetBranchAddress("m1ZZIso", &l1IsIso, &b_l1IsIso); + fChain->SetBranchAddress("m2ZZIso", &l2IsIso, &b_l2IsIso); + fChain->SetBranchAddress("m1_m2_Mass", &Z1mass, &b_Z1mass); + fChain->SetBranchAddress("m1_m2_Pt", &Z1pt, &b_Z1pt); + fChain->SetBranchAddress("m1_m2_Phi", &Z1Phi, &b_Z1Phi); + fChain->SetBranchAddress("m1Pt", &l1Pt, &b_l1Pt); + fChain->SetBranchAddress("m2Pt", &l2Pt, &b_l2Pt); + fChain->SetBranchAddress("m1Eta", &l1Eta, &b_l1Eta); + fChain->SetBranchAddress("m2Eta", &l2Eta, &b_l2Eta); + fChain->SetBranchAddress("m1Phi", &l1Phi, &b_l1Phi); + fChain->SetBranchAddress("m2Phi", &l2Phi, &b_l2Phi); + fChain->SetBranchAddress("ePt", &l3Pt, &b_l3Pt); + fChain->SetBranchAddress("eEta", &l3Eta, &b_l3Eta); + fChain->SetBranchAddress("ePhi", &l3Phi, &b_l3Phi); + fChain->SetBranchAddress("m1SIP3D", &l1SIP3D, &b_l1SIP3D); + fChain->SetBranchAddress("m2SIP3D", &l2SIP3D, &b_l2SIP3D); + fChain->SetBranchAddress("eSIP3D", &l3SIP3D, &b_l3SIP3D); + fChain->SetBranchAddress("m1PdgId", &l1PdgId, &b_l1PdgId); + fChain->SetBranchAddress("m2PdgId", &l2PdgId, &b_l2PdgId); + fChain->SetBranchAddress("ePdgId", &l3PdgId, &b_l3PdgId); + fChain->SetBranchAddress("eMtToMET", &l3MtToMET, &b_l3MtToMET); + } + else if (channel_ == mmm) { + //channel_ = mmm; + fChain->SetBranchAddress("run", &run, &b_run); + fChain->SetBranchAddress("lumi", &lumi, &b_lumi); + fChain->SetBranchAddress("evt", &evt, &b_evt); + //fChain->SetBranchAddress("duplicated", &duplicated, &b_duplicated); + if (year_ == yr2016 || year_ == yr2017){ + fChain->SetBranchAddress("m1PASTightIDNoVtx", &l1IsTight, &b_l1IsTight); + fChain->SetBranchAddress("m2PASTightIDNoVtx", &l2IsTight, &b_l2IsTight); + fChain->SetBranchAddress("m3PASTightIDNoVtx", &l3IsTight, &b_l3IsTight);} + else{ + fChain->SetBranchAddress("m1ZZTightIDNoVtx", &l1IsTight, &b_l1IsTight); + fChain->SetBranchAddress("m2ZZTightIDNoVtx", &l2IsTight, &b_l2IsTight); + fChain->SetBranchAddress("m3ZZTightIDNoVtx", &l3IsTight, &b_l3IsTight); + } + fChain->SetBranchAddress("m1ZZIso", &l1IsIso, &b_l1IsIso); + fChain->SetBranchAddress("m2ZZIso", &l2IsIso, &b_l2IsIso); + fChain->SetBranchAddress("m3ZZIso", &l3IsIso, &b_l3IsIso); + fChain->SetBranchAddress("m1_m2_Mass", &Z1mass, &b_Z1mass); + fChain->SetBranchAddress("m1_m2_Pt", &Z1pt, &b_Z1pt); + fChain->SetBranchAddress("m1_m2_Phi", &Z1Phi, &b_Z1Phi); + fChain->SetBranchAddress("m1Pt", &l1Pt, &b_l1Pt); + fChain->SetBranchAddress("m2Pt", &l2Pt, &b_l2Pt); + fChain->SetBranchAddress("m3Pt", &l3Pt, &b_l3Pt); + fChain->SetBranchAddress("m1Eta", &l1Eta, &b_l1Eta); + fChain->SetBranchAddress("m2Eta", &l2Eta, &b_l2Eta); + fChain->SetBranchAddress("m3Eta", &l3Eta, &b_l3Eta); + fChain->SetBranchAddress("m1Phi", &l1Phi, &b_l1Phi); + fChain->SetBranchAddress("m2Phi", &l2Phi, &b_l2Phi); + fChain->SetBranchAddress("m3Phi", &l3Phi, &b_l3Phi); + fChain->SetBranchAddress("m1SIP3D", &l1SIP3D, &b_l1SIP3D); + fChain->SetBranchAddress("m2SIP3D", &l2SIP3D, &b_l2SIP3D); + fChain->SetBranchAddress("m3SIP3D", &l3SIP3D, &b_l3SIP3D); + fChain->SetBranchAddress("m1PdgId", &l1PdgId, &b_l1PdgId); + fChain->SetBranchAddress("m2PdgId", &l2PdgId, &b_l2PdgId); + fChain->SetBranchAddress("m3PdgId", &l3PdgId, &b_l3PdgId); + fChain->SetBranchAddress("m3MtToMET", &l3MtToMET, &b_l3MtToMET); + } + else + throw std::invalid_argument("Invalid channel choice in ZZSelectorBase!"); + + fChain->SetBranchAddress("type1_pfMETEt", &type1_pfMETEt, &b_type1_pfMETEt); + +} + +void ZZSelectorBase::LoadBranchesNanoAOD(Long64_t entry, std::pair variation) { + throw std::domain_error("NanoAOD ntuples not supported for ZZSelector!"); +} + +void ZZSelectorBase::SetBranchesNanoAOD() { + throw std::domain_error("NanoAOD ntuples not supported for ZZSelector!"); +} + +void ZZSelectorBase::LoadBranchesUWVV(Long64_t entry, std::pair variation) { + weight = 1; + b_l1Pt->GetEntry(entry); + b_l2Pt->GetEntry(entry); + b_l3Pt->GetEntry(entry); + b_l1Eta->GetEntry(entry); + b_l2Eta->GetEntry(entry); + b_l3Eta->GetEntry(entry); + b_l1Phi->GetEntry(entry); + b_l2Phi->GetEntry(entry); + b_l3Phi->GetEntry(entry); + b_l1SIP3D->GetEntry(entry); + b_l2SIP3D->GetEntry(entry); + b_l3SIP3D->GetEntry(entry); + b_l1PdgId->GetEntry(entry); + b_l2PdgId->GetEntry(entry); + b_l3PdgId->GetEntry(entry); + b_run->GetEntry(entry); + b_lumi->GetEntry(entry); + b_evt->GetEntry(entry); + if (channel_ == eeee || channel_ == eemm || channel_ == mmee || channel_ == mmmm) { + b_l4Pt->GetEntry(entry); + b_l4Eta->GetEntry(entry); + b_l4Phi->GetEntry(entry); + b_l4SIP3D->GetEntry(entry); + b_l4PdgId->GetEntry(entry); + b_l1Mass->GetEntry(entry); + b_l2Mass->GetEntry(entry); + b_l3Mass->GetEntry(entry); + b_l4Mass->GetEntry(entry); + b_l4IsTight->GetEntry(entry); + b_l4IsIso->GetEntry(entry); + //b_l4PVDXY->GetEntry(entry); + //b_l4PVDZ->GetEntry(entry); + b_Z2mass->GetEntry(entry); + b_Z2pt->GetEntry(entry); + b_Z2Phi->GetEntry(entry); + b_Z1Eta->GetEntry(entry); + b_Z2Eta->GetEntry(entry); + } + b_Z1mass->GetEntry(entry); + b_Z1pt->GetEntry(entry); + b_Z1Phi->GetEntry(entry); + b_type1_pfMETEt->GetEntry(entry); + b_l1IsTight->GetEntry(entry); + b_l1IsIso->GetEntry(entry); + b_l2IsTight->GetEntry(entry); + b_l2IsIso->GetEntry(entry); + b_l3IsTight->GetEntry(entry); + b_l3IsIso->GetEntry(entry); + if (channel_ == eeee || channel_ == eemm || channel_ == mmee){ + b_l1IsGap->GetEntry(entry); + b_l2IsGap->GetEntry(entry); + b_l3IsGap->GetEntry(entry); + b_l4IsGap->GetEntry(entry); + } + if (channel_ == eee || channel_ == eem || channel_ == emm || channel_ == mmm) { + b_l3MtToMET->GetEntry(entry); + } + //std::cout<<"IsMC: "<GetEntry(entry); + b_nTruePU->GetEntry(entry); + weight = genWeight; + //Prefiring weights for 2016 and 2017 + //std::cout<<"genWeight: "<GetEntry(entry); + weight *= L1prefiringWeight; + //std::cout<<"PrefiredWeight: "< + + + diff --git a/test2016.sh b/test2016.sh new file mode 100755 index 00000000..709e6cbf --- /dev/null +++ b/test2016.sh @@ -0,0 +1 @@ +./Utilities/scripts/makeHistFile.py -a ZZ4l2016 -s SignalSync --output_file zzTest2016 --uwvv -c eeee,eemm,mmee,mmmm --test -f 2016SignalSync
+
+ [log] - + [verbose log] - + [pdf] +