Ejemplo n.º 1
0
def test_stack():
    stack = HistStack()
    assert_equal(len(stack), 0)
    stack.Add(Hist(10, 0, 1, fillstyle='solid', color='red'))
    stack.Add(Hist(10, 0, 1, fillstyle='solid', color='blue'))
    stack.Add(Hist(10, 0, 1, fillstyle='solid', color='green'))
    assert_equal(len(stack), 3)
    stack2 = stack.Clone()
    assert_equal(stack2[2].linecolor, 'green')

    # test stacked=True
    a = Hist(2, 0, 1)
    b = Hist(2, 0, 1)
    a.Fill(0.2)
    b.Fill(0.2)
    b.Fill(0.8, 5)
    stack = HistStack([a, b])
    assert_equal(stack.min(), 2)
    assert_equal(stack.max(), 5)

    # test stacked=False
    a = Hist(2, 0, 20)
    b = Hist(2, 10, 20)  # binning may be different
    a.Fill(0.2)
    b.Fill(15, 5)
    stack = HistStack([a, b], stacked=False)
    assert_equal(stack.min(), 0)
    assert_equal(stack.max(), 5)
Ejemplo n.º 2
0
def test_stack():
    stack = HistStack()
    stack.Add(Hist(10, 0, 1, fillstyle='solid', color='red'))
    stack.Add(Hist(10, 0, 1, fillstyle='solid', color='blue'))
    stack.Add(Hist(10, 0, 1, fillstyle='solid', color='green'))
    assert_equal(len(stack), 3)
    stack2 = stack.Clone()
    assert_equal(stack2[2].linecolor, 'green')
Ejemplo n.º 3
0
def make_control_region_data_mc_comparision(
        histograms,
        histogram_name,
        variable,
        x_label=r'$m(\mathrm{t}\bar{\mathrm{t}})$ [GeV]',
        x_min=300,
        x_max=1800,
        y_label='Events/50 GeV'):
    qcd = histograms['QCD'][histogram_name]
    ttjet = histograms['TTJet'][histogram_name]
    wjets = histograms['WJets'][histogram_name]
    zjets = histograms['ZJets'][histogram_name]
    single_top = histograms['SingleTop'][histogram_name]
    other = ttjet + wjets + zjets + single_top
    data = histograms['data'][histogram_name]
    data.SetMarkerSize(3)
    qcd.SetTitle('QCD from data')
    other.SetTitle('Combined other background')
    data.SetTitle('Data')

    qcd.fillcolor = 'yellow'
    other.fillcolor = 'red'

    qcd.fillstyle = 'solid'
    other.fillstyle = 'solid'
    stack = HistStack()
    stack.Add(other)
    stack.Add(qcd)

    # plot with matplotlib
    plt.figure(figsize=(16, 12), dpi=200, facecolor='white')
    axes = plt.axes()

    rplt.hist(stack, stacked=True, axes=axes)
    rplt.errorbar(data, xerr=None, emptybins=False, axes=axes)

    plt.xlabel(x_label, CMS.x_axis_title)
    plt.ylabel(y_label, CMS.y_axis_title)
    plt.tick_params(**CMS.axis_label_major)
    plt.tick_params(**CMS.axis_label_minor)
    plt.title(get_title(variable), CMS.title)
    plt.legend(numpoints=1, loc='upper right', prop=CMS.legend_properties)
    axes.set_xlim(xmin=x_min, xmax=x_max)
    axes.set_ylim(ymin=0)
    plt.tight_layout()
    plt.savefig(variable + '.png')
    plt.savefig(variable + '.pdf')
Ejemplo n.º 4
0
map(h3.Fill, x1_obs)
map(h3.Fill, x2_obs)

# set visual attributes
h1.fillstyle = 'solid'
h1.fillcolor = 'green'
h1.linecolor = 'green'
h1.linewidth = 0

h2.fillstyle = 'solid'
h2.fillcolor = 'red'
h2.linecolor = 'red'
h2.linewidth = 0

stack = HistStack()
stack.Add(h1)
stack.Add(h2)

ratio = h3 / (h1 + h2)
ratio = Hist.divide(h3, h1 + h2)

# plot with matplotlib
plt.figure(figsize=(16, 12), dpi=200)
gs = gridspec.GridSpec(2, 1, height_ratios=[5, 1])
axes = plt.axes()
ax0 = plt.subplot(gs[0])
ax0.minorticks_on()
rplt.bar(stack, stacked=True)
rplt.errorbar(h3, xerr=False, emptybins=False)
# plt.xlabel('Mass', position=(1., 0.), ha='right', fontsize = 24)
plt.ylabel('Events', va='top', fontsize=40)
Ejemplo n.º 5
0
set_style('ATLAS')

mus = (0, -1, 2)
sigmas = (2, 1, 0.5)
events = (1000, 2000, 100)
colors = ('lawngreen', 'forestgreen', 'mistyrose')
styles = ('\\', '/', '-')

canvas = Canvas()
objects = []

# create a stack
stack = HistStack()
stack.Add(
    Hist(100, -5, 5, color='salmon',
         drawstyle='hist').FillRandom(F1('TMath::Gaus(x, 2, 1)'), 500))
stack.Add(
    Hist(100, -5, 5, color='powderblue',
         drawstyle='hist').FillRandom(F1('TMath::Gaus(x, 2, 0.6)'), 300))
objects.append(stack)

# create some random histograms
for i, (mu, sigma, n, c,
        s) in enumerate(zip(mus, sigmas, events, colors, styles)):
    hist = Hist(100,
                -5,
                5,
                color=c,
                fillstyle=s,
                drawstyle='hist' if i % 2 == 0 else '')
