Example #1
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'))
def drawBottom(pad, totBkg, bkgHistos, sigHisto, llnjvar) :
    pad.cd()
    totBkg.SetStats(False)
    totBkg.SetMinimum(0.) # force this to avoid negative fluct due to fake
    totBkg.Draw('axis')
    pad.Update() # necessary to fool root's dumb object ownership
    stack = r.THStack('stack_'+llnjvar,'')
    pad.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')
    pad.Update()
    sigHisto.SetLineColor(r.kRed)
    sigHisto.SetLineWidth(2*sigHisto.GetLineWidth())
    sigHisto.Draw('same')
    pad.Update()
    topRightLabel(pad, llnjvar, xpos=0.125, align=13)
    drawLegendWithDictKeys(pad, dictSum(bkgHistos, {'signal' : sigHisto}), opt='f')
    pad.RedrawAxis()
    pad._stack = stack
    pad._histos = [h for h in stack.GetHists()]
    pad.Update()
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)
def plotHistRatioAndFit(histos, ratio, fitfunc, outfname, graphics_attributes={}) :
    can = r.TCanvas('can_'+outfname, outfname, 800, 600)
    botPad, topPad = buildBotTopPads(can, splitFraction=0.35)
    can.cd()
    topPad.Draw()
    topPad.cd()
    pm = first(histos)
    pm.Draw('axis')
    xAx, yAx = pm.GetXaxis(), pm.GetYaxis()
    xAx.SetTitle('')
    xAx.SetLabelSize(0)
    yAx.SetRangeUser(0.0, 1.2)
    yAx.SetNdivisions(505) # for some reason some of the inputs are already ratios with -201
    textScaleUp = 1.0/topPad.GetHNDC()
    yAx.SetLabelSize(textScaleUp*0.04)
    yAx.SetTitleSize(textScaleUp*0.04)
    yAx.SetTitle(graphics_attributes['ytitle'])
    yAx.SetTitleOffset(yAx.GetTitleOffset()/textScaleUp)
    for k, h in histos.iteritems() :
        h.SetMarkerStyle(graphics_attributes['markers'][k])
        h.SetMarkerColor(graphics_attributes['colors'][k]) 
        h.SetLineColor(graphics_attributes['colors'][k])
        h.Draw('same')
    labels = graphics_attributes['labels']
    drawLegendWithDictKeys(topPad, dict([(labels[s], histos[s]) for s in histos.keys()]), legWidth=0.4)
    can.cd()
    botPad.Draw()
    botPad.cd()
    ratio.Draw('axis')
    textScaleUp = 1.0/botPad.GetHNDC()
    xAx, yAx = ratio.GetXaxis(), ratio.GetYaxis()
    yAx.SetRangeUser(0.0, 2.0)
    xAx.SetTitle(graphics_attributes['xtitle'])
    yAx.SetNdivisions(-202)
    yAx.SetTitle('Data/Sim')
    yAx.CenterTitle()
    for a in [xAx, yAx] :
        if a.GetLabelSize()>0.04 : continue
        a.SetLabelSize(a.GetLabelSize()*textScaleUp)
        a.SetTitleSize(a.GetTitleSize()*textScaleUp)
        a.SetTitleOffset(a.GetTitleOffset()/textScaleUp)
    ratio.SetMarkerStyle(graphics_attributes['markers']['data'])
    fitfunc.SetLineWidth(2)
    fitfunc.SetLineStyle(2)
    fitfunc.Draw('same')
    ratio.Draw('same')
    tex = r.TLatex()
    tex.SetNDC(True)
    p0, p0Err, chi2, ndf = fitResults(fitfunc)
    fitParLabel = "Const. fit : %s #pm %s"%(pdgRound(p0, p0Err))
    fitGoodLabel = "#chi^{2}/DOF : %.2f / %d"%(chi2, ndf)
    tex.SetTextSize(yAx.GetTitleSize())
    tex.SetTextFont(yAx.GetTitleFont())
    tex.DrawLatex(0.15, 0.40, "#splitline{%s}{%s}"%(fitParLabel, fitGoodLabel))
    can.Update()
    outfname = outfname+'.png'
    rmIfExists(outfname) # avoid root warnings
    can.SaveAs(outfname)
