def draw(pad, hists, label=('','')) :
    pad.Draw()
    pad.cd()
    h_data = hists[dataSample()]
    stack = r.THStack('stack_'+h_data.GetName(), '')
    leg = topRightLegend(pad, 0.275, 0.475, shift=-0.025)
    leg.SetBorderSize(0)
    leg.AddEntry(h_data, dataSample(), 'P')
    for s in mcSamples() :
        h = hists[s]
        h.SetMarkerSize(0)
        h.SetFillColor(colors[s])
        h.SetLineColor(h.GetFillColor())
        h.SetDrawOption('bar')
        stack.Add(h)
    for s in mcSamples()[::-1] : leg.AddEntry(hists[s], s, 'F') # stack goes b-t, legend goes t-b
    h_data.SetMarkerStyle(r.kFullDotLarge)
    stack.Draw('hist')
    h_data.Draw('p same')
    leg.Draw('same')
    tex = r.TLatex()
    tex.SetNDC(True)
    label = "#splitline{%s}{%s}"%(label[0], label[1]) if len(label)==2 else label
    tex.DrawLatex(0.25, 0.95, label)
    pad.Update() # force stack to create padMaster
    padMaster = stack.GetHistogram()
    pMin, pMax = getMinMax([padMaster, h_data])
    stack.SetMaximum(pMax)
    pad._graphical_objects = [stack, h_data, leg, tex] + [h for h in stack.GetStack()]
    pad.Update()
예제 #2
0
def plotStackedHistos(histos={},
                      datakey=None,
                      stackkeys=[],
                      outputDir='',
                      region='',
                      colors={},
                      verbose=False):
    "input: a dictionary of histos[group]"
    mkdirIfNeeded(outputDir)
    bkg_histos = dict([(k, h) for k, h in histos.iteritems()
                       if k in stackkeys])
    tot_bkg = summedHisto(bkg_histos.values(), label='')
    err_band = None  # tmp disable
    # err_band = buildErrBandGraph(tot_bkg, computeStatErr2(tot_bkg))
    empty_bkg = tot_bkg.Integral() == 0
    if empty_bkg:
        if verbose: print "empty backgrounds, skip %s" % tot_bkg.GetName()
        return
    histoname = tot_bkg.GetName()
    can = r.TCanvas('c_' + histoname, histoname, 800, 600)
    can.cd()
    pm = tot_bkg  # pad master
    pm.SetStats(False)
    pm.Draw('axis')
    can.Update()  # necessary to fool root's dumb object ownership
    stack = r.THStack('stack_' + tot_bkg.GetName(), '')
    can.Update()
    r.SetOwnership(stack, False)
    for s, h in bkg_histos.iteritems():
        h.SetFillColor(colors[s] if s in colors else r.kOrange)
        h.SetDrawOption('bar')
        h.SetDirectory(0)
        stack.Add(h)
    stack.Draw('hist same')
    # err_band.Draw('E2 same')
    data = histos[datakey] if datakey and datakey in histos else None
    if data and data.GetEntries():
        data.SetMarkerStyle(r.kFullDotLarge)
        data.Draw('p same')
        if verbose:
            print "data : nEntries {:.1f} totWeight {:.1f} ".format(
                data.GetEntries(), data.Integral())
    yMin, yMax = getMinMax([h for h in [tot_bkg, data, err_band] if h])
    # pm.SetMinimum(0.5)
    pm.SetMaximum(1.1 * yMax)
    can.Update()
    # can.SetLogy()
    topRightLabel(can,
                  "#splitline{%s}{%s}" % (histoname, region),
                  xpos=0.125,
                  align=13)
    drawLegendWithDictKeys(can,
                           dictSum(bkg_histos, {'stat err': err_band}),
                           opt='f')
    can.RedrawAxis()
    can._stack = stack
    can._histos = [h for h in stack.GetHists()] + [data]
    can.Update()
    if verbose: print os.path.join(outputDir, histoname + '.png')
    can.SaveAs(os.path.join(outputDir, histoname + '.png'))
예제 #3
0
def plot1dEfficiencies(effs={}, canvasName='', outputDir='./', frameTitle='title;p_{T} [GeV]; efficiency', zoomIn=False) :
    can = r.TCanvas(canvasName, '', 800, 600)
    can.cd()
    padMaster = None
    colors, markers = SampleUtils.colors, SampleUtils.markers
    for s,h in effs.iteritems() :
        h.SetLineColor(colors[s] if s in colors else r.kBlack)
        h.SetMarkerColor(h.GetLineColor())
        h.SetMarkerStyle(markers[s] if s in markers else r.kFullCircle)
        drawOpt = 'ep same' if padMaster else 'ep'
        h.Draw(drawOpt)
        if not padMaster : padMaster = h
    minY, maxY = getMinMax(effs.values()) if zoomIn else (0.0, 1.0)
    padMaster.GetYaxis().SetRangeUser(min([0.0, minY]), 1.1*maxY)
    padMaster.SetMinimum(0.0)
    padMaster.SetMaximum(1.1*maxY)
    padMaster.SetMaximum(0.25 if (maxY < 0.25 and zoomIn) else 1.1)
    padMaster.SetTitle(frameTitle)
    padMaster.SetStats(False)
    drawLegendWithDictKeys(can, effs)
    can.Update()
    for ext in ['png','eps'] :
        outFilename = outputDir+'/'+canvasName+'.'+ext
        rmIfExists(outFilename)
        can.SaveAs(outFilename)
def plotPerSourceEff(histosPerVar={}, outputDir='', lepton='', region='', sample='', verbose=False, zoomIn=True):
    "plot efficiency for each source (and 'anysource') as a function of each var; expect histos[var][source][loose,tight]"
    variables = histosPerVar.keys()
    sources = [s for s in first(histosPerVar).keys() if s!='real'] # only fake eff really need a scale factor
    colors = colorsLineSources
    mkdirIfNeeded(outputDir)
    for var in filter(lambda x : x in ['pt1', 'eta1'], histosPerVar.keys()):
        histosPerSource = dict((s, histosPerVar[var][s]) for s in sources)
        canvasBasename = region+'_efficiency_'+lepton+'_'+var+("_%s"%sample if sample else '')
        missingSources = [s for s, h in histosPerSource.iteritems() if not h['loose'] or not h['tight']]
        if missingSources:
            if verbose : print "skip %s, missing histos for %s"%(var, str(missingSources))
            continue
        anySourceLoose = summedHisto([h['loose'] for h in histosPerSource.values()])
        anySourceTight = summedHisto([h['tight'] for h in histosPerSource.values()])
        anySourceLoose.SetName(histoNamePerSource(var, 'any', 'loose', region))
        anySourceTight.SetName(histoNamePerSource(var, 'any', 'tight', region))
        histosPerSource['any'] = { 'loose' : anySourceLoose, 'tight' : anySourceTight }
        emptyBkg = anySourceLoose.Integral()==0 or anySourceTight.Integral()==0
        if emptyBkg:
            if verbose : print "empty backgrounds, skip %s"%canvasBasename
            continue
        def computeEfficiencies(histosPerSource={}) :
            sources = histosPerSource.keys()
            num = dict((s, histosPerSource[s]['tight']) for s in sources)
            den = dict((s, histosPerSource[s]['loose']) for s in sources)
            eff = dict((s, h.Clone(h.GetName().replace('tight', 'tight_over_loose')))
                       for s, h in num.iteritems())
            [eff[s].Divide(den[s]) for s in sources]
            return eff

        effs = computeEfficiencies(histosPerSource)
        can = r.TCanvas('c_'+canvasBasename, canvasBasename, 800, 600)
        can.cd()
        pm = first(effs) # pad master
        pm.SetStats(False)
        pm.Draw('axis')
        can.Update()
        for s, h in effs.iteritems() :
            h.SetMarkerColor(colors[s] if s in colors else r.kBlack)
            h.SetLineColor(h.GetMarkerColor())
            h.SetLineWidth(2*h.GetLineWidth())
            h.SetMarkerStyle(markersSources[s] if s in markersSources else r.kDot)
            h.Draw('ep same')
            h.SetDirectory(0)
        #pprint.pprint(effs)
        yMin, yMax = getMinMax(effs.values())
        pm.SetMinimum(0.0)
        pm.SetMaximum(0.25 if yMax < 0.5 and zoomIn else 1.1)
        can.Update()
        topRightLabel(can, canvasBasename, xpos=0.125, align=13)
        drawLegendWithDictKeys(can, effs, opt='lp')
        can.RedrawAxis()
        can._histos = effs
        can.Update()
        outFname = os.path.join(outputDir, canvasBasename+'.png')
        utils.rmIfExists(outFname)
        can.SaveAs(outFname)