Ejemplo n.º 6
0
            compressed = background.CompressedAnalysis
            print compressed
            histname = "hist" + rootfile
            histogram = histname + "(" + nbins + "," + xmin + "," + xmax + ")"

            histname = compressed.Draw(variable + ">>" + histogram,
                                       selection=weight * total,
                                       drawstyle='hist',
                                       fillstyle='solid',
                                       linecolor='black',
                                       fillcolor=color)
            print histname
            print background_name
            legend.AddEntry(histname, label=background_name,
                            style='F')  #was label=background_name
            stack.Add(histname)

    #=================== DATA SAMPLES ====================================#
    objects = []
    dataobjects = []
    for (datafilename, data_weight, data_bool) in zip(data_list,
                                                      data_weight_list,
                                                      data_bool_list):
        print datafilename, data_weight, data_bool
        if data_bool == "Plot":
            print "datafilename: ", datafilename
            data = root_open(data_location + "/" + datafilename)
            treesSR = data.CompressedAnalysis
            datacut = total
            if data_weight != "1":
                print "WARNING: DATA WEIGHT IS NOT 1 PLEASE CHECK IF YOU DO NOT INTEND TO WEIGHT THE DATA"
Ejemplo n.º 7
0
        #SelectionCriteria = Cut(Luminosity) * Cut(Weight) * total
        #histogram = Hist(nbins,xmin,xmax)   
        temphist   = treeDict[sample].Draw(variable, hist= Hist(nbins,xmin,xmax),selection = Cut(Luminosity) * Cut(Weight) * total)
        temphist = temphist.merge_bins([(0,1),  (nbins,nbins+1)  ])
        sampleStyleFunc(temphist,sample,sampleDictionary)

        backgroundstacks[LegendEntry].Add(temphist.Clone())


    skimmed = 1 

    for key in backgroundstacks:
        #print "key: " + str(key )
        if 'Data' not in key:
            if 'Signal' in key:continue
            stack.Add(backgroundstacks[key].sum.Clone())
        if 'Data' in key and not BLINDED :
            datastack.Add(backgroundstacks[key].sum.Clone())

  #  print "type of stack.mergebins" + str(type(stack.merge_bins([(nbins,nbins+1)])))
    if doBreakdown:
        cutflowstring, yieldstring = produceRegionBreakdown(backgroundstacks,stack,datastack,Region,CRlist,SRlist,VVCRlist,TOPCRlist,ABCDlist)
        print "[BREAKDOWN][PRODUCED]"
        print cutflowstring        
        print yieldstring 

    SetNegativeYieldsToZero(stack,nbins)
    
    print "[BEFORE DRAW]" + str(round(time.time() - t0,2)) + "seconds"

    drawBackgrounds(stack)
Ejemplo n.º 8
0
        # else:
        # 	# hists[sample].markersize = 1.2
        # 	pass

    outputROOTFile.cd()

    # print histsToStack[0].Integral()
    # print histsToStack
    sortedHistsToStack = sorted(histsToStack,
                                key=lambda x: x.Integral(),
                                reverse=False)
    # print sortedHistsToStack

    for tmphist in sortedHistsToStack:
        if tmphist.Integral():
            stack.Add(tmphist)

    try:
        stack.sum.Integral()
    except:
        print "stack has no integral!"
        continue

    if plotWithMPL:
        gs = mpl.gridspec.GridSpec(2, 1, height_ratios=[4, 1])
        gs.update(wspace=0.00, hspace=0.00)
        axes = plt.subplot(gs[0])
        axes_ratio = plt.subplot(gs[1], sharex=axes)
        plt.setp(axes.get_xticklabels(), visible=False)

    if plotWithROOT:
