コード例 #1
0
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)
コード例 #2
0
def plot_emu_mue_with_ratio(canvas=None,
                            h_mue=None,
                            h_emu=None,
                            h_ratio=None,
                            filename='',
                            figformats=['png', 'eps']):
    c = canvas
    c.Clear()
    c._graphics = []
    c.cd()
    botPad, topPad = buildBotTopPads(c, splitFraction=0.375)
    topPad.Draw()
    topPad.cd()
    h_mue.SetStats(0)
    h_emu.SetStats(0)
    h_emu.SetLineColor(r.kBlue)
    h_mue.SetLineColor(r.kRed)
    h_mue.Draw()
    h_emu.Draw('same')
    pm = h_mue
    yMin, yMax = getMinMax([h_mue, h_emu])
    pm.SetMinimum(0.0)
    pm.SetMaximum(1.1 * yMax)
    xax = pm.GetXaxis()
    yax = pm.GetYaxis()
    xax.SetLabelSize(0)
    xax.SetTitleSize(0)
    leg = topLeftLegend(c, 0.275, 0.275, shift=0.05)
    leg.SetBorderSize(0)
    leg.SetHeader('non-prompt prediction')
    leg.AddEntry(h_mue, '#mue', 'L')
    leg.AddEntry(h_emu, 'e#mu', 'L')
    leg.Draw()
    c._graphics.append(leg)
    c.cd()
    botPad.Draw()
    botPad.cd()
    h_ratio.SetLineColor(r.kBlack)
    h_ratio.SetTitle('')
    xax = h_ratio.GetXaxis()
    yax = h_ratio.GetYaxis()
    yax.SetRangeUser(0.0, 2.0)
    yax.SetTitle('e#mu / #mue ratio')
    xA, yA = h_ratio.GetXaxis(), h_ratio.GetYaxis()
    textScaleUp = 1.0 / botPad.GetHNDC()
    yA.SetNdivisions(-104)
    yA.CenterTitle()
    yA.SetTitleOffset(yA.GetTitleOffset() / textScaleUp)
    for a in [xA, yA]:
        a.SetLabelSize(a.GetLabelSize() * textScaleUp)
        a.SetTitleSize(a.GetTitleSize() * textScaleUp)
    h_ratio.Draw()
    refline = referenceLine(xA.GetXmin(), xA.GetXmax())
    refline.Draw()
    c._graphics.append(refline)
    c.Update()
    for ext in figformats:
        c.SaveAs("{0}.{1}".format(filename, ext))
コード例 #3
0
def plot_emu_mue_with_ratio(canvas=None, h_mue=None, h_emu=None, h_ratio=None,
                            filename='', figformats=['png', 'eps'], label=''):
    c = canvas
    c.Clear()
    c._graphics = []
    c.cd()
    botPad, topPad = buildBotTopPads(c, splitFraction=0.375)
    topPad.Draw()
    topPad.cd()
    h_mue.SetStats(0)
    h_emu.SetStats(0)
    h_emu.SetLineColor(r.kBlue)
    h_mue.SetLineColor(r.kRed)
    h_mue.Draw()
    h_emu.Draw('same')
    pm = h_mue
    yMin, yMax = getMinMax([h_mue, h_emu])
    pm.SetMinimum(0.0)
    pm.SetMaximum(1.1 * yMax)
    xax = pm.GetXaxis()
    yax = pm.GetYaxis()
    xax.SetLabelSize(0)
    xax.SetTitleSize(0)
    leg = topRightLegend(c, 0.275, 0.275, shift=0.05)
    leg.SetBorderSize(0)
    leg.SetHeader(label)
    leg.AddEntry(h_mue, '#mue', 'L')
    leg.AddEntry(h_emu, 'e#mu', 'L')
    leg.Draw()
    c._graphics.append(leg)
    c.cd()
    botPad.Draw()
    botPad.cd()
    h_ratio.SetLineColor(r.kBlack)
    h_ratio.SetTitle('')
    xax = h_ratio.GetXaxis()
    yax = h_ratio.GetYaxis()
    yax.SetRangeUser(0.0, 2.0)
    yax.SetTitle('e#mu / #mue ratio')
    xA, yA = h_ratio.GetXaxis(), h_ratio.GetYaxis()
    textScaleUp = 1.0/botPad.GetHNDC()
    yA.SetNdivisions(-104)
    yA.CenterTitle()
    yA.SetTitleOffset(yA.GetTitleOffset()/textScaleUp)
    for a in [xA, yA] :
        a.SetLabelSize(a.GetLabelSize()*textScaleUp)
        a.SetTitleSize(a.GetTitleSize()*textScaleUp)
    h_ratio.Draw()
    refline = referenceLine(xA.GetXmin(), xA.GetXmax())
    refline.Draw()
    c._graphics.append(refline)
    c.Update()
    for ext in figformats:
        c.SaveAs("{0}.{1}".format(filename, ext))
        print "{0}.{1}".format(filename, ext)
コード例 #4
0
def main() :
    parser = optparse.OptionParser(usage=usage)
    parser.add_option('-t', '--tag')
    parser.add_option('-f', '--input_fake')
    parser.add_option('-i', '--input_dir')
    parser.add_option('-o', '--output_dir')
    parser.add_option('-v','--verbose', action='store_true', default=False)
    (opts, args) = parser.parse_args()
    requiredOptions = ['tag', 'input_fake', 'input_dir', 'output_dir',]
    otherOptions = ['verbose']
    allOptions = requiredOptions + otherOptions
    def optIsNotSpecified(o) : return not hasattr(opts, o) or getattr(opts,o) is None
    if any(optIsNotSpecified(o) for o in requiredOptions) : parser.error('Missing required option')
    tag           = opts.tag.strip('_')
    inputFakeFile = opts.input_fake
    inputDirname  = opts.input_dir
    outputDir     = opts.output_dir
    outputDir     = outputDir if outputDir.endswith('/') else outputDir+'/'
    verbose       = opts.verbose
    if verbose : print '\nUsing the following options:\n'+'\n'.join("%s : %s"%(o, str(getattr(opts, o))) for o in allOptions)

    inputFiles = getInputFiles(inputDirname, tag, verbose)
    inputFiles[fakeSample()] = r.TFile.Open(inputFakeFile)
    assert all(f for f in inputFiles.values()), ("missing inputs: \n%s"%'\n'.join(["%s : %s"%kv for kv in inputFiles.iteritems()]))
    mkdirIfNeeded(outputDir)

    for region in ['cr8lptee', 'cr8lptmm', 'cr9lpt', 'sr8', 'sr9', 'srSsEwk', 'crSsEwkLoose'] :
        for channel in ['ee', 'em', 'mm'] :
            for varname in ['l0_pt', 'l1_pt', 'll_M', 'metrel', 'met', 'njets', 'nbjets'] :
                histo_basename = region+'_'+channel+'_'+varname
                hists, err2s = buildHists(inputFiles, histo_basename)
                if not hists[dataSample()].GetEntries() : continue
                err_band     = buildErrBandGraph(hists['sm'], err2s)
                err_band_r   = buildErrBandRatioGraph(err_band)
                can = r.TCanvas('can_'+histo_basename, histo_basename, 800, 600)
                botPad, topPad = buildBotTopPads(can)
                can.cd()
                topPad.Draw()
                drawTop(topPad, hists, err_band, (channel, region))
                can.cd()
                botPad.Draw()
                drawBot(botPad, hists[dataSample()], hists['sm'], err_band_r, xaxisLabel(varname))
                can.Update()
                outFilename = outputDir+histo_basename+'.png'
                rmIfExists(outFilename) # avoid root warnings
                can.SaveAs(outFilename)
    if verbose : print "output saved to \n%s"%outputDir