def plotStackedHistos(histosPerGroup={}, outputDir='', region='', verbose=False):
    groups = histosPerGroup.keys()
    variables = first(histosPerGroup).keys()
    leptonTypes = first(first(histosPerGroup)).keys()
    colors = getGroupColor()
    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 g not in ['data', 'signal']])
        totBkg = summedHisto(bkgHistos.values())
        err_band = None # 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]) # fixme with err_band
        yMin, yMax = 0.0, data.GetMaximum()
        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')
        drawLegendWithDictKeys(can, bkgHistos, 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 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)
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 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)
Example #10
0
def plotComparison(histo1, histo2, canvas, outname, label1, label2, verbose):
    h1, h2 = histo1, histo2
    if not h1.Integral() and not h2.Integral(): return
    canvas.cd()
    canvas.Clear()
    h1.SetMarkerColor(r.kBlack)
    h2.SetMarkerColor(r.kRed)
    h1.SetMarkerStyle(r.kFullCircle)
    h2.SetMarkerStyle(r.kOpenCircle)
    h1.SetMaximum(1.1 * max([h.GetMaximum() for h in [h1, h2]]))
    h1.SetStats(0)
    h1.SetStats(0)
    h1.Draw()
    h2.Draw('same')
    ks = h1.KolmogorovTest(h2) if h2.Integral() and h1.Integral() else 0.0
    leg = drawLegendWithDictKeys(canvas, {
        label1: h1,
        label2: h2,
    },
                                 legWidth=0.35,
                                 legHeight=0.275)
    header = "%s : KS=%.3f" % (h1.GetName(), ks)
    leg.SetHeader(header)
    if ks < 0.05: print header
    canvas.Update()
    canvas.SaveAs(outname + '.png')
    if verbose: print "saving %s" % outname
def plotComparison(histo1, histo2, canvas, outname, label1, label2, verbose) :
    h1, h2 = histo1, histo2
    if not h1.Integral() and not h2.Integral() : return
    canvas.cd()
    canvas.Clear()
    h1.SetMarkerColor(r.kBlack)
    h2.SetMarkerColor(r.kRed)
    h1.SetMarkerStyle(r.kFullCircle)
    h2.SetMarkerStyle(r.kOpenCircle)
#     h1.SetMaximum(1.1*max([h.GetMaximum() for h in [h1, h2]]))
#     h1.SetMinimum(0.5*max([h.GetMinimum() for h in [h1, h2]]))
    h1.SetMaximum(1.1)
    h1.SetMinimum(0.0)
    h1.SetStats(0)
    h1.SetStats(0)
    h1.Draw()
    h2.Draw('same')
    ks = h1.KolmogorovTest(h2) if h2.Integral() and h1.Integral() else 0.0
    leg = drawLegendWithDictKeys(canvas, {label1 : h1, label2 : h2, },
                                 legWidth=0.35, legHeight=0.275)
    header = "%s : KS=%.3f"%(h1.GetName(), ks)
    leg.SetHeader(header)
    if ks<0.05 : print header
    canvas.Update()
    canvas.SaveAs(outname+'.png')
    if verbose : print "saving %s"%outname
