def plotSampleSet(channel,sampleset,tag="",outdir="plots"): """Test plotting of SampleSet class for data/MC comparison.""" LOG.header("plotSampleSet") selections = [ 'q_1*q_2<0 && iso_1<0.15 && idDecayModeNewDMs_2 && idDeepTau2017v2p1VSjet_2>=16 && idDeepTau2017v2p1VSe_2>=2 && idDeepTau2017v2p1VSmu_2>=8 && !lepton_vetoes_notau && metfilter', ] variables = [ Var('m_vis', 40, 0, 200), Var('mt_1', "mt(mu,MET)", 40, 0, 200), Var('pt_1', "Muon pt", 40, 0, 120, ), Var('pt_2', "tau_h pt", 40, 0, 120, ), Var('eta_1', "Muon eta", 30, -3, 3, ymargin=1.6, ncols=2), Var('eta_2', "tau_h eta", 30, -3, 3, ymargin=1.6, ncols=2), Var('njets', 8, 0, 8), Var('rawDeepTau2017v2p1VSjet_2', 'rawDeepTau2017v2p1VSjet', 22, 0.78, 1, pos='left'), ] text = "#mu#tau_{h} baseline" if channel=='mutau' else "e#tau_{h} baseline" # PLOT outdir = ensuredir(outdir) parallel = True #and False fname = "%s/plotPico_$VAR%s"%(outdir,tag) for selection in selections: stacks = sampleset.getstack(variables,selection,method='QCD_OSSS',parallel=parallel) for stack, variable in stacks.iteritems(): #position = "" #variable.position or 'topright' stack.draw() stack.drawlegend() #position) stack.drawtext(text) stack.saveas(fname,ext=['png','pdf']) stack.close()
def plotsamples(datasample, expsamples, tag=""): """Test Sample.gethist method and plot data/MC comparison.""" LOG.header("plotsamples") # SETTING outdir = ensuredir("plots") fname = "%s/testSamples_$VAR%s.png" % (outdir, tag) # MAKE 1D HISTS for selection, weight in selections: histdict = {} for sample in [datasample] + expsamples: hists = sample.gethist(variables, selection) histdict[sample] = hists print ">>> %r: %s" % (sample.name, [repr(h.GetName()) for h in hists]) # PLOT for i, variable in enumerate(variables): #LOG.header(variable) datahist = histdict[datasample][i] exphists = [histdict[s][i] for s in expsamples] plot = Stack(variable, datahist, exphists) plot.draw(ratio=True) plot.drawlegend(position=position) plot.drawtext(text) plot.saveas(fname) plot.close()
def plotSampleSet(samples, tag="", singlevar=False): """Test SampleSet class: join samples, print out, and plot.""" LOG.header("testSampleSet") # GET HISTS for selection, weight in selections: if singlevar: result = samples.gethists(variables[0], selection, split=False) result.printall() #var, datahist, exphists = result #print var #print datahist #print exphists else: result = samples.gethists(variables, selection, split=False) result.printall() # PLOT outdir = ensuredir("plots") fname = "%s/testSamplesSet_$VAR%s.png" % (outdir, tag) for selection, weight in selections: if singlevar: stack = samples.getstack(variables[0], selection, split=False) stack.draw() stack.drawlegend(position=position) stack.saveas(fname) #tag="_SampleSet",outdir=outdir) stack.close() else: stacks = samples.getstack(variables, selection, split=False) for stack in stacks: stack.draw() stack.drawlegend(position=position) stack.saveas(fname) #tag="_SampleSet",outdir=outdir) stack.close()
def main(args): LOG.header("Prepare samples") sampleset = [ ('ZTT', "Z -> #tau_{mu}#tau_{h}", 1.00), ('WJ', "W + jets", 0.40), ('QCD', "QCD multijet", 0.30), ('TT', "t#bar{t}", 0.15), ('Data', "Observed", -1 ), ] lumi = 0.001 # [fb-1] to cancel xsec [pb] nevts = args.nevts snames = [n[0] for n in sampleset] scales = {n[0]: n[2] for n in sampleset} # relative contribtions to pseudo data outdir = ensuredir('plots') indir = outdir filedict = makesamples(nevts,sample=snames,scales=scales,outdir=outdir) datasample = None expsamples = [ ] #CMSStyle.setCMSEra(2018) setera(2018,lumi) for name, title, xsec in sampleset: file, tree = filedict[name] fname = file.GetName() color = None #STYLE.getcolor(name,verb=2) data = name.lower()=='data' file.Close() sample = Sample(name,title,fname,xsec,color=color,data=data) #sample = Sample(name,title,fname,xsec,lumi=lumi,color=color,data=data) if sample.isdata: datasample = sample else: expsamples.append(sample) plotsamples(datasample,expsamples) plotsamples2D(datasample,expsamples) testMergedSamples(datasample,expsamples)
def __iter__(self): """Start iteration over samples. Returns Variable, TH1D, list (of TH1D), list (of TH1D)""" vars = self.vars data = self.data exp = self.exp sig = self.signal if islist(vars): nvars = len(vars) if (exp and len(exp) != nvars) or (sig and len(sig) != nvars): LOG.warning( "HistSet.__init__: Number of histograms (data=%d,exp=%d,sig=%s) does not match number of variables (%s)" % (len(data), len(exp), len(sig), nvars)) if not isinstance(data, dict) and not isinstance( exp, dict) and (not sig or isinstance(sig, dict)): LOG.warning( "HistSet.__init__: Types do not match: data=%s, exp=%s, sig=%s" % (type(data), type(exp), type(sig))) if self.signal: for var in self.vars: yield var, data[var], exp[var], sig[var] else: for var in self.vars: yield var, data[var], exp[var] else: if self.signal: for val in [vars, data, exp, sig]: yield val else: for val in [vars, data, exp]: yield val
def plotsamples2D(datasample,expsamples): """Test Sample.gethist2D method.""" LOG.header("plotsamples2D") for selection, weight in selections: histdict = { } for sample in [datasample]+expsamples: hists = sample.gethist2D(variables2D,selection) histdict[sample] = hists print ">>> %r: %s"%(sample.name,[repr(h.GetName()) for h in hists])
def plot(sampleset, channel, parallel=True, tag="", outdir="plots", histdir="", era=""): """Test plotting of SampleSet class for data/MC comparison.""" LOG.header("plot") # SELECTIONS inclusive = "(q_1*q_2<0)" inclusive = inclusive.replace(" ", "") inclusive_cr_qcd = inclusive.replace( "q_1*q_2<0", "q_1*q_2>0" ) # inverting the opposite-sign requirement of the mutau pair into a same-sign requirment selections = [ Sel('inclusive', inclusive), Sel('inclusive_cr_qcd', inclusive_cr_qcd), ] # VARIABLES # TODO section 5: extend with other variables, which are available in the flat n-tuples variables = [ Var('m_vis', 40, 0, 200), ] # PLOT and HIST outdir = ensuredir(repkey(outdir, CHANNEL=channel, ERA=era)) histdir = ensuredir(repkey(histdir, CHANNEL=channel, ERA=era)) outhists = R.TFile.Open(histdir, 'recreate') exts = ['png', 'pdf'] for selection in selections: outhists.mkdir(selection.filename) stacks = sampleset.getstack( variables, selection, method='QCD_OSSS', scale=1.1, parallel=parallel ) # the 'scale' keyword argument - chosen as 1.1 for mutau - # is an extrapolation factor for the QCD shape from the same-sign # to the opposite-sign region fname = "%s/$VAR_%s-%s-%s$TAG" % (outdir, channel, selection.filename, era) text = "%s: %s" % (channel.replace('mu', "#mu").replace( 'tau', "#tau_{h}"), selection.title) for stack, variable in stacks.iteritems(): outhists.cd(selection.filename) for h in stack.hists: h.Write(h.GetName().replace("QCD_", "QCD"), R.TH1.kOverwrite) stack.draw() stack.drawlegend(x1=0.6, x2=0.95, y1=0.35, y2=0.95) stack.drawtext(text) stack.saveas(fname, ext=exts, tag=tag) stack.close() outhists.Close()
def getcolor(sample,color=kWhite,**kwargs): """Get color for some sample name.""" if hasattr(sample,'name'): sample = sample.name for key in sample_colors: #sorted(sample_colors,key=lambda x: len(x),reverse=True) if re.findall(key.replace('*',".*"),sample): # glob -> regex wildcard LOG.verb("SampleStyle.getcolor: Found color %s for %r from search term %r!"%(sample_colors[key],sample,key),kwargs,level=3) color = sample_colors[key] break else: LOG.warning("SampleStyle.getcolor: Could not find color for %r! Returning %s..."%(sample,color)) return color
def gettitle(sample,default=None,**kwargs): """Get title for some sample name.""" if sample in sample_titles: LOG.verb("SampleStyle.gettitle: Found title %s for %r!"%(sample_titles[sample],sample),kwargs,level=3) sample = sample_titles[sample] elif default: sample = default else: LOG.warning("SampleStyle.gettitle: Could not find title for %r! Returning %r..."%(sample,sample)) if kwargs.get('latex',False): sample = makelatex(sample) return sample
def testSampleSet(datasample, expsamples, tag=""): """Test SampleSet class: join samples, print out, and plot.""" LOG.header("testSampleSet") print ">>> Joining samples in one set" % (expsamples) checkMergedSample = True and False singlevar = True and False if checkMergedSample: color = expsamples[0].fillcolor bkgsample = MergedSample('Bkg', "Background", expsamples[1:], color=color) expsamples = [expsamples[0], bkgsample] expsample = MergedSample('Exp', "Expected", expsamples, color=color) expsamples = [expsample] samples = SampleSet(datasample, expsamples) print ">>> samples=%s" % samples print ">>> " samples.printtable() samples.printobjs() print ">>> " # GET HISTS for selection, weight in selections: if singlevar: result = samples.gethists(variables[0], selection) result.printall() #var, datahist, exphists = result #print var #print datahist #print exphists else: result = samples.gethists(variables, selection) result.printall() # PLOT outdir = ensuredir("plots") fname = "%s/testSamplesSet_$VAR%s.png" % (outdir, tag) for selection, weight in selections: if singlevar: stack = samples.getstack(variables[0], selection) stack.draw() stack.drawlegend(position=position) stack.saveas(fname) #tag="_SampleSet",outdir=outdir) stack.close() else: stacks = samples.getstack(variables, selection) for stack in stacks: stack.draw() stack.drawlegend(position=position) stack.saveas(fname) #tag="_SampleSet",outdir=outdir) stack.close()
def testCMSera(): """Test setCMSera""" LOG.header("testCMSera") erasets = [ '7', '8', '2012', (7,8), 2016, 2017, 2018, (2016,2017,2018), 'Run2', 'Phase2', ] for eras in erasets: eras = ensurelist(eras) args = ','.join(repr(y) for y in eras) result = CMSStyle.setCMSEra(*eras) print ">>> CMSStyle.setCMSera(%s) = %r"%(args,result)
def main(): selections = [ "", "pt_1>50 && pt_2>50", Selection("pt_1>50 && pt_2>50"), ] mvisbins = [0, 30, 40, 50, 60, 70, 75, 80, 90, 100, 120, 200] pt_1bins = [0, 30, 40, 50, 60, 70, 75, 80, 90, 100, 120, 200] xvar = Variable('m_vis', 40, 0, 200) yvar = Variable('pt_1', 40, 0, 200) varlist1 = [ Variable('m_vis', 40, 0, 200), Variable('njets', 8, 0, 8), ] varlist2 = [ ('m_vis', mvisbins), ('njets', 8, 0, 8), ] xvarlist1 = varlist1 yvarlist1 = varlist1[::-1] # reverse xvarlist2 = varlist2 yvarlist2 = varlist2[::-1] # reverse # UNWRAP args to gethist LOG.header("unwrap_gethist_args") name, func = "unwrap_gethist_args", unwrap_gethist_args for selection in selections: printIO(name, func, 'm_vis', 40, 0, 200, selection) printIO(name, func, 'm_vis', mvisbins, selection) printIO(name, func, xvar, selection) printIO(name, func, varlist1, selection) printIO(name, func, varlist2, selection) print ">>> " # UNWRAP args to gethist2D LOG.header("unwrap_gethist2D_args") name, func = "unwrap_gethist2D_args", unwrap_gethist2D_args for selection in selections: printIO(name, func, 'm_vis', 40, 0, 200, 'pt_1', 40, 0, 200, selection) printIO(name, func, 'm_vis', mvisbins, 'pt_1', pt_1bins, selection) printIO(name, func, 'm_vis', 40, 0, 200, 'pt_1', pt_1bins, selection) printIO(name, func, 'm_vis', mvisbins, 'pt_1', 40, 0, 200, selection) printIO(name, func, xvar, yvar, selection) printIO(name, func, (xvar, yvar), selection) printIO(name, func, [(xvar, yvar)], selection) printIO(name, func, xvarlist1, yvarlist1, selection) printIO(name, func, xvarlist2, yvarlist2, selection) printIO(name, func, zip(xvarlist1, yvarlist1), selection) print ">>> "
def testMergedSamples(datasample,expsamples): """Test MergedSample class: join samples, print out, and plot.""" LOG.header("testMergedSamples") print ">>> Joining samples %s"%(expsamples) #color = expsamples[0].fillcolor STYLE.sample_colors['Exp'] = STYLE.kOrange STYLE.sample_colors['Bkg'] = STYLE.kOrange bkgsample = MergedSample("Bkg","Background",expsamples[1:]) #,color=color) expsamples = [expsamples[0],bkgsample] expsample = MergedSample("Exp","Expected",expsamples) #,color=color) print ">>> " expsample.printheader() expsample.printrow() expsample.printobjs() print ">>> " plotsamples(datasample,[expsample],tag='_merged')
def makesamples(channel,era,fpattern): LOG.header("makesamples") weight = "genweight*trigweight*puweight*idisoweight_1*idweight_2" expsamples = [ # table of MC samples to be converted to Sample objects ('DY', "DYJetsToLL_M-10to50", "Drell-Yan 10-50", 18610.0, {'extraweight': 'zptweight'} ), ('DY', "DYJetsToLL_M-50", "Drell-Yan 50", 4963.0, {'extraweight': 'zptweight'} ), ('DY', "DY1JetsToLL_M-50", "Drell-Yan 1J 50", 1012.0, {'extraweight': 'zptweight'} ), ('DY', "DY2JetsToLL_M-50", "Drell-Yan 2J 50", 334.7, {'extraweight': 'zptweight'} ), ('DY', "DY3JetsToLL_M-50", "Drell-Yan 3J 50", 102.3, {'extraweight': 'zptweight'} ), ('DY', "DY4JetsToLL_M-50", "Drell-Yan 4J 50", 54.52, {'extraweight': 'zptweight'} ), ('WJ', "WJetsToLNu", "W + jets", 50260.0, ), ('WJ', "W1JetsToLNu", "W + 1J", 9625.0 ), ('WJ', "W2JetsToLNu", "W + 2J", 3161.0 ), ('WJ', "W3JetsToLNu", "W + 3J", 954.8 ), ('WJ', "W4JetsToLNu", "W + 4J", 494.6 ), ('VV', "WW", "WW", 75.88 ), ('VV', "WZ", "WZ", 27.6 ), ('VV', "ZZ", "ZZ", 12.14 ), ('ST', "ST_t-channel_top", "ST t-channel t", 136.02 ), ('ST', "ST_t-channel_antitop", "ST t-channel at", 80.95 ), ('ST', "ST_tW_top", "ST tW", 35.85 ), ('ST', "ST_tW_antitop", "ST atW", 35.85 ), ('TT', "TT", "ttbar", 831.76, {'extraweight': 'ttptweight'} ), ] datasamples = { # table of data samples (per channel) to be converted to Sample objects 'mutau': ('Data', "SingleMuon_Run%d?"%era, 'Observed'), 'etau': ('Data', "SingleElectron_Run%d?"%era), } # SAMPLE SET sampleset = getsampleset(datasamples,expsamples,channel=channel,era=era,file=fpattern,weight=weight) sampleset.stitch("W*Jets", incl='WJ', name='WJ' ) sampleset.stitch("DY*J*M-50", incl='DYJ', name="DY_M-50", title="Drell-Yan M=50GeV" ) #sampleset.stitch("DY*J*M-10to50", incl='DYJ', name="DY_M-10to50", title="Drell-Yan 10<M<50GeV" ) sampleset.join('DY', name='DY', title="Drell-Yan" ) sampleset.join('VV','WZ','WW','ZZ', name='VV', title="Diboson" ) sampleset.join('TT','ST', name='Top', title="ttbar and single top" ) sampleset.split('DY',[ ('ZTT',"Z -> tau_{#mu}tau_{h}", "genmatch_2==5"), ('ZL', "Drell-Yan with l -> tau_{h}","genmatch_2>0 && genmatch_2<5"), ('ZJ', "Drell-Yan with j -> tau_{h}","genmatch_2==0") ]) sampleset.printtable() return sampleset
def checklegend(samples,tag=""): """Check legend entries: colors, titles, ...""" # https://root.cern.ch/doc/master/classTLegend.html LOG.header("checklegend"+tag.replace(' ','')) output = ensuredir('plots') fname = "%s/testStyle_legend%s"%(output,tag) #height = 0.05*(len(samples)) xdim = 550 ydim = 50*(len(samples)+2) #width = 0.4 #x1, y1 = 0.1, 0.9 print ">>> Canvas: %sx%s (nsamples=%d)"%(xdim,ydim,len(samples)) canvas = TCanvas('canvas','canvas',xdim,ydim) #legend = TLegend(x1,y1,x1+width,y1-height) legend = TLegend(0,0,1,1) legend.SetBorderSize(0) legend.SetMargin(0.12) #legend.SetTextSize(tsize) #legend.SetNColumns(ncols) #legend.SetColumnSeparation(colsep) #legend.SetHeader("HTT style",'C') legend.SetTextFont(42) # bold for title hists = [ ] for sample in samples: color = STYLE.getcolor(sample,verb=2) title = STYLE.gettitle(sample,latex=True,verb=2) style = 'ep' if 'Data' in sample else 'f' hist = TH1F(sample,title,1,0,1) hist.SetFillColor(color) #hist.SetLineColor(kBlack) hist.SetLineWidth(2) hist.SetMarkerColor(kBlack) #hist.SetMarkerStyle(1) legend.AddEntry(hist,title,style) if 'Data' in sample: hist.Draw('E1') hists.append(hist) legend.Draw() canvas.SaveAs(fname+".png") canvas.SaveAs(fname+".pdf") canvas.Close()
def main(): cut = "pt_1>50 && pt_2>50" mvisbins = [0, 30, 40, 50, 60, 70, 75, 80, 90, 100, 120, 200] pt_1bins = [0, 30, 40, 50, 60, 70, 75, 80, 90, 100, 120, 200] xvar = Variable('m_vis', 40, 0, 200) yvar = Variable('pt_1', 40, 0, 200) varlist1 = [ Variable('m_vis', 40, 0, 200), Variable('njets', 8, 0, 8), ] varlist2 = [ ('m_vis', mvisbins), ('njets', 8, 0, 8), ] xvarlist1 = varlist1 yvarlist1 = varlist1[::-1] # reverse xvarlist2 = varlist2 yvarlist2 = varlist2[::-1] # reverse # UNWRAP args to gethist LOG.header("unwrap_gethist_args") name, func = "unwrap_gethist_args", unwrap_gethist_args printIO(name, func, xvar, cut) printIO(name, func, 'm_vis', 40, 0, 200, cut) printIO(name, func, 'm_vis', mvisbins, cut) printIO(name, func, varlist1, cut) printIO(name, func, varlist2, cut) # UNWRAP args to gethist2D LOG.header("unwrap_gethist2D_args") name, func = "unwrap_gethist2D_args", unwrap_gethist2D_args printIO(name, func, xvar, yvar, cut) printIO(name, func, (xvar, yvar), cut) printIO(name, func, 'm_vis', 40, 0, 200, 'pt_1', 40, 0, 200, cut) printIO(name, func, 'm_vis', mvisbins, 'pt_1', pt_1bins, cut) printIO(name, func, xvarlist1, yvarlist1, cut) printIO(name, func, xvarlist2, yvarlist2, cut)
def main(args): LOG.header("Prepare samples") sampleset = [ ('ZTT', "Z -> #tau_{mu}#tau_{h}", 1.00), ('WJ', "W + jets", 0.40), ('QCD', "QCD multijet", 0.30), ('TT', "t#bar{t}", 0.15), ('Data', "Observed", -1), ] lumi = 0.001 # [fb-1] to cancel xsec [pb] nevts = args.nevts snames = [n[0] for n in sampleset] scales = {n[0]: n[2] for n in sampleset} # relative contribtions to pseudo data outdir = ensuredir('plots') indir = outdir filedict = makesamples(nevts, sample=snames, scales=scales, outdir=outdir) #CMSStyle.setCMSEra(2018) setera(2018, lumi) samples = makeSampleSet(sampleset, filedict) testget(samples) plotSampleSet(samples)
def testget(samples): """Test SampleSet.get* help functions.""" LOG.header("testget") incl = False for regex in [True, False]: for unique in [True, False]: kwargs = {'unique': unique, 'incl': incl, 'regex': regex} print ">>> unique=%s, incl=%s, regex=%s" % ( LOG.getcolor(unique), incl, LOG.getcolor(regex)) print ">>> SampleSet.get('DY', unique=%s,regex=%s): %r" % ( unique, regex, samples.get('DY', **kwargs)) print ">>> SampleSet.get('ZTT',unique=%s,regex=%s): %r" % ( unique, regex, samples.get('ZTT', **kwargs)) print ">>> SampleSet.get('WJ', unique=%s,regex=%s): %r" % ( unique, regex, samples.get('WJ', **kwargs)) print ">>> SampleSet.get('TT', unique=%s,regex=%s): %r" % ( unique, regex, samples.get('TT', **kwargs)) if not regex: print ">>> SampleSet.get('*TT',unique=%s,regex=%s): %r" % ( unique, regex, samples.get('*TT', **kwargs)) print ">>> SampleSet.get('?TT',unique=%s,regex=%s): %r" % ( unique, regex, samples.get('?TT', **kwargs)) else: print ">>> SampleSet.get('.*TT',unique=%s,regex=%s): %r" % ( unique, regex, samples.get('.*TT', **kwargs)) print ">>> SampleSet.get('.TT',unique=%s,regex=%s): %r" % ( unique, regex, samples.get('.TT', **kwargs)) print ">>> " regex = False for incl in [True, False]: for unique in [True, False]: kwargs = {'unique': unique, 'incl': incl, 'regex': regex} print ">>> unique=%s, incl=%s, regex=%s" % ( LOG.getcolor(unique), LOG.getcolor(incl), regex) print ">>> SampleSet.get('ZTT','TT',unique=%s,incl=%s): %r" % ( unique, incl, samples.get('ZTT', 'TT', **kwargs)) print ">>> SampleSet.get('QCD','WJ',unique=%s,incl=%s): %r" % ( unique, incl, samples.get('QCD', 'WJ', **kwargs)) print ">>> " print ">>> SampleSet.get('TT?',unique=False,regex=False,split=True): %r" % ( samples.get('TT?', unique=False, regex=False, split=True)) print ">>> SampleSet.getexp(): %r" % (samples.getexp()) print ">>> SampleSet.getexp('TT'): %r" % (samples.getexp('TT')) #print ">>> SampleSet.getmc(): %r"%(samples.getmc()) #print ">>> SampleSet.getdata(): %r"%(samples.getdata()) print ">>> "
def getsampleset(channel, era, **kwargs): verbosity = LOG.getverbosity(kwargs) year = getyear(era) # get integer year split = kwargs.get( 'split', ['DY']) # split samples (e.g. DY) into genmatch components join = kwargs.get('join', ['VV', 'Top']) # join samples (e.g. VV, top) tag = kwargs.get('tag', "") table = kwargs.get('table', True) # print sample set table setera(era) # set era for plot style and lumi-xsec normalization # SM BACKGROUND MC SAMPLES if era == '2016': expsamples = [ # table of MC samples to be converted to Sample objects # GROUP NAME TITLE XSEC EXTRA OPTIONS ('DY', "DYJetsToLL_M-10to50", "Drell-Yan 10-50", 18610.0, { 'extraweight': 'zptweight' }), ('DY', "DYJetsToLL_M-50", "Drell-Yan 50", 4963.0, { 'extraweight': 'zptweight' }), ('DY', "DY1JetsToLL_M-50", "Drell-Yan 1J 50", 1012.0, { 'extraweight': 'zptweight' }), ('DY', "DY2JetsToLL_M-50", "Drell-Yan 2J 50", 334.7, { 'extraweight': 'zptweight' }), ('DY', "DY3JetsToLL_M-50", "Drell-Yan 3J 50", 102.3, { 'extraweight': 'zptweight' }), ('DY', "DY4JetsToLL_M-50", "Drell-Yan 4J 50", 54.52, { 'extraweight': 'zptweight' }), ('WJ', "WJetsToLNu", "W + jets", 50260.0), ('WJ', "W1JetsToLNu", "W + 1J", 9625.0), ('WJ', "W2JetsToLNu", "W + 2J", 3161.0), ('WJ', "W3JetsToLNu", "W + 3J", 954.8), ('WJ', "W4JetsToLNu", "W + 4J", 494.6), ('VV', "WW", "WW", 75.88), ('VV', "WZ", "WZ", 27.6), ('VV', "ZZ", "ZZ", 12.14), ('ST', "ST_t-channel_top", "ST t-channel t", 136.02), ('ST', "ST_t-channel_antitop", "ST t-channel at", 80.95), ('ST', "ST_tW_top", "ST tW", 35.85), ('ST', "ST_tW_antitop", "ST atW", 35.85), ('TT', "TT", "ttbar", 831.76, { 'extraweight': 'ttptweight' }), ] elif era == '2017': expsamples = [ # table of MC samples to be converted to Sample objects # GROUP NAME TITLE XSEC EXTRA OPTIONS ('DY', "DYJetsToLL_M-10to50", "Drell-Yan 10-50", 18610.0, { 'extraweight': 'zptweight' }), ('DY', "DYJetsToLL_M-50", "Drell-Yan 50", 5343.0, { 'extraweight': 'zptweight' }), ('DY', "DY1JetsToLL_M-50", "Drell-Yan 1J 50", 877.8, { 'extraweight': 'zptweight' }), ('DY', "DY2JetsToLL_M-50", "Drell-Yan 2J 50", 304.4, { 'extraweight': 'zptweight' }), ('DY', "DY3JetsToLL_M-50", "Drell-Yan 3J 50", 111.5, { 'extraweight': 'zptweight' }), ('DY', "DY4JetsToLL_M-50", "Drell-Yan 4J 50", 44.05, { 'extraweight': 'zptweight' }), ('WJ', "WJetsToLNu", "W + jets", 52940.0), ('WJ', "W1JetsToLNu", "W + 1J", 8104.0), ('WJ', "W2JetsToLNu", "W + 2J", 2793.0), ('WJ', "W3JetsToLNu", "W + 3J", 992.5), ('WJ', "W4JetsToLNu", "W + 4J", 544.3), ('VV', "WW", "WW", 75.88), ('VV', "WZ", "WZ", 27.6), ('VV', "ZZ", "ZZ", 12.14), ('ST', "ST_t-channel_top", "ST t-channel t", 136.02), ('ST', "ST_t-channel_antitop", "ST t-channel at", 80.95), ('ST', "ST_tW_top", "ST tW", 35.85), ('ST', "ST_tW_antitop", "ST atW", 35.85), ('TT', "TTTo2L2Nu", "ttbar 2l2#nu", 88.29, { 'extraweight': 'ttptweight' }), ('TT', "TTToHadronic", "ttbar hadronic", 377.96, { 'extraweight': 'ttptweight' }), ('TT', "TTToSemiLeptonic", "ttbar semileptonic", 365.35, { 'extraweight': 'ttptweight' }), ] elif era == 'UL2017': expsamples = [ # table of MC samples to be converted to Sample objects # GROUP NAME TITLE XSEC EXTRA OPTIONS #( 'DY', "DYJetsToLL_M-10to50", "Drell-Yan 10-50", 18610.0, {'extraweight': 'zptweight'} ), ('DY', "DYJetsToLL_M-50", "Drell-Yan 50", 5343.0, { 'extraweight': 'zptweight' }), ('DY', "DY1JetsToLL_M-50", "Drell-Yan 1J 50", 877.8, { 'extraweight': 'zptweight' }), ('DY', "DY2JetsToLL_M-50", "Drell-Yan 2J 50", 304.4, { 'extraweight': 'zptweight' }), ('DY', "DY3JetsToLL_M-50", "Drell-Yan 3J 50", 111.5, { 'extraweight': 'zptweight' }), ('DY', "DY4JetsToLL_M-50", "Drell-Yan 4J 50", 44.05, { 'extraweight': 'zptweight' }), ('WJ', "WJetsToLNu", "W + jets", 52940.0), ('WJ', "W1JetsToLNu", "W + 1J", 8104.0), ('WJ', "W2JetsToLNu", "W + 2J", 2793.0), ('WJ', "W3JetsToLNu", "W + 3J", 992.5), ('WJ', "W4JetsToLNu", "W + 4J", 544.3), ('VV', "WW", "WW", 75.88), ('VV', "WZ", "WZ", 27.6), ('VV', "ZZ", "ZZ", 12.14), ('ST', "ST_t-channel_top", "ST t-channel t", 136.02), ('ST', "ST_t-channel_antitop", "ST t-channel at", 80.95), ('ST', "ST_tW_top", "ST tW", 35.85), ('ST', "ST_tW_antitop", "ST atW", 35.85), ('TT', "TTTo2L2Nu", "ttbar 2l2#nu", 88.29, { 'extraweight': 'ttptweight' }), ('TT', "TTToHadronic", "ttbar hadronic", 377.96, { 'extraweight': 'ttptweight' }), ('TT', "TTToSemiLeptonic", "ttbar semileptonic", 365.35, { 'extraweight': 'ttptweight' }), ] elif era == '2018': expsamples = [ # table of MC samples to be converted to Sample objects # GROUP NAME TITLE XSEC EXTRA OPTIONS ('DY', "DYJetsToLL_M-10to50", "Drell-Yan 10-50", 18610.0, { 'extraweight': 'zptweight' }), ('DY', "DYJetsToLL_M-50", "Drell-Yan 50", 4963.0, { 'extraweight': 'zptweight' }), ('DY', "DY1JetsToLL_M-50", "Drell-Yan 1J 50", 1012.0, { 'extraweight': 'zptweight' }), ('DY', "DY2JetsToLL_M-50", "Drell-Yan 2J 50", 334.7, { 'extraweight': 'zptweight' }), ('DY', "DY3JetsToLL_M-50", "Drell-Yan 3J 50", 102.3, { 'extraweight': 'zptweight' }), ('DY', "DY4JetsToLL_M-50", "Drell-Yan 4J 50", 54.52, { 'extraweight': 'zptweight' }), ('WJ', "WJetsToLNu", "W + jets", 52940.0), ('WJ', "W1JetsToLNu", "W + 1J", 8104.0), ('WJ', "W2JetsToLNu", "W + 2J", 2793.0), ('WJ', "W3JetsToLNu", "W + 3J", 992.5), ('WJ', "W4JetsToLNu", "W + 4J", 544.3), ('VV', "WW", "WW", 75.88), ('VV', "WZ", "WZ", 27.6), ('VV', "ZZ", "ZZ", 12.14), ('ST', "ST_t-channel_top", "ST t-channel t", 136.02), ('ST', "ST_t-channel_antitop", "ST t-channel at", 80.95), ('ST', "ST_tW_top", "ST tW", 35.85), ('ST', "ST_tW_antitop", "ST atW", 35.85), ('TT', "TTTo2L2Nu", "ttbar 2l2#nu", 88.29, { 'extraweight': 'ttptweight' }), ('TT', "TTToHadronic", "ttbar hadronic", 377.96, { 'extraweight': 'ttptweight' }), ('TT', "TTToSemiLeptonic", "ttbar semileptonic", 365.35, { 'extraweight': 'ttptweight' }), ] else: LOG.throw(IOError, "Did not recognize era %r!" % (era)) # OBSERVED DATA SAMPLES if 'tautau' in channel: dataset = "Tau_Run%d?" % year elif 'mutau' in channel: dataset = "SingleMuon_Run%d?" % year elif 'etau' in channel: dataset = "EGamma_Run%d?" % year if year == 2018 else "SingleElectron_Run%d?" % year elif 'mumu' in channel: dataset = "SingleMuon_Run%d?" % year elif 'emu' in channel: dataset = "SingleMuon_Run%d?" % year elif 'ee' in channel: dataset = "EGamma_Run%d?" % year if year == 2018 else "SingleElectron_Run%d?" % year else: LOG.throw(IOError, "Did not recognize channel %r!" % (channel)) datasample = ('Data', dataset) # GROUP, NAME # SAMPLE SET weight = "genweight*trigweight*puweight*idisoweight_1*idweight_2" if era == 'UL2017': weight = weight.replace("*idweight_2", "") fname = "$PICODIR/$SAMPLE_$CHANNEL$TAG.root" kwargs.setdefault('weight', weight) # common weight for MC kwargs.setdefault('fname', fname) # default filename pattern sampleset = _getsampleset(datasample, expsamples, channel=channel, era=era, **kwargs) # JOIN # Note: titles are set via STYLE.sample_titles sampleset.stitch("W*Jets", incl='WJ', name='WJ') # W + jets sampleset.stitch("DY*J*M-50", incl='DYJ', name="DY_M50") # Drell-Yan, M > 50 GeV #sampleset.stitch("DY*J*M-10to50", incl='DYJ', name="DY_M10to50" ) sampleset.join('DY', name='DY') # Drell-Yan, M < 50 GeV + M > 50 GeV if 'VV' in join: sampleset.join('VV', 'WZ', 'WW', 'ZZ', name='VV') # Diboson if 'TT' in join and era != 'year': sampleset.join('TT', name='TT') # ttbar if 'ST' in join: sampleset.join('ST', name='ST') # single top if 'Top' in join: sampleset.join('TT', 'ST', name='Top') # ttbar + single top # SPLIT # Note: titles are set via STYLE.sample_titles if split and channel.count('tau') == 1: ZTT = STYLE.sample_titles.get('ZTT', "Z -> %s" % channel) # title if channel.count('tau') == 1: ZTT = ZTT.replace("{l}", "{mu}" if "mu" in channel else "{e}") GMR = "genmatch_2==5" GML = "genmatch_2>0 && genmatch_2<5" GMJ = "genmatch_2==0" GMF = "genmatch_2<5" elif channel.count('tau') == 2: ZTT = ZTT.replace("{l}", "{h}") GMR = "genmatch_1==5 && genmatch_2==5" GML = "(genmatch_1<5 || genmatch_2<5) && genmatch_1>0 && genmatch_2>0" GMJ = "(genmatch_1==0 || genmatch_2==0)" GMF = "(genmatch_1<5 || genmatch_2<5)" else: LOG.throw(IOError, "Did not recognize channel %r!" % (channel)) if 'DY' in split: sampleset.split('DY', [ ('ZTT', ZTT, GMR), ('ZL', GML), ('ZJ', GMJ), ]) if 'DM' in split: # split DY by decay modes samples.split('DY', [ ('ZTT_DM0', ZTT + ", h^{#pm}", GMR + " && decayMode_2==0"), ('ZTT_DM1', ZTT + ", h^{#pm}h^{0}", GMR + " && decayMode_2==1"), ('ZTT_DM10', ZTT + ", h^{#pm}h^{#mp}h^{#pm}", GMR + " && decayMode_2==10"), ('ZTT_DM11', ZTT + ", h^{#pm}h^{#mp}h^{#pm}h^{0}", GMR + " && decayMode_2==11"), ('ZL', GML), ('ZJ', GMJ), ]) if 'TT' in split: sampleset.split('TT', [ ('TTT', GMR), ('TTJ', GMF), ]) if table: sampleset.printtable(merged=True, split=True) return sampleset
def plot(sampleset, channel, parallel=True, tag="", outdir="plots", histdir="", era=""): """Test plotting of SampleSet class for data/MC comparison.""" LOG.header("plot") # SELECTIONS inclusive = "(q_1*q_2<0)" inclusive = inclusive.replace(" ", "") inclusive_cr_qcd = inclusive.replace( "q_1*q_2<0", "q_1*q_2>0" ) # inverting the opposite-sign requirement of the mutau pair into a same-sign requirment general_cuts = "(pt_1>26.0)&&(pt_2>20.0)&&(eta_1>-2.1)&&(eta_1<2.1)&&(eta_2>-2.3)&&(eta_2<2.3)" selections = [ Sel('kinematic sel.', general_cuts), #Sel('inclusive',inclusive), #Sel('inclusive_cr_qcd',inclusive_cr_qcd), ] # VARIABLES # TODO section 5: extend with other variables, which are available in the flat n-tuples variables = [ Var('m_vis', 40, 0, 200), Var('pt_1', "Muon pt", 40, 0, 120, ctitle={ 'etau': "Electron pt", 'tautau': "Leading tau_h pt", 'emu': "Electron pt" }), Var('pt_2', "tau_h pt", 40, 0, 120, ctitle={ 'tautau': "Subleading tau_h pt", 'emu': "Muon pt" }), Var('eta_1', "Muon eta", 30, -3, 3, ctitle={ 'etau': "Electron eta", 'tautau': "Leading tau_h eta", 'emu': "Electron eta" }, ymargin=1.6, pos='T', ncols=2), Var('eta_2', "tau_h eta", 30, -3, 3, ctitle={ 'etau': "Electron eta", 'tautau': "Subleading tau_h eta", 'emu': "Muon eta" }, ymargin=1.6, pos='T', ncols=2), #Var('m_vis', 40, 0, 200), Var('mt_1', "mt(mu,MET)", 40, 0, 200), #Var("jpt_1", 29, 10, 300, veto=[r"njets\w*==0"]), #Var("jpt_2", 29, 10, 300, veto=[r"njets\w*==0"]), # #Var("jeta_1", 53, -5.4, 5.2, ymargin=1.6,pos='T',ncols=2,veto=[r"njets\w*==0"]), # #Var("jeta_2", 53, -5.4, 5.2, ymargin=1.6,pos='T',ncols=2,veto=[r"njets\w*==0"]), # Var('njets', 8, 0, 8), Var('met', 50, 0, 150), Var('pt_ll', "p_{T}(mutau_h)", 25, 0, 200, ctitle={ 'etau': "p_{T}(etau_h)", 'tautau': "p_{T}(tau_htau_h)", 'emu': "p_{T}(emu)" }), #Var('dR_ll', "DR(mutau_h)", 30, 0, 6.0, ctitle={'etau':"DR(etau_h)",'tautau':"DR(tau_htau_h)",'emu':"DR(emu)"}), #Var('deta_ll', "deta(mutau_h)", 20, 0, 6.0, ctitle={'etau':"deta(etau_h)",'tautau':"deta(tautau)",'emu':"deta(emu)"},logy=True,pos='TRR'), #, ymargin=8, logyrange=2.6 #Var('dzeta', 56, -180, 100, pos='L;y=0.88',units='GeV'), #Var("pzetavis", 50, 0, 200 ), Var('rawDeepTau2017v2p1VSjet_2', "rawDeepTau2017v2p1VSjet", 100, 0.0, 1, ncols=2, pos='L;y=0.85', logy=True, ymargin=2.5), Var('rawDeepTau2017v2p1VSjet_2', "rawDeepTau2017v2p1VSjet", 20, 0.80, 1, fname="$VAR_zoom", ncols=2, pos='L;y=0.85'), Var('rawDeepTau2017v2p1VSe_2', "rawDeepTau2017v2p1VSe", 30, 0.0, 1, fname="$VAR", ncols=2, logy=True, pos='L;y=0.85'), Var('rawDeepTau2017v2p1VSe_2', "rawDeepTau2017v2p1VSe", 30, 0.70, 1, fname="$VAR_zoom", ncols=2, logy=True, pos='L;y=0.85'), # Var('rawDeepTau2017v2p1VSmu_2', "rawDeepTau2017v2p1VSmu", 20, 0.80, 1, fname="$VAR_zoom",ncols=2,logy=True,logyrange=4,pos='L;y=0.85'), # Var('npv', 40, 0, 80 ), ] # PLOT and HIST outdir = ensuredir(repkey(outdir, CHANNEL=channel, ERA=era)) histdir = ensuredir(repkey(histdir, CHANNEL=channel, ERA=era)) outhists = R.TFile.Open(histdir, 'recreate') exts = ['png', 'pdf'] for selection in selections: outhists.mkdir(selection.filename) stacks = sampleset.getstack( variables, selection, method='QCD_OSSS', scale=1.1, parallel=parallel ) # the 'scale' keyword argument - chosen as 1.1 for mutau - # is an extrapolation factor for the QCD shape from the same-sign # to the opposite-sign region fname = "%s/$VAR_%s-%s-%s$TAG" % (outdir, channel, selection.filename, era) text = "%s: %s" % (channel.replace('mu', "#mu").replace( 'tau', "#tau_{h}"), selection.title) for stack, variable in stacks.iteritems(): outhists.cd(selection.filename) for h in stack.hists: h.Write(h.GetName().replace("QCD_", "QCD"), R.TH1.kOverwrite) stack.draw() stack.drawlegend(x1=0.6, x2=0.95, y1=0.35, y2=0.95) stack.drawtext(text) stack.saveas(fname, ext=exts, tag=tag) stack.close() outhists.Close()
def getsampleset(channel, era, **kwargs): verbosity = LOG.getverbosity(kwargs) year = getyear(era) # get integer year tag = kwargs.get('tag', "") table = kwargs.get('table', True) # print sample set table setera(era) # set era for plot style and lumi normalization negative_fractions = { "DYJetsToLL_M-50": 0.0004, "WJetsToLNu": 0.0004, "WW_TuneCP5_13TeV-pythia8": 0.0, # <-- no adaption of effective events needed "WZ_TuneCP5_13TeV-pythia8": 0.0, # <-- no adaption of effective events needed "ZZ_TuneCP5_13TeV-pythia8": 0.0, # <-- no adaption of effective events needed "ST_t-channel_top": 0.033, "ST_t-channel_antitop": 0.031, "ST_tW_top": 0.002, "ST_tW_antitop": 0.002, "TTTo2L2Nu": 0.004, "TTToHadronic": 0.004, "TTToSemiLeptonic": 0.004, } # SM BACKGROUND MC SAMPLES expsamples = [ # table of MC samples to be converted to Sample objects # GROUP NAME TITLE XSEC [pb] effective NEVENTS = simulated NEVENTS * ( 1 - 2 * negative fraction) # Cross-secitons: https://twiki.cern.ch/twiki/bin/viewauth/CMS/StandardModelCrossSectionsat13TeV, Z/a* (50) ('DY', "DYJetsToLL_M-50", "Drell-Yan 50", 6077.22, { "nevts": 100194597 * (1.0 - 2 * negative_fractions["DYJetsToLL_M-50"]) }), # Cross-sections: https://twiki.cern.ch/twiki/bin/viewauth/CMS/StandardModelCrossSectionsat13TeV, Total W ('WJ', "WJetsToLNu", "W + jets", 3 * 20508.9, { "nevts": 71072199 * (1.0 - 2 * negative_fractions["WJetsToLNu"]) }), # Cross-sections: https://twiki.cern.ch/twiki/bin/viewauth/CMS/StandardModelCrossSectionsat13TeV, W+ W- ('VV', "WW", "WW", 118.7, { "nevts": 7850000 }), # Cross-sections: from generator (https://cms-gen-dev.cern.ch/xsdb with 'process_name=WZ_TuneCP5_13TeV-pythia8') ('VV', "WZ", "WZ", 27.6, { "nevts": 3885000 }), # Cross-sections: from generator (https://cms-gen-dev.cern.ch/xsdb with 'process_name=ZZ_TuneCP5_13TeV-pythia8') ('VV', "ZZ", "ZZ", 12.14, { "nevts": 1979000 }), # Cross-sections: # https://twiki.cern.ch/twiki/bin/viewauth/CMS/SingleTopSigma ('ST', "ST_t-channel_top", "ST t-channel t", 136.02, { "nevts": 154307600 * (1.0 - 2 * negative_fractions["ST_t-channel_top"]) }), ('ST', "ST_t-channel_antitop", "ST t-channel at", 80.95, { "nevts": 79090800 * (1.0 - 2 * negative_fractions["ST_t-channel_antitop"]) }), ('ST', "ST_tW_top", "ST tW", 35.85, { "nevts": 9598000 * (1.0 - 2 * negative_fractions["ST_tW_top"]) }), ('ST', "ST_tW_antitop", "ST atW", 35.85, { "nevts": 7623000 * (1.0 - 2 * negative_fractions["ST_tW_antitop"]) }), # Cross-sections: https://twiki.cern.ch/twiki/bin/view/LHCPhysics/TtbarNNLO#Top_quark_pair_cross_sections_at, m_top = 172.5 GeV + PDG for W boson decays ('TT', "TTTo2L2Nu", "ttbar 2l2#nu", 831.76 * (3 * 0.1086)**2, { "nevts": 64310000 * (1.0 - 2 * negative_fractions["TTTo2L2Nu"]) }), ('TT', "TTToHadronic", "ttbar hadronic", 831.76 * 2 * (3 * 0.1086) * (0.6741), { "nevts": 199524000 * (1.0 - 2 * negative_fractions["TTToHadronic"]) }), ('TT', "TTToSemiLeptonic", "ttbar semileptonic", 831.76 * (0.6741)**2, { "nevts": 199925998 * (1.0 - 2 * negative_fractions["TTToSemiLeptonic"]) }), ] # OBSERVED DATA SAMPLES if 'mutau' in channel: dataset = "SingleMuon_Run%d?" % year elif 'etau' in channel: dataset = "SingleElectron_Run%d?" % year else: LOG.throw(IOError, "Did not recognize channel %r!" % (channel)) datasample = ('Data', dataset) # Data for chosen channel # SAMPLE SET # TODO section 5: This weight needs to be extended with correction weights common to all simulated samples (MC) weight = "genweight/abs(genweight)" # normalize weight, since sometimes the generator cross-section is contained in it. kwargs.setdefault('weight', weight) # common weight for MC sampleset = _getsampleset(datasample, expsamples, channel=channel, era=era, **kwargs) # JOIN # Note: titles are set via STYLE.sample_titles sampleset.join('WW', 'WZ', 'ZZ', name='VV') # Diboson sampleset.join('VV', 'WJ', name='EWK') # Electroweak sampleset.join('TT', name='TT') # ttbar sampleset.join('ST', name='ST') # single top sampleset.join('ST', 'TT', name='Top') #ttbar & single top # SPLIT # TODO section 5: Check the generator matching for various samples in the flat n-tuples. # Is it justified to require only the tauh candidate to match to generator level hadronic tau to declare the full process with Z->tautau in mutau final state? # What is the major contribution from Drell-Yan to genmatch_2!=5? How does this look like for other processes? GMR = "genmatch_2==5" GMO = "genmatch_2!=5" sampleset.split('DY', [('ZTT', GMR), ('ZL', GMO)]) sampleset.split('Top', [('TopT', GMR), ('TopJ', GMO)]) sampleset.split('EWK', [('EWKT', GMR), ('EWKJ', GMO)]) if table: sampleset.printtable(merged=True, split=True) return sampleset
def plot(sampleset, channel, parallel=True, tag="", outdir="plots", histdir="", era=""): """Test plotting of SampleSet class for data/MC comparison.""" LOG.header("plot") # SELECTIONS inclusive = "(q_1*q_2<0)" inclusive = inclusive.replace(" ", "") # inclusive_cr_qcd = inclusive.replace("q_1*q_2<0","q_1*q_2>0") # inverting the opposite-sign requirement of the mutau pair into a same-sign requirment general_cuts = "(pt_1>26.0)&&(pt_2>20.0)&&(eta_1>-2.1)&&(eta_1<2.1)&&(eta_2>-2.3)&&(eta_2<2.3)" isolation = "(iso_1<0.15)" mt_cut = "(mt<40.0)" mt_pmet_cut = "(mt_pmet<40.0)" topo_cut = "(miss_Pdz-0.85*vis_Pdz>-20)" isdDT = "(iso_2>0.8)" deeptau = "(anti_e_2>=2)&&(anti_mu_2>=8)&&(id_2>=16)" final = general_cuts + "&&" + isolation + "&&" + mt_cut + "&&" + mt_pmet_cut + "&&" + topo_cut + "&&" + deeptau + "&&" + isdDT selections = [ Sel('nominal', inclusive), Sel('kinematic sel.', general_cuts), Sel('isolation', isolation), Sel('mt<40.0', mt_cut), Sel('mtPmet<40.0', mt_pmet_cut), Sel('TopologicalDis', topo_cut), Sel('DeepTau', deeptau), Sel('isoDeepTau', isdDT), Sel('FinalSelection', final), # Sel('inclusive_cr_qcd',inclusive_cr_qcd), ] # VARIABLES # TODO section 5: extend with other variables, which are available in the flat n-tuples variables = [ Var('m_vis', 40, 0, 200), # For nominal cuts # Var('miss_Pdz - 0.85*vis_Pdz', 40, -200, 150), # Var('pt_1', 40, 10, 100), # Var('eta_1', 40, -3, 3), # Var('iso_1', 40, -0.1, 0.5), # # Var('decayMode_1', 30, 0, 30), # # Var('pt_2', 40, 10, 100), # Var('eta_2', 40, -3, 3), # Var('anti_e_2', 40, -10, 10), # Var('anti_mu_2', 40, -10, 10), # Var('iso_2', 40, 0.0, 1.2), # Var('decayMode_2', 30, 0, 30), # # Var('genWeight', 40, -1, 2), # # Var('n_jet',10, 0, 10), # Var('jet1_pt', 40, 10, 100), # Var('jet1_eta',40, -3, 3), # Var('jet2_pt', 40, 10, 100), # Var('jet2_eta', 40, -3, 3), # # Var('n_bjet', 10, 0, 10), # Var('bjet1_pt', 40, 10, 100), # Var('bjet1_eta',40, -3, 3), # Var('bjet2_pt', 40, 10, 100), # Var('bjet2_eta', 40, -3, 3), # # Var('rawMET_phi', 40, -3.5, 3.5), # Var('rawMET_pt', 40, 0, 150), # Var('rawMET_sumEt', 40, 30, 3000), # Var('puppiMET_phi', 40, -3.5, 3.5), # Var('puppiMET_pt', 40, 0, 150), # Var('puppiMET_sumEt', 40, 30, 500), # # Var('vis_Z_pt',40, 0, 200), # Var('real_Z_pt',40, 0, 200), # Var('real_Z_pt_pmet',40, 0, 200), # # Var('dphi',40, -3.5, 3.5), # Var('dphi_pmet',40, -3.5, 3.5), # # Var('mt', 40, 0, 250), # Var('mt_pmet', 40, 0, 250), # # Var('deltaR', 40, 0, 10.0), # Var('puRho', 40, 2, 50), # Var('n_pvert', 50, 0, 50), # Var('n_pileup', 10, 0, 10), ] # PLOT and HIST outdir = ensuredir(repkey(outdir, CHANNEL=channel, ERA=era)) histdir = ensuredir(repkey(histdir, CHANNEL=channel, ERA=era)) outhists = R.TFile.Open(histdir, 'recreate') exts = ['png', 'pdf'] for selection in selections: outhists.mkdir(selection.filename) stacks = sampleset.getstack( variables, selection, method='QCD_OSSS', scale=1.1, parallel=parallel ) # the 'scale' keyword argument - chosen as 1.1 for mutau - # is an extrapolation factor for the QCD shape from the same-sign # to the opposite-sign region fname = "%s/$VAR_%s-%s-%s$TAG" % (outdir, channel, selection.filename, era) text = "%s: %s" % (channel.replace('mu', "#mu").replace( 'tau', "#tau_{h}"), selection.title) for stack, variable in stacks.iteritems(): outhists.cd(selection.filename) for h in stack.hists: print("-----", h.Integral()) h.Write(h.GetName().replace("QCD_", "QCD"), R.TH1.kOverwrite) stack.draw() stack.drawlegend(x1=0.6, x2=0.95, y1=0.35, y2=0.95) stack.drawtext(text) stack.saveas(fname, ext=exts, tag=tag) stack.close() outhists.Close()
def getsampleset(channel, era, **kwargs): verbosity = LOG.getverbosity(kwargs) year = getyear(era) # get integer year dysample = kwargs.get('dy', "jet") dyweight = kwargs.get('dyweight', "") split = kwargs.get('split', []) # split samples (e.g. DY) into genmatch components join = kwargs.get('join', ['VV', 'Top']) # join samples (e.g. VV, top) tag = kwargs.get('tag', "") table = kwargs.get('table', True) # print sample set table setera(era) # set global era for plot style and lumi-xsec normalization if 'UL2016' in era and 'VFP' not in era: # join pre-/post-VFP into full UL2016 kwargs['table'] = False kwargs1 = kwargs.copy() # prevent overwriting kwargs2 = kwargs.copy() # prevent overwriting sampleset1 = getsampleset(channel, era + "_preVFP", **kwargs1) sampleset2 = getsampleset(channel, era + "_postVFP", **kwargs2) setera(era) # reset era for plot style and lumi-xsec normalization sampleset = sampleset1 + sampleset2 # merge samples if table: sampleset.printtable(merged=True, split=True) return sampleset # SM BACKGROUND MC SAMPLES xsec_dy_lo = 4963.0 # MadGraph (LO) xsec_dy_nlo = 6529.0 # aMC@NLO xsec_dy_nnlo = 3 * 2025.74 # FEWZ (NNLO) k_lo = xsec_dy_nnlo / xsec_dy_lo k_nlo = 1. #xsec_dy_nnlo/xsec_dy_nlo if 'UL' in era: expsamples = [ # table of MC samples to be converted to Sample objects # GROUP NAME TITLE XSEC EXTRA OPTIONS #( 'DY', "DYJetsToLL_M-10to50", "Drell-Yan 10-50", 18610.0 ), ('DY', "DYJetsToLL_M-50", "Drell-Yan 50", 5343.0, { 'extraweight': dyweight }), ('DY', "DY1JetsToLL_M-50", "Drell-Yan 1J 50", 877.8, { 'extraweight': dyweight }), ('DY', "DY2JetsToLL_M-50", "Drell-Yan 2J 50", 304.4, { 'extraweight': dyweight }), ('DY', "DY3JetsToLL_M-50", "Drell-Yan 3J 50", 111.5, { 'extraweight': dyweight }), ('DY', "DY4JetsToLL_M-50", "Drell-Yan 4J 50", 44.05, { 'extraweight': dyweight }), ###( 'DY', "DYJetsToMuTauh_M-50", "DYJetsToMuTauh_M-50", 5343.0, {'extraweight': dyweight} ), ('WJ', "WJetsToLNu", "W + jets", 52940.0), ('WJ', "W1JetsToLNu", "W + 1J", 8104.0), ('WJ', "W2JetsToLNu", "W + 2J", 2793.0), ('WJ', "W3JetsToLNu", "W + 3J", 992.5), ('WJ', "W4JetsToLNu", "W + 4J", 544.3), ('VV', "WW", "WW", 75.88), ('VV', "WZ", "WZ", 27.6), ('VV', "ZZ", "ZZ", 12.14), ('ST', "ST_t-channel_top", "ST t-channel t", 136.02), ('ST', "ST_t-channel_antitop", "ST t-channel at", 80.95), ('ST', "ST_tW_top", "ST tW", 35.85), ('ST', "ST_tW_antitop", "ST atW", 35.85), ('TT', "TTTo2L2Nu", "ttbar 2l2#nu", 88.29, { 'extraweight': 'ttptweight' }), ('TT', "TTToHadronic", "ttbar hadronic", 377.96, { 'extraweight': 'ttptweight' }), ('TT', "TTToSemiLeptonic", "ttbar semileptonic", 365.35, { 'extraweight': 'ttptweight' }), ] else: if era == '2016': expsamples = [ ] # table of MC samples to be converted to Sample objects if 'mass' in dysample: expsamples += [ # GROUP NAME TITLE XSEC EXTRA OPTIONS ('DY', "DYJetsToLL_M-100to200", "Drell-Yan 100to200", k_nlo * 226.6, { 'extraweight': dyweight }), ('DY', "DYJetsToLL_M-200to400", "Drell-Yan 200to400", k_nlo * 7.77, { 'extraweight': dyweight }), ('DY', "DYJetsToLL_M-400to500", "Drell-Yan 400to500", k_nlo * 0.4065, { 'extraweight': dyweight }), ('DY', "DYJetsToLL_M-500to700", "Drell-Yan 500to700", k_nlo * 0.2334, { 'extraweight': dyweight }), ('DY', "DYJetsToLL_M-700to800", "Drell-Yan 700to800", k_nlo * 0.03614, { 'extraweight': dyweight }), ('DY', "DYJetsToLL_M-800to1000", "Drell-Yan 800to1000", k_nlo * 0.03047, { 'extraweight': dyweight }), ('DY', "DYJetsToLL_M-1000to1500", "Drell-Yan 1000to1500", k_nlo * 0.01636, { 'extraweight': dyweight }), ('DY', "DYJetsToLL_M-1500to2000", "Drell-Yan 1500to2000", k_nlo * 0.00218, { 'extraweight': dyweight }), ('DY', "DYJetsToLL_M-2000to3000", "Drell-Yan 2000to3000", k_nlo * 0.0005156, { 'extraweight': dyweight }), ] else: expsamples += [ # GROUP NAME TITLE XSEC EXTRA OPTIONS ('DY', "DYJetsToLL_M-10to50", "Drell-Yan 10-50", 18610.0, { 'extraweight': dyweight }), ('DY', "DYJetsToLL_M-50", "Drell-Yan 50", 4963.0, { 'extraweight': dyweight }), ('DY', "DY1JetsToLL_M-50", "Drell-Yan 1J 50", 1012.0, { 'extraweight': dyweight }), ('DY', "DY2JetsToLL_M-50", "Drell-Yan 2J 50", 334.7, { 'extraweight': dyweight }), ('DY', "DY3JetsToLL_M-50", "Drell-Yan 3J 50", 102.3, { 'extraweight': dyweight }), ('DY', "DY4JetsToLL_M-50", "Drell-Yan 4J 50", 54.52, { 'extraweight': dyweight }), ] expsamples += [ # GROUP NAME TITLE XSEC EXTRA OPTIONS ('WJ', "WJetsToLNu", "W + jets", 50260.0), ('WJ', "W1JetsToLNu", "W + 1J", 9625.0), ('WJ', "W2JetsToLNu", "W + 2J", 3161.0), ('WJ', "W3JetsToLNu", "W + 3J", 954.8), ('WJ', "W4JetsToLNu", "W + 4J", 494.6), ('VV', "WW", "WW", 75.88), ('VV', "WZ", "WZ", 27.6), ('VV', "ZZ", "ZZ", 12.14), ('ST', "ST_t-channel_top", "ST t-channel t", 136.02), ('ST', "ST_t-channel_antitop", "ST t-channel at", 80.95), ('ST', "ST_tW_top", "ST tW", 35.85), ('ST', "ST_tW_antitop", "ST atW", 35.85), ('TT', "TT", "ttbar", 831.76, { 'extraweight': 'ttptweight' }), ] elif era == '2017': expsamples = [ ] # table of MC samples to be converted to Sample objects if 'mass' in dysample: expsamples += [ # GROUP NAME TITLE XSEC EXTRA OPTIONS ('DY', "DYJetsToLL_M-100to200", "Drell-Yan 100to200", k_nlo * 247.8, { 'extraweight': dyweight }), ('DY', "DYJetsToLL_M-200to400", "Drell-Yan 200to400", k_nlo * 8.502, { 'extraweight': dyweight }), ('DY', "DYJetsToLL_M-400to500", "Drell-Yan 400to500", k_nlo * 0.4514, { 'extraweight': dyweight }), ('DY', "DYJetsToLL_M-500to700", "Drell-Yan 500to700", k_nlo * 0.2558, { 'extraweight': dyweight }), ('DY', "DYJetsToLL_M-700to800", "Drell-Yan 700to800", k_nlo * 0.04023, { 'extraweight': dyweight }), ('DY', "DYJetsToLL_M-800to1000", "Drell-Yan 800to1000", k_nlo * 0.03406, { 'extraweight': dyweight }), ('DY', "DYJetsToLL_M-1000to1500", "Drell-Yan 1000to1500", k_nlo * 0.01828, { 'extraweight': dyweight }), ('DY', "DYJetsToLL_M-1500to2000", "Drell-Yan 1500to2000", k_nlo * 0.002367, { 'extraweight': dyweight }), ('DY', "DYJetsToLL_M-2000to3000", "Drell-Yan 2000to3000", k_nlo * 0.0005409, { 'extraweight': dyweight }), ('DY', "DYJetsToLL_M-3000toInf", "Drell-Yan 3000toInf", k_nlo * 3.048e-05, { 'extraweight': dyweight }), ] else: expsamples += [ # GROUP NAME TITLE XSEC EXTRA OPTIONS ('DY', "DYJetsToLL_M-10to50", "Drell-Yan 10-50", 18610.0, { 'extraweight': dyweight }), ('DY', "DYJetsToLL_M-50", "Drell-Yan 50", 5343.0, { 'extraweight': dyweight }), ('DY', "DY1JetsToLL_M-50", "Drell-Yan 1J 50", 877.8, { 'extraweight': dyweight }), ('DY', "DY2JetsToLL_M-50", "Drell-Yan 2J 50", 304.4, { 'extraweight': dyweight }), ('DY', "DY3JetsToLL_M-50", "Drell-Yan 3J 50", 111.5, { 'extraweight': dyweight }), ('DY', "DY4JetsToLL_M-50", "Drell-Yan 4J 50", 44.05, { 'extraweight': dyweight }), ] expsamples += [ # GROUP NAME TITLE XSEC EXTRA OPTIONS ('WJ', "WJetsToLNu", "W + jets", 52940.0), ('WJ', "W1JetsToLNu", "W + 1J", 8104.0), ('WJ', "W2JetsToLNu", "W + 2J", 2793.0), #( 'WJ', "W3JetsToLNu", "W + 3J", 992.5 ), ('WJ', "W4JetsToLNu", "W + 4J", 544.3), ('VV', "WW", "WW", 75.88), ('VV', "WZ", "WZ", 27.6), ('VV', "ZZ", "ZZ", 12.14), ('ST', "ST_t-channel_top", "ST t-channel t", 136.02), ('ST', "ST_t-channel_antitop", "ST t-channel at", 80.95), ('ST', "ST_tW_top", "ST tW", 35.85), ('ST', "ST_tW_antitop", "ST atW", 35.85), ('TT', "TTTo2L2Nu", "ttbar 2l2#nu", 88.29, { 'extraweight': 'ttptweight' }), ('TT', "TTToHadronic", "ttbar hadronic", 377.96, { 'extraweight': 'ttptweight' }), ('TT', "TTToSemiLeptonic", "ttbar semileptonic", 365.35, { 'extraweight': 'ttptweight' }), ] elif era == '2018': expsamples = [ ] # table of MC samples to be converted to Sample objects if 'mass' in dysample: expsamples += [ # GROUP NAME TITLE XSEC EXTRA OPTIONS ('DY', "DYJetsToLL_M-100to200", "Drell-Yan 100to200", k_nlo * 247.8, { 'extraweight': dyweight }), ('DY', "DYJetsToLL_M-200to400", "Drell-Yan 200to400", k_nlo * 8.502, { 'extraweight': dyweight }), ('DY', "DYJetsToLL_M-400to500", "Drell-Yan 400to500", k_nlo * 0.4514, { 'extraweight': dyweight }), ('DY', "DYJetsToLL_M-500to700", "Drell-Yan 500to700", k_nlo * 0.2558, { 'extraweight': dyweight }), ('DY', "DYJetsToLL_M-700to800", "Drell-Yan 700to800", k_nlo * 0.04023, { 'extraweight': dyweight }), ('DY', "DYJetsToLL_M-800to1000", "Drell-Yan 800to1000", k_nlo * 0.03406, { 'extraweight': dyweight }), ('DY', "DYJetsToLL_M-1000to1500", "Drell-Yan 1000to1500", k_nlo * 0.01828, { 'extraweight': dyweight }), ('DY', "DYJetsToLL_M-1500to2000", "Drell-Yan 1500to2000", k_nlo * 0.002367, { 'extraweight': dyweight }), ('DY', "DYJetsToLL_M-2000to3000", "Drell-Yan 2000to3000", k_nlo * 0.0005409, { 'extraweight': dyweight }), ('DY', "DYJetsToLL_M-3000toInf", "Drell-Yan 3000toInf", k_nlo * 3.048e-05, { 'extraweight': dyweight }), ] else: expsamples += [ # GROUP NAME TITLE XSEC EXTRA OPTIONS ('DY', "DYJetsToLL_M-10to50", "Drell-Yan 10-50", 18610.0, { 'extraweight': dyweight }), ('DY', "DYJetsToLL_M-50", "Drell-Yan 50", 5343.0, { 'extraweight': dyweight }), ('DY', "DY1JetsToLL_M-50", "Drell-Yan 1J 50", 877.8, { 'extraweight': dyweight }), ('DY', "DY2JetsToLL_M-50", "Drell-Yan 2J 50", 304.4, { 'extraweight': dyweight }), ('DY', "DY3JetsToLL_M-50", "Drell-Yan 3J 50", 111.5, { 'extraweight': dyweight }), ('DY', "DY4JetsToLL_M-50", "Drell-Yan 4J 50", 44.05, { 'extraweight': dyweight }), ] expsamples += [ # GROUP NAME TITLE XSEC EXTRA OPTIONS ('WJ', "WJetsToLNu", "W + jets", 52940.0), ('WJ', "W1JetsToLNu", "W + 1J", 8104.0), ('WJ', "W2JetsToLNu", "W + 2J", 2793.0), ('WJ', "W3JetsToLNu", "W + 3J", 992.5), ('WJ', "W4JetsToLNu", "W + 4J", 544.3), ('VV', "WW", "WW", 75.88), ('VV', "WZ", "WZ", 27.6), ('VV', "ZZ", "ZZ", 12.14), ('ST', "ST_t-channel_top", "ST t-channel t", 136.02), ('ST', "ST_t-channel_antitop", "ST t-channel at", 80.95), ('ST', "ST_tW_top", "ST tW", 35.85), ('ST', "ST_tW_antitop", "ST atW", 35.85), ('TT', "TTTo2L2Nu", "ttbar 2l2#nu", 88.29, { 'extraweight': 'ttptweight' }), ('TT', "TTToHadronic", "ttbar hadronic", 377.96, { 'extraweight': 'ttptweight' }), ('TT', "TTToSemiLeptonic", "ttbar semileptonic", 365.35, { 'extraweight': 'ttptweight' }), ] else: LOG.throw(IOError, "Did not recognize era %r!" % (era)) # OBSERVED DATA SAMPLES dataset = "SingleMuon_Run%d?" % year datasample = ('Data', dataset) # GROUP, NAME # SAMPLE SET weight = "genweight*trigweight*puweight*idisoweight_1*idisoweight_2" fname = "$PICODIR/$SAMPLE_$CHANNEL$TAG.root" kwargs.setdefault('weight', weight) # common weight for MC kwargs.setdefault('fname', fname) # default filename pattern sampleset = _getsampleset(datasample, expsamples, channel=channel, era=era, **kwargs) # JOIN ZMM = STYLE.sample_titles.get('ZMM', "Z -> mumu") # title # Note: titles are set via STYLE.sample_titles sampleset.stitch("W*Jets", incl='WJ', name='WJ') # W + jets if 'mass' not in dysample: sampleset.stitch("DY*J*M-10to50", incl='DYJ', name="DY_M10to50") sampleset.stitch("DY*J*M-50", incl='DYJ', name='DY') # Drell-Yan, M > 50 GeV sampleset.join('DY', name='DY') # Drell-Yan, M < 50 GeV + M > 50 GeV if 'VV' in join: sampleset.join('VV', 'WZ', 'WW', 'ZZ', name='VV') # Diboson if 'TT' in join and era != 'year': sampleset.join('TT', name='TT') # ttbar if 'ST' in join: sampleset.join('ST', name='ST') # single top if 'Top' in join: sampleset.join('TT', 'ST', name='Top') # ttbar + single top # SPLIT GMR = "genmatch_1>0 && genmatch_2>0" GMF = "(genmatch_1<=0 || genmatch_2<=0)" if 'DY' in split: sampleset.split('DY', [ ('ZMM', ZMM, GMR), ('ZJ', GMF), ]) if 'TT' in split: sampleset.split('TT', [ ('TMM', GMR), ('TTJ', GMF), ]) if table: sampleset.printtable(merged=True, split=True) return sampleset
def plot(sampleset, channel, parallel=True, tag="", outdir="plots", histdir="", era=""): """Test plotting of SampleSet class for data/MC comparison.""" LOG.header("plot") # SELECTIONS inclusive = "(q_1*q_2<0)" inclusive = inclusive.replace(" ", "") #inclusive_cr_qcd = inclusive.replace("q_1*q_2<0","q_1*q_2>0") # inverting the opposite-sign requirement of the mutau pair into a same-sign requirment zregion = "%s && mt_1_puppimet<60 && nbjets==0 && m_vis>40 && m_vis<100 && dzeta_puppimet>-50 " % ( inclusive) selections = [ Sel('inclusive', inclusive), Sel('zregion', zregion), #Sel('inclusive_cr_qcd',inclusive_cr_qcd), ] # VARIABLES # TODO section 5: extend with other variables, which are available in the flat n-tuples variables = [ Var('m_vis', 40, 0, 200), Var('pt_vis', "p_{T}^{vis} ", 40, 0, 200), Var('pt_Z_puppimet', "p_{T}^{Z} with puppi", 40, 0, 200), #Var('pt_Z_PFmet', "p_{T}^{Z} with PF", 40, 0, 200), #Var('m_2', "m_tau_h", 28, 0.2, 1.6), Var('mt_1_puppimet', "mt(mu,MET) with puppi", 40, 0, 200), #Var('mt_1_PFmet', "mt(mu,MET) with PF", 40, 0, 200), Var('dzeta_puppimet', "D_{zeta} with puppi", 56, -180, 100, pos='L;y=0.88', units='GeV'), #Var('dzeta_PFmet', "D_{zeta} with PF", 56, -180, 100, pos='L;y=0.88',units='GeV'), Var( 'pt_1', "Muon pt", 40, 0, 120, ), Var( 'pt_2', "tau_h pt", 40, 0, 120, ), Var('eta_1', "Muon eta", 30, -3, 3, ymargin=1.6, ncols=2), Var('eta_2', "tau_h eta", 30, -3, 3, ymargin=1.6, ncols=2), Var('njets', 8, 0, 8), Var('nbjets', 8, 0, 8), Var('dR_ll', "DR(mutau_h)", 30, 0, 6.0, ctitle={ 'etau': "DR(etau_h)", 'tautau': "DR(tau_htau_h)", 'emu': "DR(emu)" }), #Var('met_puppimet', "p_{T}^{miss} with puppi", 50, 0, 150), #Var('met_PFmet', "p_{T}^{miss} with PF", 50, 0, 150), Var('rho', "#rho", 40, 0, 80), Var('npv', 40, 0, 80), Var('npv_good', "npv_{good}", 40, 0, 80), Var('id_2', "tau ID vs jet", 65, 0, 65), Var('anti_e_2', "tau ID vs ele", 65, 0, 65), Var('anti_mu_2', "tau ID vs muon", 20, 0, 20), ] # PLOT and HIST outdir = ensuredir(repkey(outdir, CHANNEL=channel, ERA=era)) histdir = ensuredir(repkey(histdir, CHANNEL=channel, ERA=era)) outhists = R.TFile.Open(histdir, 'recreate') exts = ['png'] #exts = ['png','pdf'] for selection in selections: outhists.mkdir(selection.filename) stacks = sampleset.getstack( variables, selection, method='QCD_OSSS', scale=1.1, parallel=parallel ) # the 'scale' keyword argument - chosen as 1.1 for mutau - # is an extrapolation factor for the QCD shape from the same-sign # to the opposite-sign region fname = "%s/$VAR_%s-%s-%s$TAG" % (outdir, channel, selection.filename, era) text = "%s: %s" % (channel.replace('mu', "#mu").replace( 'tau', "#tau_{h}"), selection.title) for stack, variable in stacks.iteritems(): outhists.cd(selection.filename) for h in stack.hists: h.Write(h.GetName().replace("QCD_", "QCD"), R.TH1.kOverwrite) stack.draw() stack.drawlegend(x1=0.6, x2=0.95, y1=0.35, y2=0.95) stack.drawtext(text) stack.saveas(fname, ext=exts, tag=tag) stack.close() outhists.Close()