Beispiel #1
0
class TauSF:
    
    def __init__(self, year, algorithm, wp_iso, wp_e, wp_mu):
        self.sftool_iso = TauIDSFTool(YEARLIB[year], ISOLIB[algorithm], WPLIB[wp_iso])
        self.sftool_e = TauIDSFTool(YEARLIB[year], ELIB[getCorrespondingLightLepDiscr(algorithm)[0]],  WPLIB[wp_e])
        self.sftool_mu = TauIDSFTool(YEARLIB[year], MULIB[getCorrespondingLightLepDiscr(algorithm)[1]],  WPLIB[wp_mu])

    def getSF(self, chain, index):
        if chain._tauGenStatus[index] == 1 or chain._tauGenStatus[index] == 3:
            return self.sftool_e.getSFvsEta(chain._lEta[index], chain._tauGenStatus[index])
        elif chain._tauGenStatus[index] == 2 or chain._tauGenStatus[index] == 4:
            return self.sftool_mu.getSFvsEta(chain._lEta[index], chain._tauGenStatus[index])
        elif chain._tauGenStatus[index] == 5:
            return self.sftool_iso.getSFvsPT(chain._lPt[index], chain._tauGenStatus[index])
        else:
            return 1.
Beispiel #2
0
 def __init__(self, fname, **kwargs):
   kwargs['channel'] = 'mutau'
   super(ModuleMuTau,self).__init__(fname,**kwargs)
   self.out = TreeProducerMuTau(fname,self)
   
   # TRIGGERS
   if self.year==2016:
     self.trigger    = lambda e: e.HLT_IsoMu22 or e.HLT_IsoMu22_eta2p1 or e.HLT_IsoTkMu22 or e.HLT_IsoTkMu22_eta2p1 #or e.HLT_IsoMu19_eta2p1_LooseIsoPFTau20_SingleL1
     self.muonCutPt  = lambda e: 23
     self.muonCutEta = lambda e: 2.4 if e.HLT_IsoMu22 or e.HLT_IsoTkMu22 else 2.1
   elif self.year==2017:
     self.trigger    = lambda e: e.HLT_IsoMu24 or e.HLT_IsoMu27 #or e.HLT_IsoMu20_eta2p1_LooseChargedIsoPFTau27_eta2p1_CrossL1
     self.muonCutPt  = lambda e: 25 if e.HLT_IsoMu24 else 28
     self.muonCutEta = lambda e: 2.4
   else:
     self.trigger    = lambda e: e.HLT_IsoMu24 or e.HLT_IsoMu27 #or e.HLT_IsoMu20_eta2p1_LooseChargedIsoPFTau27_eta2p1_CrossL1
     self.muonCutPt  = lambda e: 25
     self.muonCutEta = lambda e: 2.4
   self.tauCutPt     = 20
   self.tauCutEta    = 2.3
   
   # CORRECTIONS
   if self.ismc:
     self.muSFs      = MuonSFs(era=self.era,verb=self.verbosity) # muon id/iso/trigger SFs
     self.tesTool    = TauESTool(tauSFVersion[self.year]) # real tau energy scale corrections
     #self.fesTool    = TauFESTool(tauSFVersion[self.year]) # e -> tau fake negligible
     self.tauSFsT    = TauIDSFTool(tauSFVersion[self.year],'DeepTau2017v2p1VSjet','Tight')
     self.tauSFsM    = TauIDSFTool(tauSFVersion[self.year],'DeepTau2017v2p1VSjet','Medium')
     self.tauSFsT_dm = TauIDSFTool(tauSFVersion[self.year],'DeepTau2017v2p1VSjet','Tight', dm=True)
     self.etfSFs     = TauIDSFTool(tauSFVersion[self.year],'DeepTau2017v2p1VSe',  'VLoose')
     self.mtfSFs     = TauIDSFTool(tauSFVersion[self.year],'DeepTau2017v2p1VSmu', 'Tight')
   
   # CUTFLOW
   self.out.cutflow.addcut('none',         "no cut"                     )
   self.out.cutflow.addcut('trig',         "trigger"                    )
   self.out.cutflow.addcut('muon',         "muon"                       )
   self.out.cutflow.addcut('tau',          "tau"                        )
   self.out.cutflow.addcut('pair',         "pair"                       )
   self.out.cutflow.addcut('weight',       "no cut, weighted", 15       )
   self.out.cutflow.addcut('weight_no0PU', "no cut, weighted, PU>0", 16 ) # use for normalization
Beispiel #3
0
 def __init__(self, fname, **kwargs):
   kwargs['channel'] = 'etau'
   super(ModuleETau,self).__init__(fname,**kwargs)
   self.out = TreeProducerETau(fname,self)
   
   # TRIGGERS
   jsonfile       = os.path.join(datadir,"trigger/tau_triggers_%d.json"%(self.year))
   self.trigger   = TrigObjMatcher(jsonfile,trigger='SingleElectron',isdata=self.isdata)
   self.eleCutPt  = self.trigger.ptmins[0]
   self.tauCutPt  = 20
   self.eleCutEta = 2.3
   self.tauCutEta = 2.3
   
   # CORRECTIONS
   if self.ismc:
     self.eleSFs  = ElectronSFs(year=self.year) # electron id/iso/trigger SFs
     self.tesTool = TauESTool(tauSFVersion[self.year]) # real tau energy scale corrections
     self.fesTool = TauFESTool(tauSFVersion[self.year]) # e -> tau fake energy scale
     self.tauSFs  = TauIDSFTool(tauSFVersion[self.year],'DeepTau2017v2p1VSjet','Tight')
     self.etfSFs  = TauIDSFTool(tauSFVersion[self.year],'DeepTau2017v2p1VSe',  'VLoose')
     self.mtfSFs  = TauIDSFTool(tauSFVersion[self.year],'DeepTau2017v2p1VSmu', 'Tight')
   
   # CUTFLOW
   self.out.cutflow.addcut('none',         "no cut"                     )
   self.out.cutflow.addcut('trig',         "trigger"                    )
   self.out.cutflow.addcut('electron',     "electron"                   )
   self.out.cutflow.addcut('tau',          "tau"                        )
   self.out.cutflow.addcut('pair',         "pair"                       )
   self.out.cutflow.addcut('weight',       "no cut, weighted", 15       )
   self.out.cutflow.addcut('weight_no0PU', "no cut, weighted, PU>0", 16 ) # use for normalization
Beispiel #4
0
 def __init__(self, year, algorithm, wp_iso, wp_e, wp_mu):
     self.sftool_iso = TauIDSFTool(YEARLIB[year], ISOLIB[algorithm],
                                   WPLIB[wp_iso])
     self.sftool_e = TauIDSFTool(
         YEARLIB[year], ELIB[getCorrespondingLightLepDiscr(algorithm)[0]],
         WPLIB[wp_e])
     self.sftool_mu = TauIDSFTool(
         YEARLIB[year], MULIB[getCorrespondingLightLepDiscr(algorithm)[1]],
         WPLIB[wp_mu])
Beispiel #5
0
    def __init__(self, fname, **kwargs):
        kwargs['channel'] = 'mutau'
        super(ModuleTauTau, self).__init__(fname, **kwargs)
        self.out = TreeProducerTauTau(fname, self)

        # TRIGGERS
        jsonfile = os.path.join(datadir,
                                "trigger/tau_triggers_%d.json" % (self.year))
        self.trigger = TrigObjMatcher(jsonfile,
                                      trigger='ditau',
                                      isdata=self.isdata)
        self.tauCutPt = 40
        self.tauCutEta = 2.1

        # CORRECTIONS
        if self.ismc:
            self.trigTool = TauTriggerSFs('tautau', 'Medium', year=self.year)
            self.trigTool_tight = TauTriggerSFs('tautau',
                                                'Tight',
                                                year=self.year)
            self.tesTool = TauESTool(
                tauSFVersion[self.year])  # real tau energy scale
            self.fesTool = TauFESTool(
                tauSFVersion[self.year])  # e -> tau fake energy scale
            self.tauSFs = TauIDSFTool(tauSFVersion[self.year],
                                      'DeepTau2017v2p1VSjet',
                                      'Medium',
                                      dm=True)
            self.tauSFs_tight = TauIDSFTool(tauSFVersion[self.year],
                                            'DeepTau2017v2p1VSjet',
                                            'Tight',
                                            dm=True)
            self.etfSFs = TauIDSFTool(tauSFVersion[self.year],
                                      'DeepTau2017v2p1VSe', 'VVLoose')
            self.mtfSFs = TauIDSFTool(tauSFVersion[self.year],
                                      'DeepTau2017v2p1VSmu', 'Loose')

        # CUTFLOW
        self.out.cutflow.addcut('none', "no cut")
        self.out.cutflow.addcut('trig', "trigger")
        self.out.cutflow.addcut('tau', "tau")
        self.out.cutflow.addcut('pair', "ditau pair")
        self.out.cutflow.addcut('weight', "no cut, weighted", 15)
        self.out.cutflow.addcut('weight_no0PU', "no cut, weighted, PU>0",
                                16)  # use for normalization
import ROOT
from Configurations.Weights.WeightDefinition import Weight as Weight
from TauPOG.TauIDSFs.TauIDSFTool import TauIDSFTool
import TauIDFunctions

tauIDWeight_2016 = Weight()
tauIDWeight_2016.name = 'TauIDWeight'
tauIDWeight_2016.SFTool = TauIDSFTool("2016Legacy","DeepTau2017v2p1VSjet",'Medium')
tauIDWeight_2016.CalculateWeight = TauIDFunctions.CalculateTauIDWeight
tauIDWeight_2016.hasUpDownUncertainties = True
tauIDWeight_2016.uncertaintyVariationList = [
    "TauID_pT0to35_UP",
    "TauID_pT0to35_DOWN",
    "TauID_pT35to40_UP",
    "TauID_pT35to40_DOWN",
    "TauID_pTgt40_UP",
    "TauID_pTgt40_DOWN",
    ]
tauIDWeight_2016.InitUncertaintyVariations()
tauIDWeight_2016.uncertaintyVariationFunctions = {
    "TauID_pT0to35_UP": TauIDFunctions.CalculateTauIDWeight_pT0to35_UP,
    "TauID_pT0to35_DOWN": TauIDFunctions.CalculateTauIDWeight_pT0to35_DOWN,
    "TauID_pT35to40_UP": TauIDFunctions.CalculateTauIDWeight_pT35to40_UP,
    "TauID_pT35to40_DOWN": TauIDFunctions.CalculateTauIDWeight_pT35to40_DOWN,
    "TauID_pTgt40_UP": TauIDFunctions.CalculateTauIDWeight_pTgt40_UP,
    "TauID_pTgt40_DOWN": TauIDFunctions.CalculateTauIDWeight_pTgt40_DOWN,
    }

tauIDWeight_2017 = Weight()
tauIDWeight_2017.name = 'TauIDWeight'
tauIDWeight_2017.SFTool = TauIDSFTool("2017ReReco",'DeepTau2017v2p1VSjet','Medium')
Beispiel #7
0
def printSFTable(year,id,wp,vs='pt'):
  assert vs in ['pt','dm','eta'], "'vs' argument should be pt', 'dm' or 'eta'!"
  dm = (vs=='dm')
  sftool = TauIDSFTool(year,id,wp,dm=dm)
  if vs=='pt':
      ptvals = [10,20,21,25,26,30,31,35,40,50,70,100,200,500,600,700,800,1000,1500,2000,]
      print ">>> "
      print ">>> SF for %s WP of %s in %s"%(wp,id,year)
      print ">>> "
      print ">>> %10s"%('var \ pt')+''.join("%9.1f"%pt for pt in ptvals)
      print ">>> %10s"%("central") +''.join("%9.5f"%sftool.getSFvsPT(pt,5)        for pt in ptvals)
      print ">>> %10s"%("up")      +''.join("%9.5f"%sftool.getSFvsPT(pt,5,'Up')   for pt in ptvals)
      print ">>> %10s"%("down")    +''.join("%9.5f"%sftool.getSFvsPT(pt,5,'Down') for pt in ptvals)
      print ">>> "
      ###sftool.getSFvsDM(25,1,5)   # results in an error
      ###sftool.getSFvsEta(1.5,1,5) # results in an error
  elif vs=='dm':
    dmvals = [0,1,5,6,10,11]
    for pt in [25,50]:
      print ">>> "
      print ">>> SF for %s WP of %s in %s with pT = %s GeV"%(wp,id,year,pt)
      print ">>> "
      print ">>> %10s"%('var \ DM')+''.join("%9d"%dm for dm in dmvals)
      print ">>> %10s"%("central") +''.join("%9.5f"%sftool.getSFvsDM(pt,dm,5)        for dm in dmvals)
      print ">>> %10s"%("up")      +''.join("%9.5f"%sftool.getSFvsDM(pt,dm,5,'Up')   for dm in dmvals)
      print ">>> %10s"%("down")    +''.join("%9.5f"%sftool.getSFvsDM(pt,dm,5,'Down') for dm in dmvals)
      print ">>> "
      ###sftool.getSFvsPT(pt,5)     # results in an error
      ###sftool.getSFvsEta(1.5,1,5) # results in an error
  elif vs=='eta':
    etavals = [0,0.2,0.5,1.0,1.5,2.0,2.2,2.3,2.4]
    for genmatch in [1,2]:
      print ">>> "
      print ">>> SF for %s WP of %s in %s with genmatch %d"%(wp,id,year,genmatch)
      print ">>> "
      print ">>> %10s"%('var \ eta')+''.join("%9.3f"%eta for eta in etavals)
      print ">>> %10s"%("central")  +''.join("%9.5f"%sftool.getSFvsEta(eta,genmatch)        for eta in etavals)
      print ">>> %10s"%("up")       +''.join("%9.5f"%sftool.getSFvsEta(eta,genmatch,'Up')   for eta in etavals)
      print ">>> %10s"%("down")     +''.join("%9.5f"%sftool.getSFvsEta(eta,genmatch,'Down') for eta in etavals)
      print ">>> "