Ejemplo n.º 9
0
def stack(x, *args, **kwargs):

    ## parse arguments
    _data = kwargs.pop('data', None)
    _bkgs = kwargs.pop('bkgs', None)
    _sigs = kwargs.pop('sigs', None)
    _treename = kwargs.pop('treename', None)
    _datasearchpath = kwargs.pop('datasearchpath', None)
    _datadrivensearchpath = kwargs.pop('datadrivensearchpath', None)
    _bkgsearchpath = kwargs.pop('bkgsearchpath', None)
    _sigsearchpath = kwargs.pop('sigsearchpath', None)
    _lumi = kwargs.pop('lumi', None)

    global data
    global bkgs
    global sigs
    global treename
    global datasearchpath
    global datadrivensearchpath
    global bkgsearchpath
    global sigsearchpath
    global lumi

    data = _data or data
    bkgs = _bkgs or bkgs
    sigs = _sigs or sigs
    treename = _treename or treename
    datasearchpath = _datasearchpath or datasearchpath
    datadrivensearchpath = _datadrivensearchpath or datadrivensearchpath
    bkgsearchpath = _bkgsearchpath or bkgsearchpath
    sigsearchpath = _sigsearchpath or sigsearchpath
    if _lumi:
        lumi = float(_lumi)

    xtitle = kwargs.pop('xtitle', '')
    ytitle = kwargs.pop('ytitle', '')
    logx = bool(kwargs.pop('logx', False))
    logy = bool(kwargs.pop('logy', False))
    blind = kwargs.pop('blind', None)
    has_blinded_data = False

    ## save stuff to bookkeep and return
    stuff = dict()
    stuff['x'] = x

    ## get data histogram
    h_data = None
    if data:
        sp = datasearchpath  # HACK: just data to True!
        newx = '%s::%s::%s' % (sp, treename, x)
        h_data = ipyhep.tree.project(newx, *args, **kwargs)
        if h_data:
            stuff['h_data'] = h_data

    ## blind the data?
    if h_data and not blind is None:
        if isinstance(blind, tuple):
            blind1, blind2 = blind
            nbins = h_data.GetNbinsX()
            for i_bin in xrange(1, nbins +
                                2):  # skip underflow (but not overflow)
                xval1 = h_data.GetXaxis().GetBinLowEdge(i_bin)
                xval2 = h_data.GetXaxis().GetBinUpEdge(i_bin)
                if xval1 >= blind1 and xval2 <= blind2:
                    h_data.SetBinContent(i_bin, 0.0)
                    h_data.SetBinError(i_bin, 0.0)
                    has_blinded_data = True
        else:
            nbins = h_data.GetNbinsX()
            for i_bin in xrange(1, nbins +
                                2):  # skip underflow (but not overflow)
                xval = h_data.GetXaxis().GetBinLowEdge(i_bin)
                if xval >= blind:
                    h_data.SetBinContent(i_bin, 0.0)
                    h_data.SetBinError(i_bin, 0.0)
                    has_blinded_data = True

    ## get background histograms
    h_bkgs = list()
    n_bkgs = list()
    if bkgs:
        for bkg in bkgs:
            if isinstance(bkg, list):
                h_subtotal = None
                for dsid in bkg:
                    assert isinstance(dsid, str)
                    h_bkg = None
                    if dsid.isdigit():
                        ## mc backgrounds
                        sp = bkgsearchpath % int(dsid)
                        newx = '%s::%s::%s' % (sp, treename, x)
                        h_bkg = ipyhep.tree.project(newx, *args, **kwargs)
                    else:
                        ## data-driven backgrounds
                        assert dsid == 'fakes' or dsid == 'efakes'
                        sp = datadrivensearchpath % dsid
                        newx = '%s::%s::%s' % (sp, treename, x)
                        h_bkg = ipyhep.tree.project(newx, *args, **kwargs)
                    if h_bkg:
                        if h_subtotal:
                            h_subtotal.Add(h_bkg)
                        else:
                            h_subtotal = h_bkg.Clone()
                if h_subtotal:
                    h_bkgs.append(h_subtotal)
                    dsid = bkg[0]
                    n_bkgs.append(dsid)
            else:
                dsid = bkg
                assert isinstance(dsid, str)
                h_bkg = None
                if dsid.isdigit():
                    ## mc backgrounds
                    sp = bkgsearchpath % int(dsid)
                    newx = '%s::%s::%s' % (sp, treename, x)
                    h_bkg = ipyhep.tree.project(newx, *args, **kwargs)
                else:
                    ## data-driven backgrounds
                    assert dsid == 'fakes' or dsid == 'efakes'
                    sp = datadrivensearchpath % dsid
                    newx = '%s::%s::%s' % (sp, treename, x)
                    h_bkg = ipyhep.tree.project(newx, *args, **kwargs)
                if h_bkg:
                    h_bkgs.append(h_bkg)
                    n_bkgs.append(dsid)
        if h_bkgs:
            stuff['h_bkgs'] = h_bkgs

    ## get signal histograms
    h_sigs = list()
    n_sigs = list()
    if sigs:
        for dsid in sigs:
            sp = sigsearchpath % int(dsid)
            newx = '%s::%s::%s' % (sp, treename, x)
            h_sig = ipyhep.tree.project(newx, *args, **kwargs)
            if h_sig:
                h_sigs.append(h_sig)
                n_sigs.append(dsid)
        if h_sigs:
            stuff['h_sigs'] = h_sigs

    assert h_sigs

    ## style data
    if h_data:
        h_data.title = 'Data'
        h_data.linecolor = ipyhep.style.black
        h_data.linewidth = 2
        h_data.markercolor = ipyhep.style.black
        h_data.markerstyle = 20
        h_data.markersize = 1.2
        h_data.fillstyle = ipyhep.style.fill_hollow
        h_data.drawstyle = 'PE'
        h_data.legendstyle = 'LP'

    ## scale and style background histograms
    if h_bkgs:
        assert len(h_bkgs) == len(n_bkgs), '%s\n%s' % (h_bkgs, n_bkgs)

        for h, dsid in zip(h_bkgs, n_bkgs):
            sf = ipyhep.sampleops.get_sf(dsid)
            if dsid.isdigit():
                sf *= lumi / __ntuple_lumi
            h.Scale(sf)

            h.title = ipyhep.sampleops.get_label(dsid)
            h.linecolor = ipyhep.style.black
            h.linewidth = 1
            h.markercolor = ipyhep.sampleops.get_color(dsid)
            h.fillcolor = ipyhep.sampleops.get_color(dsid)
            h.fillstyle = ipyhep.style.fill_solid
            h.legendstyle = 'F'

    ## calculate stat error on total background
    h_bkg_total = None
    if h_bkgs:
        for h_bkg in h_bkgs:
            if h_bkg_total:
                h_bkg_total.Add(h_bkg)
            else:
                h_bkg_total = h_bkg.Clone()
        stuff['h_bkg_total'] = h_bkg_total

    ## style h_bkg_total
    if h_bkg_total:
        h_bkg_total.title = 'stat. uncert.'
        h_bkg_total.linecolor = ipyhep.style.black
        h_bkg_total.linewidth = 1
        h_bkg_total.markerstyle = 0
        h_bkg_total.fillcolor = ipyhep.style.dark_gray
        h_bkg_total.fillstyle = ipyhep.style.fill_lines
        h_bkg_total.drawstyle = 'E2'
        h_bkg_total.legendstyle = 'LF'

    ## scale and style signal histograms
    if h_sigs:
        assert len(h_sigs) == len(n_sigs)
        for h, dsid in zip(h_sigs, n_sigs):
            sf = ipyhep.sampleops.get_sf(dsid)
            sf *= lumi / __ntuple_lumi
            h.Scale(sf)

            h.title = ipyhep.sampleops.get_label(dsid)
            h.linecolor = ipyhep.sampleops.get_color(dsid)
            h.linewidth = 3
            h.fillstyle = ipyhep.style.fill_hollow
            h.markerstyle = 0
            h.drawstyle = 'HIST'
            h.legendstyle = 'L'

    ## build list of all_hists
    all_hists = list()
    main_hists = list()
    if h_data:
        all_hists.append(h_data)
        main_hists.append(h_data)
    if h_bkgs:
        all_hists.extend(h_bkgs)
        main_hists.extend(h_bkgs)
    if h_bkg_total:
        all_hists.append(h_bkg_total)
        main_hists.append(h_bkg_total)
    if h_sigs:
        all_hists.extend(h_sigs)

    ## get statistics
    if all_hists:
        stats_list = list()
        for h in all_hists:
            stats_list.extend(get_stats(h))
        html = convert_table_to_html(convert_stats_to_table(stats_list))
        stuff['html'] = html

    ## renormalize for bin widths
    bins = kwargs.pop('bins', None)
    if bins and isinstance(bins, list):
        for h in all_hists:
            renormalize_for_bin_widths(h, bins)

    ## stack background histograms
    if h_bkgs:
        assert len(h_bkgs) == len(n_bkgs), '%s\n%s' % (h_bkgs, n_bkgs)

        h_bkgs.reverse()
        n_bkgs.reverse()

        hstack = HistStack()
        for h in h_bkgs:
            hstack.Add(h)
        hstack.title = 'stack sum'
        hstack.drawstyle = 'HIST'
        stuff['stack'] = hstack

        h_bkgs.reverse()
        n_bkgs.reverse()