예제 #5
0
def plot_emu_mue_with_ratio(canvas=None,
                            h_mue=None,
                            h_emu=None,
                            h_ratio=None,
                            filename='',
                            figformats=['png', 'eps']):
    c = canvas
    c.Clear()
    c._graphics = []
    c.cd()
    botPad, topPad = buildBotTopPads(c, splitFraction=0.375)
    topPad.Draw()
    topPad.cd()
    h_mue.SetStats(0)
    h_emu.SetStats(0)
    h_emu.SetLineColor(r.kBlue)
    h_mue.SetLineColor(r.kRed)
    h_mue.Draw()
    h_emu.Draw('same')
    pm = h_mue
    yMin, yMax = getMinMax([h_mue, h_emu])
    pm.SetMinimum(0.0)
    pm.SetMaximum(1.1 * yMax)
    xax = pm.GetXaxis()
    yax = pm.GetYaxis()
    xax.SetLabelSize(0)
    xax.SetTitleSize(0)
    leg = topLeftLegend(c, 0.275, 0.275, shift=0.05)
    leg.SetBorderSize(0)
    leg.SetHeader('non-prompt prediction')
    leg.AddEntry(h_mue, '#mue', 'L')
    leg.AddEntry(h_emu, 'e#mu', 'L')
    leg.Draw()
    c._graphics.append(leg)
    c.cd()
    botPad.Draw()
    botPad.cd()
    h_ratio.SetLineColor(r.kBlack)
    h_ratio.SetTitle('')
    xax = h_ratio.GetXaxis()
    yax = h_ratio.GetYaxis()
    yax.SetRangeUser(0.0, 2.0)
    yax.SetTitle('e#mu / #mue ratio')
    xA, yA = h_ratio.GetXaxis(), h_ratio.GetYaxis()
    textScaleUp = 1.0 / botPad.GetHNDC()
    yA.SetNdivisions(-104)
    yA.CenterTitle()
    yA.SetTitleOffset(yA.GetTitleOffset() / textScaleUp)
    for a in [xA, yA]:
        a.SetLabelSize(a.GetLabelSize() * textScaleUp)
        a.SetTitleSize(a.GetTitleSize() * textScaleUp)
    h_ratio.Draw()
    refline = referenceLine(xA.GetXmin(), xA.GetXmax())
    refline.Draw()
    c._graphics.append(refline)
    c.Update()
    for ext in figformats:
        c.SaveAs("{0}.{1}".format(filename, ext))
def plotStackedHistosSources(histosPerVar={},
                             outputDir='',
                             region='',
                             verbose=False):
    variables = histosPerVar.keys()
    sources = first(histosPerVar).keys()
    colors = colorsFillSources
    mkdirIfNeeded(outputDir)
    for var in variables:
        for lOrT in ['loose', 'tight']:
            histos = dict((s, histosPerVar[var][s][lOrT]) for s in sources)
            canvasBasename = region + '_region_' + var + '_' + lOrT
            missingSources = [s for s, h in histos.iteritems() if not h]
            if missingSources:
                if verbose:
                    print "skip %s, missing histos for %s" % (
                        var, str(missingSources))
                continue
            totBkg = summedHisto(histos.values())
            err_band = None  # buildErrBandGraph(totBkg, computeStatErr2(totBkg))
            emptyBkg = totBkg.Integral() == 0
            if emptyBkg:
                if verbose: print "empty backgrounds, skip %s" % canvasBasename
                continue
            can = r.TCanvas('c_' + canvasBasename, canvasBasename, 800, 600)
            can.cd()
            pm = totBkg  # pad master
            pm.SetStats(False)
            pm.Draw('axis')
            can.Update()  # necessary to fool root's dumb object ownership
            stack = r.THStack('stack_' + canvasBasename, '')
            can.Update()
            r.SetOwnership(stack, False)
            for s, h in histos.iteritems():
                h.SetFillColor(colors[s] if s in colors else r.kOrange)
                h.SetDrawOption('bar')
                h.SetDirectory(0)
                stack.Add(h)
            stack.Draw('hist same')
            # err_band.Draw('E2 same')
            yMin, yMax = getMinMax(
                [h for h in [totBkg, err_band] if h is not None])
            pm.SetMinimum(0.0)
            pm.SetMaximum(1.1 * yMax)
            can.Update()
            topRightLabel(can, canvasBasename, xpos=0.125, align=13)
            # drawLegendWithDictKeys(can, dictSum(histos, {'stat err':err_band}), opt='f')
            drawLegendWithDictKeys(can, histos, opt='f')
            can.RedrawAxis()
            can._stack = stack
            can._histos = [h for h in stack.GetHists()]
            can.Update()
            outFname = os.path.join(outputDir, canvasBasename + '.png')
            utils.rmIfExists(outFname)
            can.SaveAs(outFname)
예제 #7
0
def plot_emu_mue_with_ratio(canvas=None, h_mue=None, h_emu=None, h_ratio=None,
                            filename='', figformats=['png', 'eps'], label=''):
    c = canvas
    c.Clear()
    c._graphics = []
    c.cd()
    botPad, topPad = buildBotTopPads(c, splitFraction=0.375)
    topPad.Draw()
    topPad.cd()
    h_mue.SetStats(0)
    h_emu.SetStats(0)
    h_emu.SetLineColor(r.kBlue)
    h_mue.SetLineColor(r.kRed)
    h_mue.Draw()
    h_emu.Draw('same')
    pm = h_mue
    yMin, yMax = getMinMax([h_mue, h_emu])
    pm.SetMinimum(0.0)
    pm.SetMaximum(1.1 * yMax)
    xax = pm.GetXaxis()
    yax = pm.GetYaxis()
    xax.SetLabelSize(0)
    xax.SetTitleSize(0)
    leg = topRightLegend(c, 0.275, 0.275, shift=0.05)
    leg.SetBorderSize(0)
    leg.SetHeader(label)
    leg.AddEntry(h_mue, '#mue', 'L')
    leg.AddEntry(h_emu, 'e#mu', 'L')
    leg.Draw()
    c._graphics.append(leg)
    c.cd()
    botPad.Draw()
    botPad.cd()
    h_ratio.SetLineColor(r.kBlack)
    h_ratio.SetTitle('')
    xax = h_ratio.GetXaxis()
    yax = h_ratio.GetYaxis()
    yax.SetRangeUser(0.0, 2.0)
    yax.SetTitle('e#mu / #mue ratio')
    xA, yA = h_ratio.GetXaxis(), h_ratio.GetYaxis()
    textScaleUp = 1.0/botPad.GetHNDC()
    yA.SetNdivisions(-104)
    yA.CenterTitle()
    yA.SetTitleOffset(yA.GetTitleOffset()/textScaleUp)
    for a in [xA, yA] :
        a.SetLabelSize(a.GetLabelSize()*textScaleUp)
        a.SetTitleSize(a.GetTitleSize()*textScaleUp)
    h_ratio.Draw()
    refline = referenceLine(xA.GetXmin(), xA.GetXmax())
    refline.Draw()
    c._graphics.append(refline)
    c.Update()
    for ext in figformats:
        c.SaveAs("{0}.{1}".format(filename, ext))
        print "{0}.{1}".format(filename, ext)