Beispiel #8
0
def AddFinalWeights(FileToRun, args):
    print("")
    print("Creating final weights branch for " + FileToRun)
    print("")

    CheckFile = ROOT.TFile(FileToRun)
    FileName = FileToRun[FileToRun.rfind("/") + 1:]
    print(FileName)

    try:
        CheckFile.mt_Selected.CrossSectionWeighting
    except:
        print("Failed to find cross section weightings. Adding them...")
        AddCrossSectionWeightings.AddCrossSectionWeightings(FileToRun, args)
    try:
        CheckFile.mt_Selected.ZPTWeighting
    except:
        print("Failed to find ZPT weights. Adding them...")
        AddZPTReweighting.ApplyZPTReweighting(FileToRun, args)
    if FileName != "Data.root" and FileName != "Embedded.root":
        try:
            CheckFile.mt_Selected.PileupWeight
        except:
            print("Failed to find pileup weights. Adding them...")
            AddPileupWeightings.AddPileupWeightings(FileToRun, args)
        try:
            CheckFile.mt_Selected.MuAndTriggerSF
        except:
            print("Failed to find mu scale factors. Adding them...")
            AddKITMuAndTriggerSFs.AddKITMuAndTriggerSFs(FileToRun, args)
    CheckFile.Close()

    ReweightFile = ROOT.TFile(FileToRun, "UPDATE")
    FinalWeighting = array('f', [0])
    FinalWeighting_ZPT_DOWN = array('f', [0])
    FinalWeighting_ZPT_UP = array('f', [0])
    FinalWeighting_TOP_UP = array('f', [0])
    FinalWeighting_TOP_DOWN = array('f', [0])

    TheBranch = ReweightFile.mt_Selected.Branch('FinalWeighting',
                                                FinalWeighting,
                                                'FinalWeighitng/F')
    TheBranch_ZPT_DOWN = ReweightFile.mt_Selected.Branch(
        'FinalWeighting_ZPT_DOWN', FinalWeighting_ZPT_DOWN,
        'FinalWeighitng_ZPT_DOWN/F')
    TheBranch_ZPT_UP = ReweightFile.mt_Selected.Branch(
        'FinalWeighting_ZPT_UP', FinalWeighting_ZPT_UP,
        'FinalWeighting_ZPT_UP/F')
    TheBranch_TOP_UP = ReweightFile.mt_Selected.Branch(
        'FinalWeighting_TOP_UP', FinalWeighting_TOP_UP,
        'FinalWeighting_TOP_UP/F')
    TheBranch_TOP_DOWN = ReweightFile.mt_Selected.Branch(
        'FinalWeighting_TOP_DOWN', FinalWeighting_TOP_DOWN,
        'FinalWeighting_TOP_DOWN/F')

    #get the embedded weighting file.
    ScaleFactorFile = ROOT.TFile(
        "/data/aloeliger/CMSSW_9_4_0/src/LegacyCorrectionsWorkspace/output/htt_scalefactors_legacy_2018.root"
    )
    #ScaleFactorFile = ROOT.TFile("/data/aloeliger/CMSSW_9_4_0/src/SMHTTAnalysis/NtuplePolishing/Weightings/htt_scalefactors_v18_2.root")
    ScaleFactorWorkspace = ScaleFactorFile.w

    print("Adding the final weighting...")

    Embedded_XTrg_MuLegWeight = 0.0
    Embedded_XTrg_TauLegWeight = 0.0
    X_Trg_Events = 0.0

    tauSFTool = TauIDSFTool("2018ReReco", "DeepTau2017v2p1VSjet", 'Medium')

    for i in tqdm(range(ReweightFile.mt_Selected.GetEntries())):
        ReweightFile.mt_Selected.GetEntry(i)
        TauVector = ROOT.TLorentzVector()
        TauVector.SetPtEtaPhiM(ReweightFile.mt_Selected.pt_2,
                               ReweightFile.mt_Selected.eta_2,
                               ReweightFile.mt_Selected.phi_2,
                               ReweightFile.mt_Selected.m_2)
        MuVector = ROOT.TLorentzVector()
        MuVector.SetPtEtaPhiM(ReweightFile.mt_Selected.pt_1,
                              ReweightFile.mt_Selected.eta_1,
                              ReweightFile.mt_Selected.phi_1,
                              ReweightFile.mt_Selected.m_1)
        MetVector = ROOT.TLorentzVector()
        MetVector.SetPtEtaPhiM(ReweightFile.mt_Selected.met, 0.0,
                               ReweightFile.mt_Selected.metphi, 0.0)

        #all we have for 2018 so far is cross section and pileup weight
        #we're just using 2017 Tau ID SF temporarily
        Weight = ReweightFile.mt_Selected.CrossSectionWeighting

        if (not args.DisablePileupWeighting and FileName != "Data.root"
                and FileName != "Embedded.root"):
            Weight = Weight * ReweightFile.mt_Selected.PileupWeight
            Weight = Weight * ReweightFile.mt_Selected.bweight  # add in the btagging weight to MCs
        if (not args.DisableMuSFs and FileName != "Data.root"
                and FileName != "Embedded.root"):
            Weight = Weight * ReweightFile.mt_Selected.MuAndTriggerSF

        if (FileName != "Data.root" and FileName != "Embedded.root"):
            #Weight = Weight * 0.90 #0.90 tight tau ID
            Weight = Weight * tauSFTool.getSFvsPT(TauVector.Pt())  #
        elif FileName == "Embedded.root":
            Weight = Weight * 0.88

        if not args.DisableEtaWeighting:
            if (ReweightFile.mt_Selected.gen_match_2 == 2
                    or ReweightFile.mt_Selected.gen_match_2 == 4):
                if (abs(TauVector.Eta()) < 0.4):
                    Weight = Weight * 1.28
                elif (abs(TauVector.Eta()) < 0.8):
                    Weight = Weight * 1.2
                elif (abs(TauVector.Eta()) < 1.2):
                    Weight = Weight * 1.08
                elif (abs(TauVector.Eta()) < 1.7):
                    Weight = Weight * 1.0
                elif (abs(TauVector.Eta()) < 2.3):
                    Weight = Weight * 2.3

        Trigger24 = ReweightFile.mt_Selected.Trigger24
        Trigger27 = ReweightFile.mt_Selected.Trigger27
        Trigger2027 = ReweightFile.mt_Selected.Trigger2027

        if not args.DisableEmbeddingReconstructionWeighting:
            if (FileName == "Embedded.root"):
                if ReweightFile.mt_Selected.l2_decayMode == 0:
                    Weight = Weight * 0.975
                elif ReweightFile.mt_Selected.l2_decayMode == 1:
                    Weight = Weight * 0.975 * 1.051
                elif ReweightFile.mt_Selected.l2_decayMode == 10:
                    Weight = Weight * 0.975 * 0.975 * 0.975
                ScaleFactorWorkspace.var("m_pt").setVal(MuVector.Pt())
                ScaleFactorWorkspace.var("m_eta").setVal(MuVector.Eta())
                ScaleFactorWorkspace.var("gt_pt").setVal(MuVector.Pt())
                ScaleFactorWorkspace.var("gt_eta").setVal(MuVector.Eta())
                ScaleFactorWorkspace.var("gt1_pt").setVal(MuVector.Pt())
                ScaleFactorWorkspace.var("gt1_eta").setVal(MuVector.Eta())
                ScaleFactorWorkspace.var("gt2_pt").setVal(TauVector.Pt())
                ScaleFactorWorkspace.var("gt2_eta").setVal(TauVector.Eta())
                ScaleFactorWorkspace.var("m_iso").setVal(
                    ReweightFile.mt_Selected.iso_1)
                ScaleFactorWorkspace.var("t_pt").setVal(TauVector.Pt())
                Weight = Weight * ScaleFactorWorkspace.function(
                    "m_sel_trg_ratio").getVal()
                Weight = Weight * ScaleFactorWorkspace.function(
                    "m_sel_idEmb_ratio").getVal()
                ScaleFactorWorkspace.var("gt_pt").setVal(TauVector.Pt())
                ScaleFactorWorkspace.var("gt_eta").setVal(TauVector.Eta())
                Weight = Weight * ScaleFactorWorkspace.function(
                    "m_sel_idEmb_ratio").getVal()
                Weight = Weight * ScaleFactorWorkspace.function(
                    "m_iso_binned_embed_kit_ratio").getVal()
                Weight = Weight * ScaleFactorWorkspace.function(
                    "m_id_embed_kit_ratio").getVal()
                if (Trigger24 or Trigger27):
                    Weight = Weight * ScaleFactorWorkspace.function(
                        "m_trg24_27_embed_kit_ratio").getVal()
                elif (Trigger2027):
                    X_Trg_Events += 1.0
                    Embedded_XTrg_MuLegWeight += ScaleFactorWorkspace.function(
                        "m_trg_binned_20_embed_ratio").getVal()
                    Weight = Weight * ScaleFactorWorkspace.function(
                        "m_trg_binned_20_embed_ratio").getVal(
                        )  #This weight causes huge problems
                    #Weight = Weight*ScaleFactorWorkspace.function("mt_emb_LooseChargedIsoPFTau27_kit_ratio").getVal()
                    Embedded_XTrg_TauLegWeight += ScaleFactorWorkspace.function(
                        "mt_emb_LooseChargedIsoPFTau27_tight_kit_ratio"
                    ).getVal()
                    Weight = Weight * ScaleFactorWorkspace.function(
                        "mt_emb_LooseChargedIsoPFTau27_tight_kit_ratio"
                    ).getVal()
                else:
                    print(
                        "Something weird went through our trigger definitions."
                    )

        #top pt reweighting
        if not args.DisableTopReweighting:
            TopFactor = 1.0
            if (FileName == "TTToHadronic.root"
                    or FileName == "TTToSemiLeptonic.root"
                    or FileName == "TTTo2L2Nu.root"):
                pttop1 = ReweightFile.mt_Selected.pt_top1
                if pttop1 > 400:
                    pttop1 = 400
                pttop2 = ReweightFile.mt_Selected.pt_top2
                if pttop2 > 400:
                    pttop2 = 400
                topfactor = math.sqrt(
                    math.exp(0.0615 - 0.0005 * pttop1) *
                    math.exp(0.0615 - 0.0005 * pttop2))
                Weight_TOP_UP = Weight * (2.0 * (topfactor - 1.0) + 1.0)
                Weight_TOP_DOWN = Weight
                Weight = Weight * TopFactor

        if not args.DisableZPTWeighting:
            Weight_ZPT_DOWN = Weight * ReweightFile.mt_Selected.ZPTWeighting_DOWN
            Weight_ZPT_UP = Weight * ReweightFile.mt_Selected.ZPTWeighting_UP
            Weight = Weight * ReweightFile.mt_Selected.ZPTWeighting

        #ALWAYS
        if FileName == "Data.root":
            Weight = 1.0
        FinalWeighting[0] = Weight
        if not args.DisableZPTWeighting:
            FinalWeighting_ZPT_DOWN[0] = Weight_ZPT_DOWN
            FinalWeighting_ZPT_UP[0] = Weight_ZPT_UP
        if not args.DisableTopReweighting and (
                FileName == "TTToHadronic.root" or FileName
                == "TTToSemiLeptonic.root" or FileName == "TTTo2L2Nu.root"):
            FinalWeighting_TOP_UP[0] = Weight_TOP_UP
            FinalWeighting_TOP_DOWN[0] = Weight_TOP_DOWN

        TheBranch.Fill()
        if not args.DisableZPTWeighting:
            TheBranch_ZPT_DOWN.Fill()
            TheBranch_ZPT_UP.Fill()
        if not args.DisableTopReweighting and (
                FileName == "TTToHadronic.root" or FileName
                == "TTToSemiLeptonic.root" or FileName == "TTTo2L2Nu.root"):
            TheBranch_TOP_UP.Fill()
            TheBranch_TOP_DOWN.Fill()

    if FileName == "Embedded.root":
        Embedded_XTrg_MuLegWeight = Embedded_XTrg_MuLegWeight / X_Trg_Events
        Embedded_XTrg_TauLegWeight = Embedded_XTrg_TauLegWeight / X_Trg_Events
        print("Embedded X trg mu leg weight (avg): " +
              str(Embedded_XTrg_MuLegWeight))
        print("Embedded X trg tau leg weight (avg): " +
              str(Embedded_XTrg_TauLegWeight))

    ReweightFile.cd()
    ReweightFile.mt_Selected.Write('', ROOT.TObject.kOverwrite)
    ReweightFile.Write()
    ReweightFile.Close()
