コード例 #1
0
    def getWeight(self, row, cut='loose'):
        if row.isData:
            weight = 1.
        else:
            # per event weights
            base = ['genWeight', 'pileupWeight', 'triggerEfficiency']
            if self.shift == 'trigUp':
                base = ['genWeight', 'pileupWeight', 'triggerEfficiencyUp']
            if self.shift == 'trigDown':
                base = ['genWeight', 'pileupWeight', 'triggerEfficiencyDown']
            if self.shift == 'puUp':
                base = ['genWeight', 'pileupWeightUp', 'triggerEfficiency']
            if self.shift == 'puDown':
                base = ['genWeight', 'pileupWeightDown', 'triggerEfficiency']
            for lep in zip(self.leps):
                if self.shift == 'lepUp':
                    base += ['{0}_{1}ScaleUp'.format(lep, cut)]
                elif self.shift == 'lepDown':
                    base += ['{0}_{1}ScaleDown'.format(lep, cut)]
                else:
                    base += ['{0}_{1}Scale'.format(lep, cut)]
            vals = [getattr(row, scale) for scale in base]
            for scale, val in zip(base, vals):
                if val != val:
                    logging.warning('{0}: {1} is NaN'.format(
                        row.channel, scale))
            weight = prod([val for val in vals if val == val])
            # scale to lumi/xsec
            weight *= float(
                self.intLumi) / self.sampleLumi if self.sampleLumi else 0.
            if hasattr(row, 'qqZZkfactor'):
                weight *= row.qqZZkfactor / 1.1  # ZZ variable k factor

        return weight
コード例 #2
0
    def getWeight(self,row,cut='loose'):
        if row.isData:
            weight = 1.
        else:
            # per event weights
            base = ['genWeight','pileupWeight','triggerEfficiency']
            if self.shift=='trigUp': base = ['genWeight','pileupWeight','triggerEfficiencyUp']
            if self.shift=='trigDown': base = ['genWeight','pileupWeight','triggerEfficiencyDown']
            if self.shift=='puUp': base = ['genWeight','pileupWeightUp','triggerEfficiency']
            if self.shift=='puDown': base = ['genWeight','pileupWeightDown','triggerEfficiency']
            for lep in zip(self.leps):
                if self.shift == 'lepUp':
                    base += ['{0}_{1}ScaleUp'.format(lep,cut)]
                elif self.shift == 'lepDown':
                    base += ['{0}_{1}ScaleDown'.format(lep,cut)]
                else:
                    base += ['{0}_{1}Scale'.format(lep,cut)]
            base += ['m_mediumScale']
            vals = [getattr(row,scale) for scale in base]
            for scale,val in zip(base,vals):
                if val != val: logging.warning('{0}: {1} is NaN'.format(row.channel,scale))
            weight = prod([val for val in vals if val==val])
            # scale to lumi/xsec
            weight *= float(self.intLumi)/self.sampleLumi if self.sampleLumi else 0.
            if hasattr(row,'qqZZkfactor'): weight *= row.qqZZkfactor/1.1 # ZZ variable k factor

        return weight