def plotStackedHistos(histosPerGroup={}, outputDir='', region='', verbose=False):
    groups = histosPerGroup.keys()
    variables = first(histosPerGroup).keys()
    leptonTypes = first(first(histosPerGroup)).keys()
    colors = SampleUtils.colors
    mkdirIfNeeded(outputDir)
    histosPerName = dict([(region+'_'+var+'_'+lt, # one canvas for each histo, so key with histoname w/out group
                           dict([(g, histosPerGroup[g][var][lt]) for g in groups]))
                          for var in variables for lt in leptonTypes])
    for histoname, histosPerGroup in histosPerName.iteritems():
        missingGroups = [g for g, h in histosPerGroup.iteritems() if not h]
        if missingGroups:
            if verbose : print "skip %s, missing histos for %s"%(histoname, str(missingGroups))
            continue
        bkgHistos = dict([(g, h) for g, h in histosPerGroup.iteritems() if isBkgSample(g)])
        totBkg = summedHisto(bkgHistos.values())
        err_band = buildErrBandGraph(totBkg, computeStatErr2(totBkg))
        emptyBkg = totBkg.Integral()==0
        if emptyBkg:
            if verbose : print "empty backgrounds, skip %s"%histoname
            continue
        can = r.TCanvas('c_'+histoname, histoname, 800, 600)
        can.cd()
        pm = totBkg # pad master
        pm.SetStats(False)
        pm.Draw('axis')
        can.Update() # necessary to fool root's dumb object ownership
        stack = r.THStack('stack_'+histoname,'')
        can.Update()
        r.SetOwnership(stack, False)
        for s, h in bkgHistos.iteritems() :
            h.SetFillColor(colors[s] if s in colors else r.kOrange)
            h.SetDrawOption('bar')
            h.SetDirectory(0)
            stack.Add(h)
        stack.Draw('hist same')
        err_band.Draw('E2 same')
        data = histosPerGroup['data']
        if data and data.GetEntries():
            data.SetMarkerStyle(r.kFullDotLarge)
            data.Draw('p same')
        yMin, yMax = getMinMax([h for h in [totBkg, data, err_band] if h])
        pm.SetMinimum(0.0)
        pm.SetMaximum(1.1*yMax)
        can.Update()
        topRightLabel(can, histoname, xpos=0.125, align=13)
        drawLegendWithDictKeys(can, dictSum(bkgHistos, {'stat err':err_band}), opt='f')
        can.RedrawAxis()
        can._stack = stack
        can._histos = [h for h in stack.GetHists()]+[data]
        can.Update()
        outFname = os.path.join(outputDir, histoname+'.png')
        utils.rmIfExists(outFname)
        can.SaveAs(outFname)
def plotStackedHistosWithData(histosPerGroup={}, outputDir='', canvasname='', canvastitle='', colors={}, verbose=False):
    "histosPerGroup[group], where group=data is treated as special"
    groups = histosPerGroup.keys()
    mkdirIfNeeded(outputDir)
    missingGroups = [g for g, h in histosPerGroup.iteritems() if not h]
    if missingGroups:
        if verbose : print "skip %s, missing histos for %s"%(histoname, str(missingGroups))
        return
    bkgHistos = dict([(g, h) for g, h in histosPerGroup.iteritems() if not isDataSample(g)])
    totBkg = summedHisto(bkgHistos.values())
    err_band = buildErrBandGraph(totBkg, computeStatErr2(totBkg))
    emptyBkg = totBkg.Integral()==0
    histoname, region = totBkg.GetName(), 'emu' # tmp replacement vars, to be fixed
    if emptyBkg:
        if verbose : print "empty backgrounds, skip %s"%histoname
        return
    can = r.TCanvas(canvasname, canvastitle, 800, 600)
    can.cd()
    pm = totBkg # pad master
    pm.SetStats(False)
    pm.Draw('axis')
    can.Update() # necessary to fool root's dumb object ownership
    stack = r.THStack('stack_'+histoname,'')
    can.Update()
    r.SetOwnership(stack, False)
    for s, h in bkgHistos.iteritems() :
        h.SetFillColor(colors[s] if s in colors else r.kOrange)
        h.SetDrawOption('bar')
        h.SetDirectory(0)
        stack.Add(h)
    stack.Draw('hist same')
    err_band.Draw('E2 same')
    data = histosPerGroup['data'] if 'data' in histosPerGroup else None
    if data and data.GetEntries():
        data.SetMarkerStyle(r.kFullDotLarge)
        data.Draw('p same')
        if verbose :
            print "integrals : {0} tot.bkg.: {1}, data: {2}".format(histoname, totBkg.Integral(), data.Integral())
    else:
        print "no data"
    yMin, yMax = getMinMax([h for h in [totBkg, data, err_band] if h])
    pm.SetMinimum(0.0)
    pm.SetMaximum(1.1*yMax)
    can.Update()
    topRightLabel(can, "#splitline{%s}{%s}"%(histoname, region), xpos=0.15, ypos=(1.0-0.5*can.GetTopMargin()), align=13)
    drawLegendWithDictKeys(can, dictSum(bkgHistos, {'stat err':err_band}), opt='f')
    can.RedrawAxis()
    can._stack = stack
    can._histos = [h for h in stack.GetHists()]+[data]
    can.Update()
    filename=os.path.join(outputDir, histoname+'.png')
    rmIfExists(filename)
    can.SaveAs(filename)
def drawTop(pad, hists, err_band, label=('','')) :
    pad.Draw()
    pad.cd()
    h_data = hists[dataSample()]
    h_bkg  = hists['sm']
    stack = r.THStack('stack_'+h_data.GetName(), '')
    leg = topRightLegend(pad, 0.275, 0.475, shift=-0.025)
    leg.SetBorderSize(0)
    leg.AddEntry(h_data, dataSample(), 'P')
    leg.AddEntry(h_bkg, 'sm', 'L')
    counters = dict()
    if 'nbjets' in h_data.GetName() :
        counters['data'] = integralAndError(h_data)
        counters['sm'] = integralAndError(h_bkg)
    for s in bkSamples() :
        h = hists[s]
        h.SetMarkerSize(0)
        h.SetFillColor(colors[s])
        h.SetLineColor(h.GetFillColor())
        h.SetDrawOption('bar')
        if 'nbjets' in h.GetName() : counters[s] = integralAndError(h)
        stack.Add(h)
    for s in bkSamples()[::-1] : leg.AddEntry(hists[s], s, 'F') # stack goes b-t, legend goes t-b
    h_data.SetMarkerStyle(r.kFullDotLarge)
    stack.Draw('hist')
    h_bkg.Draw('hist same')
    err_band.Draw('E2 same')
    h_data.Draw('p same')
    leg.AddEntry(err_band, 'Uncertainty', 'F')
    leg.Draw('same')
    tex = r.TLatex()
    tex.SetNDC(True)
    label = "#splitline{%s}{%s}"%(label[0], label[1]) if len(label)==2 else label
    tex.DrawLatex(0.50, 0.85, label)
    pad.Update() # force stack to create padMaster
    padMaster = stack.GetHistogram()
    pMin, pMax = getMinMax([h_bkg, h_data, err_band])
    stack.SetMaximum(pMax)
    xAx, yAx = padMaster.GetXaxis(), padMaster.GetYaxis()
    xAx.SetTitle('')
    xAx.SetLabelSize(0)
    textScaleUp = 1.0/pad.GetHNDC()
    yAx.SetLabelSize(textScaleUp*yAx.GetLabelSize())
    pad._graphical_objects = [stack, h_data, h_bkg, err_band, leg, tex] + [h for h in stack.GetStack()]
    pad.Update()
    if 'nbjets' in h_data.GetName() :
        print h_data.GetName()
        print " | ".join(["%12s"%k for k,v in sorted(counters.items())])
        print " | ".join(["%12s"%("%.1f +/- %.1f"%v) for k,v in sorted(counters.items())])