Beispiel #9
0
class ModuleMuTau(ModuleTauPair):
  
  def __init__(self, fname, **kwargs):
    kwargs['channel'] = 'mutau'
    super(ModuleMuTau,self).__init__(fname,**kwargs)
    self.out = TreeProducerMuTau(fname,self)
    
    # TRIGGERS
    if self.year==2016:
      self.trigger    = lambda e: e.HLT_IsoMu22 or e.HLT_IsoMu22_eta2p1 or e.HLT_IsoTkMu22 or e.HLT_IsoTkMu22_eta2p1 #or e.HLT_IsoMu19_eta2p1_LooseIsoPFTau20_SingleL1
      self.muonCutPt  = lambda e: 23
      self.muonCutEta = lambda e: 2.4 if e.HLT_IsoMu22 or e.HLT_IsoTkMu22 else 2.1
    elif self.year==2017:
      self.trigger    = lambda e: e.HLT_IsoMu24 or e.HLT_IsoMu27 #or e.HLT_IsoMu20_eta2p1_LooseChargedIsoPFTau27_eta2p1_CrossL1
      self.muonCutPt  = lambda e: 25 if e.HLT_IsoMu24 else 28
      self.muonCutEta = lambda e: 2.4
    else:
      self.trigger    = lambda e: e.HLT_IsoMu24 or e.HLT_IsoMu27 #or e.HLT_IsoMu20_eta2p1_LooseChargedIsoPFTau27_eta2p1_CrossL1
      self.muonCutPt  = lambda e: 25
      self.muonCutEta = lambda e: 2.4
    self.tauCutPt     = 20
    self.tauCutEta    = 2.3
    
    # CORRECTIONS
    if self.ismc:
      self.muSFs      = MuonSFs(era=self.era,verb=self.verbosity) # muon id/iso/trigger SFs
      self.tesTool    = TauESTool(tauSFVersion[self.year]) # real tau energy scale corrections
      #self.fesTool    = TauFESTool(tauSFVersion[self.year]) # e -> tau fake negligible
      self.tauSFsT    = TauIDSFTool(tauSFVersion[self.year],'DeepTau2017v2p1VSjet','Tight')
      self.tauSFsM    = TauIDSFTool(tauSFVersion[self.year],'DeepTau2017v2p1VSjet','Medium')
      self.tauSFsT_dm = TauIDSFTool(tauSFVersion[self.year],'DeepTau2017v2p1VSjet','Tight', dm=True)
      self.etfSFs     = TauIDSFTool(tauSFVersion[self.year],'DeepTau2017v2p1VSe',  'VLoose')
      self.mtfSFs     = TauIDSFTool(tauSFVersion[self.year],'DeepTau2017v2p1VSmu', 'Tight')
    
    # CUTFLOW
    self.out.cutflow.addcut('none',         "no cut"                     )
    self.out.cutflow.addcut('trig',         "trigger"                    )
    self.out.cutflow.addcut('muon',         "muon"                       )
    self.out.cutflow.addcut('tau',          "tau"                        )
    self.out.cutflow.addcut('pair',         "pair"                       )
    self.out.cutflow.addcut('weight',       "no cut, weighted", 15       )
    self.out.cutflow.addcut('weight_no0PU', "no cut, weighted, PU>0", 16 ) # use for normalization
    
  
  def beginJob(self):
    """Before processing any events or files."""
    super(ModuleMuTau,self).beginJob()
    print ">>> %-12s = %s"%('tauwp',      self.tauwp)
    print ">>> %-12s = %s"%('muonCutPt',  self.muonCutPt)
    print ">>> %-12s = %s"%('muonCutEta', self.muonCutEta)
    print ">>> %-12s = %s"%('tauCutPt',   self.tauCutPt)
    print ">>> %-12s = %s"%('tauCutEta',  self.tauCutEta)
    pass
    
  
  def analyze(self, event):
    """Process and pre-select events; fill branches and return True if the events passes,
    return False otherwise."""
    sys.stdout.flush()
    
    
    ##### NO CUT #####################################
    self.out.cutflow.fill('none')
    if self.isdata:
      self.out.cutflow.fill('weight',1.)
      if event.PV_npvs>0:
        self.out.cutflow.fill('weight_no0PU',1.)
      else:
        return False
    else:
      self.out.cutflow.fill('weight',event.genWeight)
      self.out.pileup.Fill(event.Pileup_nTrueInt)
      if event.Pileup_nTrueInt>0:
        self.out.cutflow.fill('weight_no0PU',event.genWeight)
      else:
        return False
    
    
    ##### TRIGGER ####################################
    if not self.trigger(event):
      return False
    self.out.cutflow.fill('trig')
    
    
    ##### MUON #######################################
    muons = [ ]
    for muon in Collection(event,'Muon'):
      if muon.pt<self.muonCutPt(event): continue
      if abs(muon.eta)>self.muonCutEta(event): continue
      if abs(muon.dz)>0.2: continue
      if abs(muon.dxy)>0.045: continue
      if not muon.mediumId: continue
      if muon.pfRelIso04_all>0.50: continue
      muons.append(muon)
    if len(muons)==0:
      return False
    self.out.cutflow.fill('muon')
    
    
    ##### TAU ########################################
    taus = [ ]
    for tau in Collection(event,'Tau'):
      if abs(tau.eta)>self.tauCutEta: continue
      if abs(tau.dz)>0.2: continue
      if tau.decayMode not in [0,1,10,11]: continue
      if abs(tau.charge)!=1: continue
      if tau.idDeepTau2017v2p1VSe<1: continue # VVVLoose
      if tau.idDeepTau2017v2p1VSmu<1: continue # VLoose
      if tau.idDeepTau2017v2p1VSjet<self.tauwp: continue
      if self.ismc:
        tau.es   = 1 # store energy scale for propagating to MET
        genmatch = tau.genPartFlav
        if genmatch==5: # real tau
          if self.tes!=None: # user-defined energy scale (for TES studies)
            tes = self.tes
          else: # recommended energy scale (apply by default)
            tes = self.tesTool.getTES(tau.pt,tau.decayMode,unc=self.tessys)
          if tes!=1:
            tau.pt   *= tes
            tau.mass *= tes
            tau.es    = tes # store for later reuse
        elif self.ltf and 0<genmatch<5: # lepton -> tau fake
          tau.pt   *= self.ltf
          tau.mass *= self.ltf
          tau.es    = self.ltf # store for later reuse
        #elif genmatch in [1,3]: # electron -> tau fake (apply by default, override with 'ltf=1.0')
        #  fes = self.fesTool.getFES(tau.eta,tau.decayMode,unc=self.fes)
        #  tau.pt   *= fes
        #  tau.mass *= fes
        #  tau.es    = fes
        elif self.jtf!=1.0 and genmatch==0: # jet -> tau fake
          tau.pt   *= self.jtf
          tau.mass *= self.jtf
          tau.es    = self.jtf
      if tau.pt<self.tauCutPt: continue
      taus.append(tau)
    if len(taus)==0:
      return False
    self.out.cutflow.fill('tau')
    
    
    ##### MUTAU PAIR #################################
    ltaus = [ ]
    for muon in muons:
      for tau in taus:
        if tau.DeltaR(muon)<0.5: continue
        ltau = LeptonTauPair(muon,muon.pfRelIso04_all,tau,tau.rawDeepTau2017v2p1VSjet)
        ltaus.append(ltau)
    if len(ltaus)==0:
      return False
    muon, tau = max(ltaus).pair
    muon.tlv  = muon.p4()
    tau.tlv   = tau.p4()
    genmatch  = -1 if self.isdata else tau.genPartFlav
    self.out.cutflow.fill('pair')
    
    
    # VETOES
    extramuon_veto, extraelec_veto, dilepton_veto = getlepvetoes(event,[ ],[muon],[tau],self.channel)
    self.out.extramuon_veto[0], self.out.extraelec_veto[0], self.out.dilepton_veto[0] = getlepvetoes(event,[ ],[muon],[ ],self.channel)
    self.out.lepton_vetoes[0]       = self.out.extramuon_veto[0] or self.out.extraelec_veto[0] or self.out.dilepton_veto[0]
    self.out.lepton_vetoes_notau[0] = extramuon_veto or extraelec_veto or dilepton_veto
    
    # TIGHTEN PRE-SELECTION
    if self.dotight: # do not save all events to reduce disk space
      fail = (self.out.lepton_vetoes[0] and self.out.lepton_vetoes_notau[0]) or\
             (tau.idMVAoldDM2017v2<1 and tau.idDeepTau2017v2p1VSjet<1) or\
             (tau.idAntiMu<2  and tau.idDeepTau2017v2p1VSmu<2) or\
             (tau.idAntiEle<2 and tau.idDeepTau2017v2p1VSe<1)
      if (self.tes not in [1,None] or self.tessys!=None) and (fail or tau.genPartFlav!=5):
        return False
      if (self.ltf!=1 or self.fes!=None) and tau.genPartFlav<1 and tau.genPartFlav>4:
        return False
      ###if self.jtf!=1 and tau.genPartFlav!=0:
      ###  return False
    
    # EVENT
    self.fillEventBranches(event)
    
    
    # MUON
    self.out.pt_1[0]                       = muon.pt
    self.out.eta_1[0]                      = muon.eta
    self.out.phi_1[0]                      = muon.phi
    self.out.m_1[0]                        = muon.mass
    self.out.y_1[0]                        = muon.tlv.Rapidity()
    self.out.dxy_1[0]                      = muon.dxy
    self.out.dz_1[0]                       = muon.dz
    self.out.q_1[0]                        = muon.charge
    self.out.iso_1[0]                      = muon.pfRelIso04_all
    
    
    # TAU
    self.out.pt_2[0]                       = tau.pt
    self.out.eta_2[0]                      = tau.eta
    self.out.phi_2[0]                      = tau.phi
    self.out.m_2[0]                        = tau.mass
    self.out.y_2[0]                        = tau.tlv.Rapidity()
    self.out.dxy_2[0]                      = tau.dxy
    self.out.dz_2[0]                       = tau.dz
    self.out.q_2[0]                        = tau.charge
    self.out.dm_2[0]                       = tau.decayMode
    self.out.iso_2[0]                      = tau.rawIso
    self.out.idiso_2[0]                    = idIso(tau) # cut-based tau isolation (rawIso)
    self.out.rawAntiEle_2[0]               = tau.rawAntiEle
    self.out.rawMVAoldDM2017v2_2[0]        = tau.rawMVAoldDM2017v2
    self.out.rawMVAnewDM2017v2_2[0]        = tau.rawMVAnewDM2017v2
    self.out.rawDeepTau2017v2p1VSe_2[0]    = tau.rawDeepTau2017v2p1VSe
    self.out.rawDeepTau2017v2p1VSmu_2[0]   = tau.rawDeepTau2017v2p1VSmu
    self.out.rawDeepTau2017v2p1VSjet_2[0]  = tau.rawDeepTau2017v2p1VSjet
    self.out.idAntiEle_2[0]                = tau.idAntiEle
    self.out.idAntiMu_2[0]                 = tau.idAntiMu
    self.out.idDecayMode_2[0]              = tau.idDecayMode
    self.out.idDecayModeNewDMs_2[0]        = tau.idDecayModeNewDMs
    self.out.idMVAoldDM2017v2_2[0]         = tau.idMVAoldDM2017v2
    self.out.idMVAnewDM2017v2_2[0]         = tau.idMVAnewDM2017v2
    self.out.idDeepTau2017v2p1VSe_2[0]     = tau.idDeepTau2017v2p1VSe
    self.out.idDeepTau2017v2p1VSmu_2[0]    = tau.idDeepTau2017v2p1VSmu
    self.out.idDeepTau2017v2p1VSjet_2[0]   = tau.idDeepTau2017v2p1VSjet
    self.out.chargedIso_2[0]               = tau.chargedIso
    self.out.neutralIso_2[0]               = tau.neutralIso
    self.out.leadTkPtOverTauPt_2[0]        = tau.leadTkPtOverTauPt
    self.out.photonsOutsideSignalCone_2[0] = tau.photonsOutsideSignalCone
    self.out.puCorr_2[0]                   = tau.puCorr
    
    
    # GENERATOR
    if self.ismc:
      self.out.genmatch_1[0]     = muon.genPartFlav
      self.out.genmatch_2[0]     = tau.genPartFlav
      pt, phi, eta, status       = matchgenvistau(event,tau)
      self.out.genvistaupt_2[0]  = pt
      self.out.genvistaueta_2[0] = eta
      self.out.genvistauphi_2[0] = phi
      self.out.gendm_2[0]        = status
      if self.dozpt:
        self.out.mutaufilter     = filtermutau(event) # for stitching DYJetsToTauTauToMuTauh
    
    
    # JETS
    jets, met, njets_vars, met_vars = self.fillJetBranches(event,muon,tau)
    if self.ismc:
      self.out.jpt_match_2[0], self.out.jpt_genmatch_2[0] = matchtaujet(event,tau,self.ismc)
    else:
      self.out.jpt_match_2[0] = matchtaujet(event,tau,self.ismc)[0]
    
    
    # WEIGHTS
    if self.ismc:
      self.fillCommonCorrBraches(event,jets,met,njets_vars,met_vars)
      if muon.pfRelIso04_all<0.50 and tau.idDeepTau2017v2p1VSjet>=2:
        self.btagTool.fillEffMaps(jets,usejec=self.dojec)
      
      # MUON WEIGHTS
      self.out.trigweight[0]          = self.muSFs.getTriggerSF(muon.pt,muon.eta)
      self.out.idisoweight_1[0]       = self.muSFs.getIdIsoSF(muon.pt,muon.eta)
      
      # DEFAULTS
      self.out.idweight_2[0]          = 1.
      self.out.idweight_dm_2[0]       = 1.
      self.out.idweight_medium_2[0]   = 1.
      
      self.out.ltfweight_2[0]         = 1.
      if not self.dotight:
        self.out.idweightUp_2[0]      = 1.
        self.out.idweightDown_2[0]    = 1.
        self.out.idweightUp_dm_2[0]   = 1.
        self.out.idweightDown_dm_2[0] = 1.
        self.out.ltfweightUp_2[0]     = 1.
        self.out.ltfweightDown_2[0]   = 1.
      
      # TAU WEIGHTS
      if tau.genPartFlav==5: # real tau
        self.out.idweight_2[0]        = self.tauSFsT.getSFvsPT(tau.pt)
        self.out.idweight_medium_2[0] = self.tauSFsM.getSFvsPT(tau.pt)
        self.out.idweight_dm_2[0]     = self.tauSFsT_dm.getSFvsDM(tau.pt,tau.decayMode)
        if not self.dotight:
          self.out.idweightUp_2[0]    = self.tauSFsT.getSFvsPT(tau.pt,unc='Up')
          self.out.idweightDown_2[0]  = self.tauSFsT.getSFvsPT(tau.pt,unc='Down')
          self.out.idweightUp_dm_2[0]   = self.tauSFsT_dm.getSFvsDM(tau.pt,tau.decayMode,unc='Up')
          self.out.idweightDown_dm_2[0] = self.tauSFsT_dm.getSFvsDM(tau.pt,tau.decayMode,unc='Down')
      elif tau.genPartFlav in [1,3]: # muon -> tau fake
        self.out.ltfweight_2[0]       = self.etfSFs.getSFvsEta(tau.eta,tau.genPartFlav)
        if not self.dotight:
          self.out.ltfweightUp_2[0]   = self.etfSFs.getSFvsEta(tau.eta,tau.genPartFlav,unc='Up')
          self.out.ltfweightDown_2[0] = self.etfSFs.getSFvsEta(tau.eta,tau.genPartFlav,unc='Down')
      elif tau.genPartFlav in [2,4]: # electron -> tau fake
        self.out.ltfweight_2[0]       = self.mtfSFs.getSFvsEta(tau.eta,tau.genPartFlav)
        if not self.dotight:
          self.out.ltfweightUp_2[0]   = self.mtfSFs.getSFvsEta(tau.eta,tau.genPartFlav,unc='Up')
          self.out.ltfweightDown_2[0] = self.mtfSFs.getSFvsEta(tau.eta,tau.genPartFlav,unc='Down')
      self.out.weight[0]              = self.out.genweight[0]*self.out.puweight[0]*self.out.trigweight[0]*self.out.idisoweight_1[0] #*self.out.idisoweight_2[0]
    elif self.isembed:
      ###self.applyCommonEmbdedCorrections(event,jets,jetIds50,met,njets_vars,met_vars)
      self.out.genweight[0]           = event.genWeight
      self.out.trackweight[0]         = 0.975 if tau.decayMode==0 else 1.0247 if tau.decayMode==1 else 0.927 if tau.decayMode==10 else 0.974 if tau.decayMode==11 else 1.0
    
    
    # MET & DILEPTON VARIABLES
    self.fillMETAndDiLeptonBranches(event,muon,tau,met,met_vars)
    
    
    self.out.fill()
    return True
def AddFinalWeights(FileToRun, args):
    print("")
    print("Creating final weights branch for: " + FileToRun)
    print("")
    CheckFile = ROOT.TFile(FileToRun)
    #make the name easier to understand
    FileName = FileToRun[FileToRun.rfind("/") + 1:]
    #Need cross section weighting. Check for it
    try:
        CheckFile.mt_Selected.CrossSectionWeighting
    except:
        print("Failed to find cross section weightings. Adding them...")
        AddCrossSectionWeightings.AddCrossSectionWeightings(FileToRun, args)
    try:
        CheckFile.mt_Selected.ZPTWeighting
    except:
        print("Failed to find ZPT Weights. Adding them...")
        AddZPTReweighting.Apply2016ZPTReweighting(FileToRun, args)
    if FileName != "Data.root" and FileName != "Embedded.root":
        try:
            CheckFile.mt_Selected.PileupWeight
        except:
            print("Failed to find pileup weights. Adding them...")
            AddPileupWeightings.AddPileupWeightings(FileToRun, args)
        try:
            CheckFile.mt_Selected.MuAndTriggerSF
        except:
            print("Failed to find muon scale factors. Adding them...")
            AddKITMuAndTriggerSFs.AddKITMuAndTriggerSFs(FileToRun, args)
    CheckFile.Close()

    ReweightFile = ROOT.TFile(FileToRun, "UPDATE")
    #we create different weights for different shapes.
    FinalWeighting = array('f', [0])
    FinalWeighting_ZPT_DOWN = array('f', [0])
    FinalWeighting_ZPT_UP = array('f', [0])
    FinalWeighting_TOP_UP = array('f', [0])
    FinalWeighting_TOP_DOWN = array('f', [0])

    TheBranch = ReweightFile.mt_Selected.Branch('FinalWeighting',
                                                FinalWeighting,
                                                'FinalWeighitng/F')
    TheBranch_ZPT_DOWN = ReweightFile.mt_Selected.Branch(
        'FinalWeighting_ZPT_DOWN', FinalWeighting_ZPT_DOWN,
        'FinalWeighitng_ZPT_DOWN/F')
    TheBranch_ZPT_UP = ReweightFile.mt_Selected.Branch(
        'FinalWeighting_ZPT_UP', FinalWeighting_ZPT_UP,
        'FinalWeighting_ZPT_UP/F')
    TheBranch_TOP_UP = ReweightFile.mt_Selected.Branch(
        'FinalWeighting_TOP_UP', FinalWeighting_TOP_UP,
        'FinalWeighting_TOP_UP/F')
    TheBranch_TOP_DOWN = ReweightFile.mt_Selected.Branch(
        'FinalWeighting_TOP_DOWN', FinalWeighting_TOP_DOWN,
        'FinalWeighting_TOP_DOWN/F')

    tauSFTool = TauIDSFTool(2016, "DeepTau2017v2p1", 'Medium')

    for i in tqdm(range(ReweightFile.mt_Selected.GetEntries())):
        ReweightFile.mt_Selected.GetEntry(i)

        MuVector = ROOT.TLorentzVector()
        TauVector = ROOT.TLorentzVector()
        MuVector.SetPtEtaPhiM(ReweightFile.mt_Selected.pt_1,
                              ReweightFile.mt_Selected.eta_1,
                              ReweightFile.mt_Selected.phi_1,
                              ReweightFile.mt_Selected.m_1)
        TauVector.SetPtEtaPhiM(ReweightFile.mt_Selected.pt_2,
                               ReweightFile.mt_Selected.eta_2,
                               ReweightFile.mt_Selected.phi_2,
                               ReweightFile.mt_Selected.m_2)

        Weight = ReweightFile.mt_Selected.CrossSectionWeighting  #cross section
        #if not a data file, pileup reweight it
        if (not args.DisablePileupWeighting and FileName != "Data.root"
                and FileName != "Embedded.root"):
            Weight = Weight * ReweightFile.mt_Selected.PileupWeight
        #possible overlap on trigger SFs?
        if (not args.DisableMuAndTriggerSFs and FileName != "Data.root"
                and FileName != "Embedded.root"):
            Weight = Weight * ReweightFile.mt_Selected.MuAndTriggerSF
        if FileName != "Embedded.root" and FileName != "Data.root":
            Weight = Weight * tauSFTool.getSFvsPT(TauVector.Pt())

        #mu->tau FR Sf's
        if not args.DisableEtaWeighting:
            if (ReweightFile.mt_Selected.gen_match_2 == 2
                    or ReweightFile.mt_Selected.gen_match_2 == 4):
                if (abs(TauVector.Eta()) < 0.4):
                    Weight = Weight * 1.47
                elif (abs(TauVector.Eta()) < 0.8):
                    Weight = Weight * 1.55
                elif (abs(TauVector.Eta()) < 1.2):
                    Weight = Weight * 1.33
                elif (abs(TauVector.Eta()) < 1.7):
                    Weight = Weight * 1.72
                elif (abs(TauVector.Eta()) < 2.3):
                    Weight = Weight * 2.50
            elif (ReweightFile.mt_Selected.gen_match_2 == 1
                  or ReweightFile.mt_Selected.gen_match_2 == 3):
                if (abs(TauVector.Eta()) < 1.460):
                    Weight = Weight * 1.21
                elif (abs(TauVector.Eta()) >= 1.559):
                    Weight = Weight * 1.38

        #Top PT Reweighting
        if not args.DisableTopReweighting:
            TopFactor = 1.0
            if (FileName == "TT.root"):
                pttop1 = ReweightFile.mt_Selected.pt_top1
                if pttop1 > 400:
                    pttop1 = 400
                pttop2 = ReweightFile.mt_Selected.pt_top2
                if pttop2 > 400:
                    pttop2 = 400
                topfactor = math.sqrt(
                    math.exp(0.0615 - 0.0005 * pttop1) *
                    math.exp(0.0615 - 0.0005 * pttop2))
                Weight_TOP_UP = Weight * (2.0 * (topfactor - 1.0) + 1.0)
                Weight_TOP_DOWN = Weight
                Weight = Weight * TopFactor

        #ZPT Weighting
        if not args.DisableZPTWeighting:
            Weight_ZPT_DOWN = Weight * ReweightFile.mt_Selected.ZPTWeighting_DOWN
            Weight_ZPT_UP = Weight * ReweightFile.mt_Selected.ZPTWeighting_UP
            Weight = Weight * ReweightFile.mt_Selected.ZPTWeighting

        if FileName == "Data.root":
            Weight = 1.0

        FinalWeighting[0] = Weight
        if not args.DisableZPTWeighting:
            FinalWeighting_ZPT_DOWN[0] = Weight_ZPT_DOWN
            FinalWeighting_ZPT_UP[0] = Weight_ZPT_UP
        if not args.DisableTopReweighting and (FileName == "TT.root"):
            FinalWeighting_TOP_UP[0] = Weight_TOP_UP
            FinalWeighting_TOP_DOWN[0] = Weight_TOP_DOWN

        TheBranch.Fill()
        if not args.DisableZPTWeighting:
            TheBranch_ZPT_DOWN.Fill()
            TheBranch_ZPT_UP.Fill()
        if not args.DisableTopReweighting and (FileName == "TT.root"):
            TheBranch_TOP_UP.Fill()
            TheBranch_TOP_DOWN.Fill()

    ReweightFile.cd()
    ReweightFile.mt_Selected.Write('', ROOT.TObject.kOverwrite)
    ReweightFile.Write()
    ReweightFile.Close()
Beispiel #11
0
import ROOT
import math
ROOT.PyConfig.IgnoreCommandLineOptions = True

from PhysicsTools.NanoAODTools.postprocessing.framework.datamodel import Collection
from PhysicsTools.NanoAODTools.postprocessing.framework.eventloop import Module

from TauPOG.TauIDSFs.TauIDSFTool import TauIDSFTool
tauSFTool_jet = TauIDSFTool('2018ReReco', 'DeepTau2017v2p1VSjet', 'VVTight')
tauSFTool_ele = TauIDSFTool('2018ReReco', 'DeepTau2017v2p1VSe', 'VVTight')
tauSFTool_muo = TauIDSFTool('2018ReReco', 'DeepTau2017v2p1VSmu', 'Tight')
from TauPOG.TauIDSFs.TauIDSFTool import TauESTool
testool_jet = TauESTool('2018ReReco', 'DeepTau2017v2p1VSjet')
from TauPOG.TauIDSFs.TauIDSFTool import TauFESTool
testool_ele = TauFESTool('2018ReReco', 'DeepTau2017v2p1VSe')

from MuonPOG.MuonSFs.MuonSFTool import MuonSFTool
muonSFTool = MuonSFTool()

from PhysicsTools.NanoAODTools.postprocessing.tools import deltaR


class ZMuTauProducer(Module):
    def __init__(self, isMC_):
        self.isMC__ = isMC_
        pass

    def beginJob(self):
        pass

    def endJob(self):
