## backgrounds / mc #if args.background == "OnlyTTZ": # mc = [ TTZtoLLNuNu ] #elif args.background == "All": # mc = [ TTZtoLLNuNu , TTX, WZ, TTW, TZQ, rare ]#, nonprompt ] #else: # mc = [] mc = [] for sample in mc: sample.style = styles.fillStyle(sample.color) # reweighting if args.reweightPtGToSM: sel_string = "&&".join([ getFilterCut(isData=False), getLeptonSelection('all'), cutInterpreter.cutString(args.selection) ]) TTZ_ptG = TTZtoLLNuNu.get1DHistoFromDraw("gamma_pt[0]", [20, 0, 1000], selectionString=sel_string, weightString="weight") TTZ_ptG.Scale(1. / TTZ_ptG.Integral()) def get_reweight(var, histo): def reweight(event, sample): i_bin = histo.FindBin(getattr(event, var)) return histo.GetBinContent(i_bin) return reweight
) def getLeptonSelection(mode): if mode == "mumumumu": return "nMuons_tight_4l==4&&nElectrons_tight_4l==0" elif mode == "mumumue": return "nMuons_tight_4l==3&&nElectrons_tight_4l==1" elif mode == "mumuee": return "nMuons_tight_4l==2&&nElectrons_tight_4l==2" elif mode == "mueee": return "nMuons_tight_4l==1&&nElectrons_tight_4l==3" elif mode == "eeee": return "nMuons_tight_4l==0&&nElectrons_tight_4l==4" elif mode == 'all': return "nMuons_tight_4l+nElectrons_tight_4l==4" # reweighting if args.reweightPtZToSM: sel_string = "&&".join([ getFilterCut(isData=False), getLeptonSelection('all'), cutInterpreter.cutString(args.selection) ]) TTZ_ptZ = TTZtoLLNuNu.get1DHistoFromDraw("Z_pt", [20, 0, 1000], selectionString=sel_string, weightString="weight") TTZ_ptZ.Scale(1. / TTZ_ptZ.Integral()) def get_reweight(var, histo): def reweight(event, sample): i_bin = histo.FindBin(getattr(event, var)) return histo.GetBinContent(i_bin) return reweight
for mva in mvas: reader_nonprompt.addMethod(method=mva) sequence.append( makeDiscriminator(mva) ) # # Loop over channels # yields = {} allPlots = {} allModes = ['mumu','mue','ee'] for index, mode in enumerate(allModes): yields[mode] = {} if not args.noData: data_sample = Run2016 data_sample.texName = "data (legacy)" data_sample.setSelectionString([getFilterCut(isData=True), getLeptonSelection(mode)]) data_sample.name = "data" data_sample.read_variables = ["evt/I","run/I"] data_sample.style = styles.errorStyle(ROOT.kBlack) lumi_scale = data_sample.lumi/1000 # lumi_scale = 300 lumi_scale = 35.9 weight_ = lambda event, sample: event.weight TTZ_mc = TTZtoLLNuNu tWZ_sample = TWZ if args.nominalSignal else yt_TWZ_filter if args.WZpowheg: mc = [ tWZ_sample, TTZ_mc , TTX, WZ_powheg, rare, ZZ, nonprompt_TWZ_3l, Xgamma ] else:
def selection(self, dataMC, mllMin, metMin, zWindow1, zWindow2, zMassRange, nJets, nBTags, nElectrons=-1, nMuons=-1, hadronicSelection=False, isFastSim=False): '''Define full selection dataMC: 'Data' or 'MC' nElectrons, nMuons: Number of E and M. -1: all zWindow: offZ, onZ, or allZ hadronicSelection: whether to return only the hadronic selection isFastSim: adjust filter cut etc. for fastsim ''' nLeptons = self.nLeptons # Get the right channel and do sanity checks if nElectrons < 0 and nMuons < 0: # this should be the new "all" case. Just pass else: if nElectrons + nMuons != nLeptons: raise NotImplementedError("Electrons and Muons don't add up!") #Consistency checks if self.sys['selectionModifier']: assert self.sys[ 'selectionModifier'] in jmeVariations + metVariations + [ 'genMet' ], "Don't know about systematic variation %r, take one of %s" % ( self.sys['selectionModifier'], ",".join(jmeVariations + ['genMet'])) assert dataMC in ['Data', 'MC'], "dataMC = Data or MC, got %r." % dataMC #Postfix for variables (only for MC and if we have a jme variation) sysStr = "" metStr = "" if dataMC == "MC" and self.sys['selectionModifier'] in jmeVariations: sysStr = "_" + self.sys['selectionModifier'] if dataMC == "MC" and self.sys['selectionModifier'] in metVariations: metStr = "_" + self.sys['selectionModifier'] res = {'cuts': [], 'prefixes': []} if nJets and not (nJets[0] == 0 and nJets[1] < 0): assert nJets[0] >= 0 and ( nJets[1] >= nJets[0] or nJets[1] < 0), "Not a good nJets selection: %r" % nJets njetsstr = "nJetSelected" + sysStr + ">=" + str(nJets[0]) prefix = "nJets" + str(nJets[0]) if nJets[1] >= 0: njetsstr += "&&" + "nJetSelected" + sysStr + "<=" + str( nJets[1]) if nJets[1] != nJets[0]: prefix += str(nJets[1]) else: prefix += 'p' res['cuts'].append(njetsstr) res['prefixes'].append(prefix) if nBTags and not (nBTags[0] == 0 and nBTags[1] < 0): assert nBTags[0] >= 0 and ( nBTags[1] >= nBTags[0] or nBTags[1] < 0), "Not a good nBTags selection: %r" % nBTags nbtstr = "nBTag" + sysStr + ">=" + str(nBTags[0]) prefix = "nbtag" + str(nBTags[0]) if nBTags[1] >= 0: nbtstr += "&&nBTag" + sysStr + "<=" + str(nBTags[1]) if nBTags[1] != nBTags[0]: prefix += str(nBTags[1]) else: prefix += 'p' res['cuts'].append(nbtstr) res['prefixes'].append(prefix) if metMin and metMin > 0: res['cuts'].append('met_pt' + sysStr + metStr + '>=' + str(metMin)) res['prefixes'].append('met' + str(metMin)) if not hadronicSelection: if mllMin and mllMin > 0: res['cuts'].append('min_dl_mass>=' + str(mllMin)) res['prefixes'].append('mll' + str(mllMin)) if nMuons >= 0 and nElectrons >= 0: chStr = "(nMuons_%s==%i&&nElectrons_%s==%i)" % ( self.leptonId, nMuons, self.leptonId, nElectrons) else: # this is for the 'all' channel if not self.nonprompt: chStr = "nLeptons_%s==%i" % (self.leptonId, nLeptons) else: chStr = "nLeptons_%s>=%i" % (self.leptonId, nLeptons) #Z window # two different cases: Z_mass for 3l, Z1_mass_4l and Z2_mass_4l for 4l if nLeptons == 3: res['cuts'].append(getZCut(zWindow1, "Z_mass", zMassRange)) if not self.nonprompt: res['cuts'].append("Z_fromTight>0") elif nLeptons == 4: res['cuts'].append(getZCut(zWindow1, "Z1_mass_4l", zMassRange)) if zWindow2 == 'offZ': # if number of muons is even, go off-Z if nMuons % 2 == 0: logger.info("Z window 2 off Z, nMuons %s", nMuons) res['cuts'].append( getZCut("offZ", "Z2_mass_4l", zMassRange)) else: logger.info("Z window 2 all Z, nMuons %s", nMuons) res['cuts'].append( getZCut("allZ", "Z2_mass_4l", zMassRange)) else: logger.info("Z window 2 %s, nMuons %s", zWindow2, nMuons) res['cuts'].append( getZCut(zWindow2, "Z2_mass_4l", zMassRange)) # no Z-mass cut for 2l case res['cuts'].append(chStr) if not self.nonprompt: res['cuts'].append('nLeptons_%s==%i' % (self.leptonId, nLeptons)) else: res['cuts'].append('nLeptons_%s>=%i' % (self.leptonId, nLeptons)) if nLeptons == 1: lep_pt = "(lep_%s*(lep_pt - lep_ptCorr) + lep_ptCorr)" % self.tight_ID res['cuts'].append("Sum$(%s>40&&lep_%s>0)>0" % (lep_pt, self.leptonId)) res['cuts'].append("nlep==1") # loose lepton veto elif nLeptons == 2: raise NotImplementedError("Not yet thought about SS selection") elif nLeptons == 3: lep_pt = "(lep_%s*(lep_pt - lep_ptCorr) + lep_ptCorr)" % self.tight_ID leptonSelection = [\ "Sum$(%s>40&&lep_%s>0)>0"%(lep_pt, self.leptonId),\ "Sum$(%s>20&&lep_%s>0)>1"%(lep_pt, self.leptonId),\ "Sum$(%s>10&&lep_%s>0)>2"%(lep_pt, self.leptonId),\ ] res['cuts'].append("&&".join(leptonSelection)) res['cuts'].append( "!(nLeptons_tight_4l>=4)" ) # make sure to remove full overlap with 4l. This is enought, what is below shouldn't be necessary. if self.nonprompt: res['cuts'].append("nLeptons_tight_3l<3") #res['cuts'].append("min_dl_mass_FO_3l>12") #######################UPDATE ## need to veto 4l events to remove overlap #baseline4l = Setup(self.year, nLeptons=4) #baseline4l.parameters.update({'nJets':(2,-1), 'nBTags':(0,-1), 'zMassRange':20}) #for c in quadlepChannels: # res['cuts'].append("!(%s)"%baseline4l.preselection(dataMC, nElectrons=c.nE, nMuons=c.nM, short=True)['cut']) elif nLeptons == 4: res['cuts'].append( "Sum$(lep_pt>40&&lep_%s>0)>0 && Sum$(lep_pt>10&&lep_%s>0)>3" % (self.leptonId, self.leptonId)) #check if this is good enough res['cuts'].append("min_dl_mass>12&&totalLeptonCharge==0") else: raise NotImplementedError( "nLeptons has to be 1 or 2 or 3 or 4. That's already more than enough to think about." ) # Need a better solution for the Setups for different eras if self.year == 20167: self.year = 2016 #FIXME since we use 2016 MC for now if not self.short: res['cuts'].append( getFilterCut(isData=(dataMC == 'Data'), isFastSim=isFastSim, year=self.year)) # apply triggers in MC if not dataMC == 'Data': tr = triggerSelector(self.year) if not self.short: res['cuts'].append(tr.getSelection("MC")) res['cuts'].extend(self.externalCuts) return { 'cut': "&&".join(res['cuts']), 'prefix': '-'.join(res['prefixes']), 'weightStr': (self.weightString() if dataMC == 'MC' else 'weight') }
# # Loop over channels # yields = {} allPlots = {} allModes = ['nLep'] for index, mode in enumerate(allModes): yields[mode] = {} logger.info("Working on mode %s", mode) if not args.noData: data_sample = Run2016 if args.year == 2016 else Run2017 data_sample.texName = "data" data_sample.setSelectionString([ getFilterCut(isData=True, year=args.year), getLeptonSelection(mode) ]) data_sample.name = "data" data_sample.read_variables = ["evt/I", "run/I"] data_sample.style = styles.errorStyle(ROOT.kBlack) lumi_scale = data_sample.lumi / 1000 if args.noData: lumi_scale = 35.9 if args.year == 2016 else 41.0 weight_ = lambda event, sample: event.weight lumi_scale = 300 TTZ_mc = TTZtoLLNuNu if args.year == 2016: mc = [yt_TWW]
DY_noGS.color = ROOT.kOrange + 8 DY_noGS.texName = "DY (LO), N_{true b-jets}#geq2, no GS" DY_unknown = copy.deepcopy(DY_HT_LO) DY_unknown.color = ROOT.kRed - 3 DY_unknown.texName = "DY (LO), N_{true b-jets}#geq2, unknown" DY_fakeBs = copy.deepcopy(DY_HT_LO) DY_fakeBs.color = ROOT.kGreen + 3 DY_fakeBs.texName = "DY (LO), N_{true b-jets}=0" #mc = [DY_twoTrueBsElse, DY_twoTrueBsFromG, DY_twoTrueBsFromP, DY_twoTrueBsFromQ, DY_oneTrueBs, DY_fakeBs,TTX,boson, Top] mc = [DY_GS, DY_noGS, DY_unknown, DY_fakeBs, TTX, boson, Top] for s in mc: s.setSelectionString([getFilterCut(isData=False), tr.getSelection("MC")]) s.read_variables = ['reweightPU36fb/F', 'reweightBTagDeepCSV_SF/F'] s.weight = lambda event, s: event.reweightBTagDeepCSV_SF * event.reweightPU36fb s.style = styles.fillStyle(s.color) s.scale = lumi_scale #nBFromG = "Sum$(abs(genPartAll_pdgId)==5&&abs(genPartAll_motherId)>5&&(abs(genPartAll_motherId)==21))" #nBFromP = "Sum$(abs(genPartAll_pdgId)==5&&abs(genPartAll_motherId)>5&&(abs(genPartAll_motherId)==2212))" #nBFromQ = "Sum$(abs(genPartAll_pdgId)==5&&abs(genPartAll_motherId)<5)" # #DY_twoTrueBsFromG.addSelectionString(["Sum$(jet_pt>30&&abs(jet_eta)<2.4&&jet_id>0&&jet_btagDeepCSV>0.6324&&jet_hadronFlavour==5)>=2 && %s>=2"%nBFromG]) #DY_twoTrueBsFromP.addSelectionString(["Sum$(jet_pt>30&&abs(jet_eta)<2.4&&jet_id>0&&jet_btagDeepCSV>0.6324&&jet_hadronFlavour==5)>=2 && %s>=2 && %s<2"%(nBFromP,nBFromG)]) #DY_twoTrueBsFromQ.addSelectionString(["Sum$(jet_pt>30&&abs(jet_eta)<2.4&&jet_id>0&&jet_btagDeepCSV>0.6324&&jet_hadronFlavour==5)>=2 && %s>=2 && %s<2 && %s<2"%(nBFromQ,nBFromP,nBFromG)]) #DY_twoTrueBsElse.addSelectionString(["Sum$(jet_pt>30&&abs(jet_eta)<2.4&&jet_id>0&&jet_btagDeepCSV>0.6324&&jet_hadronFlavour==5)>=2 && %s<2 && %s<2 && %s<2"%(nBFromG,nBFromQ,nBFromP)]) #DY_oneTrueBs.addSelectionString(["Sum$(jet_pt>30&&abs(jet_eta)<2.4&&jet_id>0&&jet_btagDeepCSV>0.6324&&jet_hadronFlavour==5)==1"])
offZ2 = "&&abs(Z2_mass_4l-91.2)>20" if args.selection.count("offZ2") else "" offZ2 = "&&met_pt > 80" if args.selection.count("offZ2met") else offZ2 print offZ2 def getLeptonSelection( mode ): if mode=="mumumumu": return "nMuons_tight_4l==4&&nElectrons_tight_4l==0" + offZ2 elif mode=="mumumue": return "nMuons_tight_4l==3&&nElectrons_tight_4l==1" elif mode=="mumuee": return "nMuons_tight_4l==2&&nElectrons_tight_4l==2" + offZ2 elif mode=="mueee": return "nMuons_tight_4l==1&&nElectrons_tight_4l==3" elif mode=="eeee": return "nMuons_tight_4l==0&&nElectrons_tight_4l==4" + offZ2 elif mode=='all': return "nMuons_tight_4l+nElectrons_tight_4l==4" # reweighting if args.reweightPtZToSM: sel_string = "&&".join([getFilterCut(isData=False), getLeptonSelection('all'), cutInterpreter.cutString(args.selection)]) TTZ_ptZ = TTZtoLLNuNu.get1DHistoFromDraw("Z_pt", [20,0,1000], selectionString = sel_string, weightString="weight") TTZ_ptZ.Scale(1./TTZ_ptZ.Integral()) def get_reweight( var, histo ): def reweight(event, sample): i_bin = histo.FindBin(getattr( event, var ) ) return histo.GetBinContent(i_bin) return reweight for signal in signals: logger.info( "Computing PtZ reweighting for signal %s", signal.name ) signal_ptZ = signal.get1DHistoFromDraw("Z_pt", [20,0,1000], selectionString = sel_string, weightString="weight") signal_ptZ.Scale(1./signal_ptZ.Integral())
DY_noGS.texName = "DY (LO), N_{true b-jets}#geq2, no GS" DY_unknown = copy.deepcopy(DY_HT_LO) DY_unknown.color = ROOT.kRed-3 DY_unknown.texName = "DY (LO), N_{true b-jets}#geq2, unknown" DY_fakeBs = copy.deepcopy(DY_HT_LO) DY_fakeBs.color = ROOT.kGreen+3 DY_fakeBs.texName = "DY (LO), N_{true b-jets}=0" #mc = [DY_twoTrueBsElse, DY_twoTrueBsFromG, DY_twoTrueBsFromP, DY_twoTrueBsFromQ, DY_oneTrueBs, DY_fakeBs,TTX,boson, Top] mc = [DY_GS,DY_noGS,DY_unknown,DY_fakeBs,TTX,boson, Top] for s in mc: s.setSelectionString([getFilterCut(isData=False), tr.getSelection("MC")]) s.read_variables = ['reweightPU36fb/F', 'reweightBTagDeepCSV_SF/F'] s.weight = lambda event, s: event.reweightBTagDeepCSV_SF*event.reweightPU36fb s.style = styles.fillStyle(s.color) s.scale = lumi_scale #nBFromG = "Sum$(abs(genPartAll_pdgId)==5&&abs(genPartAll_motherId)>5&&(abs(genPartAll_motherId)==21))" #nBFromP = "Sum$(abs(genPartAll_pdgId)==5&&abs(genPartAll_motherId)>5&&(abs(genPartAll_motherId)==2212))" #nBFromQ = "Sum$(abs(genPartAll_pdgId)==5&&abs(genPartAll_motherId)<5)" # #DY_twoTrueBsFromG.addSelectionString(["Sum$(jet_pt>30&&abs(jet_eta)<2.4&&jet_id>0&&jet_btagDeepCSV>0.6324&&jet_hadronFlavour==5)>=2 && %s>=2"%nBFromG]) #DY_twoTrueBsFromP.addSelectionString(["Sum$(jet_pt>30&&abs(jet_eta)<2.4&&jet_id>0&&jet_btagDeepCSV>0.6324&&jet_hadronFlavour==5)>=2 && %s>=2 && %s<2"%(nBFromP,nBFromG)]) #DY_twoTrueBsFromQ.addSelectionString(["Sum$(jet_pt>30&&abs(jet_eta)<2.4&&jet_id>0&&jet_btagDeepCSV>0.6324&&jet_hadronFlavour==5)>=2 && %s>=2 && %s<2 && %s<2"%(nBFromQ,nBFromP,nBFromG)]) #DY_twoTrueBsElse.addSelectionString(["Sum$(jet_pt>30&&abs(jet_eta)<2.4&&jet_id>0&&jet_btagDeepCSV>0.6324&&jet_hadronFlavour==5)>=2 && %s<2 && %s<2 && %s<2"%(nBFromG,nBFromQ,nBFromP)]) #DY_oneTrueBs.addSelectionString(["Sum$(jet_pt>30&&abs(jet_eta)<2.4&&jet_id>0&&jet_btagDeepCSV>0.6324&&jet_hadronFlavour==5)==1"])
def selection(self, dataMC, mllMin, metMin, zWindow, nJets, nBTags, channel='all', hadronicSelection=False, isFastSim=False): '''Define full selection dataMC: 'Data' or 'MC' channel: all, EE, MuMu or EMu zWindow: offZ, onZ, or allZ hadronicSelection: whether to return only the hadronic selection isFastSim: adjust filter cut etc. for fastsim ''' #Consistency checks if self.sys['selectionModifier']: assert self.sys[ 'selectionModifier'] in jmeVariations + metVariations + [ 'genMet' ], "Don't know about systematic variation %r, take one of %s" % ( self.sys['selectionModifier'], ",".join(jmeVariations + ['genMet'])) assert dataMC in ['Data', 'MC'], "dataMC = Data or MC, got %r." % dataMC #Postfix for variables (only for MC and if we have a jme variation) sysStr = "" metStr = "" if dataMC == "MC" and self.sys['selectionModifier'] in jmeVariations: sysStr = "_" + self.sys['selectionModifier'] if dataMC == "MC" and self.sys['selectionModifier'] in metVariations: metStr = "_" + self.sys['selectionModifier'] res = {'cuts': [], 'prefixes': []} if nJets and not (nJets[0] == 0 and nJets[1] < 0): assert nJets[0] >= 0 and ( nJets[1] >= nJets[0] or nJets[1] < 0), "Not a good nJets selection: %r" % nJets njetsstr = "nJetSelected" + sysStr + ">=" + str(nJets[0]) prefix = "nJets" + str(nJets[0]) if nJets[1] >= 0: njetsstr += "&&" + "nJetSelected" + sysStr + "<=" + str( nJets[1]) if nJets[1] != nJets[0]: prefix += str(nJets[1]) else: prefix += 'p' res['cuts'].append(njetsstr) res['prefixes'].append(prefix) if nBTags and not (nBTags[0] == 0 and nBTags[1] < 0): assert nBTags[0] >= 0 and ( nBTags[1] >= nBTags[0] or nBTags[1] < 0), "Not a good nBTags selection: %r" % nBTags nbtstr = "nBTag" + sysStr + ">=" + str(nBTags[0]) prefix = "nbtag" + str(nBTags[0]) if nBTags[1] >= 0: nbtstr += "&&nBTag" + sysStr + "<=" + str(nBTags[1]) if nBTags[1] != nBTags[0]: prefix += str(nBTags[1]) else: prefix += 'p' res['cuts'].append(nbtstr) res['prefixes'].append(prefix) if metMin and metMin > 0: res['cuts'].append('met_pt' + sysStr + metStr + '>=' + str(metMin)) res['prefixes'].append('met' + str(metMin)) if not hadronicSelection: if mllMin and mllMin > 0: res['cuts'].append('Z_mass>=' + str(mllMin)) res['prefixes'].append('mll' + str(mllMin)) presel3mu = "(nGoodMuons==3&&nGoodElectrons==0)" presel2mu1e = "(nGoodMuons==2&&nGoodElectrons==1)" presel2e1mu = "(nGoodMuons==1&&nGoodElectrons==2)" presel3e = "(nGoodMuons==0&&nGoodElectrons==3)" allPresels = [presel3mu, presel2mu1e, presel2e1mu, presel3e] #Z window assert zWindow in [ 'offZ', 'onZ', 'allZ' ], "zWindow must be one of onZ, offZ, allZ. Got %r" % zWindow if zWindow == 'onZ': res['cuts'].append(getZCut(zWindow, self.zMassRange)) if zWindow == 'offZ' and channel != "EMu": res['cuts'].append( getZCut(zWindow, self.zMassRange) ) # Never use offZ when in emu channel, use allZ instead #lepton channel assert channel in allChannels, "channel must be one of " + ",".join( allChannels) + ". Got %r." % channel if channel == "3mu": chStr = presel3mu elif channel == "2mu1e": chStr = presel2mu1e elif channel == "2e1mu": chStr = presel2e1mu elif channel == "3e": chStr = presel3e elif channel == "all": chStr = "(" + '||'.join(allPresels) + ')' res['cuts'].append(chStr) res['cuts'].append('nlep==3') res['cuts'].append("lep_pt[0]>40&&lep_pt[1]>20&&lep_pt[2]>10") res['cuts'].append( getFilterCut(isData=(dataMC == 'Data'), isFastSim=isFastSim)) res['cuts'].extend(self.externalCuts) return { 'cut': "&&".join(res['cuts']), 'prefix': '-'.join(res['prefixes']), 'weightStr': (self.weightString() if dataMC == 'MC' else 'weight') }
SingleMuon_Run2016.setSelectionString("(HLT_SingleMuTTZ)") SingleEleMu_Run2016.setSelectionString( "(HLT_SingleEleTTZ && !HLT_SingleMuTTZ)") #data_sample.texName = "data (2#mu, 1e)" elif mode == "muee": data_sample = [SingleEleMu_Run2016, SingleMuon_Run2016] SingleMuon_Run2016.setSelectionString("(HLT_SingleMuTTZ)") SingleEleMu_Run2016.setSelectionString( "(HLT_SingleEleTTZ && !HLT_SingleMuTTZ)") #data_sample.texName = "data (1#mu, 2e)" elif mode == "all": data_sample = [ SingleEleMu_Run2016, SingleMuon_Run2016, SingleElectron_Run2016 ] SingleMuon_Run2016.setSelectionString( [getFilterCut(isData=True), "(HLT_SingleMuTTZ)"]) SingleEleMu_Run2016.setSelectionString([ getFilterCut(isData=True), "(HLT_SingleEleTTZ && !HLT_SingleMuTTZ)" ]) for d in data_sample: d.texName = "data" d.read_variables = ['weight/F'] d.style = styles.errorStyle(ROOT.kBlack) lumi_scale = sum(d.lumi for d in data_sample) / float(len(data_sample)) / 1000 data_weight = lambda event, sample: event.weight data_weight_string = "weight" logger.info('Lumi scale is ' + str(lumi_scale))
data_2017D_sample = SingleEleMu_Run2017EF data_2017D_sample.texName = "data 2017EF (1#mu, 1e)" data_2017EF_sample = SingleEleMu_Run2017EF data_2017EF_sample.texName = "data 2017EF (1#mu, 1e)" data_2017_samples = [ data_2017BC_sample, data_2017Cv2D_sample, data_2017EF_sample ] data_2016_samples = [ copy.deepcopy(data_2016_sample) for x in data_2017_samples ] else: raise ValueError for i_s, data_2017_sample in enumerate(data_2017_samples): data_2017_sample.setSelectionString( [getFilterCut(isData=True, year=2017), getLeptonSelection(mode)]) data_2017_sample.read_variables = ["evt/I", "run/I"] data_2017_sample.style = styles.errorStyle(colors[i_s]) lumi_2017_scale = data_2017_sample.lumi / 1000 for i_s, data_2016_sample in enumerate(data_2016_samples): data_2016_sample.setSelectionString( [getFilterCut(isData=True, year=2016), getLeptonSelection(mode)]) data_2016_sample.read_variables = ["evt/I", "run/I"] data_2016_sample.style = styles.lineStyle(colors[i_s] + 1, errors=True) lumi_2016_scale = data_2016_sample.lumi / 1000 weight_ = lambda event, sample: event.weight stack_samples = []
) # define 3l selections def getLeptonSelection(mode): if mode == "mumumu": return "nGoodMuons==3&&nGoodElectrons==0" elif mode == "mumue": return "nGoodMuons==2&&nGoodElectrons==1" elif mode == "muee": return "nGoodMuons==1&&nGoodElectrons==2" elif mode == "eee": return "nGoodMuons==0&&nGoodElectrons==3" elif mode == 'all': return "nGoodMuons+nGoodElectrons==3" # reweighting if args.reweightPtZToSM: sel_string = "&&".join([ getFilterCut(isData=False), getLeptonSelection('all'), cutInterpreter.cutString(args.selection) ]) TTZ_ptZ = TTZtoLLNuNu.get1DHistoFromDraw("Z_pt", [20, 0, 1000], selectionString=sel_string, weightString="weight") TTZ_ptZ.Scale(1. / TTZ_ptZ.Integral()) def get_reweight(var, histo): def reweight(event, sample): i_bin = histo.FindBin(getattr(event, var)) return histo.GetBinContent(i_bin) return reweight
sequence.append(getLooseLeptonMult) # # Loop over channels # yields = {} allPlots = {} allModes = ['mumumu', 'mumue', 'muee', 'eee'] for index, mode in enumerate(allModes): yields[mode] = {} if not args.noData: data_sample = Run2016 data_sample.texName = "data (legacy)" data_sample.setSelectionString( [getFilterCut(isData=True), getLeptonSelection(mode)]) data_sample.name = "data" data_sample.read_variables = ["evt/I", "run/I"] data_sample.style = styles.errorStyle(ROOT.kBlack) lumi_scale = data_sample.lumi / 1000 if args.noData: lumi_scale = 35.9 weight_ = lambda event, sample: event.weight TTZ_mc = TTZtoLLNuNu if args.WZpowheg: mc = [TWZ, TTZ_mc, TTX, WZ_powheg, rare, ZZ, nonpromptMC, Xgamma] else: mc = [TWZ, TTZ_mc, TTX, WZ_amcatnlo, rare, ZZ, nonpromptMC, Xgamma]
elif mode=='all': return "nGoodMuons+nGoodElectrons==2" ## backgrounds / mc #if args.background == "OnlyTTZ": # mc = [ TTZtoLLNuNu ] #elif args.background == "All": # mc = [ TTZtoLLNuNu , TTX, WZ, TTW, TZQ, rare ]#, nonprompt ] #else: # mc = [] mc = [] for sample in mc: sample.style = styles.fillStyle(sample.color) # reweighting if args.reweightPtGToSM: sel_string = "&&".join([getFilterCut(isData=False), getLeptonSelection('all'), cutInterpreter.cutString(args.selection)]) TTG_ptG = ttGamma0j_ll.get1DHistoFromDraw("photon_pt", [20,0,1000], selectionString = sel_string, weightString="weight") TTG_ptG.Scale(1./TTG_ptG.Integral()) def get_reweight( var, histo ): def reweight(event, sample): i_bin = histo.FindBin(getattr( event, var ) ) return histo.GetBinContent(i_bin) return reweight for signal in signals: logger.info( "Computing PtG reweighting for signal %s", signal.name ) signal_ptG = signal.get1DHistoFromDraw("photon_pt", [20,0,1000], selectionString = sel_string, weightString="weight") signal_ptG.Scale(1./signal_ptG.Integral())
elif mode=="all": return "nGoodLeptons==3" # # Loop over channels # allPlots = {} allModes = ['mumumu','mumue','muee', 'eee', 'all'] allModes = ['all'] for index, mode in enumerate(allModes): logger.info('Working on mode ' + str(mode)) if args.year == 2016: data_sample = Run2016 data_sample.setSelectionString([getFilterCut(isData=True), getLeptonSelection(mode)]) elif args.year == 2017: data_sample = Run2017 data_sample.setSelectionString([getFilterCut(isData=True, year=2017), getLeptonSelection(mode)]) lumi_scale = data_sample.lumi/1000 data_sample.texName = "data" data_sample.read_variables = ['weight/F'] data_sample.style = styles.errorStyle( ROOT.kBlack ) data_weight = lambda event, sample: event.weight data_weight_string = "weight" logger.info('Lumi scale is ' + str(lumi_scale)) if args.year == 2016:
for s in quadlep_samples: logger.info("Sample: %s", s.name) hists[s.name] = mt2ll_hist.Clone() hists[s.name].Reset() hists[s.name].legendText = s.texName met_hists[s.name] = met_hist.Clone() met_hists[s.name].Reset() met_hists[s.name].legendText = s.texName # selection for data or MC. Trigger and filters and stuff! for mode in modes: logger.info("Working on mode %s", mode) if s.isData: s.setSelectionString([ getFilterCut(isData=True, year=2016), quadlepSelection, getLeptonSelection(mode) ]) else: s.setSelectionString([ getFilterCut(isData=False, year=2016), quadlepSelection, tr.getSelection("MC"), getLeptonSelection(mode) ]) reader = s.treeReader(variables=variables) reader.start() while reader.run(): r = reader.event