コード例 #5
0
def plotVar(bkgHistos, sigHistos, llnjvar, plotdir='./') :
    def preferredSignal(signals):
        pref = 'Herwigpp_sM_wA_noslep_notauhad_WH_2Lep_1'
        return pref if pref in signals else first(sorted(signals))
    signalSample = preferredSignal(sigHistos.keys())
    allHistos = bkgHistos.values() + [sigHistos[signalSample],]
    allHistosEmpty = all([h.GetEntries()==0 for h in allHistos])
    if allHistosEmpty : return
    can = r.TCanvas('can_'+llnjvar, llnjvar, 800, 800)
    botPad, topPad = buildBotTopPads(can, splitFraction=0.75, squeezeMargins=False)
    totBkg = summedHisto(bkgHistos.values())
    totBkg.SetDirectory(0)
    can._totBkg = totBkg
    can._histos = [bkgHistos, sigHistos]
    can.cd()
    botPad.Draw()
    drawBottom(botPad, totBkg, bkgHistos, sigHistos[signalSample], llnjvar)
    can.cd()
    topPad.Draw()
    drawTop(topPad, totBkg, sigHistos[signalSample])
    mkdirIfNeeded(plotdir)
    outFilename = plotdir+'/'+llnjvar+'.png'
    rmIfExists(outFilename) # avoid root warnings
    can.SaveAs(outFilename)