def AddFinalWeights(FileToRun, args):
    print("")
    print("Creating final weights branch for: " + FileToRun)
    print("")
    CheckFile = ROOT.TFile(FileToRun)
    #make the name easier to understand
    FileName = FileToRun[FileToRun.rfind("/") + 1:]
    #Need cross section weighting. Check for it
    try:
        CheckFile.mt_Selected.CrossSectionWeighting
    except:
        print("Failed to find cross section weightings. Adding them...")
        AddCrossSectionWeightings.AddCrossSectionWeightings(FileToRun, args)
    try:
        CheckFile.mt_Selected.ZPTWeighting
    except:
        print("Failed to find ZPT Weights. Adding them...")
        AddZPTReweighting.ApplyZPTReweighting(FileToRun, args)
    #Pileup weight everything that isn't data
    if FileName != "Data.root" and FileName != "Embedded.root":
        try:
            CheckFile.mt_Selected.PileupWeight
        except:
            print("Failed to find pileup weights. Adding them...")
            AddPileupWeightings.AddPileupWeightings(FileToRun, args)
        try:
            CheckFile.mt_Selected.MuAndTriggerSF
        except:
            print("Failed to find muon scale factors. Adding them...")
            AddKITMuAndTriggerSFs.AddKITMuAndTriggerSFs(FileToRun, args)
        #try:
        #    CheckFile.mt_Selected.TriggerSF
        #except:
        #    print("Failed to find MC trigger scale factors. Adding them...")
        #    AddMCTriggerScaleFactors.AddMCTriggerScaleFactors(FileToRun,args)

    #we actually need to reload the file and the tree now, because it may have changed
    CheckFile.Close()

    ReweightFile = ROOT.TFile(FileToRun, "UPDATE")
    #we create different weights for different shapes.
    FinalWeighting = array('f', [0])
    FinalWeighting_ZPT_DOWN = array('f', [0])
    FinalWeighting_ZPT_UP = array('f', [0])
    FinalWeighting_TOP_UP = array('f', [0])
    FinalWeighting_TOP_DOWN = array('f', [0])

    TheBranch = ReweightFile.mt_Selected.Branch('FinalWeighting',
                                                FinalWeighting,
                                                'FinalWeighitng/F')
    TheBranch_ZPT_DOWN = ReweightFile.mt_Selected.Branch(
        'FinalWeighting_ZPT_DOWN', FinalWeighting_ZPT_DOWN,
        'FinalWeighitng_ZPT_DOWN/F')
    TheBranch_ZPT_UP = ReweightFile.mt_Selected.Branch(
        'FinalWeighting_ZPT_UP', FinalWeighting_ZPT_UP,
        'FinalWeighting_ZPT_UP/F')
    TheBranch_TOP_UP = ReweightFile.mt_Selected.Branch(
        'FinalWeighting_TOP_UP', FinalWeighting_TOP_UP,
        'FinalWeighting_TOP_UP/F')
    TheBranch_TOP_DOWN = ReweightFile.mt_Selected.Branch(
        'FinalWeighting_TOP_DOWN', FinalWeighting_TOP_DOWN,
        'FinalWeighting_TOP_DOWN/F')

    FirstScaleFactorFile = ROOT.TFile(
        "/data/aloeliger/CMSSW_9_4_0/src/SMHTTAnalysis/NtuplePolishing/Weightings/CorrectionsWorkspace/htt_scalefactors_v17_6.root"
    )
    FirstWorkSpace = FirstScaleFactorFile.w

    SecondScaleFactorFile = ROOT.TFile(
        "/data/aloeliger/CMSSW_9_4_0/src/SMHTTAnalysis/NtuplePolishing/Weightings/htt_scalefactors_2017_v2.root"
    )
    SecondWorkSpace = SecondScaleFactorFile.w

    print("Adding the final weighting...")

    tauSFTool = TauIDSFTool("2017ReReco", "DeepTau2017v2p1VSjet", 'Medium')

    for i in tqdm(range(ReweightFile.mt_Selected.GetEntries())):
        ReweightFile.mt_Selected.GetEntry(i)

        MuVector = ROOT.TLorentzVector()
        TauVector = ROOT.TLorentzVector()
        MuVector.SetPtEtaPhiM(ReweightFile.mt_Selected.pt_1,
                              ReweightFile.mt_Selected.eta_1,
                              ReweightFile.mt_Selected.phi_1,
                              ReweightFile.mt_Selected.m_1)
        TauVector.SetPtEtaPhiM(ReweightFile.mt_Selected.pt_2,
                               ReweightFile.mt_Selected.eta_2,
                               ReweightFile.mt_Selected.phi_2,
                               ReweightFile.mt_Selected.m_2)

        Weight = ReweightFile.mt_Selected.CrossSectionWeighting  #cross section
        #if not a data file, pileup reweight it
        if (not args.DisablePileupWeighting and FileName != "Data.root"
                and FileName != "Embedded.root"):
            Weight = Weight * ReweightFile.mt_Selected.PileupWeight
        #possible overlap on trigger SFs?
        if (not args.DisableMuAndTriggerSFs and FileName != "Data.root"
                and FileName != "Embedded.root"):
            Weight = Weight * ReweightFile.mt_Selected.MuAndTriggerSF

        #Tau ID weighting
        if FileName != "Embedded.root" and FileName != "Data.root":
            Weight = Weight * tauSFTool.getSFvsPT(TauVector.Pt())
        elif FileName == "Embedded.root":
            Weight = Weight * 0.97

        #mu to tau fake SFs
        if not args.DisableEtaWeighting:
            if (ReweightFile.mt_Selected.gen_match_2 == 2
                    or ReweightFile.mt_Selected.gen_match_2 == 4):
                if (abs(TauVector.Eta()) < 0.4):
                    Weight = Weight * 1.17
                elif (abs(TauVector.Eta()) < 0.8):
                    Weight = Weight * 1.29
                elif (abs(TauVector.Eta()) < 1.2):
                    Weight = Weight * 1.14
                elif (abs(TauVector.Eta()) < 1.7):
                    Weight = Weight * 0.93
                elif (abs(TauVector.Eta()) < 2.3):
                    Weight = Weight * 1.61
            elif (ReweightFile.mt_Selected.gen_match_2 == 1
                  or ReweightFile.mt_Selected.gen_match_2 == 3):
                if (abs(TauVector.Eta()) < 1.460):
                    Weight = Weight * 1.09
                elif (abs(TauVector.Eta()) >= 1.559):
                    Weight = Weight * 1.19

        Trigger24 = (ReweightFile.mt_Selected.passMu24
                     and ReweightFile.mt_Selected.matchMu24_1
                     and ReweightFile.mt_Selected.filterMu24_1
                     and ReweightFile.mt_Selected.pt_1 > 25.0)
        Trigger27 = (ReweightFile.mt_Selected.passMu27
                     and ReweightFile.mt_Selected.matchMu27_1
                     and ReweightFile.mt_Selected.filterMu27_1
                     and ReweightFile.mt_Selected.pt_1 > 25.0)
        Trigger2027 = (ReweightFile.mt_Selected.passMu20Tau27
                       and ReweightFile.mt_Selected.matchMu20Tau27_1
                       and ReweightFile.mt_Selected.filterMu20Tau27_1
                       and ReweightFile.mt_Selected.filterMu20Tau27_2
                       and ReweightFile.mt_Selected.pt_1 > 21
                       and ReweightFile.mt_Selected.pt_2 > 31
                       and ReweightFile.mt_Selected.pt_1 < 25
                       and abs(ReweightFile.mt_Selected.eta_1) < 2.1
                       and abs(ReweightFile.mt_Selected.eta_2) < 2.1)
        #no tau trigger matching in embedded
        if (FileName == "Embedded.root"):
            Trigger2027 = (  #ReweightFile.mt_Selected.passMu20Tau27 
                #and ReweightFile.mt_Selected.matchMu20Tau27_1
                #and ReweightFile.mt_Selected.filterMu20Tau27_1
                #and ReweightFile.mt_Selected.pt_1 > 21 and ReweightFile.mt_Selected.pt_2 > 31
                ReweightFile.mt_Selected.pt_1 > 21
                and ReweightFile.mt_Selected.pt_2 > 31
                and ReweightFile.mt_Selected.pt_1 < 25
                and abs(ReweightFile.mt_Selected.eta_1) < 2.1
                and abs(ReweightFile.mt_Selected.eta_2 < 2.1))

        #Embedded trigger whatever
        if not args.DisableEmbeddingReconstructionWeighting:
            if (FileName == "Embedded.root"):
                if ReweightFile.mt_Selected.l2_decayMode == 0:
                    Weight = Weight * 0.975
                elif ReweightFile.mt_Selected.l2_decayMode == 1:
                    Weight = Weight * 0.975 * 1.051
                elif ReweightFile.mt_Selected.l2_decayMode == 10:
                    Weight = Weight * 0.975 * 0.975 * 0.975
                FirstWorkSpace.var("m_pt").setVal(MuVector.Pt())
                FirstWorkSpace.var("m_eta").setVal(MuVector.Eta())
                FirstWorkSpace.var("gt_pt").setVal(MuVector.Pt())
                FirstWorkSpace.var("gt_eta").setVal(MuVector.Eta())
                FirstWorkSpace.var("gt1_pt").setVal(MuVector.Pt())
                FirstWorkSpace.var("gt1_eta").setVal(MuVector.Eta())
                FirstWorkSpace.var("gt2_pt").setVal(TauVector.Pt())
                FirstWorkSpace.var("gt2_eta").setVal(TauVector.Eta())
                FirstWorkSpace.var("m_iso").setVal(
                    ReweightFile.mt_Selected.iso_1)
                FirstWorkSpace.var("t_pt").setVal(TauVector.Pt())
                Weight = Weight * FirstWorkSpace.function(
                    "m_sel_trg_ratio").getVal()
                Weight = Weight * FirstWorkSpace.function(
                    "m_sel_idEmb_ratio").getVal()
                FirstWorkSpace.var("gt_pt").setVal(TauVector.Pt())
                FirstWorkSpace.var("gt_eta").setVal(TauVector.Eta())
                Weight = Weight * FirstWorkSpace.function(
                    "m_sel_idEmb_ratio").getVal()
                Weight = Weight * FirstWorkSpace.function(
                    "m_iso_binned_embed_kit_ratio").getVal()
                Weight = Weight * FirstWorkSpace.function(
                    "m_id_embed_kit_ratio").getVal()
                if (Trigger24 or Trigger27):
                    Weight = Weight * FirstWorkSpace.function(
                        "m_trg24_27_embed_kit_ratio").getVal()
                else:
                    Weight = Weight * FirstWorkSpace.function(
                        "m_trg_MuTau_Mu20Leg_kit_ratio_embed").getVal()
                    Weight = Weight * FirstWorkSpace.function(
                        "mt_emb_LooseChargedIsoPFTau27_kit_ratio").getVal()

        #Top pT reweighting
        if not args.DisableTopReweighting:
            TopFactor = 1.0
            if (FileName == "TTToHadronic.root"
                    or FileName == "TTToSemiLeptonic.root"
                    or FileName == "TTTo2L2Nu.root"):
                pttop1 = ReweightFile.mt_Selected.pt_top1
                if pttop1 > 400:
                    pttop1 = 400
                pttop2 = ReweightFile.mt_Selected.pt_top2
                if pttop2 > 400:
                    pttop2 = 400
                topfactor = math.sqrt(
                    math.exp(0.0615 - 0.0005 * pttop1) *
                    math.exp(0.0615 - 0.0005 * pttop2))
                Weight_TOP_UP = Weight * (2.0 * (topfactor - 1.0) + 1.0)
                Weight_TOP_DOWN = Weight
                Weight = Weight * TopFactor

        #ZPT Weighting
        if not args.DisableZPTWeighting:
            Weight_ZPT_DOWN = Weight * ReweightFile.mt_Selected.ZPTWeighting_DOWN
            Weight_ZPT_UP = Weight * ReweightFile.mt_Selected.ZPTWeighting_UP
            Weight = Weight * ReweightFile.mt_Selected.ZPTWeighting

        #MC Trigger Scale Factors
        #if (not args.DisableMCTriggerSFs and not(FileName == "Data.root" or FileName == "Embedded.root")):
        #    Weight = Weight * ReweightFile.mt_Selected.TriggerSF

        #ALWAYS
        if FileName == "Data.root":
            Weight = 1.0

        FinalWeighting[0] = Weight
        if not args.DisableZPTWeighting:
            FinalWeighting_ZPT_DOWN[0] = Weight_ZPT_DOWN
            FinalWeighting_ZPT_UP[0] = Weight_ZPT_UP
        if not args.DisableTopReweighting and (
                FileName == "TTToHadronic.root" or FileName
                == "TTToSemiLeptonic.root" or FileName == "TTTo2L2Nu.root"):
            FinalWeighting_TOP_UP[0] = Weight_TOP_UP
            FinalWeighting_TOP_DOWN[0] = Weight_TOP_DOWN

        TheBranch.Fill()
        if not args.DisableZPTWeighting:
            TheBranch_ZPT_DOWN.Fill()
            TheBranch_ZPT_UP.Fill()
        if not args.DisableTopReweighting and (
                FileName == "TTToHadronic.root" or FileName
                == "TTToSemiLeptonic.root" or FileName == "TTTo2L2Nu.root"):
            TheBranch_TOP_UP.Fill()
            TheBranch_TOP_DOWN.Fill()
    ReweightFile.cd()
    ReweightFile.mt_Selected.Write('', ROOT.TObject.kOverwrite)
    ReweightFile.Write()
    ReweightFile.Close()
Beispiel #13
0
from Configurations.Weights.WeightDefinition import Weight as Weight
from TauPOG.TauIDSFs.TauIDSFTool import TauIDSFTool


def CalculateTauFakeRateWeight(self, theTree):
    tauVector = ROOT.TLorentzVector()
    tauVector.SetPtEtaPhiM(theTree.pt_1, theTree.eta_1, theTree.phi_1,
                           theTree.m_1)
    self.value[0] = self.eleSFTool.getSFvsEta(
        tauVector.Eta(), theTree.gen_match_2) * self.muSFTool.getSFvsEta(
            tauVector.Eta(), theTree.gen_match_2)


tauFakeRateWeight_2016 = Weight()
tauFakeRateWeight_2016.name = 'TauFakeRateWeight'
tauFakeRateWeight_2016.eleSFTool = TauIDSFTool("2016Legacy", 'antiEleMVA6',
                                               'VLoose')
tauFakeRateWeight_2016.muSFTool = TauIDSFTool("2016Legacy", 'antiMu3', 'Tight')
tauFakeRateWeight_2016.CalculateWeight = CalculateTauFakeRateWeight

tauFakeRateWeight_2017 = Weight()
tauFakeRateWeight_2017.name = 'TauFakeRateWeight'
tauFakeRateWeight_2017.eleSFTool = TauIDSFTool("2017ReReco", 'antiEleMVA6',
                                               'VLoose')
tauFakeRateWeight_2017.muSFTool = TauIDSFTool("2017ReReco", 'antiMu3', 'Tight')
tauFakeRateWeight_2017.CalculateWeight = CalculateTauFakeRateWeight

tauFakeRateWeight_2018 = Weight()
tauFakeRateWeight_2018.name = 'TauFakeRateWeight'
tauFakeRateWeight_2018.eleSFTool = TauIDSFTool("2018ReReco", 'antiEleMVA6',
                                               'VLoose')