#    ## convert data to TGraphAsymmErrors
#    g_data = None
#    if h_data:
#        if __use_poissonize:
#            g_data = poissonize.GetPoissonizedGraph(h_data)
#        else:
#            g_data = ROOT.TGraphAsymmErrors()
#            i_g = 0
#            nbins = h_data.GetNbinsX()
#            for i_bin in xrange(1, nbins+1): # skip underflow/overflow
#                c = h_data.GetBinContent(i_bin)
#                e = h_data.GetBinError(i_bin)
#                if c != 0.0:
#                    g_data.SetPoint(i_g, h_data.GetBinCenter(i_bin), c)
#                    g_ratio.SetPointError(i_g,
#                            h_data.GetBinWidth(i_bin)/2.,
#                            h_data.GetBinWidth(i_bin)/2.,
#                            e,
#                            e)
#                i_g += 1

## build list of objects to draw
    objects = list()
    if h_bkgs:
        objects.append(stuff['stack'])
        objects.append(stuff['h_bkg_total'])
    if h_sigs:
        objects.extend(h_sigs)
    if h_data:
        objects.append(h_data)

    ## set xlimits and ylimits
    ypadding = 0.21
    logy_crop_value = 7e-3
    xmin, xmax, ymin, ymax = 0.0, 1.0, 0.0, 1.0
    if objects:
        xmin, xmax, ymin, ymax = get_limits(objects,
                                            logx=logx,
                                            logy=logy,
                                            ypadding=ypadding,
                                            logy_crop_value=logy_crop_value)
    if logy:
        ymin = 7e-3
    else:
        ymin = 0.0
    xlimits = (xmin, xmax)
    ylimits = (ymin, ymax)
    stuff['xlimits'] = xlimits
    stuff['ylimits'] = ylimits

    ## remove xtitle for do_ratio
    _xtitle = xtitle
    if h_data and h_bkg_total and kwargs.get('do_ratio'):
        _xtitle = ''

    ## make canvas
    canvas = Canvas(800, 600)
    stuff['canvas'] = canvas

    ## draw the objects
    if objects:
        canvas.cd()
        draw(objects,
             pad=canvas,
             xtitle=_xtitle,
             ytitle=ytitle,
             xlimits=xlimits,
             ylimits=ylimits)

    ## set log x/y, for some reason doesn't work before draw
    if logx or logy:
        if logx:
            canvas.SetLogx()
        if logy:
            canvas.SetLogy()
        canvas.Update()

    ## draw blind_line
    if has_blinded_data:
        if isinstance(blind, tuple):
            blind_list = list(blind)
        else:
            blind_list = [blind]
        blind_lines = list()
        for bl in blind_list:
            line_y1 = ymin
            line_y2 = ymax
            blind_line = ROOT.TLine(bl, line_y1, bl, line_y2)
            blind_line.SetLineColor(ROOT.kGray + 2)
            blind_line.SetLineStyle(7)
            blind_line.SetLineWidth(2)
            blind_line.Draw()
            blind_lines.append(blind_line)
        stuff['blind_lines'] = blind_lines
        canvas.Update()

    ## legend
    lefty = True
    if h_bkg_total:
        lefty = is_left_sided(h_bkg_total)
    elif h_data:
        lefty = is_left_sided(h_data)
    elif h_sigs:
        lefty = is_left_sided(h_sigs[0])

    if main_hists:
        header = '%.1f fb^{-1}, 13 TeV' % (lumi / 1000.0)
        if lefty:
            legend = Legend(main_hists,
                            pad=canvas,
                            header=header,
                            textsize=16,
                            topmargin=0.03,
                            leftmargin=0.60,
                            rightmargin=0.02,
                            entrysep=0.01,
                            entryheight=0.04)
        else:
            legend = Legend(main_hists,
                            pad=canvas,
                            header=header,
                            textsize=16,
                            topmargin=0.03,
                            leftmargin=0.03,
                            rightmargin=0.59,
                            entrysep=0.01,
                            entryheight=0.04)
        legend.Draw()
        stuff['legend'] = legend

    if h_sigs:
        #        header = 'ATLAS Internal'
        header = ''
        if lefty:
            legend2 = Legend(h_sigs,
                             pad=canvas,
                             header=header,
                             textsize=16,
                             topmargin=0.03,
                             leftmargin=0.37,
                             rightmargin=0.23,
                             entrysep=0.01,
                             entryheight=0.04)
        else:
            legend2 = Legend(h_sigs,
                             pad=canvas,
                             header=header,
                             textsize=16,
                             topmargin=0.03,
                             leftmargin=0.20,
                             rightmargin=0.40,
                             entrysep=0.01,
                             entryheight=0.04)
        legend2.Draw()
        stuff['legend2'] = legend2

    ## do_ratio
    if h_data and h_bkg_total and kwargs.get('do_ratio'):

        ## top canvas
        top_canvas = stuff.pop('canvas')
        stuff['top_canvas'] = top_canvas

        ## make SM/SM with error band: h_ratio_band
        i_sfratio = int(kwargs.get('sfratio', -1))
        if i_sfratio < 0:  # ratio plot of Data/Model
            h_ratio_band = h_bkg_total.Clone()
            nbins = h_ratio_band.GetNbinsX()
            for i_bin in xrange(nbins + 2):
                h_ratio_band.SetBinContent(i_bin, 1.0)
                c = h_bkg_total.GetBinContent(i_bin)
                e = h_bkg_total.GetBinError(i_bin) / c if c > 0.0 else 0.0
                h_ratio_band.SetBinError(i_bin, e)
            stuff['h_ratio_band'] = h_ratio_band
        else:  # ratio plot of Scale Factor for ith background
            hi = h_bkgs[i_sfratio]
            h_ratio_band = hi.Clone()
            nbins = h_ratio_band.GetNbinsX()
            for i_bin in xrange(nbins + 2):
                h_ratio_band.SetBinContent(i_bin, 1.0)
                c = hi.GetBinContent(i_bin)
                e = hi.GetBinError(i_bin) / c if c > 0.0 else 0.0
                h_ratio_band.SetBinError(i_bin, e)
            stuff['h_ratio_band'] = h_ratio_band

        ## make data/(SM) h_ratio
        if i_sfratio < 0:
            h_ratio = h_data.Clone()
            h_ratio.Divide(h_data, h_bkg_total, 1.0, 1.0)
            stuff['h_ratio'] = h_ratio
        else:
            ## SF1 = 1.0 + (data - MCtot) / MC1
            sfname = kwargs.get('sfname')
            sffile = kwargs.get('sffile')
            if not sfname:
                sfname = 'h_sf'
            hi = h_bkgs[i_sfratio]
            h_numer = h_data.Clone()
            h_numer.Add(h_bkg_total, -1.0)
            ## do the division
            h_ratio = h_data.Clone(sfname)
            h_ratio.Divide(h_numer, hi, 1.0, 1.0)
            ## add the 1.0
            nbins = h_ratio.GetNbinsX()
            for i_bin in xrange(nbins + 2):
                c = h_ratio.GetBinContent(i_bin)
                h_ratio.SetBinContent(i_bin, c + 1.0)
                h_ratio_band.SetBinContent(i_bin, c + 1.0)
            ## ignore bins with no data for SF
            for i_bin in xrange(nbins + 2):
                c = h_data.GetBinContent(i_bin)
                if c <= 0:
                    h_ratio.SetBinContent(i_bin, 0.0)
                    h_ratio.SetBinError(i_bin, 0.0)
                    h_ratio_band.SetBinError(i_bin, 0.0)
            stuff['h_ratio'] = h_ratio
            if sffile:
                f_out = ipyhep.file.write(h_ratio, sffile)