コード例 #6
0
ファイル: plot_emu.py プロジェクト: gerbaudo/SusyntHlfv
def plotHistos(histoData=None, histoSignal=None, histoTotBkg=None, histosBkg={},
               statErrBand=None, systErrBand=None, # these are TGraphAsymmErrors
               canvasName='canvas', outdir='./', options=None,
               stack_order=[],
               topLabel='',
               drawStatErr=False, drawSystErr=False,
               drawYieldAndError=False, printYieldSummary=False) :
    "Note: blinding can be required for only a subrange of the histo, so it is taken care of when filling"
    verbose = options.verbose
    formatAuxMaterial = options.format_aux
    setAtlasStyle()
    padMaster = histoData
    if verbose : print "plotting ",padMaster.GetName(),' (',padMaster.GetEntries(),' entries)'
    can = r.TCanvas(canvasName, padMaster.GetTitle(), 800, 800)
    botPad, topPad = buildBotTopPads(can, squeezeMargins=False)
    can.cd()
    topPad.Draw()
    # draw top
    topPad.cd()
    topPad._hists = [padMaster]
    if formatAuxMaterial:
        for ax in [padMaster.GetXaxis(), padMaster.GetYaxis()]:
            ax.SetTitle(prettify(ax.GetTitle()))
    padMaster.Draw('axis')
    topPad.Update() # necessary to fool root's dumb object ownership of the stack
    stack = r.THStack('stack_'+padMaster.GetName(), '')
    r.SetOwnership(stack, False)
    topPad._hists.append(stack)
    leg = topRightLegend(can,
                         0.300 if formatAuxMaterial else 0.225,
                         0.400 if formatAuxMaterial else 0.325,
                         shiftX=-0.1 if formatAuxMaterial else 0.0,
                         shiftY=-0.1 if formatAuxMaterial else 0.0)
    topPad._leg = leg
    leg.SetBorderSize(0)
    leg.SetTextFont(padMaster.GetTitleFont())
    leg._reversedEntries = []
    def integralWou(h):
        "Integral with underflow and overflow"
        return h.Integral(0, h.GetNbinsX()+1)
    for group, histo in sortedAs(histosBkg, stack_order) :
        histo.SetFillColor(getGroupColor(group))
        histo.SetLineWidth(2)
        histo.SetLineColor(r.kBlack)
        stack.Add(histo)
        topPad._hists.append(histo)
        leg._reversedEntries.append((histo,
                                     prettify(group) if formatAuxMaterial else
                                     "{0}: {1:.2f}".format(group, integralWou(histo)), 'F'))
    if not formatAuxMaterial:
        leg._reversedEntries.append((dummyHisto(),
                                     "{0}, {1:.2f}".format('bkg', sum([integralWou(h) for h in stack.GetHists()])), 'l'))
    if statErrBand and drawStatErr :
        statErrBand.SetFillStyle(3006)
        leg._reversedEntries.append((statErrBand, 'stat', 'f'))
    if systErrBand and drawSystErr :
        systErrBand.SetFillStyle(3007)
        leg._reversedEntries.append((systErrBand, 'syst', 'f'))
    leg._reversedEntries.append((histoData,
                                 "Data {0}".format(prettify(topLabel)) if formatAuxMaterial else
                                 "{0}, {1:.2f}".format('data', integralWou(histoData)), 'p'))
    for h, g, o in leg._reversedEntries[::-1] : leg.AddEntry(h, g, o) # stack goes b-t, legend goes t-b
    stack.Draw('hist same')
    histoData.SetMarkerStyle(r.kFullCircle)
    histoData.SetLineWidth(2)
    dataGraph = graphWithPoissonError(histoData)
    dataGraph.Draw('same p')
    isRightSignal = False
    if histoSignal:
        histoSignal.SetFillStyle(0)
        histoSignal.SetFillColor(0)
        histoSignal.SetLineColor(getGroupColor('signal'))
        histoSignal.SetLineWidth(3)
        isRightSignal = (all(s in histoSignal.GetName() for s in ['signaltaumu', 'sr_mue']) or
                         all(s in histoSignal.GetName() for s in ['signaltaue', 'sr_emu']))
        if isRightSignal: histoSignal.Draw('histo same')
    if statErrBand and drawStatErr :
        statErrBand.SetFillStyle(3006)
        statErrBand.Draw('E2 same')
        leg.AddEntry(statErrBand, 'stat', 'f')
    if systErrBand and drawSystErr :
        systErrBand.SetFillStyle(3007)
        systErrBand.Draw('E2 same')
        leg.AddEntry(systErrBand, 'syst', 'f')
    totErrBand = systUtils.addErrorBandsInQuadrature(statErrBand, systErrBand)
    if totErrBand :
        totErrBand.Draw('E2 same')
        totErrBand.SetFillStyle(3005)
        leg.AddEntry(totErrBand, 'stat+syst', 'f')
        if printYieldSummary:
            print_total_error = False
            print ("{}:".format(topLabel if topLabel else dataGraph.GetName())+

                   (" expected {:.2f}^{{+{:.2f}}}_{{{:.2f}}}".format(totErrBand.GetY()[0],
                                                                    totErrBand.GetErrorYhigh(0),
                                                                    totErrBand.GetErrorYlow(0))
                    if print_total_error else
                    " expected {:.2f}^{{+{:.2f}}}_{{{:.2f}}} (stat) ^{{+{:.2f}}}_{{{:.2f}}} (syst)"
                    .format(totErrBand.GetY()[0],
                            statErrBand.GetErrorYhigh(0) if statErrBand else 0.0,
                            statErrBand.GetErrorYlow(0) if statErrBand else 0.0,
                            systErrBand.GetErrorYhigh(0) if systErrBand else 0.0,
                            systErrBand.GetErrorYlow(0) if systErrBand else 0.0)
                    )+
                   " obs {:.2f}".format(dataGraph.GetY()[0]))
    if histoSignal and isRightSignal:
        hname = histoSignal.GetName()
        label = ('H#rightarrow#mu#tau' if 'signaltaumu' in hname else
                 'H#rightarrowe#tau'   if 'signaltaue' in hname else
                 'signal')
        label = ("{}, BR=1%".format(label) if formatAuxMaterial else
                 "{}, BR=1%, {:.2f}".format(label, integralWou(histoSignal)))
        leg.AddEntry(histoSignal, label, 'l')
    leg.Draw('same')
    topPad.Update()
    tex = r.TLatex()
    tex.SetTextSize(0.5 * tex.GetTextSize())
    tex.SetNDC(True)
    label  = "%s tot bkg : "%(can.GetName())
    label += "%.3f #pm %.3f (stat)"%(integralAndError(histoTotBkg))
    if systErrBand :
        sysUp, sysDo = systUtils.totalUpDownVariation(systErrBand)
        label += "#pm #splitline{%.3f}{%.3f} (syst)"%(sysUp, sysDo)
    if drawYieldAndError :
        tex.DrawLatex(0.10, 0.95, label)
        topPad.SetTopMargin(2.0*topPad.GetTopMargin())
    atlasLabel = drawAtlasLabel(can, align=13, scale=0.75,
                                xpos=0.175 if formatAuxMaterial else 0.125,
                                ypos=0.945 if formatAuxMaterial else None,
                                public=True)
    if topLabel and not formatAuxMaterial : topRightLabel(can, topLabel, ypos=1.0)
    yMin, yMax = getMinMax([histoData, dataGraph, histoTotBkg, histoSignal, totErrBand])
    padMaster.SetMinimum(0.0)
    padMaster.SetMaximum(1.1 * yMax)
    padMaster.GetXaxis().SetLabelSize(0)
    padMaster.GetXaxis().SetTitleSize(0)
    increaseAxisFont(padMaster.GetXaxis())
    increaseAxisFont(padMaster.GetYaxis())
    topPad.RedrawAxis()
    topPad.Update() # force stack to create padMaster
    # draw bot (ratio)
    can.cd()
    botPad.Draw()
    botPad.cd()
    ratio = systUtils.buildAsymmRatioGraph(dataGraph, totErrBand)
    ratioPadMaster = padMaster.Clone(padMaster.GetName()+'_ratio')
    ratioPadMaster.SetDirectory(0)
    ratioPadMaster.Clear()
    yMin, yMax = 0.0, 2.0
    ratioPadMaster.SetMinimum(yMin)
    ratioPadMaster.SetMaximum(yMax)
    ratioPadMaster.SetStats(0)
    ratioPadMaster.Draw('axis')
    x_lo, x_hi = getXrange(ratioPadMaster)
    refLines = [referenceLine(x_lo, x_hi, y, y) for y in [0.5, 1.0, 1.5]]
    for l in refLines : l.Draw()
    err_band_r = systUtils.buildErrBandRatioGraph(totErrBand)
    err_band_r.Draw('E2 same')
    ratio.Draw('ep')
    xA, yA = ratioPadMaster.GetXaxis(), ratioPadMaster.GetYaxis()
    textScaleUp = 0.75*1.0/botPad.GetHNDC()
    # if xaxis_title : xA.SetTitle(xaxis_title)
    yA.SetNdivisions(-104)
    yA.SetTitle('Data/Bkg')
    yA.CenterTitle()
    yA.SetTitleOffset(yA.GetTitleOffset()/textScaleUp)
    xA.SetTitleSize(yA.GetTitleSize()) # was set to 0 for padmaster, restore it
    xA.SetLabelSize(yA.GetLabelSize())
    for a in [xA, yA] :
        a.SetLabelSize(a.GetLabelSize()*textScaleUp)
        a.SetTitleSize(a.GetTitleSize()*textScaleUp)
    botPad._graphical_objects = [ratio, ratioPadMaster, err_band_r] + refLines # avoid garbage collection
    botPad.Update()
    can.Update()
    for ext in ['png','eps'] : can.SaveAs(outdir+'/'+can.GetName()+'.'+ext)