コード例 #3
0
    def getWeight(self,row):
        if row.isData:
            weight = 1.
        else:
            # per event weights
            base = ['genWeight','pileupWeight','triggerEfficiency']
            if self.shift=='trigUp': base = ['genWeight','pileupWeight','triggerEfficiencyUp']
            if self.shift=='trigDown': base = ['genWeight','pileupWeight','triggerEfficiencyDown']
            if self.shift=='puUp': base = ['genWeight','pileupWeightUp','triggerEfficiency']
            if self.shift=='puDown': base = ['genWeight','pileupWeightDown','triggerEfficiency']
            vals = [getattr(row,scale) for scale in base]
            # muon
            m1id = self.getMuonScaleFactor('LooseID',row.z1_pt,row.z1_eta)
            m1iso = self.getMuonScaleFactor('LooseIsoFromLooseID',row.z1_pt,row.z1_eta)
            m2id = self.getMuonScaleFactor('LooseID',row.z2_pt,row.z2_eta)
            m2iso = self.getMuonScaleFactor('LooseIsoFromLooseID',row.z2_pt,row.z2_eta) if row.z_deltaR>0.4 else [1.0, 0., 0.]
            if self.shift=='lepUp':
                vals += [m1id[0]+m1id[1], m1iso[0]+m1iso[1]]
                vals += [m2id[0]+m2id[1], m2iso[0]+m2iso[1]]
            elif self.shift=='lepDown':
                vals += [m1id[0]-m1id[1], m1iso[0]-m1iso[1]]
                vals += [m2id[0]-m2id[1], m2iso[0]-m2iso[1]]
            else:
                vals += [m1id[0], m1iso[0]]
                vals += [m2id[0], m2iso[0]]
            for scale,val in zip(base,vals):
                if val != val: logging.warning('{0}: {1} is NaN'.format(row.channel,scale))
            weight = prod([val for val in vals if val==val])
            # scale to lumi/xsec
            weight *= float(self.intLumi)/self.sampleLumi if self.sampleLumi else 0.
            if hasattr(row,'qqZZkfactor'): weight *= row.qqZZkfactor/1.1 # ZZ variable k factor
            if hasattr(row,'zPtWeight'): weight *= row.zPtWeight # Z pt scale factor

        return weight
コード例 #4
0
    def getWeight(self,row,fakeLeps=[]):
        if row.isData:
            weight = 1.
        else:
            # gen weight
            base = ['genWeight']
            vals = [getattr(row,scale) for scale in base]
            # trigger efficiency: TODO
            # pileup weight
            vals += [self.getPileup(row.numTrueVertices)]
            # lepton efficiency
            for l,lep in enumerate(self.leps):
                pt = getattr(row,'{}_pt'.format(lep))
                eta = getattr(row,'{}_eta'.format(lep))
                f = row.channel[l]
                val,err = self.getScalefactor(f,pt,eta)
                vals += [val]
                #print l, lep, f, pt, eta, val, err
            weight = prod([val for val in vals if val==val])
            # scale to lumi/xsec
            weight *= float(self.intLumi)/self.sampleLumi if self.sampleLumi else 0.
        for lep in fakeLeps:
            pt = getattr(row,'{}_pt'.format(lep))
            eta = getattr(row,'{}_eta'.format(lep))
            f = row.channel[self.leps.index(lep)]
            val,err = self.getFakeRate(f,pt,eta)
            weight *= val/(1-val)

        return weight
コード例 #5
0
    def getWeight(self, row, fakeLeps=[]):
        if row.isData:
            weight = 1.
        else:
            # gen weight
            base = ['genWeight']
            vals = [getattr(row, scale) for scale in base]
            # trigger efficiency: TODO
            # pileup weight
            vals += [self.getPileup(row.numTrueVertices)]
            # lepton efficiency
            for l, lep in enumerate(self.leps):
                pt = getattr(row, '{}_pt'.format(lep))
                eta = getattr(row, '{}_eta'.format(lep))
                f = row.channel[l]
                val, err = self.getScalefactor(f, pt, eta)
                vals += [val]
                #print l, lep, f, pt, eta, val, err
            weight = prod([val for val in vals if val == val])
            # scale to lumi/xsec
            weight *= float(
                self.intLumi) / self.sampleLumi if self.sampleLumi else 0.
        for lep in fakeLeps:
            pt = getattr(row, '{}_pt'.format(lep))
            eta = getattr(row, '{}_eta'.format(lep))
            f = row.channel[self.leps.index(lep)]
            val, err = self.getFakeRate(f, pt, eta)
            weight *= val / (1 - val)

        return weight