tauFakeRateWeight_2018.muSFTool = TauIDSFTool("2018ReReco", 'antiMu3', 'Tight')
Beispiel #14
0
class ModuleMuTau(ModuleTauPair):
    def __init__(self, fname, **kwargs):
        kwargs['channel'] = 'mutau'
        super(ModuleMuTau, self).__init__(fname, **kwargs)
        self.out = TreeProducerMuTau(fname, self)

        # TRIGGERS
        if self.year == 2016:
            self.trigger = lambda e: e.HLT_IsoMu22 or e.HLT_IsoMu22_eta2p1 or e.HLT_IsoTkMu22 or e.HLT_IsoTkMu22_eta2p1  #or e.HLT_IsoMu19_eta2p1_LooseIsoPFTau20_SingleL1
            self.muonCutPt = lambda e: 23
            self.muonCutEta = lambda e: 2.4 if e.HLT_IsoMu22 or e.HLT_IsoTkMu22 else 2.1
        elif self.year == 2017:
            self.trigger = lambda e: e.HLT_IsoMu24 or e.HLT_IsoMu27  #or e.HLT_IsoMu20_eta2p1_LooseChargedIsoPFTau27_eta2p1_CrossL1
            self.muonCutPt = lambda e: 25 if e.HLT_IsoMu24 else 28
            self.muonCutEta = lambda e: 2.4
        else:
            self.trigger = lambda e: e.HLT_IsoMu24 or e.HLT_IsoMu27  #or e.HLT_IsoMu20_eta2p1_LooseChargedIsoPFTau27_eta2p1_CrossL1
            self.muonCutPt = lambda e: 25
            self.muonCutEta = lambda e: 2.4
        self.tauCutPt = 20
        self.tauCutEta = 2.3

        # CORRECTIONS
        if self.ismc:
            self.muSFs = MuonSFs(year=self.year)
            self.tesTool = TauESTool(tauSFVersion[self.year])
            self.tauSFs = TauIDSFTool(tauSFVersion[self.year],
                                      'DeepTau2017v2p1VSjet', 'Tight')
            self.etfSFs = TauIDSFTool(tauSFVersion[self.year],
                                      'DeepTau2017v2p1VSe', 'VLoose')
            self.mtfSFs = TauIDSFTool(tauSFVersion[self.year],
                                      'DeepTau2017v2p1VSmu', 'Tight')

        # CUTFLOW
        self.out.cutflow.addcut('none', "no cut")
        self.out.cutflow.addcut('trig', "trigger")
        self.out.cutflow.addcut('muon', "muon")
        self.out.cutflow.addcut('tau', "tau")
        self.out.cutflow.addcut('pair', "pair")
        self.out.cutflow.addcut('weight', "no cut, weighted", 15)
        self.out.cutflow.addcut('weight_no0PU', "no cut, weighted, PU>0",
                                16)  # use for normalization

    def beginJob(self):
        """Before processing any events or files."""
        super(ModuleMuTau, self).beginJob()
        print ">>> %-12s = %s" % ('muonCutPt', self.muonCutPt)
        print ">>> %-12s = %s" % ('muonCutEta', self.muonCutEta)
        print ">>> %-12s = %s" % ('tauCutPt', self.tauCutPt)
        print ">>> %-12s = %s" % ('tauCutEta', self.tauCutEta)
        pass

    def analyze(self, event):
        """Process and pre-select events; fill branches and return True if the events passes,
    return False otherwise."""
        sys.stdout.flush()

        ##### NO CUT #####################################
        self.out.cutflow.fill('none')
        if self.isdata:
            self.out.cutflow.fill('weight', 1.)
            if event.PV_npvs > 0:
                self.out.cutflow.fill('weight_no0PU', 1.)
            else:
                return False
        else:
            self.out.cutflow.fill('weight', event.genWeight)
            self.out.pileup.Fill(event.Pileup_nTrueInt)
            if event.Pileup_nTrueInt > 0:
                self.out.cutflow.fill('weight_no0PU', event.genWeight)
            else:
                return False

        ##### TRIGGER ####################################
        if not self.trigger(event):
            return False
        self.out.cutflow.fill('trig')

        ##### MUON #######################################
        muons = []
        for muon in Collection(event, 'Muon'):
            if muon.pt < self.muonCutPt(event): continue
            if abs(muon.eta) > self.muonCutEta(event): continue
            if abs(muon.dz) > 0.2: continue
            if abs(muon.dxy) > 0.045: continue
            if not muon.mediumId: continue
            if muon.pfRelIso04_all > 0.50: continue
            muons.append(muon)
        if len(muons) == 0:
            return False
        self.out.cutflow.fill('muon')

        ##### TAU ########################################
        taus = []
        for tau in Collection(event, 'Tau'):
            if abs(tau.eta) > self.tauCutEta: continue
            if abs(tau.dz) > 0.2: continue
            if tau.decayMode not in [0, 1, 10, 11]: continue
            if abs(tau.charge) != 1: continue
            if self.ismc:
                genmatch = tau.genPartFlav
                if genmatch == 5:  # real tau
                    tes = 1
                    if self.tes != None:
                        tes *= self.tes
                    else:
                        tes *= self.tesTool.getTES(tau.pt,
                                                   tau.decayMode,
                                                   unc=self.tessys)
                    if tes != 1:
                        tau.pt *= tes
                        tau.mass *= tes
                elif self.ltf != 1.0 and 0 < genmatch < 5:  # lepton -> tau fake
                    tau.pt *= self.ltf
                    tau.mass *= self.ltf
                elif self.jtf != 1.0 and genmatch == 0:  # jet -> tau fake
                    tau.pt *= self.jtf
                    tau.mass *= self.jtf
            if tau.pt < self.tauCutPt: continue
            if tau.idDeepTau2017v2p1VSe < 1: continue
            if tau.idDeepTau2017v2p1VSmu < 1: continue
            taus.append(tau)
        if len(taus) == 0:
            return False
        self.out.cutflow.fill('tau')

        ##### MUTAU PAIR #################################
        ltaus = []
        for muon in muons:
            for tau in taus:
                if tau.DeltaR(muon) < 0.5: continue
                ltau = LeptonTauPair(muon, muon.pfRelIso04_all, tau,
                                     tau.rawDeepTau2017v2p1VSjet)
                ltaus.append(ltau)
        if len(ltaus) == 0:
            return False
        muon, tau = max(ltaus).pair
        muon.tlv = muon.p4()
        tau.tlv = tau.p4()
        self.out.cutflow.fill('pair')

        # VETOS
        extramuon_veto, extraelec_veto, dilepton_veto = getLeptonVetoes(
            event, [], [muon], [tau], self.channel)
        self.out.extramuon_veto[0], self.out.extraelec_veto[
            0], self.out.dilepton_veto[0] = getLeptonVetoes(
                event, [], [muon], [], self.channel)
        self.out.lepton_vetoes[0] = self.out.extramuon_veto[
            0] or self.out.extraelec_veto[0] or self.out.dilepton_veto[0]
        self.out.lepton_vetoes_notau[
            0] = extramuon_veto or extraelec_veto or dilepton_veto

        # EVENT
        self.fillEventBranches(event)

        # MUON
        self.out.pt_1[0] = muon.pt
        self.out.eta_1[0] = muon.eta
        self.out.phi_1[0] = muon.phi
        self.out.m_1[0] = muon.mass
        self.out.y_1[0] = muon.tlv.Rapidity()
        self.out.dxy_1[0] = muon.dxy
        self.out.dz_1[0] = muon.dz
        self.out.q_1[0] = muon.charge
        self.out.iso_1[0] = muon.pfRelIso04_all

        # TAU
        self.out.pt_2[0] = tau.pt
        self.out.eta_2[0] = tau.eta
        self.out.phi_2[0] = tau.phi
        self.out.m_2[0] = tau.mass
        self.out.y_2[0] = tau.tlv.Rapidity()
        self.out.dxy_2[0] = tau.dxy
        self.out.dz_2[0] = tau.dz
        self.out.q_2[0] = tau.charge
        self.out.dm_2[0] = tau.decayMode
        self.out.iso_2[0] = tau.rawIso
        self.out.idiso_2[0] = idIso(tau)  # cut-based tau isolation (rawIso)
        self.out.rawAntiEle_2[0] = tau.rawAntiEle
        self.out.rawMVAoldDM2017v2_2[0] = tau.rawMVAoldDM2017v2
        self.out.rawMVAnewDM2017v2_2[0] = tau.rawMVAnewDM2017v2
        self.out.rawDeepTau2017v2p1VSe_2[0] = tau.rawDeepTau2017v2p1VSe
        self.out.rawDeepTau2017v2p1VSmu_2[0] = tau.rawDeepTau2017v2p1VSmu
        self.out.rawDeepTau2017v2p1VSjet_2[0] = tau.rawDeepTau2017v2p1VSjet
        self.out.idAntiEle_2[0] = tau.idAntiEle
        self.out.idAntiMu_2[0] = tau.idAntiMu
        self.out.idDecayMode_2[0] = tau.idDecayMode
        self.out.idDecayModeNewDMs_2[0] = tau.idDecayModeNewDMs
        self.out.idMVAoldDM2017v2_2[0] = tau.idMVAoldDM2017v2
        self.out.idMVAnewDM2017v2_2[0] = tau.idMVAnewDM2017v2
        self.out.idDeepTau2017v2p1VSe_2[0] = tau.idDeepTau2017v2p1VSe
        self.out.idDeepTau2017v2p1VSmu_2[0] = tau.idDeepTau2017v2p1VSmu
        self.out.idDeepTau2017v2p1VSjet_2[0] = tau.idDeepTau2017v2p1VSjet
        self.out.chargedIso_2[0] = tau.chargedIso
        self.out.neutralIso_2[0] = tau.neutralIso
        self.out.leadTkPtOverTauPt_2[0] = tau.leadTkPtOverTauPt
        self.out.photonsOutsideSignalCone_2[0] = tau.photonsOutsideSignalCone
        self.out.puCorr_2[0] = tau.puCorr

        # GENERATOR
        if self.ismc:
            self.out.genmatch_1[0] = muon.genPartFlav
            self.out.genmatch_2[0] = tau.genPartFlav
            dRmin = 0.5
            taumatch = None
            for genvistau in Collection(event, 'GenVisTau'):
                dR = genvistau.DeltaR(tau)
                if dR < dRmin:
                    dRmin = dR
                    taumatch = genvistau
            if taumatch:
                self.out.genvistaupt_2[0] = taumatch.pt
                self.out.genvistaueta_2[0] = taumatch.eta
                self.out.genvistauphi_2[0] = taumatch.phi
                self.out.gendm_2[0] = taumatch.status
            else:
                self.out.genvistaupt_2[0] = -1
                self.out.genvistaueta_2[0] = -9
                self.out.genvistauphi_2[0] = -9
                self.out.gendm_2[0] = -1

        # JETS
        jets, met, njets_vars, met_vars = self.fillJetBranches(
            event, muon, tau)
        if tau.jetIdx >= 0:
            self.out.jpt_match_2[0] = event.Jet_pt[tau.jetIdx]
            if self.ismc:
                if event.Jet_genJetIdx[tau.jetIdx] >= 0:
                    self.out.jpt_genmatch_2[0] = event.GenJet_pt[
                        event.Jet_genJetIdx[tau.jetIdx]]
                else:
                    self.out.jpt_genmatch_2[0] = -1
        else:
            self.out.jpt_match_2[0] = -1

        # WEIGHTS
        if self.ismc:
            self.fillCommonCorrBraches(event, jets, met, njets_vars, met_vars)
            if muon.pfRelIso04_all < 0.50 and tau.idDeepTau2017v2p1VSjet >= 2:
                self.btagTool.fillEffMaps(jets, usejec=self.dojec)

            # MUON WEIGHTS
            self.out.trigweight[0] = self.muSFs.getTriggerSF(muon.pt, muon.eta)
            self.out.idisoweight_1[0] = self.muSFs.getIdIsoSF(
                muon.pt, muon.eta)

            # DEFAULTS
            self.out.idweight_2[0] = 1.
            self.out.ltfweight_2[0] = 1.
            if not self.dotight:
                self.out.idweightUp_2[0] = 1.
                self.out.idweightDown_2[0] = 1.
                self.out.ltfweightUp_2[0] = 1.
                self.out.ltfweightDown_2[0] = 1.

            # TAU WEIGHTS
            if tau.genPartFlav == 5:  # real tau
                self.out.idweight_2[0] = self.tauSFs.getSFvsPT(tau.pt)
                if not self.dotight:
                    self.out.idweightUp_2[0] = self.tauSFs.getSFvsPT(tau.pt,
                                                                     unc='Up')
                    self.out.idweightDown_2[0] = self.tauSFs.getSFvsPT(
                        tau.pt, unc='Down')
            elif tau.genPartFlav in [1, 3]:  # muon -> tau fake
                self.out.ltfweight_2[0] = self.etfSFs.getSFvsEta(
                    tau.eta, tau.genPartFlav)
                if not self.dotight:
                    self.out.ltfweightUp_2[0] = self.etfSFs.getSFvsEta(
                        tau.eta, tau.genPartFlav, unc='Up')
                    self.out.ltfweightDown_2[0] = self.etfSFs.getSFvsEta(
                        tau.eta, tau.genPartFlav, unc='Down')
            elif tau.genPartFlav in [2, 4]:  # electron -> tau fake
                self.out.ltfweight_2[0] = self.mtfSFs.getSFvsEta(
                    tau.eta, tau.genPartFlav)
                if not self.dotight:
                    self.out.ltfweightUp_2[0] = self.mtfSFs.getSFvsEta(
                        tau.eta, tau.genPartFlav, unc='Up')
                    self.out.ltfweightDown_2[0] = self.mtfSFs.getSFvsEta(
                        tau.eta, tau.genPartFlav, unc='Down')
            self.out.weight[0] = self.out.genweight[0] * self.out.puweight[
                0] * self.out.trigweight[0] * self.out.idisoweight_1[
                    0]  #*self.out.idisoweight_2[0]
        elif self.isembed:
            ###self.applyCommonEmbdedCorrections(event,jets,jetIds50,met,njets_vars,met_vars)
            self.out.genweight[0] = event.genWeight
            self.out.trackweight[
                0] = 0.975 if tau.decayMode == 0 else 1.0247 if tau.decayMode == 1 else 0.927 if tau.decayMode == 10 else 0.974 if tau.decayMode == 11 else 1.0

        # MET & DILEPTON VARIABLES
        self.fillMETAndDiLeptonBranches(event, muon.tlv, tau.tlv, met,
                                        met_vars)

        self.out.fill()
        return True
class lepSFProducer(Module):
    """ This module is copied from the NanoAOD-tools,
    but developed for lastest SUSY Lepton ID
    """
    def __init__(self,
                 era,
                 muonSelectionTag="Loose",
                 electronSelectionTag="Veto",
                 photonSelectionTag="Loose",
                 tauSelectionTag="Medium"):
        self.era = era
        self.muonSelectionTag = muonSelectionTag
        self.electronSelectionTag = electronSelectionTag
        self.photonSelectionTag = photonSelectionTag
        self.tauSelectionTag = tauSelectionTag

        #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Muon ~~~~~
        # Only looseID miniIso SF existed for 2016
        mu_f = []
        mu_h = []
        if self.era == "2016":
            mu_f += [
                "Muon_IDScaleFactor_wSys_%sGH.root" % self.era,
                "Muon_LooseID_MiniIso0p2SF_2016.root"
            ]
            mu_h += [
                "NUM_%sID_DEN_genTracks_eta_pt" % self.muonSelectionTag, "SF"
            ]
        if self.era == "2017":
            mu_f += [
                "Muon_IDScaleFactor_wSys_%s.root" % self.era,
                "Muon_%sID_MiniIso0p2SF_%s.root" %
                (self.muonSelectionTag, self.era)
            ]
            mu_h += [
                "NUM_%sID_DEN_genTracks_pt_abseta" % self.muonSelectionTag,
                "TnP_MC_NUM_MiniIso02Cut_DEN_%sID_PAR_pt_eta" %
                self.muonSelectionTag
            ]
        elif self.era == "2018":
            ##  SUSY recommend to use the 2017 Data/FullSim SFs for MiniIso also
            ##  for 2018, as no changes are expected and these SFs are very close to 1.
            mu_f += [
                "Muon_IDScaleFactor_wSys_%s.root" % self.era,
                "Muon_%sID_MiniIso0p2SF_%s.root" %
                (self.muonSelectionTag, "2017")
            ]
            mu_h += [
                "NUM_%sID_DEN_TrackerMuons_pt_abseta" % self.muonSelectionTag,
                "TnP_MC_NUM_MiniIso02Cut_DEN_%sID_PAR_pt_eta" %
                self.muonSelectionTag
            ]
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Electron ~~~~~
        if self.era == "2016":
            el_f = [
                "Electron_GT20GeV_RecoSF_2017v2ID_Run%s.root" % self.era,
                "Electron_LT20GeV_RecoSF_2017v2ID_Run%s.root" % self.era,
                "Electron_SUSYScaleFactors_2017v2ID_Run%s.root" % self.era,
                "Electron_SUSYScaleFactors_2017v2ID_Run%s.root" % self.era
            ]
            el_h = [
                "EGamma_SF2D", "EGamma_SF2D",
                "Run%s_CutBased%sNoIso94XV2" %
                (self.era, self.electronSelectionTag),
                "Run%s_Mini" % self.era
            ]
        elif self.era == "2017":
            el_f = [
                "Electron_GT20GeV_RecoSF_2017v2ID_Run%s.root" % self.era,
                "Electron_LT20GeV_RecoSF_2017v2ID_Run%s.root" % self.era,
                "Electron_SUSYScaleFactors_2017v2ID_Run%s.root" % self.era,
                "Electron_SUSYScaleFactors_2017v2ID_Run%s.root" % self.era
            ]
            el_h = [
                "EGamma_SF2D", "EGamma_SF2D",
                "Run%s_CutBased%sNoIso94XV2" %
                (self.era, self.electronSelectionTag),
                "Run%s_MVAVLooseTightIP2DMini" % self.era
            ]
        elif self.era == "2018":
            el_f = [
                "Electron_GT10GeV_RecoSF_2017v2ID_Run%s.root" % self.era,
                "Electron_SUSYScaleFactors_2017v2ID_Run%s.root" % self.era,
                "Electron_SUSYScaleFactors_2017v2ID_Run%s.root" % self.era
            ]
            el_h = [
                "EGamma_SF2D",
                "Run%s_CutBased%sNoIso94XV2" %
                (self.era, self.electronSelectionTag),
                "Run%s_Mini" % self.era
            ]

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Photon ~~~~~