def drawTop(pad, hists, err_band, label=('','')) :
    pad.Draw()
    pad.cd()
    h_data = hists[dataSample()]
    h_bkg  = hists['sm']
    stack = r.THStack('stack_'+h_data.GetName(), '')
    leg = topRightLegend(pad, 0.275, 0.475, shift=-0.025)
    leg.SetBorderSize(0)
    leg.AddEntry(h_data, dataSample(), 'P')
    leg.AddEntry(h_bkg, 'sm', 'L')
    counters = dict()
    if 'nbjets' in h_data.GetName() :
        counters['data'] = integralAndError(h_data)
        counters['sm'] = integralAndError(h_bkg)
    for s in bkSamples() :
        h = hists[s]
        h.SetMarkerSize(0)
        h.SetFillColor(colors[s])
        h.SetLineColor(h.GetFillColor())
        h.SetDrawOption('bar')
        if 'nbjets' in h.GetName() : counters[s] = integralAndError(h)
        stack.Add(h)
    for s in bkSamples()[::-1] : leg.AddEntry(hists[s], s, 'F') # stack goes b-t, legend goes t-b
    h_data.SetMarkerStyle(r.kFullDotLarge)
    stack.Draw('hist')
    h_bkg.Draw('hist same')
    err_band.Draw('E2 same')
    h_data.Draw('p same')
    leg.AddEntry(err_band, 'Uncertainty', 'F')
    leg.Draw('same')
    tex = r.TLatex()
    tex.SetNDC(True)
    label = "#splitline{%s}{%s}"%(label[0], label[1]) if len(label)==2 else label
    tex.DrawLatex(0.50, 0.85, label)
    pad.Update() # force stack to create padMaster
    padMaster = stack.GetHistogram()
    pMin, pMax = getMinMax([h_bkg, h_data, err_band])
    stack.SetMaximum(pMax)
    xAx, yAx = padMaster.GetXaxis(), padMaster.GetYaxis()
    xAx.SetTitle('')
    xAx.SetLabelSize(0)
    textScaleUp = 1.0/pad.GetHNDC()
    yAx.SetLabelSize(textScaleUp*yAx.GetLabelSize())
    pad._graphical_objects = [stack, h_data, h_bkg, err_band, leg, tex] + [h for h in stack.GetStack()]
    pad.Update()
    if 'nbjets' in h_data.GetName() :
        print h_data.GetName()
        print " | ".join(["%12s"%k for k,v in sorted(counters.items())])
        print " | ".join(["%12s"%("%.1f +/- %.1f"%v) for k,v in sorted(counters.items())])
def plotStackedHistosSources(histosPerVar={}, outputDir='', region='', verbose=False):
    variables = histosPerVar.keys()
    sources = first(histosPerVar).keys()
    colors = colorsFillSources
    mkdirIfNeeded(outputDir)
    for var in variables:
        for lOrT in ['loose', 'tight']:
            histos = dict((s, histosPerVar[var][s][lOrT]) for s in sources)
            canvasBasename = region+'_region_'+var+'_'+lOrT
            missingSources = [s for s, h in histos.iteritems() if not h]
            if missingSources:
                if verbose : print "skip %s, missing histos for %s"%(var, str(missingSources))
                continue
            totBkg = summedHisto(histos.values())
            err_band = None # buildErrBandGraph(totBkg, computeStatErr2(totBkg))
            emptyBkg = totBkg.Integral()==0
            if emptyBkg:
                if verbose : print "empty backgrounds, skip %s"%canvasBasename
                continue
            can = r.TCanvas('c_'+canvasBasename, canvasBasename, 800, 600)
            can.cd()
            pm = totBkg # pad master
            pm.SetStats(False)
            pm.Draw('axis')
            can.Update() # necessary to fool root's dumb object ownership
            stack = r.THStack('stack_'+canvasBasename,'')
            can.Update()
            r.SetOwnership(stack, False)
            for s, h in histos.iteritems() :
                h.SetFillColor(colors[s] if s in colors else r.kOrange)
                h.SetDrawOption('bar')
                h.SetDirectory(0)
                stack.Add(h)
            stack.Draw('hist same')
            # err_band.Draw('E2 same')
            yMin, yMax = getMinMax([h for h in [totBkg, err_band] if h is not None])
            pm.SetMinimum(0.0)
            pm.SetMaximum(1.1*yMax)
            can.Update()
            topRightLabel(can, canvasBasename, xpos=0.125, align=13)
            # drawLegendWithDictKeys(can, dictSum(histos, {'stat err':err_band}), opt='f')
            drawLegendWithDictKeys(can, histos, opt='f')
            can.RedrawAxis()
            can._stack = stack
            can._histos = [h for h in stack.GetHists()]
            can.Update()
            outFname = os.path.join(outputDir, canvasBasename+'.png')
            utils.rmIfExists(outFname)
            can.SaveAs(outFname)
예제 #13
0
def plotStackedHistos(histos={}, datakey=None, stackkeys=[], outputDir='', region='', colors={}, verbose=False):
    "input: a dictionary of histos[group]"
    mkdirIfNeeded(outputDir)
    bkg_histos = dict([(k,h) for k,h in histos.iteritems() if k in stackkeys])
    tot_bkg = summedHisto(bkg_histos.values(), label='')
    err_band = None # tmp disable
    # err_band = buildErrBandGraph(tot_bkg, computeStatErr2(tot_bkg))
    empty_bkg = tot_bkg.Integral()==0
    if empty_bkg:
        if verbose : print "empty backgrounds, skip %s"%tot_bkg.GetName()
        return
    histoname = tot_bkg.GetName()
    can = r.TCanvas('c_'+histoname, histoname, 800, 600)
    can.cd()
    pm = tot_bkg # pad master
    pm.SetStats(False)
    pm.Draw('axis')
    can.Update() # necessary to fool root's dumb object ownership
    stack = r.THStack('stack_'+tot_bkg.GetName(),'')
    can.Update()
    r.SetOwnership(stack, False)
    for s, h in bkg_histos.iteritems() :
            h.SetFillColor(colors[s] if s in colors else r.kOrange)
            h.SetDrawOption('bar')
            h.SetDirectory(0)
            stack.Add(h)
    stack.Draw('hist same')
    # err_band.Draw('E2 same')
    data = histos[datakey] if datakey and datakey in histos else None
    if data and data.GetEntries():
        data.SetMarkerStyle(r.kFullDotLarge)
        data.Draw('p same')
        if verbose:
            print "data : nEntries {:.1f} totWeight {:.1f} ".format(data.GetEntries(), data.Integral())
    yMin, yMax = getMinMax([h for h in [tot_bkg, data, err_band] if h])
    # pm.SetMinimum(0.5)
    pm.SetMaximum(1.1*yMax)
    can.Update()
    # can.SetLogy()
    topRightLabel(can, "#splitline{%s}{%s}"%(histoname, region), xpos=0.125, align=13)
    drawLegendWithDictKeys(can, dictSum(bkg_histos, {'stat err':err_band}), opt='f')
    can.RedrawAxis()
    can._stack = stack
    can._histos = [h for h in stack.GetHists()]+[data]
    can.Update()
    if verbose : print os.path.join(outputDir, histoname+'.png')
    can.SaveAs(os.path.join(outputDir, histoname+'.png'))