コード例 #6
0
    def getWeight(self,row,doFake=False,fakeNum=None,fakeDenom=None):
        chanMap = {'e': 'electrons', 'm': 'muons', 't': 'taus',}
        chan = ''.join([x for x in row.channel if x in 'emt'])
        if not fakeNum: fakeNum = 'HppMedium'
        if not fakeDenom: fakeDenom = 'HppLoose{0}'.format('New' if self.new else '')
        passID = [getattr(row,self.lepID.format(l)) for l in self.leps]
        if row.isData:
            weight = 1.
        else:
            # per event weights
            base = ['genWeight','pileupWeight','triggerEfficiency']
            if self.shift=='trigUp': base = ['genWeight','pileupWeight','triggerEfficiencyUp']
            if self.shift=='trigDown': base = ['genWeight','pileupWeight','triggerEfficiencyDown']
            if self.shift=='puUp': base = ['genWeight','pileupWeightUp','triggerEfficiency']
            if self.shift=='puDown': base = ['genWeight','pileupWeightDown','triggerEfficiency']
            for l,lep in enumerate(self.leps):
                shiftString = ''
                if self.shift == 'lepUp': shiftString = 'Up'
                if self.shift == 'lepDown': shiftString = 'Down'
                base += [self.scaleMap['P' if passID[l] else 'F'].format(lep)+shiftString]
            vals = [getattr(row,scale) for scale in base]
            for scale,val in zip(base,vals):
                if val != val: logging.warning('{0}: {1} is NaN'.format(row.channel,scale))
            weight = prod([val for val in vals if val==val])
            # scale to lumi/xsec
            weight *= float(self.intLumi)/self.sampleLumi if self.sampleLumi else 0.
            if hasattr(row,'qqZZkfactor'): weight *= row.qqZZkfactor/1.1 # ZZ variable k factor
            # b tagging (veto)
            if self.doBScales: weight *= self.getBTagWeight(row)
            for l, lep in enumerate(self.leps):
                weight *= self.getCharge(chanMap[chan[l]], getattr(row, '{}_pt'.format(lep)), getattr(row, '{}_eta'.format(lep)))
        # fake scales
        if doFake:
            pts = [getattr(row,'{0}_pt'.format(x)) for x in self.leps]
            etas = [getattr(row,'{0}_eta'.format(x)) for x in self.leps]
            region = ''.join(['P' if x else 'F' for x in passID])
            sign = -1 if region.count('F')%2==0 and region.count('F')>0 else 1
            weight *= sign
            if not row.isData and not all(passID): weight *= -1 # subtract off MC in control
            for l,lep in enumerate(self.leps):
                if not passID[l]:
                    # recalculate
                    dm = None if chan[l]!='taus' else getattr(row,'{0}_decayMode'.format(lep))
                    fn = fakeNum
                    fd = fakeDenom
                    if isinstance(fakeNum,dict): fn = fakeNum[chan[l]]
                    if isinstance(fakeDenom,dict): fd = fakeDenom[chan[l]]
                    fakeEff = self.getFakeRate(chanMap[chan[l]], pts[l], etas[l], fn, fd, dm=dm)[0]

                    # read from tree
                    #fake = self.fakeVal.format(lep)
                    #if self.shift=='fakeUp': fake += 'Up'
                    #if self.shift=='fakeDown': fake += 'Down'
                    #fakeEff = getattr(row,fake)

                    weight *= fakeEff/(1-fakeEff)

        return weight