Example #12
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'))
def plotHistos(histos1=[], histos2=[], histosRatio=[], label1='label1', label2='label2',
               canvas=None, canPrefix='', scaleXlabelsBot=1.0,
               colors={}, markers={},lineStyle1=1, lineStyle2=2, splitFraction=0.80) :
    "Assume again that the histos are in dict[sample]"
    can = canvas if canvas is not None else r.TCanvas(canPrefix+'percent_histos','')
    can.Clear()    
    can.cd()
    padTop, padBot = getPad(can, splitFraction, top=True), getPad(can, splitFraction, bot=True)
    # top pad with ratios
    can.cd()
    padTop.Draw()
    padTop.cd()
    markersr = dict(zip(colors.keys(), len(colors.keys())*[r.kOpenDiamond]))
    for h in histosRatio.values() :
        yAx = h.GetYaxis()
        yAx.SetRangeUser(0.0, 2.0)
        yAx.SetNdivisions(-202)
        yAx.SetLabelSize(1.0/(1.0-splitFraction)*yAx.GetLabelSize())
        h.SetTitle('')
        h.SetStats(0)
    #print 'fh: ',firstHisto(histos1).GetName(),' nratios :',len(histosRatio) # debug
    def bc(h) : return ["%.2f"%h.GetBinContent(b) for b in xrange(1, h.GetNbinsX()+1)]
    # print '\n'.join(["%s : %s"%(s, bc(h)) for s,h in histosRatio.iteritems()]) # debug 
    draw(padTop, histosRatio, colors, markersr, asFirst=True)
    drawUnitLine(padTop, histosRatio)
    labelR = "%s/%s ratio"%(label1[0], label2[0])
    drawLegendWithDictKeys(padTop, {label1 : firstHisto(histos1),
                                    label2 : firstHisto(histos2),
                                    labelR : firstHisto(histosRatio)
                                    },
                            legWidth=0.225, legHeight=0.75)
    # bot pad with histos
    can.cd()    
    padBot.Draw()
    padBot.cd()
    markers1 = dict(zip(colors.keys(), len(colors.keys())*[r.kOpenTriangleUp]))
    markers2 = dict(zip(colors.keys(), len(colors.keys())*[r.kOpenTriangleDown]))
    for h in histos1.values()+histos2.values() :
        h.GetYaxis().SetRangeUser(0.0, 1.08)
        h.GetXaxis().SetLabelSize(scaleXlabelsBot*h.GetXaxis().GetLabelSize())
        h.SetStats(0)
    draw(padBot, histos1, colors, markers1, lineStyle1)
    draw(padBot, histos2, colors, markers2, lineStyle2, asFirst=False)
    drawLegendWithDictKeys(padBot, histos1, legWidth=0.225)
    padBot.Update()
    return can
def plotHistos(histos1=[], histos2=[], histosRatio=[], label1='label1', label2='label2',
               canvas=None, canPrefix='', scaleXlabelsBot=1.0,
               colors={}, markers={},lineStyle1=1, lineStyle2=2, splitFraction=0.80) :
    "Assume again that the histos are in dict[sample]"
    can = canvas if canvas is not None else r.TCanvas(canPrefix+'percent_histos','')
    can.Clear()    
    can.cd()
    padTop, padBot = getPad(can, splitFraction, top=True), getPad(can, splitFraction, bot=True)
    # top pad with ratios
    can.cd()
    padTop.Draw()
    padTop.cd()
    markersr = dict(zip(colors.keys(), len(colors.keys())*[r.kOpenDiamond]))
    for h in histosRatio.values() :
        yAx = h.GetYaxis()
        yAx.SetRangeUser(0.0, 2.0)
        yAx.SetNdivisions(-202)
        yAx.SetLabelSize(1.0/(1.0-splitFraction)*yAx.GetLabelSize())
        h.SetTitle('')
        h.SetStats(0)
    #print 'fh: ',firstHisto(histos1).GetName(),' nratios :',len(histosRatio) # debug
    def bc(h) : return ["%.2f"%h.GetBinContent(b) for b in xrange(1, h.GetNbinsX()+1)]
    # print '\n'.join(["%s : %s"%(s, bc(h)) for s,h in histosRatio.iteritems()]) # debug 
    draw(padTop, histosRatio, colors, markersr, asFirst=True)
    drawUnitLine(padTop, histosRatio)
    labelR = "%s/%s ratio"%(label1[0], label2[0])
    drawLegendWithDictKeys(padTop, {label1 : firstHisto(histos1),
                                    label2 : firstHisto(histos2),
                                    labelR : firstHisto(histosRatio)
                                    },
                            legWidth=0.225, legHeight=0.75)
    # bot pad with histos
    can.cd()    
    padBot.Draw()
    padBot.cd()
    markers1 = dict(zip(colors.keys(), len(colors.keys())*[r.kOpenTriangleUp]))
    markers2 = dict(zip(colors.keys(), len(colors.keys())*[r.kOpenTriangleDown]))
    for h in histos1.values()+histos2.values() :
        h.GetYaxis().SetRangeUser(0.0, 1.08)
        h.GetXaxis().SetLabelSize(scaleXlabelsBot*h.GetXaxis().GetLabelSize())
        h.SetStats(0)
    draw(padBot, histos1, colors, markers1, lineStyle1)
    draw(padBot, histos2, colors, markers2, lineStyle2, asFirst=False)
    drawLegendWithDictKeys(padBot, histos1, legWidth=0.225)
    padBot.Update()
    return can