# The production used 2016v2 ID for 2016 photon
        if self.era == "2016":
            pho_f = [
                "Photon_%s_80XCutbased_%s.root" %
                (self.photonSelectionTag, self.era)
            ]
            pho_h = ["EGamma_SF2D"]
        else:
            pho_f = [
                "Photon_%s_2017v2Cutbased_%s.root" %
                (self.photonSelectionTag, self.era)
            ]
            pho_h = ["EGamma_SF2D"]

        # In addition to ID scale factors, analysis using it should
        # apply the electron veto scale factors

        if self.era == "2016":
            eleveto_f = ["ElectronVeto_ScaleFactors_80X_2016.root"]
            eleveto_h = ["Scaling_Factors_HasPix_R9 Inclusive"]
        else:
            eleveto_f = ["ElectronVeto_PixelSeed_ScaleFactors_2017.root"]
            eleveto_h = ["%s_ID" % self.photonSelectionTag]
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Tau ~~~~~
# Update to new TauPOG era mapping
        self.TauPOGEraMap = {
            "2016": "2016Legacy",
            "2017": "2017ReReco",
            "2018": "2018ReReco",
        }
        self.tauSFTool = TauIDSFTool(self.TauPOGEraMap[self.era],
                                     'MVAoldDM2017v2', self.tauSelectionTag)

        mu_f = [
            "%s/src/PhysicsTools/NanoSUSYTools/data/leptonSF/" %
            os.environ['CMSSW_BASE'] + f for f in mu_f
        ]
        el_f = [
            "%s/src/PhysicsTools/NanoSUSYTools/data/leptonSF/" %
            os.environ['CMSSW_BASE'] + f for f in el_f
        ]
        pho_f = [
            "%s/src/PhysicsTools/NanoSUSYTools/data/leptonSF/" %
            os.environ['CMSSW_BASE'] + f for f in pho_f
        ]
        eleveto_f = [
            "%s/src/PhysicsTools/NanoSUSYTools/data/leptonSF/" %
            os.environ['CMSSW_BASE'] + f for f in eleveto_f
        ]

        self.mu_f = ROOT.std.vector(str)(len(mu_f))
        self.mu_h = ROOT.std.vector(str)(len(mu_f))
        for i in range(len(mu_f)):
            self.mu_f[i] = mu_f[i]
            self.mu_h[i] = mu_h[i]
        self.el_f = ROOT.std.vector(str)(len(el_f))
        self.el_h = ROOT.std.vector(str)(len(el_f))
        for i in range(len(el_f)):
            self.el_f[i] = el_f[i]
            self.el_h[i] = el_h[i]
        self.pho_f = ROOT.std.vector(str)(len(pho_f))
        self.pho_h = ROOT.std.vector(str)(len(pho_f))
        for i in range(len(pho_f)):
            self.pho_f[i] = pho_f[i]
            self.pho_h[i] = pho_h[i]
        self.eleveto_f = ROOT.std.vector(str)(len(eleveto_f))
        self.eleveto_h = ROOT.std.vector(str)(len(eleveto_f))
        for i in range(len(eleveto_f)):
            self.eleveto_f[i] = eleveto_f[i]
            self.eleveto_h[i] = eleveto_h[i]

        for library in [
                "libCondFormatsJetMETObjects", "libPhysicsToolsNanoAODTools"
        ]:
            if library not in ROOT.gSystem.GetLibraries():
                print("Load Library '%s'" % library)
                ROOT.gSystem.Load(library)

    def beginJob(self):
        self._worker_mu = ROOT.LeptonEfficiencyCorrector(self.mu_f, self.mu_h)
        self._worker_el = ROOT.LeptonEfficiencyCorrector(self.el_f, self.el_h)
        self._worker_pho = ROOT.LeptonEfficiencyCorrector(
            self.pho_f, self.pho_h)
        self._worker_eleveto = ROOT.LeptonEfficiencyCorrector(
            self.eleveto_f, self.eleveto_h)

    def endJob(self):
        pass

    def beginFile(self, inputFile, outputFile, inputTree, wrappedOutputTree):
        self.out = wrappedOutputTree
        self.out.branch("Muon_%sSF" % self.muonSelectionTag            , "F" , \
                        lenVar="nMuon", title="Muon scale factor per Muon")
        self.out.branch("Muon_%sSFErr" % self.muonSelectionTag         , "F" , \
                        lenVar="nMuon", title="Muon scale factor error per Muon")
        self.out.branch("Electron_%sSF" % self.electronSelectionTag    , "F" , \
                        lenVar="nElectron", title="Reco+ID scale factor error per Electron")
        self.out.branch("Electron_%sSFErr" % self.electronSelectionTag , "F" , \
                        lenVar="nElectron", title="Reco+ID scale factor per Electron")
        self.out.branch("Photon_%sSF" % self.photonSelectionTag    , "F" , \
                        lenVar="nPhoton", title="ID scale factor per Photon")
        self.out.branch("Photon_%sSFErr" % self.photonSelectionTag , "F" , \
                        lenVar="nPhoton", title="ID scale factor error  per Photon")
        self.out.branch("Tau_%sSF" % self.tauSelectionTag    , "F" , \
                        lenVar="nTau", title="ID scale factor per Tau")
        self.out.branch("Tau_%sSF_Up" % self.tauSelectionTag    , "F" , \
                        lenVar="nTau", title="ID scale factor up error per Tau")
        self.out.branch("Tau_%sSF_Down" % self.tauSelectionTag    , "F" , \
                        lenVar="nTau", title="ID scale factor down error per Tau")

    def endFile(self, inputFile, outputFile, inputTree, wrappedOutputTree):
        pass

    def analyze(self, event):
        """process event, return True (go to next module) or False (fail, go to next event)"""
        muons = Collection(event, "Muon")
        electrons = Collection(event, "Electron")
        photons = Collection(event, "Photon")
        taus = Collection(event, "Tau")
        gens = Collection(event, "GenPart")

        sf_el = [
            self._worker_el.getSF(el.pdgId, el.pt, el.eta) for el in electrons
        ]
        if self.era == "2016":
            sf_mu = [self._worker_mu.getSF(12, mu.pt, mu.eta) for mu in muons]
        else:
            sf_mu = [
                self._worker_mu.getSF(mu.pdgId, mu.pt, mu.eta) for mu in muons
            ]
        sf_pho = [
            self._worker_pho.getSF(pho.pdgId, pho.pt, pho.eta)
            for pho in photons
        ]

        sferr_el = [
            self._worker_el.getSFErr(el.pdgId, el.pt, el.eta)
            for el in electrons
        ]
        if self.era == "2016":
            sferr_mu = [
                self._worker_mu.getSFErr(12, mu.pt, mu.eta) for mu in muons
            ]
        else:
            sferr_mu = [
                self._worker_mu.getSFErr(mu.pdgId, mu.pt, mu.eta)
                for mu in muons
            ]
        sferr_pho = [
            self._worker_pho.getSFErr(pho.pdgId, pho.pt, pho.eta)
            for pho in photons
        ]

        sferr_el = [a / b for a, b in zip(sferr_el, sf_el)]
        sferr_mu = [a / b for a, b in zip(sferr_mu, sf_mu)]

        #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Photon ~~~~~
        sf_eleveto = []
        sferr_eleveto = []
        if self.era == "2016":
            sf_eleveto = [
                self._worker_eleveto.getSF(pho.pdgId, pho.pt, abs(pho.eta))
                for pho in photons
            ]
            sferr_eleveto = [
                self._worker_eleveto.getSFErr(pho.pdgId, pho.pt, abs(pho.eta))
                for pho in photons
            ]
        else:
            for pho in photons:
                binx = 1 if pho.r9 > 0.94 else 2
                binx = binx + 3 if pho.isScEtaEE else binx
                sf_eleveto.append(
                    self._worker_eleveto.getSF(pho.pdgId, 0, binx))
                sferr_eleveto.append(
                    self._worker_eleveto.getSFErr(pho.pdgId, 0, binx))
        ssf_pho = [a * b for a, b in zip(sf_pho, sf_eleveto)]
        ssferr_pho = [
            math.sqrt(
                ((serrp / sp)**2 + (serre / se)**2)) / ssf if ssf != 0 else 0
            for sp, se, serrp, serre, ssf in zip(sf_pho, sf_eleveto, sferr_pho,
                                                 sferr_eleveto, ssf_pho)
        ]

        #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Tau ~~~~~
        sf_tau = []
        sf_tau_up = []
        sf_tau_down = []
        for tau in taus:
            genmatch = -1
            ## genPartFlave: 1 = prompt electron, 2 = prompt muon, 3 = tau->e decay,
            ## 4 = tau->mu decay, 5 = hadronic tau decay, 0 = unknown or unmatched
            if tau.genPartFlav >= 3:
                genmatch = 5
            sf_tau.append(self.tauSFTool.getSFvsPT(tau.pt, genmatch))
            sf_tau_up.append(
                self.tauSFTool.getSFvsPT(tau.pt, genmatch, unc="Up"))
            sf_tau_down.append(
                self.tauSFTool.getSFvsPT(tau.pt, genmatch, unc="Down"))

        #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Photon Electron Veto SF ~~~~~

        self.out.fillBranch("Muon_%sSF" % self.muonSelectionTag, sf_mu)
        self.out.fillBranch("Muon_%sSFErr" % self.muonSelectionTag, sferr_mu)
        self.out.fillBranch("Electron_%sSF" % self.electronSelectionTag, sf_el)
        self.out.fillBranch("Electron_%sSFErr" % self.electronSelectionTag,
                            sferr_el)
        self.out.fillBranch("Photon_%sSF" % self.photonSelectionTag, ssf_pho)
        self.out.fillBranch("Photon_%sSFErr" % self.photonSelectionTag,
                            ssferr_pho)
        self.out.fillBranch("Tau_%sSF" % self.tauSelectionTag, sf_tau)
        self.out.fillBranch("Tau_%sSF_Up" % self.tauSelectionTag, sf_tau_up)
        self.out.fillBranch("Tau_%sSF_Down" % self.tauSelectionTag,
                            sf_tau_down)
        return True
    def __init__(self,
                 era,
                 muonSelectionTag="Loose",
                 electronSelectionTag="Veto",
                 photonSelectionTag="Loose",
                 tauSelectionTag="Medium"):
        self.era = era
        self.muonSelectionTag = muonSelectionTag
        self.electronSelectionTag = electronSelectionTag
        self.photonSelectionTag = photonSelectionTag
        self.tauSelectionTag = tauSelectionTag

        #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Muon ~~~~~
        # Only looseID miniIso SF existed for 2016
        mu_f = []
        mu_h = []
        if self.era == "2016":
            mu_f += [
                "Muon_IDScaleFactor_wSys_%sGH.root" % self.era,
                "Muon_LooseID_MiniIso0p2SF_2016.root"
            ]
            mu_h += [
                "NUM_%sID_DEN_genTracks_eta_pt" % self.muonSelectionTag, "SF"
            ]
        if self.era == "2017":
            mu_f += [
                "Muon_IDScaleFactor_wSys_%s.root" % self.era,
                "Muon_%sID_MiniIso0p2SF_%s.root" %
                (self.muonSelectionTag, self.era)
            ]
            mu_h += [
                "NUM_%sID_DEN_genTracks_pt_abseta" % self.muonSelectionTag,
                "TnP_MC_NUM_MiniIso02Cut_DEN_%sID_PAR_pt_eta" %
                self.muonSelectionTag
            ]
        elif self.era == "2018":
            ##  SUSY recommend to use the 2017 Data/FullSim SFs for MiniIso also
            ##  for 2018, as no changes are expected and these SFs are very close to 1.
            mu_f += [
                "Muon_IDScaleFactor_wSys_%s.root" % self.era,
                "Muon_%sID_MiniIso0p2SF_%s.root" %
                (self.muonSelectionTag, "2017")
            ]
            mu_h += [
                "NUM_%sID_DEN_TrackerMuons_pt_abseta" % self.muonSelectionTag,
                "TnP_MC_NUM_MiniIso02Cut_DEN_%sID_PAR_pt_eta" %
                self.muonSelectionTag
            ]
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Electron ~~~~~
        if self.era == "2016":
            el_f = [
                "Electron_GT20GeV_RecoSF_2017v2ID_Run%s.root" % self.era,
                "Electron_LT20GeV_RecoSF_2017v2ID_Run%s.root" % self.era,
                "Electron_SUSYScaleFactors_2017v2ID_Run%s.root" % self.era,
                "Electron_SUSYScaleFactors_2017v2ID_Run%s.root" % self.era
            ]
            el_h = [
                "EGamma_SF2D", "EGamma_SF2D",
                "Run%s_CutBased%sNoIso94XV2" %
                (self.era, self.electronSelectionTag),
                "Run%s_Mini" % self.era
            ]
        elif self.era == "2017":
            el_f = [
                "Electron_GT20GeV_RecoSF_2017v2ID_Run%s.root" % self.era,
                "Electron_LT20GeV_RecoSF_2017v2ID_Run%s.root" % self.era,
                "Electron_SUSYScaleFactors_2017v2ID_Run%s.root" % self.era,
                "Electron_SUSYScaleFactors_2017v2ID_Run%s.root" % self.era
            ]
            el_h = [
                "EGamma_SF2D", "EGamma_SF2D",
                "Run%s_CutBased%sNoIso94XV2" %
                (self.era, self.electronSelectionTag),
                "Run%s_MVAVLooseTightIP2DMini" % self.era
            ]
        elif self.era == "2018":
            el_f = [
                "Electron_GT10GeV_RecoSF_2017v2ID_Run%s.root" % self.era,
                "Electron_SUSYScaleFactors_2017v2ID_Run%s.root" % self.era,
                "Electron_SUSYScaleFactors_2017v2ID_Run%s.root" % self.era
            ]
            el_h = [
                "EGamma_SF2D",
                "Run%s_CutBased%sNoIso94XV2" %
                (self.era, self.electronSelectionTag),
                "Run%s_Mini" % self.era
            ]

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Photon ~~~~~

# The production used 2016v2 ID for 2016 photon
        if self.era == "2016":
            pho_f = [
                "Photon_%s_80XCutbased_%s.root" %
                (self.photonSelectionTag, self.era)
            ]
            pho_h = ["EGamma_SF2D"]
        else:
            pho_f = [
                "Photon_%s_2017v2Cutbased_%s.root" %
                (self.photonSelectionTag, self.era)
            ]
            pho_h = ["EGamma_SF2D"]

        # In addition to ID scale factors, analysis using it should
        # apply the electron veto scale factors

        if self.era == "2016":
            eleveto_f = ["ElectronVeto_ScaleFactors_80X_2016.root"]
            eleveto_h = ["Scaling_Factors_HasPix_R9 Inclusive"]
        else:
            eleveto_f = ["ElectronVeto_PixelSeed_ScaleFactors_2017.root"]
            eleveto_h = ["%s_ID" % self.photonSelectionTag]
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Tau ~~~~~
# Update to new TauPOG era mapping
        self.TauPOGEraMap = {
            "2016": "2016Legacy",
            "2017": "2017ReReco",
            "2018": "2018ReReco",
        }
        self.tauSFTool = TauIDSFTool(self.TauPOGEraMap[self.era],
                                     'MVAoldDM2017v2', self.tauSelectionTag)

        mu_f = [
            "%s/src/PhysicsTools/NanoSUSYTools/data/leptonSF/" %
            os.environ['CMSSW_BASE'] + f for f in mu_f
        ]
        el_f = [
            "%s/src/PhysicsTools/NanoSUSYTools/data/leptonSF/" %
            os.environ['CMSSW_BASE'] + f for f in el_f
        ]
        pho_f = [
            "%s/src/PhysicsTools/NanoSUSYTools/data/leptonSF/" %
            os.environ['CMSSW_BASE'] + f for f in pho_f
        ]
        eleveto_f = [
            "%s/src/PhysicsTools/NanoSUSYTools/data/leptonSF/" %
            os.environ['CMSSW_BASE'] + f for f in eleveto_f
        ]

        self.mu_f = ROOT.std.vector(str)(len(mu_f))
        self.mu_h = ROOT.std.vector(str)(len(mu_f))
        for i in range(len(mu_f)):
            self.mu_f[i] = mu_f[i]
            self.mu_h[i] = mu_h[i]
        self.el_f = ROOT.std.vector(str)(len(el_f))
        self.el_h = ROOT.std.vector(str)(len(el_f))
        for i in range(len(el_f)):
            self.el_f[i] = el_f[i]
            self.el_h[i] = el_h[i]
        self.pho_f = ROOT.std.vector(str)(len(pho_f))
        self.pho_h = ROOT.std.vector(str)(len(pho_f))
        for i in range(len(pho_f)):
            self.pho_f[i] = pho_f[i]
            self.pho_h[i] = pho_h[i]
        self.eleveto_f = ROOT.std.vector(str)(len(eleveto_f))
        self.eleveto_h = ROOT.std.vector(str)(len(eleveto_f))
        for i in range(len(eleveto_f)):
            self.eleveto_f[i] = eleveto_f[i]
            self.eleveto_h[i] = eleveto_h[i]

        for library in [
                "libCondFormatsJetMETObjects", "libPhysicsToolsNanoAODTools"
        ]:
            if library not in ROOT.gSystem.GetLibraries():
                print("Load Library '%s'" % library)
                ROOT.gSystem.Load(library)