コード例 #7
0
    def getWeight(self,row,doFake=False,fakeNum=None,fakeDenom=None):
        if not fakeNum: fakeNum = 'HppMedium'
        if not fakeDenom: fakeDenom = 'HppLoose{0}'.format('New' if self.new else '')
        passID = [getattr(row,self.lepID.format(l)) for l in self.leps]
        if row.isData:
            weight = 1.
        else:
            # per event weights
            base = ['genWeight','pileupWeight','triggerEfficiency']
            if self.shift=='trigUp': base = ['genWeight','pileupWeight','triggerEfficiencyUp']
            if self.shift=='trigDown': base = ['genWeight','pileupWeight','triggerEfficiencyDown']
            if self.shift=='puUp': base = ['genWeight','pileupWeightUp','triggerEfficiency']
            if self.shift=='puDown': base = ['genWeight','pileupWeightDown','triggerEfficiency']
            for l,lep in enumerate(self.leps):
                shiftString = ''
                if self.shift == 'lepUp': shiftString = 'Up'
                if self.shift == 'lepDown': shiftString = 'Down'
                base += [self.scaleMap['P' if passID[l] else 'F'].format(lep)+shiftString]
            vals = [getattr(row,scale) for scale in base]
            for scale,val in zip(base,vals):
                if val != val: logging.warning('{0}: {1} is NaN'.format(row.channel,scale))
            weight = prod([val for val in vals if val==val])
            # scale to lumi/xsec
            weight *= float(self.intLumi)/self.sampleLumi if self.sampleLumi else 0.
            if hasattr(row,'qqZZkfactor'): weight *= row.qqZZkfactor/1.1 # ZZ variable k factor
            # b taggin (veto)
            if self.doBVeto: weight *= self.getBTagWeight(row)
        # fake scales
        if doFake:
            chanMap = {'e': 'electrons', 'm': 'muons', 't': 'taus',}
            chan = ''.join([x for x in row.channel if x in 'emt'])
            pts = [getattr(row,'{0}_pt'.format(x)) for x in self.leps]
            etas = [getattr(row,'{0}_eta'.format(x)) for x in self.leps]
            region = ''.join(['P' if x else 'F' for x in passID])
            sign = -1 if region.count('F')%2==0 and region.count('F')>0 else 1
            weight *= sign
            if not row.isData and not all(passID): weight *= -1 # subtract off MC in control
            for l,lep in enumerate(self.leps):
                if not passID[l]:
                    # recalculate
                    dm = None if chan[l]!='taus' else getattr(row,'{0}_decayMode'.format(lep))
                    fakeEff = self.getFakeRate(chanMap[chan[l]], pts[l], etas[l], fakeNum, fakeDenom, dm=dm)[0]

                    # read from tree
                    #fake = self.fakeVal.format(lep)
                    #if self.shift=='fakeUp': fake += 'Up'
                    #if self.shift=='fakeDown': fake += 'Down'
                    #fakeEff = getattr(row,fake)

                    weight *= fakeEff/(1-fakeEff)

        return weight
コード例 #8
0
 def getWeight(self,row):
     if row.isData:
         weight = 1.
     else:
         # per event weights
         base = ['genWeight','pileupWeight','triggerEfficiency','z1_mediumScale','z2_mediumScale']
         vals = [getattr(row,scale) for scale in base]
         for scale,val in zip(base,vals):
             if val != val: logging.warning('{0}: {1} is NaN'.format(row.channel,scale))
         weight = prod([val for val in vals if val==val])
         # scale to lumi/xsec
         weight *= float(self.intLumi)/self.sampleLumi if self.sampleLumi else 0.
     return weight
コード例 #9
0
    def getWeight(self,row,doFake=False,jetPt=0):
        passID = [getattr(row,self.wzTightVar[l]) for l in range(3)]
        if row.isData:
            weight = 1.
        else:
            # per event weights
            base = ['genWeight','pileupWeight','triggerEfficiency']
            if self.shift=='trigUp': base = ['genWeight','pileupWeight','triggerEfficiencyUp']
            if self.shift=='trigDown': base = ['genWeight','pileupWeight','triggerEfficiencyDown']
            if self.shift=='puUp': base = ['genWeight','pileupWeightUp','triggerEfficiency']
            if self.shift=='puDown': base = ['genWeight','pileupWeightDown','triggerEfficiency']
            for l,p in enumerate(passID):
                if self.shift == 'lepUp':
                    base += [self.wzScaleMap['P' if p else 'F'][l]+'Up']
                elif self.shift == 'lepDown':
                    base += [self.wzScaleMap['P' if p else 'F'][l]+'Down']
                else:
                    base += [self.wzScaleMap['P' if p else 'F'][l]]
            vals = [getattr(row,scale) for scale in base]
            for scale,val in zip(base,vals):
                if val != val: logging.warning('{0}: {1} is NaN'.format(row.channel,scale))
            weight = prod([val for val in vals if val==val])
            # scale to lumi/xsec
            weight *= float(self.intLumi)/self.sampleLumi if self.sampleLumi else 0.
            if hasattr(row,'qqZZkfactor'): weight *= row.qqZZkfactor/1.1 # ZZ variable k factor
        # fake scales
        if doFake:
            chanMap = {'e': 'electrons', 'm': 'muons', 't': 'taus',}
            chan = ''.join([x for x in row.channel if x in 'emt'])
            pts = [getattr(row,'{0}_pt'.format(x)) for x in self.leps]
            etas = [getattr(row,'{0}_eta'.format(x)) for x in self.leps]
            region = ''.join(['P' if x else 'F' for x in passID])
            sign = -1 if region.count('F')%2==0 and region.count('F')>0 else 1
            weight *= sign
            if not row.isData and not all(passID): weight *= -1 # subtract off MC in control
            for l,p in enumerate(passID):
                if not p:
                    if jetPt:
                        # recalculate
                        fakeEff = self.getFakeRate(chanMap[chan[l]], pts[l], etas[l], 'HppTight','HppLoose',jetPt=jetPt)[0]
                    else:
                        # read from tree
                        fake = self.wzFakeRate[l]
                        if self.shift=='fakeUp': fake += 'Up'
                        if self.shift=='fakeDown': fake += 'Down'
                        fakeEff = getattr(row,fake)
                    weight *= fakeEff/(1-fakeEff)

        return weight