예제 #14
0
def plotHisto(inputFiles={}, histoname='', canvasname='', outdir='./') :
    can = r.TCanvas(canvasname, histoname, 800, 600)
    can.cd()
    backds = [b for b in backgrounds if b in inputFiles]
    stackBkgds = filter(lambda x : x in backds, stackedBackgrounds)
    h_bkgs = dict((b, inputFiles[b].Get(histoname)) for b in backds)
    h_btot = inputFiles['allBkg'].Get(histoname) if 'allBkg' in inputFiles else None
    h_bnoHf = inputFiles['allBkgButHf'].Get(histoname) if 'allBkgButHf' in inputFiles else None
    h_data = inputFiles['data'].Get(histoname) if 'data' in inputFiles else None
    stack = r.THStack('stack_'+histoname, '')
    leg = topRightLegend(can, 0.275, 0.475, shift=-0.025)
    if h_data : leg.AddEntry(h_data, "data: %.1f"%h_data.Integral(), 'P')
    if h_btot : leg.AddEntry(h_btot, "tot bkg %.1f"%h_btot.Integral(), 'l')
    if h_bnoHf : leg.AddEntry(h_bnoHf, "bkgNoHf: %.1f"%h_bnoHf.Integral(), 'l')
    for b in stackBkgds :
        h = h_bkgs[b]
        if not h :
            print 'missing h for ',b
            continue
        h.SetMarkerSize(0)
        h.SetFillColor(colors[b])
        h.SetLineColor(h.GetFillColor())
        h.SetDrawOption('bar')
        stack.Add(h)
    for s in stackBkgds[::-1] : leg.AddEntry(h_bkgs[s], "%s: %.1f"%(s, h_bkgs[s].Integral()), 'F') # stack goes b-t, legend goes t-b
    stack.Draw('hist')
    if h_btot  :
        h_btot.SetLineWidth(2*h_btot.GetLineWidth())
        h_btot.Draw('hist same')
    if h_bnoHf :
        h_bnoHf.SetLineWidth(2*h_bnoHf.GetLineWidth())
        h_bnoHf.SetLineStyle(2)
        h_bnoHf.Draw('hist same')
    if h_data  :
        h_data.SetMarkerStyle(r.kFullDotLarge)
        h_data.Draw('p same')
    leg.Draw('same')
    yMin, yMax = getMinMax([h for h in [stack.GetHistogram(), h_btot, h_bnoHf, h_data] if h is not None])
    stack.SetMaximum(1.1*yMax)
    tex = r.TLatex()
    tex.SetNDC(True)
    tex.DrawLatex(0.15, 0.95, histoname)
    can.Update()
    for ext in ['png'] : can.SaveAs(outdir+'/'+canvasname+'.'+ext)