def plot(histos, var) :
    c = r.TCanvas('c_'+var,'')
    c.cd()
    pm = first(histos)
    pm.SetMaximum(1.1*max([h.GetMaximum() for h in histos.values()]))
    pm.Draw('axis')
    markers = dict(zip(histos.keys(),
                       [r.kPlus, r.kCircle, r.kMultiply, r.kOpenSquare, r.kOpenTriangleUp, r.kOpenTriangleDown]))
    for s,h in histos.iteritems() :
        h.SetLineColor(colors[s] if s in colors else r.kBlack)
        h.SetMarkerColor(h.GetLineColor())
        h.SetLineWidth(2*h.GetLineWidth())
        h.SetMarkerStyle(markers[s])
        h.Draw('same')
    leg = drawLegendWithDictKeys(c, histos)
    leg.Draw()
    c.Update()
    c.SaveAs(var+'.png')
Example #16
0
def plot(histos, var):
    c = r.TCanvas('c_' + var, '')
    c.cd()
    pm = first(histos)
    pm.SetMaximum(1.1 * max([h.GetMaximum() for h in histos.values()]))
    pm.Draw('axis')
    markers = dict(
        zip(histos.keys(), [
            r.kPlus, r.kCircle, r.kMultiply, r.kOpenSquare, r.kOpenTriangleUp,
            r.kOpenTriangleDown
        ]))
    for s, h in histos.iteritems():
        h.SetLineColor(colors[s] if s in colors else r.kBlack)
        h.SetMarkerColor(h.GetLineColor())
        h.SetLineWidth(2 * h.GetLineWidth())
        h.SetMarkerStyle(markers[s])
        h.Draw('same')
    leg = drawLegendWithDictKeys(c, histos)
    leg.Draw()
    c.Update()
    c.SaveAs(var + '.png')
def plotHistRatioAndFit(histos,
                        ratio,
                        fitfunc,
                        outfname,
                        graphics_attributes={}):
    can = r.TCanvas('can_' + outfname, outfname, 800, 600)
    botPad, topPad = buildBotTopPads(can, splitFraction=0.35)
    can.cd()
    topPad.Draw()
    topPad.cd()
    pm = first(histos)
    pm.Draw('axis')
    xAx, yAx = pm.GetXaxis(), pm.GetYaxis()
    xAx.SetTitle('')
    xAx.SetLabelSize(0)
    yAx.SetRangeUser(0.0, 1.2)
    yAx.SetNdivisions(
        505)  # for some reason some of the inputs are already ratios with -201
    textScaleUp = 1.0 / topPad.GetHNDC()
    yAx.SetLabelSize(textScaleUp * 0.04)
    yAx.SetTitleSize(textScaleUp * 0.04)
    yAx.SetTitle(graphics_attributes['ytitle'])
    yAx.SetTitleOffset(yAx.GetTitleOffset() / textScaleUp)
    for k, h in histos.iteritems():
        h.SetMarkerStyle(graphics_attributes['markers'][k])
        h.SetMarkerColor(graphics_attributes['colors'][k])
        h.SetLineColor(graphics_attributes['colors'][k])
        h.Draw('same')
    labels = graphics_attributes['labels']
    drawLegendWithDictKeys(topPad,
                           dict([(labels[s], histos[s])
                                 for s in histos.keys()]),
                           legWidth=0.4)
    can.cd()
    botPad.Draw()
    botPad.cd()
    ratio.Draw('axis')
    textScaleUp = 1.0 / botPad.GetHNDC()
    xAx, yAx = ratio.GetXaxis(), ratio.GetYaxis()
    yAx.SetRangeUser(0.0, 2.0)
    xAx.SetTitle(graphics_attributes['xtitle'])
    yAx.SetNdivisions(-202)
    yAx.SetTitle('Data/Sim')
    yAx.CenterTitle()
    for a in [xAx, yAx]:
        if a.GetLabelSize() > 0.04: continue
        a.SetLabelSize(a.GetLabelSize() * textScaleUp)
        a.SetTitleSize(a.GetTitleSize() * textScaleUp)
        a.SetTitleOffset(a.GetTitleOffset() / textScaleUp)
    ratio.SetMarkerStyle(graphics_attributes['markers']['data'])
    fitfunc.SetLineWidth(2)
    fitfunc.SetLineStyle(2)
    fitfunc.Draw('same')
    ratio.Draw('same')
    tex = r.TLatex()
    tex.SetNDC(True)
    p0, p0Err, chi2, ndf = fitResults(fitfunc)
    fitParLabel = "Const. fit : %s #pm %s" % (pdgRound(p0, p0Err))
    fitGoodLabel = "#chi^{2}/DOF : %.2f / %d" % (chi2, ndf)
    tex.SetTextSize(yAx.GetTitleSize())
    tex.SetTextFont(yAx.GetTitleFont())
    tex.DrawLatex(0.15, 0.40,
                  "#splitline{%s}{%s}" % (fitParLabel, fitGoodLabel))
    can.Update()
    outfname = outfname + '.png'
    rmIfExists(outfname)  # avoid root warnings
    can.SaveAs(outfname)