コード例 #10
0
ファイル: WZSkimmer.py プロジェクト: kmtos/DevTools-Plotting
    def getWeight(self,row,doFake=False,jetPt=0):
        passID = [getattr(row,self.wzTightVar[l]) for l in range(3)]
        if row.isData:
            weight = 1.
        else:
            # per event weights
            base = ['genWeight','pileupWeight','triggerEfficiency']
            if self.shift=='trigUp': base = ['genWeight','pileupWeight','triggerEfficiencyUp']
            if self.shift=='trigDown': base = ['genWeight','pileupWeight','triggerEfficiencyDown']
            if self.shift=='puUp': base = ['genWeight','pileupWeightUp','triggerEfficiency']
            if self.shift=='puDown': base = ['genWeight','pileupWeightDown','triggerEfficiency']
            for l,p in enumerate(passID):
                if self.shift == 'lepUp':
                    base += [self.wzScaleMap['P' if p else 'F'][l]+'Up']
                elif self.shift == 'lepDown':
                    base += [self.wzScaleMap['P' if p else 'F'][l]+'Down']
                else:
                    base += [self.wzScaleMap['P' if p else 'F'][l]]
            vals = [getattr(row,scale) for scale in base]
            for scale,val in zip(base,vals):
                if val != val: logging.warning('{0}: {1} is NaN'.format(row.channel,scale))
            weight = prod([val for val in vals if val==val])
            # scale to lumi/xsec
            weight *= float(self.intLumi)/self.sampleLumi if self.sampleLumi else 0.
            if hasattr(row,'qqZZkfactor'): weight *= row.qqZZkfactor/1.1 # ZZ variable k factor
        # fake scales
        if doFake:
            chanMap = {'e': 'electrons', 'm': 'muons', 't': 'taus',}
            chan = ''.join([x for x in row.channel if x in 'emt'])
            pts = [getattr(row,'{0}_pt'.format(x)) for x in self.leps]
            etas = [getattr(row,'{0}_eta'.format(x)) for x in self.leps]
            region = ''.join(['P' if x else 'F' for x in passID])
            sign = -1 if region.count('F')%2==0 and region.count('F')>0 else 1
            weight *= sign
            if not row.isData and not all(passID): weight *= -1 # subtract off MC in control
            for l,p in enumerate(passID):
                if not p:
                    if jetPt:
                        # recalculate
                        fakeEff = self.getFakeRate(chanMap[chan[l]], pts[l], etas[l], 'HppTight','HppLoose',jetPt=jetPt)[0]
                    else:
                        # read from tree
                        fake = self.wzFakeRate[l]
                        if self.shift=='fakeUp': fake += 'Up'
                        if self.shift=='fakeDown': fake += 'Down'
                        fakeEff = getattr(row,fake)
                    weight *= fakeEff/(1-fakeEff)

        return weight
