Example #1
0
    def __init__(self, fname, **kwargs):
        kwargs['channel'] = 'mumu'
        super(ModuleMuMu, self).__init__(fname, **kwargs)
        self.out = TreeProducerMuMu(fname, self)
        self.zwindow = kwargs.get('ZWindow', True)

        # 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.muon1CutPt = 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.muon1CutPt = 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.muon1CutPt = lambda e: 25
            self.muonCutEta = lambda e: 2.4
        self.muon2CutPt = 15
        self.tauCutPt = 20
        self.tauCutEta = 2.3

        # CORRECTIONS
        if self.ismc:
            self.muSFs = MuonSFs(era=self.era)

        # CUTFLOW
        self.out.cutflow.addcut('none', "no cut")
        self.out.cutflow.addcut('trig', "trigger")
        self.out.cutflow.addcut('muon', "muon")
        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
Example #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])  # for mu -> tau fake negligible
            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
Example #3
0
def muonSFs():
    LOG.header("muonSFs")

    # MUON SFs
    start1 = time.time()
    print ">>> initializing MuonSF object..."
    muSFs = MuonSFs()
    print ">>>   initialized in %.1f seconds" % (time.time() - start1)

    # GET SFs
    printtable('trigger', muSFs.getTriggerSF)
    printtable('idiso', muSFs.getIdIsoSF)
    print ">>> "

    # MUON 2018 SFs
    start1 = time.time()
    print ">>> initializing MuonSF(2018) object..."
    muSFs = MuonSFs(year=2018)
    print ">>>   initialized in %.1f seconds" % (time.time() - start1)

    # GET SFs
    printtable('trigger', muSFs.getTriggerSF)
    printtable('idiso', muSFs.getIdIsoSF)
    print ">>> "
Example #4
0
class ModuleEMu(ModuleTauPair):
    def __init__(self, fname, **kwargs):
        kwargs['channel'] = 'emu'
        super(ModuleEMu, self).__init__(fname, **kwargs)
        self.out = TreeProducerEMu(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.eleCutPt = 15
        self.eleCutEta = 2.3
        self.tauCutPt = 20
        self.tauCutEta = 2.3

        # CORRECTIONS
        if self.ismc:
            self.muSFs = MuonSFs(era=self.era)
            self.eleSFs = ElectronSFs(year=self.year)

        # CUTFLOW
        self.out.cutflow.addcut('none', "no cut")
        self.out.cutflow.addcut('trig', "trigger")
        self.out.cutflow.addcut('electron', "electron")
        self.out.cutflow.addcut('muon', "muon")
        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(ModuleEMu, self).beginJob()
        print ">>> %-12s = %s" % ('muonCutPt', self.muonCutPt)
        print ">>> %-12s = %s" % ('muonCutEta', self.muonCutEta)
        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(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
            electrons.append(electron)
        if len(electrons) == 0:
            return False
        self.out.cutflow.fill('electron')

        ##### 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')

        ##### MUMU PAIR #################################
        dileps = []
        for electron in electrons:
            for muon in muons:
                if muon.DeltaR(electron) < 0.5: continue
                ltau = LeptonPair(electron, electron.pfRelIso03_all, muon,
                                  muon.pfRelIso04_all)
                dileps.append(ltau)
        if len(dileps) == 0:
            return False
        electron, muon = max(dileps).pair
        electron.tlv = electron.p4()
        muon.tlv = muon.p4()
        self.out.cutflow.fill('pair')

        # VETOS
        extramuon_veto, extraelec_veto, dilepton_veto = getlepvetoes(
            event, [electron], [muon], [], self.channel)
        self.out.extramuon_veto[0], self.out.extraelec_veto[
            0], self.out.dilepton_veto[0] = getlepvetoes(
                event, [electron], [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 1
        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

        # MUON 2
        self.out.pt_2[0] = muon.pt
        self.out.eta_2[0] = muon.eta
        self.out.phi_2[0] = muon.phi
        self.out.m_2[0] = muon.mass
        self.out.y_2[0] = muon.tlv.Rapidity()
        self.out.dxy_2[0] = muon.dxy
        self.out.dz_2[0] = muon.dz
        self.out.q_2[0] = muon.charge
        self.out.iso_2[0] = muon.pfRelIso04_all

        # TAU for jet -> tau fake rate measurement in emu+tau events
        maxtau = None
        ptmax = 20
        for tau in Collection(event, 'Tau'):
            if tau.pt < ptmax: continue
            if electron.DeltaR(tau) < 0.5: continue
            if muon.DeltaR(tau) < 0.5: continue
            if abs(tau.eta) > 2.3: 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 ord(tau.idDeepTau2017v2p1VSe)<1: continue # VLoose
            #if ord(tau.idDeepTau2017v2p1VSmu)<1: continue # VLoose
            maxtau = tau
            ptmax = tau.pt
        if maxtau > -1:
            self.out.pt_3[0] = maxtau.pt
            self.out.eta_3[0] = maxtau.eta
            self.out.m_3[0] = maxtau.mass
            self.out.q_3[0] = maxtau.charge
            self.out.dm_3[0] = maxtau.decayMode
            self.out.iso_3[0] = maxtau.rawIso
            self.out.idiso_2[0] = idIso(
                maxtau)  # cut-based tau isolation (rawIso)
            self.out.idAntiEle_3[0] = maxtau.idAntiEle
            self.out.idAntiMu_3[0] = maxtau.idAntiMu
            self.out.idMVAoldDM2017v2_3[0] = maxtau.idMVAoldDM2017v2
            self.out.idMVAnewDM2017v2_3[0] = maxtau.idMVAnewDM2017v2
            self.out.idDeepTau2017v2p1VSe_3[0] = maxtau.idDeepTau2017v2p1VSe
            self.out.idDeepTau2017v2p1VSmu_3[0] = maxtau.idDeepTau2017v2p1VSmu
            self.out.idDeepTau2017v2p1VSjet_3[
                0] = maxtau.idDeepTau2017v2p1VSjet
            if self.ismc:
                self.out.jpt_match_3[0], self.out.jpt_genmatch_3[
                    0] = matchtaujet(event, maxtau, self.ismc)
                self.out.genmatch_3[0] = maxtau.genPartFlav
            else:
                self.out.jpt_match_3[0] = matchtaujet(event, maxtau,
                                                      self.ismc)[0]
        else:
            self.out.pt_3[0] = -1
            self.out.eta_3[0] = -9
            self.out.m_3[0] = -1
            self.out.q_3[0] = 0
            self.out.dm_3[0] = -1
            self.out.idAntiEle_3[0] = -1
            self.out.idAntiMu_3[0] = -1
            self.out.idMVAoldDM2017v2_3[0] = -1
            self.out.idMVAnewDM2017v2_3[0] = -1
            self.out.idDeepTau2017v2p1VSe_3[0] = -1
            self.out.idDeepTau2017v2p1VSmu_3[0] = -1
            self.out.idDeepTau2017v2p1VSjet_3[0] = -1
            self.out.iso_3[0] = -1
            self.out.jpt_match_3[0] = -1
            self.out.jpt_genmatch_3[0] = -1
            if self.ismc:
                self.out.jpt_genmatch_3[0] = -1
                self.out.genmatch_3[0] = -1

        # GENERATOR
        if self.ismc:
            self.out.genmatch_1[0] = electron.genPartFlav
            self.out.genmatch_2[0] = muon.genPartFlav

        # JETS
        jets, met, njets_vars, met_vars = self.fillJetBranches(
            event, electron, muon)

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

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

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

        self.out.fill()
        return True
Example #5
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
Example #6
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