예제 #15
0
def plotHistos(histoData=None, histoSignal=None, histoTotBkg=None, histosBkg={},
               statErrBand=None, systErrBand=None, # these are TGraphAsymmErrors
               canvasName='canvas', outdir='./', options=None,
               stack_order=[],
               topLabel='',
               drawStatErr=False, drawSystErr=False,
               drawYieldAndError=False, printYieldSummary=False) :
    "Note: blinding can be required for only a subrange of the histo, so it is taken care of when filling"
    verbose = options.verbose
    formatAuxMaterial = options.format_aux
    setAtlasStyle()
    padMaster = histoData
    if verbose : print "plotting ",padMaster.GetName(),' (',padMaster.GetEntries(),' entries)'
    can = r.TCanvas(canvasName, padMaster.GetTitle(), 800, 800)
    botPad, topPad = buildBotTopPads(can, squeezeMargins=False)
    can.cd()
    topPad.Draw()
    # draw top
    topPad.cd()
    topPad._hists = [padMaster]
    if formatAuxMaterial:
        for ax in [padMaster.GetXaxis(), padMaster.GetYaxis()]:
            ax.SetTitle(prettify(ax.GetTitle()))
    padMaster.Draw('axis')
    topPad.Update() # necessary to fool root's dumb object ownership of the stack
    stack = r.THStack('stack_'+padMaster.GetName(), '')
    r.SetOwnership(stack, False)
    topPad._hists.append(stack)
    leg = topRightLegend(can,
                         0.300 if formatAuxMaterial else 0.225,
                         0.400 if formatAuxMaterial else 0.325,
                         shiftX=-0.1 if formatAuxMaterial else 0.0,
                         shiftY=-0.1 if formatAuxMaterial else 0.0)
    topPad._leg = leg
    leg.SetBorderSize(0)
    leg.SetTextFont(padMaster.GetTitleFont())
    leg._reversedEntries = []
    def integralWou(h):
        "Integral with underflow and overflow"
        return h.Integral(0, h.GetNbinsX()+1)
    for group, histo in sortedAs(histosBkg, stack_order) :
        histo.SetFillColor(getGroupColor(group))
        histo.SetLineWidth(2)
        histo.SetLineColor(r.kBlack)
        stack.Add(histo)
        topPad._hists.append(histo)
        leg._reversedEntries.append((histo,
                                     prettify(group) if formatAuxMaterial else
                                     "{0}: {1:.2f}".format(group, integralWou(histo)), 'F'))
    if not formatAuxMaterial:
        leg._reversedEntries.append((dummyHisto(),
                                     "{0}, {1:.2f}".format('bkg', sum([integralWou(h) for h in stack.GetHists()])), 'l'))
    if statErrBand and drawStatErr :
        statErrBand.SetFillStyle(3006)
        leg._reversedEntries.append((statErrBand, 'stat', 'f'))
    if systErrBand and drawSystErr :
        systErrBand.SetFillStyle(3007)
        leg._reversedEntries.append((systErrBand, 'syst', 'f'))
    leg._reversedEntries.append((histoData,
                                 "Data {0}".format(prettify(topLabel)) if formatAuxMaterial else
                                 "{0}, {1:.2f}".format('data', integralWou(histoData)), 'p'))
    for h, g, o in leg._reversedEntries[::-1] : leg.AddEntry(h, g, o) # stack goes b-t, legend goes t-b
    stack.Draw('hist same')
    histoData.SetMarkerStyle(r.kFullCircle)
    histoData.SetLineWidth(2)
    dataGraph = graphWithPoissonError(histoData)
    dataGraph.Draw('same p')
    isRightSignal = False
    if histoSignal:
        histoSignal.SetFillStyle(0)
        histoSignal.SetFillColor(0)
        histoSignal.SetLineColor(getGroupColor('signal'))
        histoSignal.SetLineWidth(3)
        isRightSignal = (all(s in histoSignal.GetName() for s in ['signaltaumu', 'sr_mue']) or
                         all(s in histoSignal.GetName() for s in ['signaltaue', 'sr_emu']))
        if isRightSignal: histoSignal.Draw('histo same')
    if statErrBand and drawStatErr :
        statErrBand.SetFillStyle(3006)
        statErrBand.Draw('E2 same')
        leg.AddEntry(statErrBand, 'stat', 'f')
    if systErrBand and drawSystErr :
        systErrBand.SetFillStyle(3007)
        systErrBand.Draw('E2 same')
        leg.AddEntry(systErrBand, 'syst', 'f')
    totErrBand = systUtils.addErrorBandsInQuadrature(statErrBand, systErrBand)
    if totErrBand :
        totErrBand.Draw('E2 same')
        totErrBand.SetFillStyle(3005)
        leg.AddEntry(totErrBand, 'stat+syst', 'f')
        if printYieldSummary:
            print_total_error = False
            print ("{}:".format(topLabel if topLabel else dataGraph.GetName())+

                   (" expected {:.2f}^{{+{:.2f}}}_{{{:.2f}}}".format(totErrBand.GetY()[0],
                                                                    totErrBand.GetErrorYhigh(0),
                                                                    totErrBand.GetErrorYlow(0))
                    if print_total_error else
                    " expected {:.2f}^{{+{:.2f}}}_{{{:.2f}}} (stat) ^{{+{:.2f}}}_{{{:.2f}}} (syst)"
                    .format(totErrBand.GetY()[0],
                            statErrBand.GetErrorYhigh(0) if statErrBand else 0.0,
                            statErrBand.GetErrorYlow(0) if statErrBand else 0.0,
                            systErrBand.GetErrorYhigh(0) if systErrBand else 0.0,
                            systErrBand.GetErrorYlow(0) if systErrBand else 0.0)
                    )+
                   " obs {:.2f}".format(dataGraph.GetY()[0]))
    if histoSignal and isRightSignal:
        hname = histoSignal.GetName()
        label = ('H#rightarrow#mu#tau' if 'signaltaumu' in hname else
                 'H#rightarrowe#tau'   if 'signaltaue' in hname else
                 'signal')
        label = ("{}, BR=1%".format(label) if formatAuxMaterial else
                 "{}, BR=1%, {:.2f}".format(label, integralWou(histoSignal)))
        leg.AddEntry(histoSignal, label, 'l')
    leg.Draw('same')
    topPad.Update()
    tex = r.TLatex()
    tex.SetTextSize(0.5 * tex.GetTextSize())
    tex.SetNDC(True)
    label  = "%s tot bkg : "%(can.GetName())
    label += "%.3f #pm %.3f (stat)"%(integralAndError(histoTotBkg))
    if systErrBand :
        sysUp, sysDo = systUtils.totalUpDownVariation(systErrBand)
        label += "#pm #splitline{%.3f}{%.3f} (syst)"%(sysUp, sysDo)
    if drawYieldAndError :
        tex.DrawLatex(0.10, 0.95, label)
        topPad.SetTopMargin(2.0*topPad.GetTopMargin())
    atlasLabel = drawAtlasLabel(can, align=13, scale=0.75,
                                xpos=0.175 if formatAuxMaterial else 0.125,
                                ypos=0.945 if formatAuxMaterial else None,
                                public=True)
    if topLabel and not formatAuxMaterial : topRightLabel(can, topLabel, ypos=1.0)
    yMin, yMax = getMinMax([histoData, dataGraph, histoTotBkg, histoSignal, totErrBand])
    padMaster.SetMinimum(0.0)
    padMaster.SetMaximum(1.1 * yMax)
    padMaster.GetXaxis().SetLabelSize(0)
    padMaster.GetXaxis().SetTitleSize(0)
    increaseAxisFont(padMaster.GetXaxis())
    increaseAxisFont(padMaster.GetYaxis())
    topPad.RedrawAxis()
    topPad.Update() # force stack to create padMaster
    # draw bot (ratio)
    can.cd()
    botPad.Draw()
    botPad.cd()
    ratio = systUtils.buildAsymmRatioGraph(dataGraph, totErrBand)
    ratioPadMaster = padMaster.Clone(padMaster.GetName()+'_ratio')
    ratioPadMaster.SetDirectory(0)
    ratioPadMaster.Clear()
    yMin, yMax = 0.0, 2.0
    ratioPadMaster.SetMinimum(yMin)
    ratioPadMaster.SetMaximum(yMax)
    ratioPadMaster.SetStats(0)
    ratioPadMaster.Draw('axis')
    x_lo, x_hi = getXrange(ratioPadMaster)
    refLines = [referenceLine(x_lo, x_hi, y, y) for y in [0.5, 1.0, 1.5]]
    for l in refLines : l.Draw()
    err_band_r = systUtils.buildErrBandRatioGraph(totErrBand)
    err_band_r.Draw('E2 same')
    ratio.Draw('ep')
    xA, yA = ratioPadMaster.GetXaxis(), ratioPadMaster.GetYaxis()
    textScaleUp = 0.75*1.0/botPad.GetHNDC()
    # if xaxis_title : xA.SetTitle(xaxis_title)
    yA.SetNdivisions(-104)
    yA.SetTitle('Data/Bkg')
    yA.CenterTitle()
    yA.SetTitleOffset(yA.GetTitleOffset()/textScaleUp)
    xA.SetTitleSize(yA.GetTitleSize()) # was set to 0 for padmaster, restore it
    xA.SetLabelSize(yA.GetLabelSize())
    for a in [xA, yA] :
        a.SetLabelSize(a.GetLabelSize()*textScaleUp)
        a.SetTitleSize(a.GetTitleSize()*textScaleUp)
    botPad._graphical_objects = [ratio, ratioPadMaster, err_band_r] + refLines # avoid garbage collection
    botPad.Update()
    can.Update()
    for ext in ['png','eps'] : can.SaveAs(outdir+'/'+can.GetName()+'.'+ext)
def plotPerSourceEff(histosPerVar={},
                     outputDir='',
                     lepton='',
                     region='',
                     sample='',
                     verbose=False,
                     zoomIn=True):
    "plot efficiency for each source (and 'anysource') as a function of each var; expect histos[var][source][loose,tight]"
    variables = histosPerVar.keys()
    sources = [s for s in first(histosPerVar).keys()
               if s != 'real']  # only fake eff really need a scale factor
    colors = colorsLineSources
    mkdirIfNeeded(outputDir)
    for var in filter(lambda x: x in ['pt1', 'eta1'], histosPerVar.keys()):
        histosPerSource = dict((s, histosPerVar[var][s]) for s in sources)
        canvasBasename = region + '_efficiency_' + lepton + '_' + var + (
            "_%s" % sample if sample else '')
        missingSources = [
            s for s, h in histosPerSource.iteritems()
            if not h['loose'] or not h['tight']
        ]
        if missingSources:
            if verbose:
                print "skip %s, missing histos for %s" % (var,
                                                          str(missingSources))
            continue
        anySourceLoose = summedHisto(
            [h['loose'] for h in histosPerSource.values()])
        anySourceTight = summedHisto(
            [h['tight'] for h in histosPerSource.values()])
        anySourceLoose.SetName(histoNamePerSource(var, 'any', 'loose', region))
        anySourceTight.SetName(histoNamePerSource(var, 'any', 'tight', region))
        histosPerSource['any'] = {
            'loose': anySourceLoose,
            'tight': anySourceTight
        }
        emptyBkg = anySourceLoose.Integral() == 0 or anySourceTight.Integral(
        ) == 0
        if emptyBkg:
            if verbose: print "empty backgrounds, skip %s" % canvasBasename
            continue

        def computeEfficiencies(histosPerSource={}):
            sources = histosPerSource.keys()
            num = dict((s, histosPerSource[s]['tight']) for s in sources)
            den = dict((s, histosPerSource[s]['loose']) for s in sources)
            eff = dict(
                (s, h.Clone(h.GetName().replace('tight', 'tight_over_loose')))
                for s, h in num.iteritems())
            [eff[s].Divide(den[s]) for s in sources]
            return eff

        effs = computeEfficiencies(histosPerSource)
        can = r.TCanvas('c_' + canvasBasename, canvasBasename, 800, 600)
        can.cd()
        pm = first(effs)  # pad master
        pm.SetStats(False)
        pm.Draw('axis')
        can.Update()
        for s, h in effs.iteritems():
            h.SetMarkerColor(colors[s] if s in colors else r.kBlack)
            h.SetLineColor(h.GetMarkerColor())
            h.SetLineWidth(2 * h.GetLineWidth())
            h.SetMarkerStyle(markersSources[s] if s in
                             markersSources else r.kDot)
            h.Draw('ep same')
            h.SetDirectory(0)
        #pprint.pprint(effs)
        yMin, yMax = getMinMax(effs.values())
        pm.SetMinimum(0.0)
        pm.SetMaximum(0.25 if yMax < 0.5 and zoomIn else 1.1)
        can.Update()
        topRightLabel(can, canvasBasename, xpos=0.125, align=13)
        drawLegendWithDictKeys(can, effs, opt='lp')
        can.RedrawAxis()
        can._histos = effs
        can.Update()
        outFname = os.path.join(outputDir, canvasBasename + '.png')
        utils.rmIfExists(outFname)
        can.SaveAs(outFname)