Beispiel #17
0
def printSFTable(year, id, wp, vs='pt', emb=False, otherVSlepWP=False):
    assert vs in ['pt', 'dm',
                  'eta'], "'vs' argument should be pt', 'dm' or 'eta'!"
    dm = (vs == 'dm')
    if emb and 'VSjet' not in id:
        print "SFs for ID '%s' not available for embedded samples. Skipping..." % id
        return
    sftool = TauIDSFTool(year,
                         id,
                         wp,
                         dm=dm,
                         emb=emb,
                         otherVSlepWP=otherVSlepWP)
    if vs == 'pt':
        ptvals = [
            10,
            20,
            21,
            25,
            26,
            30,
            31,
            35,
            40,
            50,
            70,
            100,
            200,
            500,
            600,
            700,
            800,
            1000,
            1500,
            2000,
        ]
        print ">>> "
        print ">>> SF for %s WP of %s in %s" % (wp, id, year)
        print ">>> "
        print ">>> %10s" % ('var \ pt') + ''.join("%9.1f" % pt
                                                  for pt in ptvals)
        print ">>> %10s" % ("central") + ''.join(
            "%9.5f" % sftool.getSFvsPT(pt, 5) for pt in ptvals)
        print ">>> %10s" % ("up") + ''.join(
            "%9.5f" % sftool.getSFvsPT(pt, 5, 'Up') for pt in ptvals)
        print ">>> %10s" % ("down") + ''.join(
            "%9.5f" % sftool.getSFvsPT(pt, 5, 'Down') for pt in ptvals)
        print ">>> "
        ###sftool.getSFvsDM(25,1,5)   # results in an error
        ###sftool.getSFvsEta(1.5,1,5) # results in an error
    elif vs == 'dm':
        dmvals = [0, 1, 5, 6, 10, 11]
        for pt in [25, 50]:
            print ">>> "
            print ">>> SF for %s WP of %s in %s with pT = %s GeV" % (wp, id,
                                                                     year, pt)
            print ">>> "
            print ">>> %10s" % ('var \ DM') + ''.join("%9d" % dm
                                                      for dm in dmvals)
            print ">>> %10s" % ("central") + ''.join(
                "%9.5f" % sftool.getSFvsDM(pt, dm, 5) for dm in dmvals)
            print ">>> %10s" % ("up") + ''.join(
                "%9.5f" % sftool.getSFvsDM(pt, dm, 5, 'Up') for dm in dmvals)
            print ">>> %10s" % ("down") + ''.join(
                "%9.5f" % sftool.getSFvsDM(pt, dm, 5, 'Down') for dm in dmvals)
            print ">>> "
            ###sftool.getSFvsPT(pt,5)     # results in an error
            ###sftool.getSFvsEta(1.5,1,5) # results in an error
    elif vs == 'eta':
        if emb:
            print "vsEta binned SFs not available for embedded samples. Skipping..."
            return
        etavals = [0, 0.2, 0.5, 1.0, 1.5, 2.0, 2.2, 2.3, 2.4]
        for genmatch in [1, 2]:
            print ">>> "
            print ">>> SF for %s WP of %s in %s with genmatch %d" % (
                wp, id, year, genmatch)
            print ">>> "
            print ">>> %10s" % ('var \ eta') + ''.join("%9.3f" % eta
                                                       for eta in etavals)
            print ">>> %10s" % ("central") + ''.join(
                "%9.5f" % sftool.getSFvsEta(eta, genmatch) for eta in etavals)
            print ">>> %10s" % ("up") + ''.join(
                "%9.5f" % sftool.getSFvsEta(eta, genmatch, 'Up')
                for eta in etavals)
            print ">>> %10s" % ("down") + ''.join(
                "%9.5f" % sftool.getSFvsEta(eta, genmatch, 'Down')
                for eta in etavals)
            print ">>> "
Beispiel #18
0
class ModuleETau(ModuleTauPair):
    def __init__(self, fname, **kwargs):
        kwargs['channel'] = 'etau'
        super(ModuleETau, self).__init__(fname, **kwargs)
        self.out = TreeProducerETau(fname, self)

        # TRIGGERS
        jsonfile = os.path.join(datadir,
                                "trigger/tau_triggers_%d.json" % (self.year))
        self.trigger = TrigObjMatcher(jsonfile,
                                      trigger='SingleElectron',
                                      isdata=self.isdata)
        self.eleCutPt = self.trigger.ptmins[0]
        self.tauCutPt = 20
        self.eleCutEta = 2.3
        self.tauCutEta = 2.3

        # CORRECTIONS
        if self.ismc:
            self.eleSFs = ElectronSFs(
                era=self.era)  # electron id/iso/trigger SFs
            self.tesTool = TauESTool(
                tauSFVersion[self.year])  # real tau energy scale corrections
            self.fesTool = TauFESTool(
                tauSFVersion[self.year])  # e -> tau fake energy scale
            self.tauSFs = TauIDSFTool(tauSFVersion[self.year],
                                      'DeepTau2017v2p1VSjet', 'Tight')
            self.etfSFs = TauIDSFTool(tauSFVersion[self.year],
                                      'DeepTau2017v2p1VSe', 'VLoose')
            self.mtfSFs = TauIDSFTool(tauSFVersion[self.year],
                                      'DeepTau2017v2p1VSmu', 'Tight')

        # CUTFLOW
        self.out.cutflow.addcut('none', "no cut")
        self.out.cutflow.addcut('trig', "trigger")
        self.out.cutflow.addcut('electron', "electron")
        self.out.cutflow.addcut('tau', "tau")
        self.out.cutflow.addcut('pair', "pair")
        self.out.cutflow.addcut('weight', "no cut, weighted", 15)
        self.out.cutflow.addcut('weight_no0PU', "no cut, weighted, PU>0",
                                16)  # use for normalization

    def beginJob(self):
        """Before processing any events or files."""
        super(ModuleETau, self).beginJob()
        print ">>> %-12s = %s" % ('tauwp', self.tauwp)
        print ">>> %-12s = %s" % ('eleCutPt', self.eleCutPt)
        print ">>> %-12s = %s" % ('eleCutEta', self.eleCutEta)
        print ">>> %-12s = %s" % ('tauCutPt', self.tauCutPt)
        print ">>> %-12s = %s" % ('tauCutEta', self.tauCutEta)
        pass

    def analyze(self, event):
        """Process and pre-select events; fill branches and return True if the events passes,
    return False otherwise."""
        sys.stdout.flush()

        ##### NO CUT #####################################
        self.out.cutflow.fill('none')
        if self.isdata:
            self.out.cutflow.fill('weight', 1.)
            if event.PV_npvs > 0:
                self.out.cutflow.fill('weight_no0PU', 1.)
            else:
                return False
        else:
            self.out.cutflow.fill('weight', event.genWeight)
            self.out.pileup.Fill(event.Pileup_nTrueInt)
            if event.Pileup_nTrueInt > 0:
                self.out.cutflow.fill('weight_no0PU', event.genWeight)
            else:
                return False

        ##### TRIGGER ####################################
        if not self.trigger.fired(event):
            return False
        self.out.cutflow.fill('trig')

        ##### ELECTRON ###################################
        electrons = []
        for electron in Collection(event, 'Electron'):
            #if self.ismc and self.ees!=1:
            #  electron.pt   *= self.ees
            #  electron.mass *= self.ees
            if electron.pt < self.eleCutPt: continue
            if abs(electron.eta) > self.eleCutEta: continue
            if abs(electron.dz) > 0.2: continue
            if abs(electron.dxy) > 0.045: continue
            if not electron.convVeto: continue
            if electron.lostHits > 1: continue
            if not (electron.mvaFall17V2Iso_WP90
                    or electron.mvaFall17V2noIso_WP90):
                continue
            if not self.trigger.match(event, electron): continue
            electrons.append(electron)
        if len(electrons) == 0:
            return False
        self.out.cutflow.fill('electron')

        ##### TAU ########################################
        taus = []
        for tau in Collection(event, 'Tau'):
            if abs(tau.eta) > self.tauCutEta: continue
            if abs(tau.dz) > 0.2: continue
            if tau.decayMode not in [0, 1, 10, 11]: continue
            if abs(tau.charge) != 1: continue
            if tau.idDeepTau2017v2p1VSe < 1: continue  # VVVLoose
            if tau.idDeepTau2017v2p1VSmu < 1: continue  # VLoose
            if tau.idDeepTau2017v2p1VSjet < self.tauwp: continue
            if self.ismc:
                tau.es = 1  # store energy scale for propagating to MET
                genmatch = tau.genPartFlav
                if genmatch == 5:  # real tau
                    if self.tes != None:  # user-defined energy scale (for TES studies)
                        tes = self.tes
                    else:  # recommended energy scale (apply by default)
                        tes = self.tesTool.getTES(tau.pt,
                                                  tau.decayMode,
                                                  unc=self.tessys)
                    if tes != 1:
                        tau.pt *= tes
                        tau.mass *= tes
                        tau.es = tes
                elif self.ltf and 0 < genmatch < 5:  # lepton -> tau fake
                    tau.pt *= self.ltf
                    tau.mass *= self.ltf
                    tau.es = self.ltf
                elif genmatch in [
                        1, 3
                ]:  # electron -> tau fake (apply by default, override with 'ltf=1.0')
                    fes = self.fesTool.getFES(tau.eta,
                                              tau.decayMode,
                                              unc=self.fes)
                    tau.pt *= fes
                    tau.mass *= fes
                    tau.es = fes
                elif self.jtf != 1.0 and genmatch == 0:  # jet -> tau fake
                    tau.pt *= self.jtf
                    tau.mass *= self.jtf
                    tau.es = self.jtf
            if tau.pt < self.tauCutPt: continue
            taus.append(tau)
        if len(taus) == 0:
            return False
        self.out.cutflow.fill('tau')

        ##### ETAU PAIR ##################################
        ltaus = []
        for electron in electrons:
            for tau in taus:
                if tau.DeltaR(electron) < 0.5: continue
                ltau = LeptonTauPair(electron, electron.pfRelIso03_all, tau,
                                     tau.rawDeepTau2017v2p1VSjet)
                ltaus.append(ltau)

        if len(ltaus) == 0:
            return False
        electron, tau = max(ltaus).pair
        electron.tlv = electron.p4()
        tau.tlv = tau.p4()
        self.out.cutflow.fill('pair')

        # VETOS
        extramuon_veto, extraelec_veto, dilepton_veto = getlepvetoes(
            event, [electron], [], [tau], self.channel)
        self.out.extramuon_veto[0], self.out.extraelec_veto[
            0], self.out.dilepton_veto[0] = getlepvetoes(
                event, [electron], [], [], self.channel)
        self.out.lepton_vetoes[0] = self.out.extramuon_veto[
            0] or self.out.extraelec_veto[0] or self.out.dilepton_veto[0]
        self.out.lepton_vetoes_notau[
            0] = extramuon_veto or extraelec_veto or dilepton_veto

        # TIGHTEN PRE-SELECTION
        if self.dotight:  # do not save all events to reduce disk space
            fail = (self.out.lepton_vetoes[0] and self.out.lepton_vetoes_notau[0]) or\
                   (tau.idMVAoldDM2017v2<2 and tau.idDeepTau2017v2p1VSjet<1) or\
                   (tau.idAntiMu<2  and tau.idDeepTau2017v2p1VSmu<1) or\
                   (tau.idAntiEle<2 and tau.idDeepTau2017v2p1VSe<2)
            if (self.tes not in [1, None]
                    or self.tessys != None) and (fail or tau.genPartFlav != 5):
                return False
            if (self.ltf != 1 or self.fes != None
                ) and tau.genPartFlav < 1 and tau.genPartFlav > 4:
                return False
            ###if self.jtf!=1 and tau.genPartFlav!=0:
            ###  return False

        # EVENT
        self.fillEventBranches(event)

        # ELECTRON
        self.out.pt_1[0] = electron.pt
        self.out.eta_1[0] = electron.eta
        self.out.phi_1[0] = electron.phi
        self.out.m_1[0] = electron.mass
        self.out.y_1[0] = electron.tlv.Rapidity()
        self.out.dxy_1[0] = electron.dxy
        self.out.dz_1[0] = electron.dz
        self.out.q_1[0] = electron.charge
        self.out.iso_1[0] = electron.pfRelIso03_all
        self.out.cutBased_1[0] = electron.cutBased
        self.out.mvaFall17Iso_WP90_1[0] = electron.mvaFall17V2Iso_WP90
        self.out.mvaFall17Iso_WP80_1[0] = electron.mvaFall17V2Iso_WP80
        self.out.mvaFall17noIso_WP90_1[0] = electron.mvaFall17V2noIso_WP90
        self.out.mvaFall17noIso_WP80_1[0] = electron.mvaFall17V2noIso_WP80

        # TAU
        self.out.pt_2[0] = tau.pt
        self.out.eta_2[0] = tau.eta
        self.out.phi_2[0] = tau.phi
        self.out.m_2[0] = tau.mass
        self.out.y_2[0] = tau.tlv.Rapidity()
        self.out.dxy_2[0] = tau.dxy
        self.out.dz_2[0] = tau.dz
        self.out.q_2[0] = tau.charge
        self.out.dm_2[0] = tau.decayMode
        self.out.iso_2[0] = tau.rawIso
        self.out.idiso_2[0] = idIso(tau)  # cut-based tau isolation (rawIso)
        self.out.rawAntiEle_2[0] = tau.rawAntiEle
        self.out.rawMVAoldDM2017v2_2[0] = tau.rawMVAoldDM2017v2
        self.out.rawMVAnewDM2017v2_2[0] = tau.rawMVAnewDM2017v2
        self.out.rawDeepTau2017v2p1VSe_2[0] = tau.rawDeepTau2017v2p1VSe
        self.out.rawDeepTau2017v2p1VSmu_2[0] = tau.rawDeepTau2017v2p1VSmu
        self.out.rawDeepTau2017v2p1VSjet_2[0] = tau.rawDeepTau2017v2p1VSjet
        self.out.idAntiEle_2[0] = tau.idAntiEle
        self.out.idAntiMu_2[0] = tau.idAntiMu
        self.out.idDecayMode_2[0] = tau.idDecayMode
        self.out.idDecayModeNewDMs_2[0] = tau.idDecayModeNewDMs
        self.out.idMVAoldDM2017v2_2[0] = tau.idMVAoldDM2017v2
        self.out.idMVAnewDM2017v2_2[0] = tau.idMVAnewDM2017v2
        self.out.idDeepTau2017v2p1VSe_2[0] = tau.idDeepTau2017v2p1VSe
        self.out.idDeepTau2017v2p1VSmu_2[0] = tau.idDeepTau2017v2p1VSmu
        self.out.idDeepTau2017v2p1VSjet_2[0] = tau.idDeepTau2017v2p1VSjet
        self.out.chargedIso_2[0] = tau.chargedIso
        self.out.neutralIso_2[0] = tau.neutralIso
        self.out.leadTkPtOverTauPt_2[0] = tau.leadTkPtOverTauPt
        self.out.photonsOutsideSignalCone_2[0] = tau.photonsOutsideSignalCone
        self.out.puCorr_2[0] = tau.puCorr

        # GENERATOR
        if self.ismc:
            self.out.genmatch_1[0] = electron.genPartFlav
            self.out.genmatch_2[0] = tau.genPartFlav
            dRmin = 0.5
            taumatch = None
            for genvistau in Collection(event, 'GenVisTau'):
                dR = genvistau.DeltaR(tau)
                if dR < dRmin:
                    dRmin = dR
                    taumatch = genvistau
            if taumatch:
                self.out.genvistaupt_2[0] = taumatch.pt
                self.out.genvistaueta_2[0] = taumatch.eta
                self.out.genvistauphi_2[0] = taumatch.phi
                self.out.gendm_2[0] = taumatch.status
            else:
                self.out.genvistaupt_2[0] = -1
                self.out.genvistaueta_2[0] = -9
                self.out.genvistauphi_2[0] = -9
                self.out.gendm_2[0] = -1

        # JETS
        jets, met, njets_vars, met_vars = self.fillJetBranches(
            event, electron, tau)
        if self.ismc:
            self.out.jpt_match_2[0], self.out.jpt_genmatch_2[0] = matchtaujet(
                event, tau, self.ismc)
        else:
            self.out.jpt_match_2[0] = matchtaujet(event, tau, self.ismc)[0]

        # WEIGHTS
        if self.ismc:
            self.fillCommonCorrBraches(event, jets, met, njets_vars, met_vars)
            if electron.pfRelIso03_all < 0.50 and tau.idDeepTau2017v2p1VSjet >= 2:
                self.btagTool.fillEffMaps(jets, usejec=self.dojec)

            # MUON WEIGHTS
            self.out.trigweight[0] = self.eleSFs.getTriggerSF(
                electron.pt, electron.eta)
            self.out.idisoweight_1[0] = self.eleSFs.getIdIsoSF(
                electron.pt, electron.eta)

            # TAU WEIGHTS
            if tau.genPartFlav == 5:  # real tau
                self.out.idweight_2[0] = self.tauSFs.getSFvsPT(tau.pt)
                if not self.dotight:
                    self.out.idweightUp_2[0] = self.tauSFs.getSFvsPT(tau.pt,
                                                                     unc='Up')
                    self.out.idweightDown_2[0] = self.tauSFs.getSFvsPT(
                        tau.pt, unc='Down')
            elif tau.genPartFlav in [1, 3]:  # muon -> tau fake
                self.out.ltfweight_2[0] = self.etfSFs.getSFvsEta(
                    tau.eta, tau.genPartFlav)
                if not self.dotight:
                    self.out.ltfweightUp_2[0] = self.etfSFs.getSFvsEta(
                        tau.eta, tau.genPartFlav, unc='Up')
                    self.out.ltfweightDown_2[0] = self.etfSFs.getSFvsEta(
                        tau.eta, tau.genPartFlav, unc='Down')
            elif tau.genPartFlav in [2, 4]:  # electron -> tau fake
                self.out.ltfweight_2[0] = self.mtfSFs.getSFvsEta(
                    tau.eta, tau.genPartFlav)
                if not self.dotight:
                    self.out.ltfweightUp_2[0] = self.mtfSFs.getSFvsEta(
                        tau.eta, tau.genPartFlav, unc='Up')
                    self.out.ltfweightDown_2[0] = self.mtfSFs.getSFvsEta(
                        tau.eta, tau.genPartFlav, unc='Down')
            self.out.weight[0] = self.out.genweight[0] * self.out.puweight[
                0] * self.out.trigweight[0] * self.out.idisoweight_1[
                    0]  #*self.out.idisoweight_2[0]
        elif self.isembed:
            ###self.applyCommonEmbdedCorrections(event,jets,jetIds50,met,njets_vars,met_vars)
            self.out.genweight[0] = event.genWeight
            self.out.trackweight[
                0] = 0.975 if tau.decayMode == 0 else 1.0247 if tau.decayMode == 1 else 0.927 if tau.decayMode == 10 else 0.974 if tau.decayMode == 11 else 1.0

        # MET & DILEPTON VARIABLES
        self.fillMETAndDiLeptonBranches(event, electron, tau, met, met_vars)

        self.out.fill()
        return True