コード例 #11
0
    def getWeight(self, row):
        if row.isData:
            weight = 1.
        else:
            # per event weights
            base = ['genWeight', 'pileupWeight', 'triggerEfficiency']
            if self.shift == 'trigUp':
                base = ['genWeight', 'pileupWeight', 'triggerEfficiencyUp']
            if self.shift == 'trigDown':
                base = ['genWeight', 'pileupWeight', 'triggerEfficiencyDown']
            if self.shift == 'puUp':
                base = ['genWeight', 'pileupWeightUp', 'triggerEfficiency']
            if self.shift == 'puDown':
                base = ['genWeight', 'pileupWeightDown', 'triggerEfficiency']
            vals = [getattr(row, scale) for scale in base]
            # muon
            m1id = self.getMuonScaleFactor('LooseID', row.z1_pt, row.z1_eta)
            m1iso = self.getMuonScaleFactor('LooseIsoFromLooseID', row.z1_pt,
                                            row.z1_eta)
            m2id = self.getMuonScaleFactor('LooseID', row.z2_pt, row.z2_eta)
            m2iso = self.getMuonScaleFactor(
                'LooseIsoFromLooseID', row.z2_pt,
                row.z2_eta) if row.z_deltaR > 0.4 else [1.0, 0., 0.]
            if self.shift == 'lepUp':
                vals += [m1id[0] + m1id[1], m1iso[0] + m1iso[1]]
                vals += [m2id[0] + m2id[1], m2iso[0] + m2iso[1]]
            elif self.shift == 'lepDown':
                vals += [m1id[0] - m1id[1], m1iso[0] - m1iso[1]]
                vals += [m2id[0] - m2id[1], m2iso[0] - m2iso[1]]
            else:
                vals += [m1id[0], m1iso[0]]
                vals += [m2id[0], m2iso[0]]
            for scale, val in zip(base, vals):
                if val != val:
                    logging.warning('{0}: {1} is NaN'.format(
                        row.channel, scale))
            weight = prod([val for val in vals if val == val])
            # scale to lumi/xsec
            weight *= float(
                self.intLumi) / self.sampleLumi if self.sampleLumi else 0.
            if hasattr(row, 'qqZZkfactor'):
                weight *= row.qqZZkfactor / 1.1  # ZZ variable k factor
            if hasattr(row, 'zPtWeight'):
                weight *= row.zPtWeight  # Z pt scale factor

        return weight
コード例 #12
0
 def getWeight(self, row):
     if row.isData:
         weight = 1.
     else:
         # per event weights
         base = [
             'genWeight', 'pileupWeight', 'triggerEfficiency',
             'z1_mediumScale', 'z2_mediumScale'
         ]
         vals = [getattr(row, scale) for scale in base]
         for scale, val in zip(base, vals):
             if val != val:
                 logging.warning('{0}: {1} is NaN'.format(
                     row.channel, scale))
         weight = prod([val for val in vals if val == val])
         # scale to lumi/xsec
         weight *= float(
             self.intLumi) / self.sampleLumi if self.sampleLumi else 0.
     return weight