예제 #17
0
def plotHistos(
        histoData=None,
        histoSignal=None,
        histoTotBkg=None,
        histosBkg={},
        statErrBand=None,
        systErrBand=None,  # these are TGraphAsymmErrors
        canvasName='canvas',
        outdir='./',
        options=None,
        stack_order=[],
        topLabel='',
        drawStatErr=False,
        drawSystErr=False,
        drawYieldAndError=False,
        printYieldSummary=False):
    "Note: blinding can be required for only a subrange of the histo, so it is taken care of when filling"
    verbose = options.verbose
    formatAuxMaterial = options.format_aux
    setAtlasStyle()
    padMaster = histoData
    if verbose:
        print "plotting ", padMaster.GetName(), ' (', padMaster.GetEntries(
        ), ' entries)'
    can = r.TCanvas(canvasName, padMaster.GetTitle(), 800, 800)
    botPad, topPad = buildBotTopPads(can, squeezeMargins=False)
    can.cd()
    topPad.Draw()
    # draw top
    topPad.cd()
    topPad._hists = [padMaster]
    if formatAuxMaterial:
        for ax in [padMaster.GetXaxis(), padMaster.GetYaxis()]:
            ax.SetTitle(prettify(ax.GetTitle()))
    padMaster.Draw('axis')
    topPad.Update(
    )  # necessary to fool root's dumb object ownership of the stack
    stack = r.THStack('stack_' + padMaster.GetName(), '')
    r.SetOwnership(stack, False)
    topPad._hists.append(stack)
    leg = topRightLegend(can,
                         0.300 if formatAuxMaterial else 0.225,
                         0.400 if formatAuxMaterial else 0.325,
                         shiftX=-0.1 if formatAuxMaterial else 0.0,
                         shiftY=-0.1 if formatAuxMaterial else 0.0)
    topPad._leg = leg
    leg.SetBorderSize(0)
    leg.SetTextFont(padMaster.GetTitleFont())
    leg._reversedEntries = []

    def integralWou(h):
        "Integral with underflow and overflow"
        return h.Integral(0, h.GetNbinsX() + 1)

    for group, histo in sortedAs(histosBkg, stack_order):
        histo.SetFillColor(getGroupColor(group))
        histo.SetLineWidth(2)
        histo.SetLineColor(r.kBlack)
        stack.Add(histo)
        topPad._hists.append(histo)
        leg._reversedEntries.append(
            (histo, prettify(group) if formatAuxMaterial else
             "{0}: {1:.2f}".format(group, integralWou(histo)), 'F'))
    if not formatAuxMaterial:
        leg._reversedEntries.append((dummyHisto(), "{0}, {1:.2f}".format(
            'bkg', sum([integralWou(h) for h in stack.GetHists()])), 'l'))
    if statErrBand and drawStatErr:
        statErrBand.SetFillStyle(3006)
        leg._reversedEntries.append((statErrBand, 'stat', 'f'))
    if systErrBand and drawSystErr:
        systErrBand.SetFillStyle(3007)
        leg._reversedEntries.append((systErrBand, 'syst', 'f'))
    leg._reversedEntries.append(
        (histoData, "Data {0}".format(prettify(topLabel)) if formatAuxMaterial
         else "{0}, {1:.2f}".format('data', integralWou(histoData)), 'p'))
    for h, g, o in leg._reversedEntries[::-1]:
        leg.AddEntry(h, g, o)  # stack goes b-t, legend goes t-b
    stack.Draw('hist same')
    histoData.SetMarkerStyle(r.kFullCircle)
    histoData.SetLineWidth(2)
    dataGraph = graphWithPoissonError(histoData)
    dataGraph.Draw('same p')
    isRightSignal = False
    if histoSignal:
        histoSignal.SetFillStyle(0)
        histoSignal.SetFillColor(0)
        histoSignal.SetLineColor(getGroupColor('signal'))
        histoSignal.SetLineWidth(3)
        isRightSignal = (all(s in histoSignal.GetName()
                             for s in ['signaltaumu', 'sr_mue'])
                         or all(s in histoSignal.GetName()
                                for s in ['signaltaue', 'sr_emu']))
        if isRightSignal: histoSignal.Draw('histo same')
    if statErrBand and drawStatErr:
        statErrBand.SetFillStyle(3006)
        statErrBand.Draw('E2 same')
        leg.AddEntry(statErrBand, 'stat', 'f')
    if systErrBand and drawSystErr:
        systErrBand.SetFillStyle(3007)
        systErrBand.Draw('E2 same')
        leg.AddEntry(systErrBand, 'syst', 'f')
    totErrBand = systUtils.addErrorBandsInQuadrature(statErrBand, systErrBand)
    if totErrBand:
        totErrBand.Draw('E2 same')
        totErrBand.SetFillStyle(3005)
        leg.AddEntry(totErrBand, 'stat+syst', 'f')
        if printYieldSummary:
            print_total_error = False
            print(
                "{}:".format(topLabel if topLabel else dataGraph.GetName()) +
                (" expected {:.2f}^{{+{:.2f}}}_{{{:.2f}}}".format(
                    totErrBand.GetY()[0], totErrBand.GetErrorYhigh(0),
                    totErrBand.GetErrorYlow(0)) if print_total_error else
                 " expected {:.2f}^{{+{:.2f}}}_{{{:.2f}}} (stat) ^{{+{:.2f}}}_{{{:.2f}}} (syst)"
                 .format(totErrBand.GetY()[0],
                         statErrBand.GetErrorYhigh(0) if statErrBand else 0.0,
                         statErrBand.GetErrorYlow(0) if statErrBand else 0.0,
                         systErrBand.GetErrorYhigh(0) if systErrBand else 0.0,
                         systErrBand.GetErrorYlow(0) if systErrBand else 0.0))
                + " obs {:.2f}".format(dataGraph.GetY()[0]))
    if histoSignal and isRightSignal:
        hname = histoSignal.GetName()
        label = ('H#rightarrow#mu#tau' if 'signaltaumu' in hname else
                 'H#rightarrowe#tau' if 'signaltaue' in hname else 'signal')
        label = ("{}, BR=1%".format(label) if formatAuxMaterial else
                 "{}, BR=1%, {:.2f}".format(label, integralWou(histoSignal)))
        leg.AddEntry(histoSignal, label, 'l')
    leg.Draw('same')
    topPad.Update()
    tex = r.TLatex()
    tex.SetTextSize(0.5 * tex.GetTextSize())
    tex.SetNDC(True)
    label = "%s tot bkg : " % (can.GetName())
    label += "%.3f #pm %.3f (stat)" % (integralAndError(histoTotBkg))
    if systErrBand:
        sysUp, sysDo = systUtils.totalUpDownVariation(systErrBand)
        label += "#pm #splitline{%.3f}{%.3f} (syst)" % (sysUp, sysDo)
    if drawYieldAndError:
        tex.DrawLatex(0.10, 0.95, label)
        topPad.SetTopMargin(2.0 * topPad.GetTopMargin())
    atlasLabel = drawAtlasLabel(can,
                                align=13,
                                scale=0.75,
                                xpos=0.175 if formatAuxMaterial else 0.125,
                                ypos=0.945 if formatAuxMaterial else None,
                                public=True)
    if topLabel and not formatAuxMaterial:
        topRightLabel(can, topLabel, ypos=1.0)
    yMin, yMax = getMinMax(
        [histoData, dataGraph, histoTotBkg, histoSignal, totErrBand])
    padMaster.SetMinimum(0.0)
    padMaster.SetMaximum(1.1 * yMax)
    padMaster.GetXaxis().SetLabelSize(0)
    padMaster.GetXaxis().SetTitleSize(0)
    increaseAxisFont(padMaster.GetXaxis())
    increaseAxisFont(padMaster.GetYaxis())
    topPad.RedrawAxis()
    topPad.Update()  # force stack to create padMaster
    # draw bot (ratio)
    can.cd()
    botPad.Draw()
    botPad.cd()
    ratio = systUtils.buildAsymmRatioGraph(dataGraph, totErrBand)
    ratioPadMaster = padMaster.Clone(padMaster.GetName() + '_ratio')
    ratioPadMaster.SetDirectory(0)
    ratioPadMaster.Clear()
    yMin, yMax = 0.0, 2.0
    ratioPadMaster.SetMinimum(yMin)
    ratioPadMaster.SetMaximum(yMax)
    ratioPadMaster.SetStats(0)
    ratioPadMaster.Draw('axis')
    x_lo, x_hi = getXrange(ratioPadMaster)
    refLines = [referenceLine(x_lo, x_hi, y, y) for y in [0.5, 1.0, 1.5]]
    for l in refLines:
        l.Draw()
    err_band_r = systUtils.buildErrBandRatioGraph(totErrBand)
    err_band_r.Draw('E2 same')
    ratio.Draw('ep')
    xA, yA = ratioPadMaster.GetXaxis(), ratioPadMaster.GetYaxis()
    textScaleUp = 0.75 * 1.0 / botPad.GetHNDC()
    # if xaxis_title : xA.SetTitle(xaxis_title)
    yA.SetNdivisions(-104)
    yA.SetTitle('Data/Bkg')
    yA.CenterTitle()
    yA.SetTitleOffset(yA.GetTitleOffset() / textScaleUp)
    xA.SetTitleSize(
        yA.GetTitleSize())  # was set to 0 for padmaster, restore it
    xA.SetLabelSize(yA.GetLabelSize())
    for a in [xA, yA]:
        a.SetLabelSize(a.GetLabelSize() * textScaleUp)
        a.SetTitleSize(a.GetTitleSize() * textScaleUp)
    botPad._graphical_objects = [ratio, ratioPadMaster, err_band_r
                                 ] + refLines  # avoid garbage collection
    botPad.Update()
    can.Update()
    for ext in ['png', 'eps']:
        can.SaveAs(outdir + '/' + can.GetName() + '.' + ext)