コード例 #7
0
def plotHistos(
        histoData=None,
        histoSignal=None,
        histoTotBkg=None,
        histosBkg={},
        statErrBand=None,
        systErrBand=None,  # these are TGraphAsymmErrors
        canvasName='canvas',
        outdir='./',
        options=None,
        stack_order=[],
        topLabel='',
        drawStatErr=False,
        drawSystErr=False,
        drawYieldAndError=False,
        printYieldSummary=False):
    "Note: blinding can be required for only a subrange of the histo, so it is taken care of when filling"
    verbose = options.verbose
    formatAuxMaterial = options.format_aux
    setAtlasStyle()
    padMaster = histoData
    if verbose:
        print "plotting ", padMaster.GetName(), ' (', padMaster.GetEntries(
        ), ' entries)'
    can = r.TCanvas(canvasName, padMaster.GetTitle(), 800, 800)
    botPad, topPad = buildBotTopPads(can, squeezeMargins=False)
    can.cd()
    topPad.Draw()
    # draw top
    topPad.cd()
    topPad._hists = [padMaster]
    if formatAuxMaterial:
        for ax in [padMaster.GetXaxis(), padMaster.GetYaxis()]:
            ax.SetTitle(prettify(ax.GetTitle()))
    padMaster.Draw('axis')
    topPad.Update(
    )  # necessary to fool root's dumb object ownership of the stack
    stack = r.THStack('stack_' + padMaster.GetName(), '')
    r.SetOwnership(stack, False)
    topPad._hists.append(stack)
    leg = topRightLegend(can,
                         0.300 if formatAuxMaterial else 0.225,
                         0.400 if formatAuxMaterial else 0.325,
                         shiftX=-0.1 if formatAuxMaterial else 0.0,
                         shiftY=-0.1 if formatAuxMaterial else 0.0)
    topPad._leg = leg
    leg.SetBorderSize(0)
    leg.SetTextFont(padMaster.GetTitleFont())
    leg._reversedEntries = []

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

    for group, histo in sortedAs(histosBkg, stack_order):
        histo.SetFillColor(getGroupColor(group))
        histo.SetLineWidth(2)
        histo.SetLineColor(r.kBlack)
        stack.Add(histo)
        topPad._hists.append(histo)
        leg._reversedEntries.append(
            (histo, prettify(group) if formatAuxMaterial else
             "{0}: {1:.2f}".format(group, integralWou(histo)), 'F'))
    if not formatAuxMaterial:
        leg._reversedEntries.append((dummyHisto(), "{0}, {1:.2f}".format(
            'bkg', sum([integralWou(h) for h in stack.GetHists()])), 'l'))
    if statErrBand and drawStatErr:
        statErrBand.SetFillStyle(3006)
        leg._reversedEntries.append((statErrBand, 'stat', 'f'))
    if systErrBand and drawSystErr:
        systErrBand.SetFillStyle(3007)
        leg._reversedEntries.append((systErrBand, 'syst', 'f'))
    leg._reversedEntries.append(
        (histoData, "Data {0}".format(prettify(topLabel)) if formatAuxMaterial
         else "{0}, {1:.2f}".format('data', integralWou(histoData)), 'p'))
    for h, g, o in leg._reversedEntries[::-1]:
        leg.AddEntry(h, g, o)  # stack goes b-t, legend goes t-b
    stack.Draw('hist same')
    histoData.SetMarkerStyle(r.kFullCircle)
    histoData.SetLineWidth(2)
    dataGraph = graphWithPoissonError(histoData)
    dataGraph.Draw('same p')
    isRightSignal = False
    if histoSignal:
        histoSignal.SetFillStyle(0)
        histoSignal.SetFillColor(0)
        histoSignal.SetLineColor(getGroupColor('signal'))
        histoSignal.SetLineWidth(3)
        isRightSignal = (all(s in histoSignal.GetName()
                             for s in ['signaltaumu', 'sr_mue'])
                         or all(s in histoSignal.GetName()
                                for s in ['signaltaue', 'sr_emu']))
        if isRightSignal: histoSignal.Draw('histo same')
    if statErrBand and drawStatErr:
        statErrBand.SetFillStyle(3006)
        statErrBand.Draw('E2 same')
        leg.AddEntry(statErrBand, 'stat', 'f')
    if systErrBand and drawSystErr:
        systErrBand.SetFillStyle(3007)
        systErrBand.Draw('E2 same')
        leg.AddEntry(systErrBand, 'syst', 'f')
    totErrBand = systUtils.addErrorBandsInQuadrature(statErrBand, systErrBand)
    if totErrBand:
        totErrBand.Draw('E2 same')
        totErrBand.SetFillStyle(3005)
        leg.AddEntry(totErrBand, 'stat+syst', 'f')
        if printYieldSummary:
            print_total_error = False
            print(
                "{}:".format(topLabel if topLabel else dataGraph.GetName()) +
                (" expected {:.2f}^{{+{:.2f}}}_{{{:.2f}}}".format(
                    totErrBand.GetY()[0], totErrBand.GetErrorYhigh(0),
                    totErrBand.GetErrorYlow(0)) if print_total_error else
                 " expected {:.2f}^{{+{:.2f}}}_{{{:.2f}}} (stat) ^{{+{:.2f}}}_{{{:.2f}}} (syst)"
                 .format(totErrBand.GetY()[0],
                         statErrBand.GetErrorYhigh(0) if statErrBand else 0.0,
                         statErrBand.GetErrorYlow(0) if statErrBand else 0.0,
                         systErrBand.GetErrorYhigh(0) if systErrBand else 0.0,
                         systErrBand.GetErrorYlow(0) if systErrBand else 0.0))
                + " obs {:.2f}".format(dataGraph.GetY()[0]))
    if histoSignal and isRightSignal:
        hname = histoSignal.GetName()
        label = ('H#rightarrow#mu#tau' if 'signaltaumu' in hname else
                 'H#rightarrowe#tau' if 'signaltaue' in hname else 'signal')
        label = ("{}, BR=1%".format(label) if formatAuxMaterial else
                 "{}, BR=1%, {:.2f}".format(label, integralWou(histoSignal)))
        leg.AddEntry(histoSignal, label, 'l')
    leg.Draw('same')
    topPad.Update()
    tex = r.TLatex()
    tex.SetTextSize(0.5 * tex.GetTextSize())
    tex.SetNDC(True)
    label = "%s tot bkg : " % (can.GetName())
    label += "%.3f #pm %.3f (stat)" % (integralAndError(histoTotBkg))
    if systErrBand:
        sysUp, sysDo = systUtils.totalUpDownVariation(systErrBand)
        label += "#pm #splitline{%.3f}{%.3f} (syst)" % (sysUp, sysDo)
    if drawYieldAndError:
        tex.DrawLatex(0.10, 0.95, label)
        topPad.SetTopMargin(2.0 * topPad.GetTopMargin())
    atlasLabel = drawAtlasLabel(can,
                                align=13,
                                scale=0.75,
                                xpos=0.175 if formatAuxMaterial else 0.125,
                                ypos=0.945 if formatAuxMaterial else None,
                                public=True)
    if topLabel and not formatAuxMaterial:
        topRightLabel(can, topLabel, ypos=1.0)
    yMin, yMax = getMinMax(
        [histoData, dataGraph, histoTotBkg, histoSignal, totErrBand])
    padMaster.SetMinimum(0.0)
    padMaster.SetMaximum(1.1 * yMax)
    padMaster.GetXaxis().SetLabelSize(0)
    padMaster.GetXaxis().SetTitleSize(0)
    increaseAxisFont(padMaster.GetXaxis())
    increaseAxisFont(padMaster.GetYaxis())
    topPad.RedrawAxis()
    topPad.Update()  # force stack to create padMaster
    # draw bot (ratio)
    can.cd()
    botPad.Draw()
    botPad.cd()
    ratio = systUtils.buildAsymmRatioGraph(dataGraph, totErrBand)
    ratioPadMaster = padMaster.Clone(padMaster.GetName() + '_ratio')
    ratioPadMaster.SetDirectory(0)
    ratioPadMaster.Clear()
    yMin, yMax = 0.0, 2.0
    ratioPadMaster.SetMinimum(yMin)
    ratioPadMaster.SetMaximum(yMax)
    ratioPadMaster.SetStats(0)
    ratioPadMaster.Draw('axis')
    x_lo, x_hi = getXrange(ratioPadMaster)
    refLines = [referenceLine(x_lo, x_hi, y, y) for y in [0.5, 1.0, 1.5]]
    for l in refLines:
        l.Draw()
    err_band_r = systUtils.buildErrBandRatioGraph(totErrBand)
    err_band_r.Draw('E2 same')
    ratio.Draw('ep')
    xA, yA = ratioPadMaster.GetXaxis(), ratioPadMaster.GetYaxis()
    textScaleUp = 0.75 * 1.0 / botPad.GetHNDC()
    # if xaxis_title : xA.SetTitle(xaxis_title)
    yA.SetNdivisions(-104)
    yA.SetTitle('Data/Bkg')
    yA.CenterTitle()
    yA.SetTitleOffset(yA.GetTitleOffset() / textScaleUp)
    xA.SetTitleSize(
        yA.GetTitleSize())  # was set to 0 for padmaster, restore it
    xA.SetLabelSize(yA.GetLabelSize())
    for a in [xA, yA]:
        a.SetLabelSize(a.GetLabelSize() * textScaleUp)
        a.SetTitleSize(a.GetTitleSize() * textScaleUp)
    botPad._graphical_objects = [ratio, ratioPadMaster, err_band_r
                                 ] + refLines  # avoid garbage collection
    botPad.Update()
    can.Update()
    for ext in ['png', 'eps']:
        can.SaveAs(outdir + '/' + can.GetName() + '.' + ext)