def subtractRealAndComputeScaleFactor(histosPerGroup={}, variable='', outRatiohistoname='',outDataeffhistoname='',
                                      outputDir='./', region='', subtractReal=True, verbose=False):
    "efficiency scale factor"
    groups = histosPerGroup.keys()
    mkdirIfNeeded(outputDir)
    histosPerType = dict([(lt,
                           dict([(g,
                                  histosPerGroup[g][variable][lt])
                                 for g in groups]))
                          for lt in leptonTypes])
    for lt in leptonTypes :
        histosPerType[lt]['totSimBkg'] = summedHisto([histo for group,histo in histosPerType[lt].iteritems()
                                                      if group not in ['data', 'signal']])

    simuTight = histosPerType['fake_tight']['totSimBkg']
    simuLoose = histosPerType['fake_loose']['totSimBkg']
    dataTight = histosPerType['tight'     ]['data'     ]
    dataLoose = histosPerType['loose'     ]['data'     ]
    # subtract real contribution from data
    # _Note to self_: currently estimating the real contr from MC; in
    # the past also used iterative corr, which might be more
    # appropriate in cases like here, where the normalization is
    # so-so.  Todo: investigate the normalization.
    dataSubTight = dataTight.Clone(dataTight.GetName().replace('data_tight','data_minus_prompt_tight'))
    dataSubLoose = dataLoose.Clone(dataLoose.GetName().replace('data_loose','data_minus_prompt_loose'))
    dataSubTight.SetDirectory(0)
    dataSubLoose.SetDirectory(0)
    dataSubTight.Add(histosPerType['real_tight']['totSimBkg'], -1.0 if subtractReal else 0.0)
    dataSubLoose.Add(histosPerType['real_loose']['totSimBkg'], -1.0 if subtractReal else 0.0)
    effData = dataSubTight.Clone(outDataeffhistoname)
    effData.SetDirectory(0)
    effData.Divide(dataSubLoose)
    effSimu = simuTight.Clone(simuTight.GetName().replace('fake_tight','fake_eff'))
    effSimu.SetDirectory(0)
    effSimu.Divide(simuLoose)
    print "eff(T|L) vs. ",variable
    def formatFloat(floats): return ["%.4f"%f for f in floats]
    print "efficiency data : ",formatFloat(getBinContents(effData))
    print "efficiency simu : ",formatFloat(getBinContents(effSimu))
    ratio = effData.Clone(outRatiohistoname)
    ratio.SetDirectory(0)
    ratio.Divide(effSimu)
    print "sf    data/simu : ",formatFloat(getBinContents(ratio))
    print "            +/- : ",formatFloat(getBinErrors(ratio))
    can = r.TCanvas('c_'+outRatiohistoname, outRatiohistoname, 800, 600)
    botPad, topPad = rootUtils.buildBotTopPads(can)
    can.cd()
    topPad.Draw()
    topPad.cd()
    pm = effData
    pm.SetStats(0)
    pm.Draw('axis')
    xAx, yAx = pm.GetXaxis(), pm.GetYaxis()
    xAx.SetTitle('')
    xAx.SetLabelSize(0)
    yAx.SetRangeUser(0.0, 0.25)
    textScaleUp = 1.0/topPad.GetHNDC()
    yAx.SetLabelSize(textScaleUp*0.04)
    yAx.SetTitleSize(textScaleUp*0.04)
    yAx.SetTitle('#epsilon(T|L)')
    yAx.SetTitleOffset(yAx.GetTitleOffset()/textScaleUp)
    effSimu.SetLineColor(r.kRed)
    effSimu.SetMarkerStyle(r.kOpenCross)
    effSimu.SetMarkerColor(effSimu.GetLineColor())
    effData.Draw('same')
    effSimu.Draw('same')
    leg = drawLegendWithDictKeys(topPad, {'data':effData, 'simulation':simuTight}, legWidth=0.4)
    leg.SetHeader('scale factor '+region+' '+('electron' if '_el_'in outRatiohistoname else
                                              'muon' if '_mu_' in outRatiohistoname else ''))
    can.cd()
    botPad.Draw()
    botPad.cd()
    ratio.SetStats(0)
    ratio.Draw()
    textScaleUp = 1.0/botPad.GetHNDC()
    xAx, yAx = ratio.GetXaxis(), ratio.GetYaxis()
    yAx.SetRangeUser(0.0, 2.0)
    xAx.SetTitle({'pt1':'p_{T}', 'eta1':'|#eta|', 'pt1_eta1':'p_{T}'}[variable])
    yAx.SetNdivisions(-202)
    yAx.SetTitle('Data/Sim')
    yAx.CenterTitle()
    xAx.SetLabelSize(textScaleUp*0.04)
    xAx.SetTitleSize(textScaleUp*0.04)
    yAx.SetLabelSize(textScaleUp*0.04)
    yAx.SetTitleSize(textScaleUp*0.04)
    refLine = rootUtils.referenceLine(xAx.GetXmin(), xAx.GetXmax())
    refLine.Draw()
    can.Update()
    outFname = os.path.join(outputDir, region+'_'+outRatiohistoname)
    for ext in ['.eps','.png']:
        utils.rmIfExists(outFname+ext)
        can.SaveAs(outFname+ext)
    return {outRatiohistoname : ratio,
            outDataeffhistoname : effData,
            outDataeffhistoname.replace('_fake_rate_data_', '_tight_data_minus_prompt') : dataSubTight,
            outDataeffhistoname.replace('_fake_rate_data_', '_loose_data_minus_prompt') : dataSubLoose
            }
