예제 #1
0
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()
예제 #2
0
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()
예제 #3
0
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()
예제 #4
0
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)
예제 #5
0
 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
예제 #6
0
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])
예제 #7
0
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()
예제 #8
0
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
예제 #9
0
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
예제 #10
0
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()
예제 #11
0
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)
예제 #12
0
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 ">>> "
예제 #13
0
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')
예제 #14
0
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
예제 #15
0
파일: testStyle.py 프로젝트: IzaakWN/TauFW
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()
예제 #16
0
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)
예제 #17
0
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)
예제 #18
0
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 ">>> "
예제 #19
0
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
예제 #20
0
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()
예제 #21
0
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()
예제 #23
0
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()