コード例 #8
0
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
            }
コード例 #9
0
def main():
    parser = argparse.ArgumentParser(
        description=description,
        epilog=epilog,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    add_arg = parser.add_argument
    add_arg('-o', '--output-dir', default="./")
    add_arg('-p', '--process', help='one physics process, eg. ttw')
    add_arg('-s', '--systematic', help='one of the systematic variations')
    add_arg('-v', '--verbose', action='store_true')
    add_arg('-d', '--debug', action='store_true')
    args = parser.parse_args()

    set_log(args.verbose, args.debug)
    outdir = args.output_dir
    process = args.process
    systematic = args.systematic

    available_processes = get_input_samples().keys()
    if process not in available_processes:
        raise StandardError("invalid process %s, should be one of %s" %
                            (process, str(available_processes)))
    available_systematics = get_input_samples()[process].keys()
    if systematic not in available_systematics:
        raise StandardError("invalid systematic %s, should be one of %s" %
                            (systematic, str(available_systematics)))

    file_label = process + '_sys_' + systematic
    plot_label = process + ' sys. ' + systematic

    normalize_to_unity = False  # True
    luminosity = 1.0

    combiner = HistogramCombiner()

    combiner.build_samples(process=process, systematic=systematic)
    histogram_names = [
        'h_meff',
        'h_jetN',
        # 'h_electronPt', 'h_muonPt',
        # 'h_bjetEmulN', 'h_bjetN',
        # 'h_bjetEmulN_sr3b', 'h_bjetN_sr3b',
        # 'h_bjetEmulN_sr1b', 'h_bjetN_sr1b',
        # 'h_bjetEmulN_cr2bttV', 'h_bjetN_cr2bttV',
        # 'h_meff_sr3b',    'h_jetN_sr3b',    'h_met_sr3b',
        # 'h_meff_sr1b',    'h_jetN_sr1b',    'h_met_sr1b',
        # 'h_meff_sr0b5j',  'h_jetN_sr0b5j',  'h_met_sr0b5j',
        # 'h_meff_sr0b4j',  'h_jetN_sr0b4j',  'h_met_sr0b4j',
        # 'h_meff_sr0b3j',  'h_jetN_sr0b3j',  'h_met_sr0b3j',
        # 'h_meff_cr2bttV', 'h_jetN_cr2bttV', 'h_met_cr2bttV'
    ]

    combiner.compute_normalization_factors()
    output_pdf_name = outdir + '/' + file_label + '.pdf'
    c_summary = R.TCanvas('c_summary', 'plotExplicitSamples sampes summary ')
    combiner.print_sample_summary_to_pdf(
        c_summary,
        label="%s: nominal vs. %s systematic" % (process, systematic))
    c_summary.SaveAs(output_pdf_name + '(')

    for histogram_name in histogram_names:
        rebin = 'meff' in histogram_name  # and '_sr' in histogram_name # non-inclusive histos: low stats
        rebin_factor = (2 if 'meff' in histogram_name else
                        2 if 'jetN' in histogram_name else 1) if rebin else 1
        histograms = combiner.get_histograms(histogram_name=histogram_name)
        h_nom = histograms['nominal']
        h_up = histograms['up']
        h_dn = histograms['down']
        if 'h_jetFlavorMultiplicity' in histogram_name:
            h_nom = emulate_btag_multiplicity_from_truth_flavor(h_nom, 'nom')
            h_up = emulate_btag_multiplicity_from_truth_flavor(h_up, 'up')
            h_dn = emulate_btag_multiplicity_from_truth_flavor(h_dn, 'dn')
        histos = [h_nom, h_up, h_dn]
        for h in set(histos):  # set: avoid rebinning twice when up==down
            h.Rebin(rebin_factor)
        h_nom.SetLineWidth(2 * h_nom.GetLineWidth())
        h_nom.SetLineColor(R.kBlack)
        h_up.SetLineColor(R.kBlue)
        h_dn.SetLineColor(R.kRed)

        pad_master = h_nom
        pad_master.SetMaximum(1.1 * max([h.GetMaximum() for h in histos]))
        pad_master.SetMinimum(1.0 *
                              min([0.0] + [h.GetMinimum() for h in histos]))
        pad_master.GetYaxis().SetTitle('Arbitrary Units')
        pad_master.SetStats(0)
        can = R.TCanvas('c_ttV_syst_' + histogram_name,
                        'ttV explicit variations ' + pad_master.GetTitle(),
                        700, 700)
        botPad, topPad = ru.buildBotTopPads(can, squeezeMargins=False)
        # top
        can.cd()
        topPad.Draw()
        topPad.cd()
        topPad._po = [pad_master]  # persistent objects
        pad_master.GetXaxis().SetTitleSize(0)
        pad_master.GetXaxis().SetLabelSize(0)
        pad_master.Draw('axis')
        # ru.topRightLabel(topPad, pad_master.GetTitle(), xpos=0.5)
        ru.topRightLabel(topPad,
                         "#bf{#it{ATLAS}} Simulation Preliminary",
                         xpos=0.85,
                         ypos=0.9)
        ru.topRightLabel(topPad, "#sqrt{s} = 13 TeV", xpos=0.85, ypos=0.8)

        leg = ru.topRightLegend(can,
                                legWidth=0.225,
                                legHeight=0.300,
                                hShift=-0.10,
                                vShift=-0.25)
        leg.SetBorderSize(0)
        # leg.SetHeader(plot_label+ ("(norm=1)" if normalize_to_unity else "(lumi %.1f)"%luminosity))
        topPad._po.append(leg)

        def format_legend_label(h, l):
            return "{0}: {1:.2E} ({2:.0f})".format(l, h.Integral(),
                                                   h.GetEntries())

        def pretty_scale_legend_label(h, l):
            return ("nominal"
                    if l is 'nom' else "#mu = 2.0 #mu_{0}" if l is 'up' else
                    "#mu = 0.5 #mu_{0}" if l is 'dn' else 'unknown')

        for h, l in [(h_nom, 'nom'), (h_up, 'up'), (h_dn, 'dn')]:
            h.Draw('hist same')
            leg.AddEntry(h, pretty_scale_legend_label(h, l), 'l')
            topPad._po.append(h)
        leg.Draw('same')

        def integral_and_error(h):
            error = R.Double(0.0)
            integral = h.IntegralAndError(1, h.GetNbinsX() + 1, error)
            return integral, error

        def ratio_and_error(ave=(1.0, 0.01), bve=(2.0, 0.001)):
            a, sa = ave
            b, sb = bve
            if a and b:
                r = a / b
                e = r * sqrt((sa / a) * (sa / a) + (sb / b) * (sb / b))
                return r, e
            else:
                return 0.0, 0.0

        print_normalization_summary = histogram_name.startswith('h_meff')
        if print_normalization_summary:
            nom_int = h_nom.Integral()
            up_int = h_up.Integral()
            dn_int = h_dn.Integral()
            nom_int, nom_err = integral_and_error(h_nom)
            up_int, up_err = integral_and_error(h_up)
            dn_int, dn_err = integral_and_error(h_dn)
            rup, rupe = ratio_and_error((up_int, up_err), (nom_int, nom_err))
            rdn, rdne = ratio_and_error((dn_int, dn_err), (nom_int, nom_err))
            # print ("normalization change: "
            #        +"{} up {:.1%} down {:.1%} (nom {:.1f}, up {:.1f}, do {:.1f})".format(h_nom.GetName(),
            #                                                                           1.0-up_int/nom_int if nom_int else 1.0,
            #                                                                           1.0-dn_int/nom_int if nom_int else 1.0,
            #                                                                           nom_int,
            #                                                                           up_int,
            #                                                                           dn_int))
            print(
                "normalization change: " +
                "{} up {:.1%} +/- {:.1%} down {:.1%} +/- {:.1%} ".format(
                    h_nom.GetName(), 1.0 - rup, rupe, 1.0 - rdn, rdne) +
                "(integral: " +
                "nom {:.2E}  +/- {:.2E}, up {:.2E} +/- {:.2E}, do {:.2E} +/- {:.2E})"
                .format(nom_int, nom_err, up_int, up_err, dn_int, dn_err) +
                " (entries nom {:.2E} up {:.2E} do {:.2E}".format(
                    h_nom.GetEntries(), h_up.GetEntries(), h_dn.GetEntries()))
            print(
                "tex normalization change: " +
                "{} up ${:.1%} \pm {:.1%}$ down ${:.1%} \pm {:.1%}$ ".format(
                    h_nom.GetName(), 1.0 - rup, rupe, 1.0 - rdn, rdne))

            def bc(h):
                return [
                    h.GetBinContent(i) for i in range(1, 1 + h.GetNbinsX())
                ]

            def max_frac_variation(h1, h2):
                "maximum bin-by-bin fractional variation; h1 is denominator, empty bins skipped"
                bc1 = bc(h1)
                bc2 = bc(h2)
                return max(
                    [abs(b2 / b1) for b1, b2 in zip(bc1, bc2) if b1 and b2])

            def max_frac_variation_within10(h1, h2):
                """maximum bin-by-bin fractional variation; h1 is denominator.
                Bins with <0.1*peak are skipped"""
                bc1 = bc(h1)
                bc2 = bc(h2)
                m1 = max(bc1)
                m2 = max(bc2)
                return max([
                    abs(b2 / b1) for b1, b2 in zip(bc1, bc2)
                    if b1 > 0.1 * m1 and b2 > 0.1 * m2
                ])

            # print ("shape change: "
            #        +"{} up {:.1%} down {:.1%} ".format(h_nom.GetName(),
            #                                            1.0-max_frac_variation_within10(h_up, h_nom),
            #                                            1.0-max_frac_variation_within10(h_dn, h_nom)))

        topPad.Update()
        # bottom
        can.cd()
        botPad.SetTopMargin(1.25 * botPad.GetTopMargin())
        botPad.Draw()
        botPad.cd()
        ratio_up = ru.buildRatioHistogram(h_up, h_nom)
        ratio_dn = ru.buildRatioHistogram(h_dn, h_nom)
        yMin, yMax = 0.5, 1.5
        ratioPadMaster = pad_master.Clone(pad_master.GetName() + '_ratio')
        ratioPadMaster.SetMinimum(yMin)
        ratioPadMaster.SetMaximum(yMax)
        ratioPadMaster.SetStats(0)
        ratioPadMaster.Draw('axis')
        x_lo, x_hi = ru.getXrange(ratioPadMaster)
        refLines = [
            ru.referenceLine(x_lo, x_hi, y, y) for y in [0.5, 1.0, 1.5]
            if y > yMin and y < yMax
        ]
        for l in refLines:
            l.Draw()
        ratio_up.Draw('same')
        ratio_dn.Draw('same')
        xA, yA = ratioPadMaster.GetXaxis(), ratioPadMaster.GetYaxis()
        textScaleUp = 0.75 * 1.0 / botPad.GetHNDC()
        yA.SetNdivisions(-102)
        yA.SetTitle('Ratio')
        yA.CenterTitle()
        yA.SetTitleOffset(yA.GetTitleOffset() / textScaleUp)
        xA.SetTitleSize(
            yA.GetTitleSize())  # x- was set to 0 for padmaster, restore it
        xA.SetLabelSize(yA.GetLabelSize())
        xA.SetTitle(prettify_title(xA.GetTitle()))
        for a in [xA, yA]:
            a.SetLabelSize(a.GetLabelSize() * textScaleUp)
            a.SetTitleSize(a.GetTitleSize() * textScaleUp)
        botPad._graphical_objects = [ratio_up, ratio_dn, ratioPadMaster
                                     ] + refLines  # avoid garbage collection
        botPad.Update()
        can.Update()
        first_histo = histogram_name is histogram_names[0]
        last_histo = histogram_name is histogram_names[-1]
        can.SaveAs(outdir + '/' + can.GetName() + '.png')
        can.SaveAs(outdir + '/' + can.GetName() + '.eps')
        can.SaveAs(output_pdf_name + (')' if last_histo else ''))
コード例 #10
0
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
    }