def plotStackedHistos(histosPerGroup={},
                      outputDir='',
                      region='',
                      verbose=False):
    groups = histosPerGroup.keys()
    variables = first(histosPerGroup).keys()
    leptonTypes = first(first(histosPerGroup)).keys()
    colors = getGroupColor()
    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 g not in ['data', 'signal']])
        totBkg = summedHisto(bkgHistos.values())
        err_band = None  # 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]) # fixme with err_band
        yMin, yMax = 0.0, data.GetMaximum()
        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')
        drawLegendWithDictKeys(can, bkgHistos, 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 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)
def subtractRealAndComputeScaleFactor(histosPerGroup={},
                                      variable='',
                                      outRatiohistoname='',
                                      outDataeffhistoname='',
                                      outputDir='./',
                                      region='',
                                      subtractReal=True,
                                      verbose=False):
    "efficiency scale factor"
    groups = histosPerGroup.keys()
    mkdirIfNeeded(outputDir)
    histosPerType = dict([(lt,
                           dict([(g, histosPerGroup[g][variable][lt])
                                 for g in groups])) for lt in leptonTypes])
    for lt in leptonTypes:
        histosPerType[lt]['totSimBkg'] = summedHisto([
            histo for group, histo in histosPerType[lt].iteritems()
            if group not in ['data', 'signal']
        ])

    simuTight = histosPerType['fake_tight']['totSimBkg']
    simuLoose = histosPerType['fake_loose']['totSimBkg']
    dataTight = histosPerType['tight']['data']
    dataLoose = histosPerType['loose']['data']
    # subtract real contribution from data
    # _Note to self_: currently estimating the real contr from MC; in
    # the past also used iterative corr, which might be more
    # appropriate in cases like here, where the normalization is
    # so-so.  Todo: investigate the normalization.
    dataSubTight = dataTight.Clone(dataTight.GetName().replace(
        'data_tight', 'data_minus_prompt_tight'))
    dataSubLoose = dataLoose.Clone(dataLoose.GetName().replace(
        'data_loose', 'data_minus_prompt_loose'))
    dataSubTight.SetDirectory(0)
    dataSubLoose.SetDirectory(0)
    dataSubTight.Add(histosPerType['real_tight']['totSimBkg'],
                     -1.0 if subtractReal else 0.0)
    dataSubLoose.Add(histosPerType['real_loose']['totSimBkg'],
                     -1.0 if subtractReal else 0.0)
    effData = dataSubTight.Clone(outDataeffhistoname)
    effData.SetDirectory(0)
    effData.Divide(dataSubLoose)
    effSimu = simuTight.Clone(simuTight.GetName().replace(
        'fake_tight', 'fake_eff'))
    effSimu.SetDirectory(0)
    effSimu.Divide(simuLoose)
    print "eff(T|L) vs. ", variable

    def formatFloat(floats):
        return ["%.4f" % f for f in floats]

    print "efficiency data : ", formatFloat(getBinContents(effData))
    print "efficiency simu : ", formatFloat(getBinContents(effSimu))
    ratio = effData.Clone(outRatiohistoname)
    ratio.SetDirectory(0)
    ratio.Divide(effSimu)
    print "sf    data/simu : ", formatFloat(getBinContents(ratio))
    print "            +/- : ", formatFloat(getBinErrors(ratio))
    can = r.TCanvas('c_' + outRatiohistoname, outRatiohistoname, 800, 600)
    botPad, topPad = rootUtils.buildBotTopPads(can)
    can.cd()
    topPad.Draw()
    topPad.cd()
    pm = effData
    pm.SetStats(0)
    pm.Draw('axis')
    xAx, yAx = pm.GetXaxis(), pm.GetYaxis()
    xAx.SetTitle('')
    xAx.SetLabelSize(0)
    yAx.SetRangeUser(0.0, 0.25)
    textScaleUp = 1.0 / topPad.GetHNDC()
    yAx.SetLabelSize(textScaleUp * 0.04)
    yAx.SetTitleSize(textScaleUp * 0.04)
    yAx.SetTitle('#epsilon(T|L)')
    yAx.SetTitleOffset(yAx.GetTitleOffset() / textScaleUp)
    effSimu.SetLineColor(r.kRed)
    effSimu.SetMarkerStyle(r.kOpenCross)
    effSimu.SetMarkerColor(effSimu.GetLineColor())
    effData.Draw('same')
    effSimu.Draw('same')
    leg = drawLegendWithDictKeys(topPad, {
        'data': effData,
        'simulation': simuTight
    },
                                 legWidth=0.4)
    leg.SetHeader('scale factor ' + region + ' ' +
                  ('electron' if '_el_' in outRatiohistoname else
                   'muon' if '_mu_' in outRatiohistoname else ''))
    can.cd()
    botPad.Draw()
    botPad.cd()
    ratio.SetStats(0)
    ratio.Draw()
    textScaleUp = 1.0 / botPad.GetHNDC()
    xAx, yAx = ratio.GetXaxis(), ratio.GetYaxis()
    yAx.SetRangeUser(0.0, 2.0)
    xAx.SetTitle({
        'pt1': 'p_{T}',
        'eta1': '|#eta|',
        'pt1_eta1': 'p_{T}'
    }[variable])
    yAx.SetNdivisions(-202)
    yAx.SetTitle('Data/Sim')
    yAx.CenterTitle()
    xAx.SetLabelSize(textScaleUp * 0.04)
    xAx.SetTitleSize(textScaleUp * 0.04)
    yAx.SetLabelSize(textScaleUp * 0.04)
    yAx.SetTitleSize(textScaleUp * 0.04)
    refLine = rootUtils.referenceLine(xAx.GetXmin(), xAx.GetXmax())
    refLine.Draw()
    can.Update()
    outFname = os.path.join(outputDir, region + '_' + outRatiohistoname)
    for ext in ['.eps', '.png']:
        utils.rmIfExists(outFname + ext)
        can.SaveAs(outFname + ext)
    return {
        outRatiohistoname:
        ratio,
        outDataeffhistoname:
        effData,
        outDataeffhistoname.replace('_fake_rate_data_', '_tight_data_minus_prompt'):
        dataSubTight,
        outDataeffhistoname.replace('_fake_rate_data_', '_loose_data_minus_prompt'):
        dataSubLoose
    }