#                f_out.Close()

## convert ratio to a TGraphErrors so that Draw('E0')
## shows error bars for points off the pad
        g_ratio = ROOT.TGraphErrors()
        i_g = 0
        for i_bin in xrange(1, nbins + 1):  # skip underflow/overflow
            ratio_content = h_ratio.GetBinContent(i_bin)
            if ratio_content != 0.0:
                g_ratio.SetPoint(i_g, h_ratio.GetBinCenter(i_bin),
                                 ratio_content)
                g_ratio.SetPointError(i_g,
                                      h_ratio.GetBinWidth(i_bin) / 2.,
                                      h_ratio.GetBinError(i_bin))
                i_g += 1
            else:
                h_ratio.SetBinError(i_bin, 0.0)
        stuff['g_ratio'] = g_ratio

        ## style ratio
        h_ratio_band.title = 'bkg uncert.'
        if i_sfratio < 0:
            h_ratio_band.linecolor = ipyhep.style.yellow
        else:
            h_ratio_band.linecolor = ipyhep.style.light_gray
        h_ratio_band.linewidth = 0
        h_ratio_band.markerstyle = 0
        if i_sfratio < 0:
            h_ratio_band.fillcolor = ipyhep.style.yellow
        else:
            h_ratio_band.linecolor = ipyhep.style.light_gray
        h_ratio_band.fillstyle = ipyhep.style.fill_solid
        h_ratio_band.drawstyle = 'E2'
        h_ratio_band.legendstyle = 'F'
        h_ratio.title = 'ratio'
        h_ratio.linecolor = ipyhep.style.black
        h_ratio.linewidth = 2
        h_ratio.markercolor = ipyhep.style.black
        h_ratio.markerstyle = 20
        h_ratio.markersize = 1.2
        h_ratio.fillstyle = ipyhep.style.fill_hollow
        h_ratio.drawstyle = 'PE'
        h_ratio.legendstyle = 'LP'

        ## bottom canvas
        bottom_canvas = Canvas(800, 600)
        bottom_canvas.cd()
        stuff['bottom_canvas'] = bottom_canvas

        ## set ratio ylimits
        ratio_min = kwargs.get('ratio_min', -0.2)
        ratio_max = kwargs.get('ratio_max', 2.2)
        ratio_ylimits = (ratio_min, ratio_max)

        ## draw ratio band
        if i_sfratio < 0:
            _ytitle = 'Data / Model'
        else:
            hi = h_bkgs[i_sfratio]
            _ytitle = 'SF(%s)' % hi.title
        draw([h_ratio_band],
             pad=bottom_canvas,
             xtitle=xtitle,
             ytitle=_ytitle,
             xlimits=xlimits,
             ylimits=ratio_ylimits)

        ## set log x/y, for some reason doesn't work before draw?
        if logx:
            bottom_canvas.SetLogx()
            bottom_canvas.Update()

        ### make horiz lines in ratio plot every 0.5:
        line_ys = [
            y / 10.0
            for y in range(10 *
                           int(round(ratio_min)), 10 * int(round(ratio_max)) +
                           5, 5)
        ]
        line_x1 = canvas.GetUxmin()
        line_x2 = canvas.GetUxmax()
        line_xwidth = abs(line_x2 - line_x1)
        lines = []
        for line_y in line_ys:
            line = ROOT.TLine(line_x1 + 0.02 * line_xwidth, line_y,
                              line_x2 - 0.02 * line_xwidth, line_y)
            line.SetLineWidth(1)
            line.SetLineStyle(7)
            if line_y == 1.0:
                line.SetLineColor(ROOT.kGray + 2)
            else:
                line.SetLineColor(ROOT.kGray + 0)
            line.Draw()
            lines.append(line)
        stuff['lines'] = lines

        ## draw blind_line
        if has_blinded_data:
            if isinstance(blind, tuple):
                blind_list = list(blind)
            else:
                blind_list = [blind]
            blind_lines = list()
            for bl in blind_list:
                line_y1 = ymin
                line_y2 = ymax
                blind_line = ROOT.TLine(bl, line_y1, bl, line_y2)
                blind_line.SetLineColor(ROOT.kGray + 2)
                blind_line.SetLineStyle(7)
                blind_line.SetLineWidth(2)
                blind_line.Draw()
                blind_lines.append(blind_line)
            stuff['blind_lines2'] = blind_lines
            canvas.Update()

        ## draw ratio
        g_ratio.Draw('PE0')
        #        h_ratio.GetYaxis().SetRangeUser(ratio_min, ratio_max)
        #        h_ratio.Draw('PE,SAME')

        ## shared canvas
        shared_canvas = Canvas(800, 800)
        shared_plot = plot_shared_axis(top_canvas,
                                       bottom_canvas,
                                       canvas=shared_canvas,
                                       split=0.35,
                                       axissep=0.01)
        stuff['canvas'] = shared_canvas
        canvas = shared_canvas

    ## save figures
    save = kwargs.get('save')

    if save is None:  # NOTE: save can be False to skip saving
        save = ['pdf', 'png']

    if save:
        ipyhep.file.save_figures(canvas, x, save)

    global results
    results = stuff
    return stuff