コード例 #11
0
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)
コード例 #12
0
def main() :
    parser = argparse.ArgumentParser(description=description,
                                     epilog=epilog,
                                     formatter_class=argparse.RawDescriptionHelpFormatter)
    add_arg = parser.add_argument
    add_arg('-o', '--output-dir', default="./")
    add_arg('-p', '--process', help='one physics process, eg. ttw')
    add_arg('-s', '--systematic', help='one of the systematic variations')
    add_arg('-v', '--verbose', action='store_true')
    add_arg('-d', '--debug', action='store_true')
    args = parser.parse_args()

    set_log(args.verbose, args.debug)
    outdir = args.output_dir
    process = args.process
    systematic = args.systematic

    available_processes = get_input_samples().keys()
    if process not in available_processes:
        raise StandardError("invalid process %s, should be one of %s"%(process, str(available_processes)))
    available_systematics = get_input_samples()[process].keys()
    if systematic not in available_systematics:
        raise StandardError("invalid systematic %s, should be one of %s"%(systematic, str(available_systematics)))

    file_label = process+'_sys_'+systematic
    plot_label = process+' sys. '+systematic

    normalize_to_unity = False # True
    luminosity = 1.0

    combiner = HistogramCombiner()

    combiner.build_samples(process=process, systematic=systematic)
    histogram_names = ['h_meff', 'h_jetN',
                       # 'h_electronPt', 'h_muonPt',
                       # 'h_bjetEmulN', 'h_bjetN',
                       # 'h_bjetEmulN_sr3b', 'h_bjetN_sr3b',
                       # 'h_bjetEmulN_sr1b', 'h_bjetN_sr1b',
                       # 'h_bjetEmulN_cr2bttV', 'h_bjetN_cr2bttV',
                       # 'h_meff_sr3b',    'h_jetN_sr3b',    'h_met_sr3b',
                       # 'h_meff_sr1b',    'h_jetN_sr1b',    'h_met_sr1b',
                       # 'h_meff_sr0b5j',  'h_jetN_sr0b5j',  'h_met_sr0b5j',
                       # 'h_meff_sr0b4j',  'h_jetN_sr0b4j',  'h_met_sr0b4j',
                       # 'h_meff_sr0b3j',  'h_jetN_sr0b3j',  'h_met_sr0b3j',
                       # 'h_meff_cr2bttV', 'h_jetN_cr2bttV', 'h_met_cr2bttV'
                       ]

    combiner.compute_normalization_factors()
    output_pdf_name = outdir+'/'+file_label+'.pdf'
    c_summary = R.TCanvas('c_summary', 'plotExplicitSamples sampes summary ')
    combiner.print_sample_summary_to_pdf(c_summary, label="%s: nominal vs. %s systematic"%(process, systematic))
    c_summary.SaveAs(output_pdf_name+'(')


    for histogram_name in histogram_names:
        rebin = 'meff' in histogram_name # and '_sr' in histogram_name # non-inclusive histos: low stats
        rebin_factor = (2 if 'meff' in histogram_name else 2 if 'jetN' in histogram_name else 1) if rebin else 1
        histograms = combiner.get_histograms(histogram_name=histogram_name)
        h_nom = histograms['nominal']
        h_up  = histograms['up']
        h_dn  = histograms['down']
        if 'h_jetFlavorMultiplicity' in histogram_name:
            h_nom = emulate_btag_multiplicity_from_truth_flavor(h_nom, 'nom')
            h_up  = emulate_btag_multiplicity_from_truth_flavor(h_up, 'up')
            h_dn  = emulate_btag_multiplicity_from_truth_flavor(h_dn, 'dn')
        histos = [h_nom, h_up, h_dn]
        for h in set(histos): # set: avoid rebinning twice when up==down
            h.Rebin(rebin_factor)
        h_nom.SetLineWidth(2*h_nom.GetLineWidth())
        h_nom.SetLineColor(R.kBlack)
        h_up.SetLineColor(R.kBlue)
        h_dn.SetLineColor(R.kRed)

        pad_master = h_nom
        pad_master.SetMaximum(1.1*max([h.GetMaximum() for h in histos]))
        pad_master.SetMinimum(1.0*min([0.0]+[h.GetMinimum() for h in histos]))
        pad_master.GetYaxis().SetTitle('Arbitrary Units')
        pad_master.SetStats(0)
        can = R.TCanvas('c_ttV_syst_'+histogram_name, 'ttV explicit variations '+pad_master.GetTitle(), 700, 700)
        botPad, topPad = ru.buildBotTopPads(can, squeezeMargins=False)
        # top
        can.cd()
        topPad.Draw()
        topPad.cd()
        topPad._po = [pad_master] # persistent objects
        pad_master.GetXaxis().SetTitleSize(0)
        pad_master.GetXaxis().SetLabelSize(0)
        pad_master.Draw('axis')
        # ru.topRightLabel(topPad, pad_master.GetTitle(), xpos=0.5)
        ru.topRightLabel(topPad, "#bf{#it{ATLAS}} Simulation Preliminary", xpos=0.85, ypos=0.9)
        ru.topRightLabel(topPad, "#sqrt{s} = 13 TeV",                   xpos=0.85, ypos=0.8)

        leg = ru.topRightLegend(can, legWidth=0.225, legHeight=0.300, hShift=-0.10, vShift=-0.25)
        leg.SetBorderSize(0)
        # leg.SetHeader(plot_label+ ("(norm=1)" if normalize_to_unity else "(lumi %.1f)"%luminosity))
        topPad._po.append(leg)
        def format_legend_label(h, l):
            return "{0}: {1:.2E} ({2:.0f})".format(l, h.Integral(), h.GetEntries())
        def pretty_scale_legend_label(h, l):
            return ("nominal" if l is 'nom' else
                    "#mu = 2.0 #mu_{0}" if l is 'up' else
                    "#mu = 0.5 #mu_{0}" if l is 'dn' else
                    'unknown')
        for h,l in [(h_nom, 'nom'), (h_up, 'up'), (h_dn, 'dn')]:
            h.Draw('hist same')
            leg.AddEntry(h, pretty_scale_legend_label(h, l), 'l')
            topPad._po.append(h)
        leg.Draw('same')
        def integral_and_error(h):
            error = R.Double(0.0)
            integral = h.IntegralAndError(1, h.GetNbinsX()+1, error)
            return integral, error
        def ratio_and_error(ave=(1.0, 0.01), bve=(2.0, 0.001)):
            a, sa = ave
            b, sb = bve
            if a and b:
                r = a/b
                e = r * sqrt((sa/a)*(sa/a)+(sb/b)*(sb/b))
                return r, e
            else:
                return 0.0, 0.0
        print_normalization_summary = histogram_name.startswith('h_meff')
        if print_normalization_summary:
            nom_int = h_nom.Integral()
            up_int = h_up.Integral()
            dn_int = h_dn.Integral()
            nom_int, nom_err = integral_and_error(h_nom)
            up_int, up_err = integral_and_error(h_up)
            dn_int, dn_err = integral_and_error(h_dn)
            rup, rupe = ratio_and_error((up_int, up_err), (nom_int, nom_err))
            rdn, rdne = ratio_and_error((dn_int, dn_err), (nom_int, nom_err))
            # print ("normalization change: "
            #        +"{} up {:.1%} down {:.1%} (nom {:.1f}, up {:.1f}, do {:.1f})".format(h_nom.GetName(),
            #                                                                           1.0-up_int/nom_int if nom_int else 1.0,
            #                                                                           1.0-dn_int/nom_int if nom_int else 1.0,
            #                                                                           nom_int,
            #                                                                           up_int,
            #                                                                           dn_int))
            print ("normalization change: "
                   +"{} up {:.1%} +/- {:.1%} down {:.1%} +/- {:.1%} ".format(h_nom.GetName(), 1.0-rup, rupe, 1.0-rdn, rdne)
                   +"(integral: "
                   +"nom {:.2E}  +/- {:.2E}, up {:.2E} +/- {:.2E}, do {:.2E} +/- {:.2E})".format(nom_int, nom_err,
                                                                                                 up_int, up_err,
                                                                                                 dn_int, dn_err)
                   +" (entries nom {:.2E} up {:.2E} do {:.2E}".format(h_nom.GetEntries(), h_up.GetEntries(), h_dn.GetEntries()))
            print ("tex normalization change: "
                   +"{} up ${:.1%} \pm {:.1%}$ down ${:.1%} \pm {:.1%}$ ".format(h_nom.GetName(), 1.0-rup, rupe, 1.0-rdn, rdne)
                   )

            def bc(h): return [h.GetBinContent(i) for i in range(1,1+h.GetNbinsX())]
            def max_frac_variation(h1, h2):
                "maximum bin-by-bin fractional variation; h1 is denominator, empty bins skipped"
                bc1 = bc(h1)
                bc2 = bc(h2)
                return max([abs(b2/b1) for b1, b2 in zip(bc1, bc2) if b1 and b2])
            def max_frac_variation_within10(h1, h2):
                """maximum bin-by-bin fractional variation; h1 is denominator.
                Bins with <0.1*peak are skipped"""
                bc1 = bc(h1)
                bc2 = bc(h2)
                m1 = max(bc1)
                m2 = max(bc2)
                return max([abs(b2/b1) for b1, b2 in zip(bc1, bc2) if b1>0.1*m1 and b2>0.1*m2])

            # print ("shape change: "
            #        +"{} up {:.1%} down {:.1%} ".format(h_nom.GetName(),
            #                                            1.0-max_frac_variation_within10(h_up, h_nom),
            #                                            1.0-max_frac_variation_within10(h_dn, h_nom)))

        topPad.Update()
        # bottom
        can.cd()
        botPad.SetTopMargin(1.25*botPad.GetTopMargin())
        botPad.Draw()
        botPad.cd()
        ratio_up = ru.buildRatioHistogram(h_up, h_nom)
        ratio_dn = ru.buildRatioHistogram(h_dn, h_nom)
        yMin, yMax = 0.5, 1.5
        ratioPadMaster = pad_master.Clone(pad_master.GetName()+'_ratio')
        ratioPadMaster.SetMinimum(yMin)
        ratioPadMaster.SetMaximum(yMax)
        ratioPadMaster.SetStats(0)
        ratioPadMaster.Draw('axis')
        x_lo, x_hi = ru.getXrange(ratioPadMaster)
        refLines = [ru.referenceLine(x_lo, x_hi, y, y) for y in [0.5, 1.0, 1.5] if y>yMin and y<yMax]
        for l in refLines : l.Draw()
        ratio_up.Draw('same')
        ratio_dn.Draw('same')
        xA, yA = ratioPadMaster.GetXaxis(), ratioPadMaster.GetYaxis()
        textScaleUp = 0.75*1.0/botPad.GetHNDC()
        yA.SetNdivisions(-102)
        yA.SetTitle('Ratio')
        yA.CenterTitle()
        yA.SetTitleOffset(yA.GetTitleOffset()/textScaleUp)
        xA.SetTitleSize(yA.GetTitleSize()) # x- was set to 0 for padmaster, restore it
        xA.SetLabelSize(yA.GetLabelSize())
        xA.SetTitle(prettify_title(xA.GetTitle()))
        for a in [xA, yA] :
            a.SetLabelSize(a.GetLabelSize()*textScaleUp)
            a.SetTitleSize(a.GetTitleSize()*textScaleUp)
        botPad._graphical_objects = [ratio_up, ratio_dn, ratioPadMaster] + refLines # avoid garbage collection
        botPad.Update()
        can.Update()
        first_histo = histogram_name is histogram_names[0]
        last_histo  = histogram_name is histogram_names[-1]
        can.SaveAs(outdir+'/'+can.GetName()+'.png')
        can.SaveAs(outdir+'/'+can.GetName()+'.eps')
        can.SaveAs(output_pdf_name+ (')' if last_histo else ''))