Beispiel #19
0
class ModuleTauTau(ModuleTauPair):
    def __init__(self, fname, **kwargs):
        kwargs['channel'] = 'mutau'
        super(ModuleTauTau, self).__init__(fname, **kwargs)
        self.out = TreeProducerTauTau(fname, self)

        # TRIGGERS
        jsonfile = os.path.join(datadir,
                                "trigger/tau_triggers_%d.json" % (self.year))
        self.trigger = TrigObjMatcher(jsonfile,
                                      trigger='ditau',
                                      isdata=self.isdata)
        self.tauCutPt = 40
        self.tauCutEta = 2.1

        # CORRECTIONS
        if self.ismc:
            self.trigTool = TauTriggerSFs('tautau', 'Medium', year=self.year)
            self.trigTool_tight = TauTriggerSFs('tautau',
                                                'Tight',
                                                year=self.year)
            self.tesTool = TauESTool(
                tauSFVersion[self.year])  # real tau energy scale
            self.fesTool = TauFESTool(
                tauSFVersion[self.year])  # e -> tau fake energy scale
            self.tauSFs = TauIDSFTool(tauSFVersion[self.year],
                                      'DeepTau2017v2p1VSjet',
                                      'Medium',
                                      dm=True)
            self.tauSFs_tight = TauIDSFTool(tauSFVersion[self.year],
                                            'DeepTau2017v2p1VSjet',
                                            'Tight',
                                            dm=True)
            self.etfSFs = TauIDSFTool(tauSFVersion[self.year],
                                      'DeepTau2017v2p1VSe', 'VVLoose')
            self.mtfSFs = TauIDSFTool(tauSFVersion[self.year],
                                      'DeepTau2017v2p1VSmu', 'Loose')

        # CUTFLOW
        self.out.cutflow.addcut('none', "no cut")
        self.out.cutflow.addcut('trig', "trigger")
        self.out.cutflow.addcut('tau', "tau")
        self.out.cutflow.addcut('pair', "ditau pair")
        self.out.cutflow.addcut('weight', "no cut, weighted", 15)
        self.out.cutflow.addcut('weight_no0PU', "no cut, weighted, PU>0",
                                16)  # use for normalization

    def beginJob(self):
        """Before processing any events or files."""
        super(ModuleTauTau, self).beginJob()
        print ">>> %-12s = %s" % ('tauwp', self.tauwp)
        print ">>> %-12s = %s" % ('tauCutPt', self.tauCutPt)
        print ">>> %-12s = %s" % ('tauCutEta', self.tauCutEta)
        print ">>> %-12s = '%s'" % ('triggers',
                                    self.trigger.path.replace(
                                        "||", "\n>>> %s||" % (' ' * 16)))

    def analyze(self, event):
        """Process and pre-select events; fill branches and return True if the events passes,
    return False otherwise."""
        sys.stdout.flush()

        ##### NO CUT #####################################
        self.out.cutflow.fill('none')
        if self.isdata:
            self.out.cutflow.fill('weight', 1.)
            if event.PV_npvs > 0:
                self.out.cutflow.fill('weight_no0PU', 1.)
            else:
                return False
        else:
            self.out.cutflow.fill('weight', event.genWeight)
            self.out.pileup.Fill(event.Pileup_nTrueInt)
            if event.Pileup_nTrueInt > 0:
                self.out.cutflow.fill('weight_no0PU', event.genWeight)
            else:
                return False

        ##### TRIGGER ####################################
        if not self.trigger.fired(event):
            return False
        self.out.cutflow.fill('trig')

        ##### TAU ########################################
        taus = []
        for tau in Collection(event, 'Tau'):
            if abs(tau.eta) > self.tauCutEta: continue
            if abs(tau.dz) > 0.2: continue
            if tau.decayMode not in [0, 1, 10, 11]: continue
            if abs(tau.charge) != 1: continue
            if tau.idDeepTau2017v2p1VSe < 1: continue  # VVVLoose
            if tau.idDeepTau2017v2p1VSmu < 1: continue  # VLoose
            if tau.idDeepTau2017v2p1VSjet < self.tauwp: continue
            if self.ismc:
                tau.es = 1  # store energy scale for propagating to MET
                genmatch = tau.genPartFlav
                if genmatch == 5:  # real tau
                    if self.tes != None:  # user-defined energy scale (for TES studies)
                        tes = self.tes
                    else:  # (apply by default)
                        tes = self.tesTool.getTES(tau.pt,
                                                  tau.decayMode,
                                                  unc=self.tessys)
                    if tes != 1:
                        tau.pt *= tes
                        tau.mass *= tes
                        tau.es = tes
                elif self.ltf and 0 < genmatch < 5:  # lepton -> tau fake
                    tau.pt *= self.ltf
                    tau.mass *= self.ltf
                    tau.es = self.ltf
                elif genmatch in [
                        1, 3
                ]:  # electron -> tau fake (apply by default, override with 'ltf=1.0')
                    fes = self.fesTool.getFES(tau.eta,
                                              tau.decayMode,
                                              unc=self.fes)
                    tau.pt *= fes
                    tau.mass *= fes
                    tau.es = fes
                elif self.jtf != 1.0 and genmatch == 0:  # jet -> tau fake
                    tau.pt *= self.jtf
                    tau.mass *= self.jtf
                    tau.es = self.jtf
            if tau.pt < self.tauCutPt: continue
            taus.append(tau)
        if len(taus) == 0:
            return False
        self.out.cutflow.fill('tau')

        ##### DITAU PAIR #################################
        ditaus = []
        for i, tau1 in enumerate(taus, 1):
            for tau2 in taus[i:]:
                if tau1.DeltaR(tau2) < 0.5: continue
                ditau = DiTauPair(tau1, tau1.rawDeepTau2017v2p1VSjet, tau2,
                                  tau2.rawDeepTau2017v2p1VSjet)
                ditaus.append(ditau)
        if len(ditaus) == 0:
            return False
        tau1, tau2 = max(ditaus).pair
        tau1.tlv = tau1.p4()
        tau2.tlv = tau2.p4()
        self.out.cutflow.fill('pair')

        # VETOS
        extramuon_veto, extraelec_veto, dilepton_veto = getlepvetoes(
            event, [], [], [tau1, tau2], self.channel)
        self.out.extramuon_veto[0], self.out.extraelec_veto[
            0], self.out.dilepton_veto[0] = getlepvetoes(
                event, [], [], [], self.channel)
        self.out.lepton_vetoes[0] = self.out.extramuon_veto[
            0] or self.out.extraelec_veto[0]  #or self.out.dilepton_veto[0]
        self.out.lepton_vetoes_notau[
            0] = extramuon_veto or extraelec_veto  #or dilepton_veto

        # EVENT
        self.fillEventBranches(event)

        # TAU 1
        self.out.pt_1[0] = tau1.pt
        self.out.eta_1[0] = tau1.eta
        self.out.phi_1[0] = tau1.phi
        self.out.m_1[0] = tau1.mass
        self.out.y_1[0] = tau1.tlv.Rapidity()
        self.out.dxy_1[0] = tau1.dxy
        self.out.dz_1[0] = tau1.dz
        self.out.q_1[0] = tau1.charge
        self.out.dm_1[0] = tau1.decayMode
        self.out.iso_1[0] = tau1.rawIso
        self.out.idiso_1[0] = idIso(tau1)  # cut-based tau isolation (rawIso)
        self.out.rawDeepTau2017v2p1VSe_1[0] = tau1.rawDeepTau2017v2p1VSe
        self.out.rawDeepTau2017v2p1VSmu_1[0] = tau1.rawDeepTau2017v2p1VSmu
        self.out.rawDeepTau2017v2p1VSjet_1[0] = tau1.rawDeepTau2017v2p1VSjet
        self.out.idAntiEle_1[0] = tau1.idAntiEle
        self.out.idAntiMu_1[0] = tau1.idAntiMu
        self.out.idDecayMode_1[0] = tau1.idDecayMode
        self.out.idDecayModeNewDMs_1[0] = tau1.idDecayModeNewDMs
        self.out.idMVAoldDM2017v2_1[0] = tau1.idMVAoldDM2017v2
        self.out.idMVAnewDM2017v2_1[0] = tau1.idMVAnewDM2017v2
        self.out.idDeepTau2017v2p1VSe_1[0] = tau1.idDeepTau2017v2p1VSe
        self.out.idDeepTau2017v2p1VSmu_1[0] = tau1.idDeepTau2017v2p1VSmu
        self.out.idDeepTau2017v2p1VSjet_1[0] = tau1.idDeepTau2017v2p1VSjet
        self.out.chargedIso_1[0] = tau1.chargedIso
        self.out.neutralIso_1[0] = tau1.neutralIso
        self.out.leadTkPtOverTauPt_1[0] = tau1.leadTkPtOverTauPt
        self.out.photonsOutsideSignalCone_1[0] = tau1.photonsOutsideSignalCone
        self.out.puCorr_1[0] = tau1.puCorr

        # TAU 2
        self.out.pt_2[0] = tau2.pt
        self.out.eta_2[0] = tau2.eta
        self.out.phi_2[0] = tau2.phi
        self.out.m_2[0] = tau2.mass
        self.out.y_2[0] = tau2.tlv.Rapidity()
        self.out.dxy_2[0] = tau2.dxy
        self.out.dz_2[0] = tau2.dz
        self.out.q_2[0] = tau2.charge
        self.out.dm_2[0] = tau2.decayMode
        self.out.iso_2[0] = tau2.rawIso
        self.out.idiso_2[0] = idIso(tau2)  # cut-based tau isolation (rawIso)
        self.out.rawDeepTau2017v2p1VSe_2[0] = tau2.rawDeepTau2017v2p1VSe
        self.out.rawDeepTau2017v2p1VSmu_2[0] = tau2.rawDeepTau2017v2p1VSmu
        self.out.rawDeepTau2017v2p1VSjet_2[0] = tau2.rawDeepTau2017v2p1VSjet
        self.out.idAntiEle_2[0] = tau2.idAntiEle
        self.out.idAntiMu_2[0] = tau2.idAntiMu
        self.out.idDecayMode_2[0] = tau2.idDecayMode
        self.out.idDecayModeNewDMs_2[0] = tau2.idDecayModeNewDMs
        self.out.idMVAoldDM2017v2_2[0] = tau2.idMVAoldDM2017v2
        self.out.idMVAnewDM2017v2_2[0] = tau2.idMVAnewDM2017v2
        self.out.idDeepTau2017v2p1VSe_2[0] = tau2.idDeepTau2017v2p1VSe
        self.out.idDeepTau2017v2p1VSmu_2[0] = tau2.idDeepTau2017v2p1VSmu
        self.out.idDeepTau2017v2p1VSjet_2[0] = tau2.idDeepTau2017v2p1VSjet
        self.out.chargedIso_2[0] = tau2.chargedIso
        self.out.neutralIso_2[0] = tau2.neutralIso
        self.out.leadTkPtOverTauPt_2[0] = tau2.leadTkPtOverTauPt
        self.out.photonsOutsideSignalCone_2[0] = tau2.photonsOutsideSignalCone
        self.out.puCorr_2[0] = tau2.puCorr

        # GENERATOR
        if self.ismc:
            self.out.genmatch_1[0] = tau1.genPartFlav
            self.out.genmatch_2[0] = tau2.genPartFlav
            pt1, phi1, eta1, status1 = matchgenvistau(event, tau1)
            pt2, phi2, eta2, status2 = matchgenvistau(event, tau2)
            self.out.genvistaupt_1[0] = pt1
            self.out.genvistaueta_1[0] = eta1
            self.out.genvistauphi_1[0] = phi1
            self.out.gendm_1[0] = status1
            self.out.genvistaupt_2[0] = pt2
            self.out.genvistaueta_2[0] = eta2
            self.out.genvistauphi_2[0] = phi2
            self.out.gendm_2[0] = status2

        # JETS
        jets, met, njets_vars, met_vars = self.fillJetBranches(
            event, tau1, tau2)
        self.out.jpt_match_1[0], self.out.jpt_genmatch_1[0] = matchtaujet(
            event, tau1, self.ismc)
        self.out.jpt_match_2[0], self.out.jpt_genmatch_2[0] = matchtaujet(
            event, tau2, self.ismc)

        # WEIGHTS
        if self.ismc:
            self.fillCommonCorrBraches(event, jets, met, njets_vars, met_vars)
            if tau1.idDeepTau2017v2p1VSjet >= 2 and tau2.idDeepTau2017v2p1VSjet >= 2:
                self.btagTool.fillEffMaps(jets, usejec=self.dojec)
            self.out.trigweight[0] = self.trigTool.getSFPair(tau1, tau2)
            self.out.trigweight_tight[0] = self.trigTool_tight.getSFPair(
                tau1, tau2)
            if not self.dotight:
                self.out.trigweightUp[0] = self.trigTool.getSFPair(tau1,
                                                                   tau2,
                                                                   unc='Up')
                self.out.trigweightDown[0] = self.trigTool.getSFPair(
                    tau1, tau2, unc='Down')

            # DEFAULTS
            self.out.idweight_1[0] = 1.
            self.out.idweight_2[0] = 1.
            self.out.idweight_tight_1[0] = 1.
            self.out.idweight_tight_2[0] = 1.
            self.out.ltfweight_2[0] = 1.
            self.out.ltfweight_2[0] = 1.
            if not self.dotight:
                self.out.idweightUp_1[0] = 1.
                self.out.idweightUp_2[0] = 1.
                self.out.idweightDown_1[0] = 1.
                self.out.idweightDown_2[0] = 1.
                self.out.ltfweightUp_1[0] = 1.
                self.out.ltfweightUp_2[0] = 1.
                self.out.ltfweightDown_1[0] = 1.
                self.out.ltfweightDown_2[0] = 1.

            # TAU 1 WEIGHTS
            if tau1.genPartFlav == 5:
                self.out.idweight_1[0] = self.tauSFs.getSFvsDM(
                    tau1.pt, tau1.decayMode)
                self.out.idweight_tight_1[0] = self.tauSFs_tight.getSFvsDM(
                    tau1.pt, tau1.decayMode)
                if not self.dotight:
                    self.out.idweightUp_1[0] = self.tauSFs.getSFvsDM(
                        tau1.pt, tau1.decayMode, unc='Up')
                    self.out.idweightDown_1[0] = self.tauSFs.getSFvsDM(
                        tau1.pt, tau1.decayMode, unc='Down')
            elif tau1.genPartFlav > 0:
                ltfTool = self.etfSFs if tau1.genPartFlav in [
                    1, 3
                ] else self.mtfSFs
                self.out.ltfweight_1[0] = ltfTool.getSFvsEta(
                    tau1.eta, tau1.genPartFlav)
                if not self.dotight:
                    self.out.ltfweightUp_1[0] = ltfTool.getSFvsEta(
                        tau1.eta, tau1.genPartFlav, unc='Up')
                    self.out.ltfweightDown_1[0] = ltfTool.getSFvsEta(
                        tau1.eta, tau1.genPartFlav, unc='Down')

            # TAU 2 WEIGHTS
            if tau1.genPartFlav == 5:
                self.out.idweight_2[0] = self.tauSFs.getSFvsDM(
                    tau1.pt, tau1.decayMode)
                self.out.idweight_tight_2[0] = self.tauSFs_tight.getSFvsDM(
                    tau1.pt, tau1.decayMode)
                if not self.dotight:
                    self.out.idweightUp_2[0] = self.tauSFs.getSFvsDM(
                        tau1.pt, tau1.decayMode, unc='Up')
                    self.out.idweightDown_2[0] = self.tauSFs.getSFvsDM(
                        tau1.pt, tau1.decayMode, unc='Down')
            elif tau1.genPartFlav > 0:
                ltfTool = self.etfSFs if tau1.genPartFlav in [
                    1, 3
                ] else self.mtfSFs
                self.out.ltfweight_2[0] = ltfTool.getSFvsEta(
                    tau1.eta, tau1.genPartFlav)
                if not self.dotight:
                    self.out.ltfweightUp_2[0] = ltfTool.getSFvsEta(
                        tau1.eta, tau1.genPartFlav, unc='Up')
                    self.out.ltfweightDown_2[0] = ltfTool.getSFvsEta(
                        tau1.eta, tau1.genPartFlav, unc='Down')

        # MET & DILEPTON VARIABLES
        self.fillMETAndDiLeptonBranches(event, tau1, tau2, met, met_vars)

        self.out.fill()
        return True