コード例 #13
0
    def getWeight(self,
                  row,
                  doFake=False,
                  fakeNum=None,
                  fakeDenom=None,
                  fakeLeps=[]):
        if not fakeNum: fakeNum = 'HaaTight'
        if not fakeDenom: fakeDenom = 'HaaLoose'
        if row.isData:
            weight = 1.
        else:
            # per event weights
            base = ['genWeight', 'pileupWeight', 'triggerEfficiency']
            if self.shift == 'trigUp':
                base = ['genWeight', 'pileupWeight', 'triggerEfficiencyUp']
            if self.shift == 'trigDown':
                base = ['genWeight', 'pileupWeight', 'triggerEfficiencyDown']
            if self.shift == 'puUp':
                base = ['genWeight', 'pileupWeightUp', 'triggerEfficiency']
            if self.shift == 'puDown':
                base = ['genWeight', 'pileupWeightDown', 'triggerEfficiency']
            vals = [getattr(row, scale) for scale in base]
            # tau id: 0.99 for VL/L, 0.97 for M
            vals += [0.99]
            # muon
            m1id = self.getMuonScaleFactor('LooseID', row.am1_pt, row.am1_eta)
            m1iso = self.getMuonScaleFactor('LooseIsoFromLooseID', row.am1_pt,
                                            row.am1_eta)
            m2id = self.getMuonScaleFactor('LooseID', row.am2_pt, row.am2_eta)
            m2iso = self.getMuonScaleFactor('LooseIsoFromLooseID', row.am2_pt,
                                            row.am2_eta)
            m3id = self.getMuonScaleFactor('LooseID', row.atm_pt, row.atm_eta)
            if self.doMediumMuon:
                m1id = self.getMuonScaleFactor('MediumID', row.am1_pt,
                                               row.am1_eta)
                m1iso = self.getMuonScaleFactor('LooseIsoFromMediumID',
                                                row.am1_pt, row.am1_eta)
                m2id = self.getMuonScaleFactor('MediumID', row.am2_pt,
                                               row.am2_eta)
                m2iso = self.getMuonScaleFactor('LooseIsoFromMediumID',
                                                row.am2_pt, row.am2_eta)
                m3id = self.getMuonScaleFactor('MediumID', row.atm_pt,
                                               row.atm_eta)
            m1tr = self.getTrackingScaleFactor(row.am1_eta)
            m2tr = self.getTrackingScaleFactor(row.am2_eta)
            m3tr = self.getTrackingScaleFactor(row.atm_eta)
            if self.shift == 'lepUp':
                vals += [
                    m1tr[0] + m1tr[1], m1id[0] + m1id[1], m1iso[0] + m1iso[1]
                ]
                vals += [
                    m2tr[0] + m2tr[1], m2id[0] + m2id[1], m2iso[0] + m2iso[1]
                ]
                vals += [m3tr[0] + m3tr[1], m3id[0] + m3id[1]]
            elif self.shift == 'lepDown':
                vals += [
                    m1tr[0] - m1tr[1], m1id[0] - m1id[1], m1iso[0] - m1iso[1]
                ]
                vals += [
                    m2tr[0] - m2tr[1], m2id[0] - m2id[1], m2iso[0] - m2iso[1]
                ]
                vals += [m3tr[0] - m3tr[1], m3id[0] - m3id[1]]
            else:
                vals += [m1tr[0], m1id[0], m1iso[0]]
                vals += [m2tr[0], m2id[0], m2iso[0]]
                vals += [m3tr[0], m3id[0]]
            for scale, val in zip(base, vals):
                if val != val:
                    logging.warning('{0}: {1} is NaN'.format(
                        row.channel, scale))
            weight = prod([val for val in vals if val == val])
            # scale to lumi/xsec
            weight *= float(
                self.intLumi) / self.sampleLumi if self.sampleLumi else 0.
            if hasattr(row, 'qqZZkfactor'):
                weight *= row.qqZZkfactor / 1.1  # ZZ variable k factor
        # fake scales
        if doFake:
            if not row.isData: weight *= -1
            for l in fakeLeps:
                n = fakeNum[l] if isinstance(fakeNum, dict) else fakeNum
                d = fakeDenom[l] if isinstance(fakeDenom, dict) else fakeDenom
                coll = 'taus' if l in ['ath'] else 'muons'
                if coll == 'taus' and self.doDM:
                    fake = self.getFakeRate(coll,
                                            getattr(row, '{}_pt'.format(l)),
                                            getattr(row, '{}_eta'.format(l)),
                                            n,
                                            d,
                                            dm=getattr(
                                                row, '{}_decayMode'.format(l)))
                else:
                    fake = self.getFakeRate(coll,
                                            getattr(row, '{}_pt'.format(l)),
                                            getattr(row, '{}_eta'.format(l)),
                                            n, d)
                fakeEff = fake[0]
                if self.shift == 'fakeUp': fakeEff = fake[0] + fake[1]
                if self.shift == 'fakeDown': fakeEff = fake[0] - fake[1]
                if fakeEff > 0 and fakeEff < 1:
                    weight *= fakeEff / (1 - fakeEff)
                else:
                    logging.warning(
                        'invalid fake eff = {} for {} {} {}'.format(
                            fakeeff, l, n, d))

        return weight