Ejemplo n.º 10
0
def draw(
        name,
        category,
        data=None,
        data_info=None,
        model=None,
        model_colors=None,
        signal=None,
        signal_scale=1.,
        signal_on_top=False,
        signal_linestyles=None,
        signal_colors=None,
        show_signal_error=False,
        fill_signal=False,
        stack_signal=True,
        units=None,
        plot_label=None,
        ylabel='Events',
        blind=False,
        show_ratio=False,
        ratio_range=(0, 2),
        ratio_height=0.15,
        ratio_margin=0.06,
        output_formats=None,
        systematics=None,
        #systematics_components=None,
        integer=False,
        textsize=22,
        logy=False,
        logy_min=None,
        separate_legends=False,
        ypadding=None,
        legend_position='right',
        range=None,
        output_name=None,
        output_dir=PLOTS_DIR,
        arrow_values=None,
        overflow=True,
        show_pvalue=False,
        top_label=None,
        poisson_errors=True):

    if model is None and data is None and signal is None:
        # insufficient input
        raise ValueError("at least one of model, data, "
                         "or signal must be specified")

    if model is not None:
        if not isinstance(model, (list, tuple)):
            model = [model]
        if overflow:
            for hist in model:
                fold_overflow(hist)
    if signal is not None:
        if not isinstance(signal, (list, tuple)):
            signal = [signal]
        if overflow:
            for hist in signal:
                fold_overflow(hist)
    if data is not None and overflow:
        fold_overflow(data)

    # objects will be populated with all histograms in the main pad
    objects = []
    legends = []

    if show_ratio and (data is None or model is None):
        # cannot show the ratio if data or model was not specified
        show_ratio = False

    if ypadding is None:
        # select good defaults for log or linear scales
        if logy:
            ypadding = (.6, .0)
        else:
            ypadding = (.35, .0)

    template = data or model[0]
    xdivisions = min(template.nbins(), 7) if integer else 507

    if show_ratio:
        fig = RatioPlot(logy=logy,
                        ratio_title='Data / Model',
                        ratio_limits=(0, 2),
                        offset=-72,
                        ratio_margin=22,
                        prune_ratio_ticks=True)
    else:
        fig = SimplePlot(logy=logy)

    if signal is not None:
        if signal_scale != 1.:
            scaled_signal = []
            for sig in signal:
                scaled_h = sig * signal_scale
                scaled_h.SetTitle(r'%g #times %s' %
                                  (signal_scale, sig.GetTitle()))
                scaled_signal.append(scaled_h)
        else:
            scaled_signal = signal
        if signal_colors is not None:
            set_colors(scaled_signal, signal_colors)
        for i, s in enumerate(scaled_signal):
            s.drawstyle = 'HIST'
            if fill_signal:
                s.fillstyle = 'solid'
                s.fillcolor = s.linecolor
                s.linewidth = 0
                s.linestyle = 'solid'
                alpha = .75
            else:
                s.fillstyle = 'hollow'
                s.linewidth = 3
                if signal_linestyles is not None:
                    s.linestyle = signal_linestyles[i]
                else:
                    s.linestyle = 'solid'
                alpha = 1.

    if model is not None:
        if model_colors is not None:
            set_colors(model, model_colors)
        # create the model stack
        model_stack = HistStack()
        for hist in model:
            hist.SetLineWidth(0)
            hist.drawstyle = 'hist'
            model_stack.Add(hist)
        if signal is not None and signal_on_top:
            for s in scaled_signal:
                model_stack.Add(s)
        objects.append(model_stack)

    if signal is not None and not signal_on_top:
        if stack_signal:
            # create the signal stack
            signal_stack = HistStack()
            for hist in scaled_signal:
                signal_stack.Add(hist)
            objects.append(signal_stack)
        else:
            objects.extend(scaled_signal)

    if model is not None:
        # draw uncertainty band
        total_model, high_band_model, low_band_model = uncertainty_band(
            model, systematics)  #, systematics_components)
        high = total_model + high_band_model
        low = total_model - low_band_model
        error_band_model = rootpy_utils.get_band(low,
                                                 high,
                                                 middle_hist=total_model)
        error_band_model.fillstyle = '/'
        error_band_model.fillcolor = 13
        error_band_model.linecolor = 10
        error_band_model.markersize = 0
        error_band_model.markercolor = 10
        error_band_model.drawstyle = 'e2'
        objects.append(error_band_model)

    if signal is not None and show_signal_error:
        total_signal, high_band_signal, low_band_signal = uncertainty_band(
            signal, systematics)  #, systematics_components)
        high = (total_signal + high_band_signal) * signal_scale
        low = (total_signal - low_band_signal) * signal_scale
        if signal_on_top:
            high += total_model
            low += total_model
        error_band_signal = rootpy_utils.get_band(low,
                                                  high,
                                                  middle_hist=total_signal *
                                                  signal_scale)
        error_band_signal.fillstyle = '\\'
        error_band_signal.fillcolor = 13
        error_band_signal.linecolor = 10
        error_band_signal.markersize = 0
        error_band_signal.markercolor = 10
        error_band_signal.drawstyle = 'e2'
        objects.append(error_band_signal)

    if data is not None and blind is not True:
        # create the data histogram
        if isinstance(blind, tuple):
            low, high = blind
            # zero out bins in blind region
            for bin in data.bins():
                if (low < bin.x.high <= high or low <= bin.x.low < high):
                    data[bin.idx] = (0., 0.)

        if poisson_errors:
            # convert data to TGraphAsymmErrors with Poisson errors
            data_poisson = data.poisson_errors()
            data_poisson.markersize = 1.2
            data_poisson.drawstyle = 'PZ'
            objects.append(data_poisson)
        else:
            # Gaussian errors
            data.drawstyle = 'E0'
            objects.append(data)

        # draw ratio plot
        if model is not None and show_ratio:
            fig.cd('ratio')
            total_model = sum(model)
            ratio_hist = Hist.divide(data, total_model)
            # remove bins where data is zero
            max_dev = 0
            for bin in data.bins():
                if bin.value <= 0:
                    ratio_hist[bin.idx] = (-100, 0)
                else:
                    ratio_value = ratio_hist[bin.idx].value
                    dev = abs(ratio_value - 1)
                    if dev > max_dev:
                        max_dev = dev

            if max_dev < 0.2:
                ratio_range = (0.8, 1.2)
            elif max_dev < 0.4:
                ratio_range = (0.6, 1.4)
            ruler_high = (ratio_range[1] + 1.) / 2.
            ruler_low = (ratio_range[0] + 1.) / 2.

            ratio_hist.linecolor = 'black'
            ratio_hist.linewidth = 2
            ratio_hist.fillstyle = 'hollow'
            ratio_hist.drawstyle = 'E0'
            """
            # draw empty copy of ratio_hist first so lines will show
            ratio_hist_tmp = ratio_hist.Clone()
            ratio_hist_tmp.Reset()
            ratio_hist_tmp.Draw()
            ratio_hist_tmp.yaxis.SetLimits(*ratio_range)
            ratio_hist_tmp.yaxis.SetRangeUser(*ratio_range)
            ratio_hist_tmp.yaxis.SetTitle('Data / Model')
            ratio_hist_tmp.yaxis.SetNdivisions(4)
            # not certain why the following is needed
            ratio_hist_tmp.yaxis.SetTitleOffset(style.GetTitleYOffset())

            ratio_xrange = range or ratio_hist.bounds()

            ratio_hist_tmp.xaxis.SetLimits(*ratio_xrange)
            #ratio_hist_tmp.xaxis.SetRangeUser(*ratio_xrange)

            ratio_hist_tmp.xaxis.SetTickLength(
                ratio_hist_tmp.xaxis.GetTickLength() * 2)

            # draw ratio=1 line
            line = Line(ratio_xrange[0], 1,
                        ratio_xrange[1], 1)
            line.linestyle = 'dashed'
            line.linewidth = 2
            line.Draw()

            # draw high ratio line
            line_up = Line(ratio_xrange[0], ruler_high,
                           ratio_xrange[1], ruler_high)
            line_up.linestyle = 'dashed'
            line_up.linewidth = 2
            line_up.Draw()

            # draw low ratio line
            line_dn = Line(ratio_xrange[0], ruler_low,
                           ratio_xrange[1], ruler_low)
            line_dn.linestyle = 'dashed'
            line_dn.linewidth = 2
            line_dn.Draw()
            """

            # draw band below points on ratio plot
            ratio_hist_high = Hist.divide(total_model + high_band_model,
                                          total_model)
            ratio_hist_low = Hist.divide(total_model - low_band_model,
                                         total_model)
            fig.cd('ratio')
            error_band = rootpy_utils.get_band(ratio_hist_high, ratio_hist_low)
            error_band.fillstyle = '/'
            error_band.fillcolor = '#858585'
            error_band.drawstyle = 'E2'
            fig.draw('ratio', [error_band, ratio_hist], xdivisions=xdivisions)

    if separate_legends:
        fig.cd('main')
        right_legend = Legend(len(signal) + 1 if signal is not None else 1,
                              pad=fig.pad('main'),
                              **legend_params('right', textsize))
        right_legend.AddEntry(data, style='lep')
        if signal is not None:
            for s in reversed(scaled_signal):
                right_legend.AddEntry(s, style='F' if fill_signal else 'L')
        legends.append(right_legend)
        if model is not None:
            n_entries = len(model)
            if systematics:
                n_entries += 1
            model_legend = Legend(n_entries,
                                  pad=fig.pad('main'),
                                  **legend_params('left', textsize))
            for hist in reversed(model):
                model_legend.AddEntry(hist, style='F')
            if systematics:
                model_err_band = error_band_model.Clone()
                model_err_band.linewidth = 0
                model_err_band.linecolor = 'white'
                model_err_band.fillcolor = '#858585'
                model_err_band.title = 'Uncert.'
                model_legend.AddEntry(model_err_band, style='F')
            legends.append(model_legend)
    else:
        n_entries = 1
        if signal is not None:
            n_entries += len(scaled_signal)
        if model is not None:
            n_entries += len(model)
            if systematics:
                n_entries += 1
        fig.cd('main')
        legend = Legend(n_entries,
                        pad=fig.pad('main'),
                        **legend_params(legend_position, textsize))
        if data is not None:
            legend.AddEntry(data, style='lep')
        if signal is not None:
            for s in reversed(scaled_signal):
                legend.AddEntry(s, style='F' if fill_signal else 'L')
        if model:
            for hist in reversed(model):
                legend.AddEntry(hist, style='F')
            model_err_band = error_band_model.Clone()
            model_err_band.linewidth = 0
            model_err_band.linecolor = 'white'
            model_err_band.fillcolor = '#858585'
            model_err_band.title = 'Uncert.'
            legend.AddEntry(model_err_band, style='F')
        legends.append(legend)

    # draw the objects
    bounds = fig.draw('main',
                      objects,
                      ypadding=ypadding,
                      logy_crop_value=1E-1,
                      xdivisions=xdivisions)
    xaxis, yaxis = fig.axes('main')

    base_xaxis = xaxis
    base_xaxis.range_user = template.bounds()
    base_xaxis.limits = template.bounds()
    xmin, xmax, ymin, ymax = bounds

    if show_ratio:
        base_xaxis = fig.axes('ratio')[0]
        base_xaxis.range_user = template.bounds()
        base_xaxis.limits = template.bounds()

    # draw the legends
    fig.cd('main')
    for legend in legends:
        legend.Draw()

    label_plot(
        fig.pad('main'),
        template=template,
        xaxis=base_xaxis,
        yaxis=yaxis,
        xlabel=name,
        ylabel=ylabel,
        units=units,
        category_label=category.label,
        extra_label=plot_label,
        extra_label_position='right' if legend_position == 'left' else 'left',
        data_info=data_info)

    if logy and logy_min is not None:
        yaxis.min = logy_min
        ymin = logy_min

    # draw arrows
    if arrow_values is not None:
        arrow_top = ymin + (ymax - ymin) / 2.
        fig.cd('main')
        for value in arrow_values:
            arrow = Arrow(value, arrow_top, value, ymin, 0.05, '|>')
            arrow.SetAngle(30)
            arrow.SetLineWidth(2)
            arrow.Draw()

    if show_pvalue and data is not None and model:
        fig.cd('main')
        total_model = sum(model)
        # show p-value and chi^2
        pvalue = total_model.Chi2Test(data, 'WW')
        pvalue_label = ROOT.TLatex(0.6, 0.97, "p-value={0:.2f}".format(pvalue))
        pvalue_label.SetNDC(True)
        pvalue_label.SetTextFont(43)
        pvalue_label.SetTextSize(16)
        pvalue_label.Draw()
        chi2 = total_model.Chi2Test(data, 'WW CHI2/NDF')
        chi2_label = ROOT.TLatex(0.78, 0.97,
                                 "#chi^{{2}}/ndf={0:.2f}".format(chi2))
        chi2_label.SetNDC(True)
        chi2_label.SetTextFont(43)
        chi2_label.SetTextSize(16)
        chi2_label.Draw()

    if top_label is not None:
        fig.cd('main')
        label = ROOT.TLatex(
            fig.pad('main').GetLeftMargin() + 0.08, 0.97, top_label)
        label.SetNDC(True)
        label.SetTextFont(43)
        label.SetTextSize(16)
        label.Draw()

    if output_name is not None:
        # create the output filename
        filename = 'var_{0}_{1}'.format(category.name,
                                        output_name.lower().replace(' ', '_'))
        if logy:
            filename += '_logy'
        filename += '_root'
        if output_formats is None:
            output_formats = ('png', )
        # save the figure
        save_canvas(fig, output_dir, filename, formats=output_formats)

    return fig