def plotHistos(histoData=None, histoSignal=None, histoTotBkg=None, histosBkg={},
               statErrBand=None, systErrBand=None, # these are TGraphAsymmErrors
               canvasName='canvas', outdir='./', verbose=False,
               drawStatErr=False, drawSystErr=False,
               drawYieldAndError=False) :
    "Note: blinding can be required for only a subrange of the histo, so it is taken care of when filling"
    #setWhPlotStyle()
    setAtlasStyle()
    padMaster = histoData
    if verbose : print "plotting ",padMaster.GetName()
    can = r.TCanvas(canvasName, padMaster.GetTitle(), 800, 600)
    can.cd()
    can._hists = [padMaster]
    padMaster.Draw('axis')
    can.Update() # necessary to fool root's dumb object ownership of the stack
    stack = r.THStack('stack_'+padMaster.GetName(), '')
    r.SetOwnership(stack, False)
    can._hists.append(stack)
    leg = topRightLegend(can, 0.225, 0.325)
    can._leg = leg
    leg.SetBorderSize(0)
    leg._reversedEntries = []
    for group, histo in sortedAs(histosBkg, stackedGroups()) :
        histo.SetFillColor(getGroupColor(group))
        histo.SetLineWidth(2)
        histo.SetLineColor(r.kBlack)
        stack.Add(histo)
        can._hists.append(histo)
        leg._reversedEntries.append((histo, group, 'F'))
    for h, g, o in leg._reversedEntries[::-1] : leg.AddEntry(h, g, o) # stack goes b-t, legend goes t-b
    stack.Draw('hist same')
    histoData.SetMarkerStyle(r.kFullCircle)
    histoData.SetLineWidth(2)
    dataGraph = graphWithPoissonError(histoData)
    dataGraph.Draw('same p')
    if histoSignal :
        histoSignal.SetLineColor(getGroupColor('signal'))
        histoSignal.SetLineWidth(2)
        histoSignal.Draw('histo same')
        leg.AddEntry(histoSignal, '(m_{C1},m_{N1})=(130, 0)GeV', 'l')
    if statErrBand and drawStatErr :
        statErrBand.SetFillStyle(3006)
        statErrBand.Draw('E2 same')
        leg.AddEntry(statErrBand, 'stat', 'f')
    if systErrBand and drawSystErr :
        systErrBand.SetFillStyle(3007)
        systErrBand.Draw('E2 same')
        leg.AddEntry(systErrBand, 'syst', 'f')
    totErrBand = systUtils.addErrorBandsInQuadrature(statErrBand, systErrBand)
    if totErrBand :
        totErrBand.Draw('E2 same')
        totErrBand.SetFillStyle(3005)
        leg.AddEntry(totErrBand, 'stat+syst', 'f')
    leg.Draw('same')
    can.Update()
    tex = r.TLatex()
    tex.SetTextSize(0.5 * tex.GetTextSize())
    tex.SetNDC(True)
    label  = "%s tot bkg : "%(can.GetName())
    label += "%.3f #pm %.3f (stat)"%(integralAndError(histoTotBkg))
    if systErrBand :
        sysUp, sysDo = systUtils.totalUpDownVariation(systErrBand)
        label += "#pm #splitline{%.3f}{%.3f} (syst)"%(sysUp, sysDo)
    if drawYieldAndError :
        tex.DrawLatex(0.10, 0.95, label)
        can.SetTopMargin(2.0*can.GetTopMargin())
    drawAtlasLabel(can, xpos=0.125, align=13)
    yMin, yMax = getMinMax([histoData, dataGraph, histoTotBkg, histoSignal, totErrBand])
    padMaster.SetMinimum(0.0)
    padMaster.SetMaximum(1.1 * yMax)
    increaseAxisFont(padMaster.GetXaxis())
    increaseAxisFont(padMaster.GetYaxis())
    can.RedrawAxis()
    can.Update() # force stack to create padMaster
    for ext in ['png','eps'] : can.SaveAs(outdir+'/'+can.GetName()+'.'+ext)