Ejemplo n.º 11
0
def plotHistos(histos, text="", option="", statbox=True):
    """ 
    Plots a list of histograms
    """
    log = logging.getLogger('pyroplot')
    import rootpy
    from rootpy.plotting import Hist, HistStack
    from ROOT import kRed, gPad, TPaveStats
    # only for 1D and 2D type histograms:
    # determine and set maximum for all histograms
    stack = HistStack()
    for hist in histos:
        if not hist.__class__.__name__ == "Hist3D":
            stack.Add(hist)
    # determine maximum value and set it for all histograms
    if stack.GetHists():
        maxplot = stack.GetMaximum()
        minplot = stack.GetMinimum()
        for hist in stack.GetHists():
            hist.SetMaximum(maxplot)
            # special treatment for log scale Y
            if gPad.GetLogy():
                hist.SetMinimum(1.)
            else:
                # if histogram minimum is positive, set to 0.
                if minplot > 0:
                    hist.SetMinimum(0.)
    for idx, hist in enumerate(histos):
        try:
            thisopt = option
            # if not first histo, add "same" to options so previous ones are not overwritten
            if idx:
                if statbox:
                    thisopt += "sames"
                else:
                    thisopt += "same"
            histcopy = hist.DrawCopy(thisopt)
            # on first go: print identifying text on pad
            if not idx and text:
                markPad(text=text, x=.14, y=.85, size=0.041)
                if statbox:
                    thisopt += "sames"
                else:
                    thisopt += "same"
                histcopy.Draw(thisopt)
            gPad.Update()
            if statbox:
                try:
                    statBox = histcopy.GetListOfFunctions().FindObject("stats")
                    # offset from last statbox
                    offset = .18
                    # needs to be larger for Profile & 2D histos
                    if (hist.__class__.__name__ == "Profile"
                            or hist.__class__.__name__ == "Hist2D"
                            or hist.__class__.__name__ == "Profile2D"
                            or hist.__class__.__name__ == "Hist3D"):
                        offset = .26
                    statBox.SetY1NDC(statBox.GetY1NDC() - offset * (idx))
                    statBox.SetY2NDC(statBox.GetY2NDC() - offset * (idx))
                    statBox.SetTextColor(hist.GetLineColor())
                    statBox.SetBorderSize(2)
                except AttributeError:
                    log.debug("Could not get statbox for histogram " +
                              hist.GetName())

        except rootpy.ROOTError, e:
            log.error(
                "Drawing histogram %s caused ROOTError exception ('%s')" %
                (hist.GetName(), e.msg))
            gPad.Clear()  # otherwise this happens again when drawing..
            markPad(text="Could not draw %s ('%s')" % (hist.GetName(), e.msg),
                    x=0.14,
                    y=0.4,
                    size=0.023,
                    color=kRed)
            return  # give up!