def plotStackedHistos(histosFlavorSlice={}, canvasName='', outputDir='./', frameTitle='stack', colors={}) : "Plot the input histos used to compute the fractions" histos = histosFlavorSlice can = r.TCanvas(canvasName, canvasName, 800, 600) can.cd() stack = r.THStack('stack_'+canvasName, '') leg = topRightLegend(can, 0.275, 0.475, shift=-0.025) leg.SetBorderSize(0) colors = SampleUtils.colors if not colors else colors procs = sorted(histos.keys()) for p in procs: h = histos[p] h.SetFillColor(colors[p]) h.SetLineColor(h.GetFillColor()) h.SetDrawOption('bar') stack.Add(h) for s in procs[::-1] : leg.AddEntry(histos[s], s, 'F') # stack goes b-t, legend goes t-b stack.Draw('hist e') leg.Draw('same') tex = r.TLatex() tex.SetNDC(True) tex.SetTextFont(first(histos).GetTitleFont()) tex.SetTextSize(first(histos).GetTitleSize()) tex.DrawLatex(0.1, 0.925, frameTitle.split(';')[0]) can.Update() # force stack to create canMaster canMaster = stack.GetHistogram() canMaster.SetTitle(frameTitle) canMaster.Draw('axis same') can._graphical_objects = [stack, canMaster, leg, tex] + [h for h in stack.GetStack()] can.Update() for ext in ['png','eps'] : outFilename = outputDir+'/'+canvasName+'.'+ext rmIfExists(outFilename) can.SaveAs(outFilename)
def plot1dEfficiencies(effs={}, canvasName='', outputDir='./', frameTitle='title;p_{T} [GeV]; efficiency', zoomIn=False) : can = r.TCanvas(canvasName, '', 800, 600) can.cd() padMaster = None colors, markers = SampleUtils.colors, SampleUtils.markers for s,h in effs.iteritems() : h.SetLineColor(colors[s] if s in colors else r.kBlack) h.SetMarkerColor(h.GetLineColor()) h.SetMarkerStyle(markers[s] if s in markers else r.kFullCircle) drawOpt = 'ep same' if padMaster else 'ep' h.Draw(drawOpt) if not padMaster : padMaster = h minY, maxY = getMinMax(effs.values()) if zoomIn else (0.0, 1.0) padMaster.GetYaxis().SetRangeUser(min([0.0, minY]), 1.1*maxY) padMaster.SetMinimum(0.0) padMaster.SetMaximum(1.1*maxY) padMaster.SetMaximum(0.25 if (maxY < 0.25 and zoomIn) else 1.1) padMaster.SetTitle(frameTitle) padMaster.SetStats(False) drawLegendWithDictKeys(can, effs) can.Update() for ext in ['png','eps'] : outFilename = outputDir+'/'+canvasName+'.'+ext rmIfExists(outFilename) can.SaveAs(outFilename)
def plotHistRatioAndFit(histos, ratio, fitfunc, outfname, graphics_attributes={}) : can = r.TCanvas('can_'+outfname, outfname, 800, 600) botPad, topPad = buildBotTopPads(can, splitFraction=0.35) can.cd() topPad.Draw() topPad.cd() pm = first(histos) pm.Draw('axis') xAx, yAx = pm.GetXaxis(), pm.GetYaxis() xAx.SetTitle('') xAx.SetLabelSize(0) yAx.SetRangeUser(0.0, 1.2) yAx.SetNdivisions(505) # for some reason some of the inputs are already ratios with -201 textScaleUp = 1.0/topPad.GetHNDC() yAx.SetLabelSize(textScaleUp*0.04) yAx.SetTitleSize(textScaleUp*0.04) yAx.SetTitle(graphics_attributes['ytitle']) yAx.SetTitleOffset(yAx.GetTitleOffset()/textScaleUp) for k, h in histos.iteritems() : h.SetMarkerStyle(graphics_attributes['markers'][k]) h.SetMarkerColor(graphics_attributes['colors'][k]) h.SetLineColor(graphics_attributes['colors'][k]) h.Draw('same') labels = graphics_attributes['labels'] drawLegendWithDictKeys(topPad, dict([(labels[s], histos[s]) for s in histos.keys()]), legWidth=0.4) can.cd() botPad.Draw() botPad.cd() ratio.Draw('axis') textScaleUp = 1.0/botPad.GetHNDC() xAx, yAx = ratio.GetXaxis(), ratio.GetYaxis() yAx.SetRangeUser(0.0, 2.0) xAx.SetTitle(graphics_attributes['xtitle']) yAx.SetNdivisions(-202) yAx.SetTitle('Data/Sim') yAx.CenterTitle() for a in [xAx, yAx] : if a.GetLabelSize()>0.04 : continue a.SetLabelSize(a.GetLabelSize()*textScaleUp) a.SetTitleSize(a.GetTitleSize()*textScaleUp) a.SetTitleOffset(a.GetTitleOffset()/textScaleUp) ratio.SetMarkerStyle(graphics_attributes['markers']['data']) fitfunc.SetLineWidth(2) fitfunc.SetLineStyle(2) fitfunc.Draw('same') ratio.Draw('same') tex = r.TLatex() tex.SetNDC(True) p0, p0Err, chi2, ndf = fitResults(fitfunc) fitParLabel = "Const. fit : %s #pm %s"%(pdgRound(p0, p0Err)) fitGoodLabel = "#chi^{2}/DOF : %.2f / %d"%(chi2, ndf) tex.SetTextSize(yAx.GetTitleSize()) tex.SetTextFont(yAx.GetTitleFont()) tex.DrawLatex(0.15, 0.40, "#splitline{%s}{%s}"%(fitParLabel, fitGoodLabel)) can.Update() outfname = outfname+'.png' rmIfExists(outfname) # avoid root warnings can.SaveAs(outfname)
def plotPerSourceEff(histosPerVar={}, outputDir='', lepton='', region='', sample='', verbose=False, zoomIn=True): "plot efficiency for each source (and 'anysource') as a function of each var; expect histos[var][source][loose,tight]" variables = histosPerVar.keys() sources = [s for s in first(histosPerVar).keys() if s!='real'] # only fake eff really need a scale factor colors = colorsLineSources mkdirIfNeeded(outputDir) for var in filter(lambda x : x in ['pt1', 'eta1'], histosPerVar.keys()): histosPerSource = dict((s, histosPerVar[var][s]) for s in sources) canvasBasename = region+'_efficiency_'+lepton+'_'+var+("_%s"%sample if sample else '') missingSources = [s for s, h in histosPerSource.iteritems() if not h['loose'] or not h['tight']] if missingSources: if verbose : print "skip %s, missing histos for %s"%(var, str(missingSources)) continue anySourceLoose = summedHisto([h['loose'] for h in histosPerSource.values()]) anySourceTight = summedHisto([h['tight'] for h in histosPerSource.values()]) anySourceLoose.SetName(histoNamePerSource(var, 'any', 'loose', region)) anySourceTight.SetName(histoNamePerSource(var, 'any', 'tight', region)) histosPerSource['any'] = { 'loose' : anySourceLoose, 'tight' : anySourceTight } emptyBkg = anySourceLoose.Integral()==0 or anySourceTight.Integral()==0 if emptyBkg: if verbose : print "empty backgrounds, skip %s"%canvasBasename continue def computeEfficiencies(histosPerSource={}) : sources = histosPerSource.keys() num = dict((s, histosPerSource[s]['tight']) for s in sources) den = dict((s, histosPerSource[s]['loose']) for s in sources) eff = dict((s, h.Clone(h.GetName().replace('tight', 'tight_over_loose'))) for s, h in num.iteritems()) [eff[s].Divide(den[s]) for s in sources] return eff effs = computeEfficiencies(histosPerSource) can = r.TCanvas('c_'+canvasBasename, canvasBasename, 800, 600) can.cd() pm = first(effs) # pad master pm.SetStats(False) pm.Draw('axis') can.Update() for s, h in effs.iteritems() : h.SetMarkerColor(colors[s] if s in colors else r.kBlack) h.SetLineColor(h.GetMarkerColor()) h.SetLineWidth(2*h.GetLineWidth()) h.SetMarkerStyle(markersSources[s] if s in markersSources else r.kDot) h.Draw('ep same') h.SetDirectory(0) #pprint.pprint(effs) yMin, yMax = getMinMax(effs.values()) pm.SetMinimum(0.0) pm.SetMaximum(0.25 if yMax < 0.5 and zoomIn else 1.1) can.Update() topRightLabel(can, canvasBasename, xpos=0.125, align=13) drawLegendWithDictKeys(can, effs, opt='lp') can.RedrawAxis() can._histos = effs can.Update() outFname = os.path.join(outputDir, canvasBasename+'.png') utils.rmIfExists(outFname) can.SaveAs(outFname)
def plotStackedHistos(histosPerGroup={}, outputDir='', region='', verbose=False): groups = histosPerGroup.keys() variables = first(histosPerGroup).keys() leptonTypes = first(first(histosPerGroup)).keys() colors = getGroupColor() mkdirIfNeeded(outputDir) histosPerName = dict([(region+'_'+var+'_'+lt, # one canvas for each histo, so key with histoname w/out group dict([(g, histosPerGroup[g][var][lt]) for g in groups])) for var in variables for lt in leptonTypes]) for histoname, histosPerGroup in histosPerName.iteritems(): missingGroups = [g for g, h in histosPerGroup.iteritems() if not h] if missingGroups: if verbose : print "skip %s, missing histos for %s"%(histoname, str(missingGroups)) continue bkgHistos = dict([(g, h) for g, h in histosPerGroup.iteritems() if g not in ['data', 'signal']]) totBkg = summedHisto(bkgHistos.values()) err_band = None # buildErrBandGraph(totBkg, computeStatErr2(totBkg)) emptyBkg = totBkg.Integral()==0 if emptyBkg: if verbose : print "empty backgrounds, skip %s"%histoname continue can = r.TCanvas('c_'+histoname, histoname, 800, 600) can.cd() pm = totBkg # pad master pm.SetStats(False) pm.Draw('axis') can.Update() # necessary to fool root's dumb object ownership stack = r.THStack('stack_'+histoname,'') can.Update() r.SetOwnership(stack, False) for s, h in bkgHistos.iteritems() : h.SetFillColor(colors[s] if s in colors else r.kOrange) h.SetDrawOption('bar') h.SetDirectory(0) stack.Add(h) stack.Draw('hist same') # err_band.Draw('E2 same') data = histosPerGroup['data'] if data and data.GetEntries(): data.SetMarkerStyle(r.kFullDotLarge) data.Draw('p same') # yMin, yMax = getMinMax([h for h in [totBkg, data, err_band] if h]) # fixme with err_band yMin, yMax = 0.0, data.GetMaximum() pm.SetMinimum(0.0) pm.SetMaximum(1.1*yMax) can.Update() topRightLabel(can, histoname, xpos=0.125, align=13) # drawLegendWithDictKeys(can, dictSum(bkgHistos, {'stat err':err_band}), opt='f') drawLegendWithDictKeys(can, bkgHistos, opt='f') can.RedrawAxis() can._stack = stack can._histos = [h for h in stack.GetHists()]+[data] can.Update() outFname = os.path.join(outputDir, histoname+'.png') utils.rmIfExists(outFname) can.SaveAs(outFname)
def plotStackedHistosSources(histosPerVar={}, outputDir='', region='', verbose=False): variables = histosPerVar.keys() sources = first(histosPerVar).keys() colors = colorsFillSources mkdirIfNeeded(outputDir) for var in variables: for lOrT in ['loose', 'tight']: histos = dict((s, histosPerVar[var][s][lOrT]) for s in sources) canvasBasename = region + '_region_' + var + '_' + lOrT missingSources = [s for s, h in histos.iteritems() if not h] if missingSources: if verbose: print "skip %s, missing histos for %s" % ( var, str(missingSources)) continue totBkg = summedHisto(histos.values()) err_band = None # buildErrBandGraph(totBkg, computeStatErr2(totBkg)) emptyBkg = totBkg.Integral() == 0 if emptyBkg: if verbose: print "empty backgrounds, skip %s" % canvasBasename continue can = r.TCanvas('c_' + canvasBasename, canvasBasename, 800, 600) can.cd() pm = totBkg # pad master pm.SetStats(False) pm.Draw('axis') can.Update() # necessary to fool root's dumb object ownership stack = r.THStack('stack_' + canvasBasename, '') can.Update() r.SetOwnership(stack, False) for s, h in histos.iteritems(): h.SetFillColor(colors[s] if s in colors else r.kOrange) h.SetDrawOption('bar') h.SetDirectory(0) stack.Add(h) stack.Draw('hist same') # err_band.Draw('E2 same') yMin, yMax = getMinMax( [h for h in [totBkg, err_band] if h is not None]) pm.SetMinimum(0.0) pm.SetMaximum(1.1 * yMax) can.Update() topRightLabel(can, canvasBasename, xpos=0.125, align=13) # drawLegendWithDictKeys(can, dictSum(histos, {'stat err':err_band}), opt='f') drawLegendWithDictKeys(can, histos, opt='f') can.RedrawAxis() can._stack = stack can._histos = [h for h in stack.GetHists()] can.Update() outFname = os.path.join(outputDir, canvasBasename + '.png') utils.rmIfExists(outFname) can.SaveAs(outFname)
def plotFractionsStacked(histos={}, canvasName='', canvasTitle='', outputDir='./', frameTitle='title;p_{T} [GeV]; efficiency', histos2={}, h1Label='', h2Label='') : "plot stack of histos; optional histos2 are also stacked with the same colors, but with different fill style" can = r.TCanvas(canvasName, '', 800, 600) can.cd() stack = r.THStack('stack_'+canvasName, '') leg = topRightLegend(can, 0.275, 0.475, shift=+0.010) leg.SetBorderSize(0) leg.SetX1NDC(0.9) leg.SetX2NDC(1.0) colors = SampleUtils.colors procs = sorted(histos.keys()) def setHistoAtts(histo, process, colors=colors, fillStyle=None) : h, p = histo, process h.SetMarkerSize(0) h.SetFillColor(colors[p]) h.SetLineColor(h.GetFillColor()) h.SetDrawOption('bar') paleColors = {'ttbar':r.kRed-9, 'zjets' : r.kOrange-4, 'wjets' : r.kBlue-8, 'diboson' : r.kSpring+1, 'singletop' : r.kAzure+6, 'multijet' : r.kGray, 'heavyflavor' : r.kViolet-9} if fillStyle : h.SetFillColor(paleColors[p]) h.SetLineColor(h.GetFillColor()) for p in procs: h = histos[p] setHistoAtts(h, p) stack.Add(h) for s in procs[::-1] : leg.AddEntry(histos[s], ('bb/cc' if s=='heavyflavor' else s), 'F') # stack goes b-t, legend goes t-b for p in filter(lambda p: p in histos2, procs) : setHistoAtts(histos2[p], p, fillStyle=3001) stack.Add(histos2[p]) stack.Draw('hist') if h1Label or h2Label: leg.SetHeader(', '.join(["%s : %s"%(f,l) if l else '' for f,l in [('darker',h1Label), ('lighter',h2Label)]])) leg.Draw('same') tex = r.TLatex() tex.SetNDC(True) tex.DrawLatex(0.1, 0.9, 'fractions: '+frameTitle[:frameTitle.find(';')-1]) can.Update() # force stack to create canMaster canMaster = stack.GetHistogram() canMaster.SetTitle(frameTitle) canMaster.Draw('axis same') can._graphical_objects = [stack, canMaster, leg, tex] + [h for h in stack.GetStack()] can.Update() for ext in ['png','eps'] : outFilename = outputDir+'/'+canvasName+'.'+ext rmIfExists(outFilename) can.SaveAs(outFilename)
def plotStackedHistosWithData(histosPerGroup={}, outputDir='', canvasname='', canvastitle='', colors={}, verbose=False): "histosPerGroup[group], where group=data is treated as special" groups = histosPerGroup.keys() mkdirIfNeeded(outputDir) missingGroups = [g for g, h in histosPerGroup.iteritems() if not h] if missingGroups: if verbose : print "skip %s, missing histos for %s"%(histoname, str(missingGroups)) return bkgHistos = dict([(g, h) for g, h in histosPerGroup.iteritems() if not isDataSample(g)]) totBkg = summedHisto(bkgHistos.values()) err_band = buildErrBandGraph(totBkg, computeStatErr2(totBkg)) emptyBkg = totBkg.Integral()==0 histoname, region = totBkg.GetName(), 'emu' # tmp replacement vars, to be fixed if emptyBkg: if verbose : print "empty backgrounds, skip %s"%histoname return can = r.TCanvas(canvasname, canvastitle, 800, 600) can.cd() pm = totBkg # pad master pm.SetStats(False) pm.Draw('axis') can.Update() # necessary to fool root's dumb object ownership stack = r.THStack('stack_'+histoname,'') can.Update() r.SetOwnership(stack, False) for s, h in bkgHistos.iteritems() : h.SetFillColor(colors[s] if s in colors else r.kOrange) h.SetDrawOption('bar') h.SetDirectory(0) stack.Add(h) stack.Draw('hist same') err_band.Draw('E2 same') data = histosPerGroup['data'] if 'data' in histosPerGroup else None if data and data.GetEntries(): data.SetMarkerStyle(r.kFullDotLarge) data.Draw('p same') if verbose : print "integrals : {0} tot.bkg.: {1}, data: {2}".format(histoname, totBkg.Integral(), data.Integral()) else: print "no data" yMin, yMax = getMinMax([h for h in [totBkg, data, err_band] if h]) pm.SetMinimum(0.0) pm.SetMaximum(1.1*yMax) can.Update() topRightLabel(can, "#splitline{%s}{%s}"%(histoname, region), xpos=0.15, ypos=(1.0-0.5*can.GetTopMargin()), align=13) drawLegendWithDictKeys(can, dictSum(bkgHistos, {'stat err':err_band}), opt='f') can.RedrawAxis() can._stack = stack can._histos = [h for h in stack.GetHists()]+[data] can.Update() filename=os.path.join(outputDir, histoname+'.png') rmIfExists(filename) can.SaveAs(filename)
def plotStackedHistosSources(histosPerVar={}, outputDir='', region='', verbose=False): variables = histosPerVar.keys() sources = first(histosPerVar).keys() colors = colorsFillSources mkdirIfNeeded(outputDir) for var in variables: for lOrT in ['loose', 'tight']: histos = dict((s, histosPerVar[var][s][lOrT]) for s in sources) canvasBasename = region+'_region_'+var+'_'+lOrT missingSources = [s for s, h in histos.iteritems() if not h] if missingSources: if verbose : print "skip %s, missing histos for %s"%(var, str(missingSources)) continue totBkg = summedHisto(histos.values()) err_band = None # buildErrBandGraph(totBkg, computeStatErr2(totBkg)) emptyBkg = totBkg.Integral()==0 if emptyBkg: if verbose : print "empty backgrounds, skip %s"%canvasBasename continue can = r.TCanvas('c_'+canvasBasename, canvasBasename, 800, 600) can.cd() pm = totBkg # pad master pm.SetStats(False) pm.Draw('axis') can.Update() # necessary to fool root's dumb object ownership stack = r.THStack('stack_'+canvasBasename,'') can.Update() r.SetOwnership(stack, False) for s, h in histos.iteritems() : h.SetFillColor(colors[s] if s in colors else r.kOrange) h.SetDrawOption('bar') h.SetDirectory(0) stack.Add(h) stack.Draw('hist same') # err_band.Draw('E2 same') yMin, yMax = getMinMax([h for h in [totBkg, err_band] if h is not None]) pm.SetMinimum(0.0) pm.SetMaximum(1.1*yMax) can.Update() topRightLabel(can, canvasBasename, xpos=0.125, align=13) # drawLegendWithDictKeys(can, dictSum(histos, {'stat err':err_band}), opt='f') drawLegendWithDictKeys(can, histos, opt='f') can.RedrawAxis() can._stack = stack can._histos = [h for h in stack.GetHists()] can.Update() outFname = os.path.join(outputDir, canvasBasename+'.png') utils.rmIfExists(outFname) can.SaveAs(outFname)
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
def plotFractionsStacked(histos={}, canvasName='', outputDir='./', frameTitle='title;p_{T} [GeV]; fraction'): "plot stack of histos[source][group]" can = r.TCanvas(canvasName, '', 800, 600) can.cd() can.SetRightMargin(2.0*can.GetRightMargin()) stack = r.THStack('stack_'+canvasName, '') leg = rightLegend(can) leg.SetBorderSize(0) colors = SampleUtils.colors sources = sorted(histos.keys()) groups = sorted(first(histos).keys()) fillStyles = {'light':3365, 'heavy':3356, 'conv':3663} assert len(sources)<4,"can only plot up to three sources, %s"%str(sources) def setHistoAtts(histo, group, colors=colors, fillStyle=None) : h, g = histo, group h.SetMarkerSize(0) h.SetFillColor(colors[g]) h.SetLineColor(h.GetFillColor()) h.SetDrawOption('bar') if fillStyle : h.SetFillStyle(fillStyle) for s in sources: for g in groups: h = histos[s][g] setHistoAtts(h, g, fillStyle=fillStyles[s]) stack.Add(h) for s in sources[::-1]: # stack goes b-t, legend goes t-b leg.AddEntry(r.TObject(), s, '') def niceLabel(group) : return 'bb/cc' if group=='heavyflavor' else group for g in groups[::-1] : leg.AddEntry(histos[s][g], niceLabel(g) , 'F') stack.Draw('hist') leg.Draw('same') tex = r.TLatex() tex.SetNDC(True) tex.DrawLatex(0.1, 0.9, 'fractions: '+frameTitle[:frameTitle.find(';')-1]) can.Update() # force stack to create canMaster canMaster = stack.GetHistogram() canMaster.SetTitle(frameTitle) canMaster.Draw('axis same') can._graphical_objects = [stack, canMaster, leg, tex] + [h for h in stack.GetStack()] can.Update() for ext in ['png','eps'] : outFilename = outputDir+'/'+canvasName+'.'+ext rmIfExists(outFilename) can.SaveAs(outFilename)
def plot2dEfficiencies(effs={}, canvasName='', outputDir='./', frameTitle='efficiency; #eta; p_{T} [GeV]', textFormat='.3f', zoomIn=False) : can = r.TCanvas(canvasName, '', 800, 600) can.cd() origTextFormat = r.gStyle.GetPaintTextFormat() r.gStyle.SetPaintTextFormat(textFormat) for s,h in effs.iteritems() : can.Clear() # todo minZ, maxZ = getMinMax(effs.values()) if zoomIn else (0.0, 1.0) minZ, maxZ = (0.0, 1.0) h.SetMarkerSize(1.5*h.GetMarkerSize()) h.Draw('colz') h.Draw('text e same') h.GetZaxis().SetRangeUser(min([0.0, minZ]), maxZ) def dropCrPrefix(sr) : return sr.replace('CR_', '') h.SetTitle(dropCrPrefix(s)+' : '+frameTitle) h.SetStats(False) can.Update() for ext in ['png','eps'] : outFilename = outputDir+'/'+canvasName+'_'+s+'.'+ext rmIfExists(outFilename) can.SaveAs(outFilename) r.gStyle.SetPaintTextFormat(origTextFormat)
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)
def subtractRealAndComputeScaleFactor(histosPerGroup={}, variable='', outRatiohistoname='',outDataeffhistoname='', outputDir='./', region='', subtractReal=True, verbose=False): "efficiency scale factor" groups = histosPerGroup.keys() mkdirIfNeeded(outputDir) histosPerType = dict([(lt, dict([(g, histosPerGroup[g][variable][lt]) for g in groups])) for lt in leptonTypes]) for lt in leptonTypes : histosPerType[lt]['totSimBkg'] = summedHisto([histo for group,histo in histosPerType[lt].iteritems() if group not in ['data', 'signal']]) simuTight = histosPerType['fake_tight']['totSimBkg'] simuLoose = histosPerType['fake_loose']['totSimBkg'] dataTight = histosPerType['tight' ]['data' ] dataLoose = histosPerType['loose' ]['data' ] # subtract real contribution from data # _Note to self_: currently estimating the real contr from MC; in # the past also used iterative corr, which might be more # appropriate in cases like here, where the normalization is # so-so. Todo: investigate the normalization. dataSubTight = dataTight.Clone(dataTight.GetName().replace('data_tight','data_minus_prompt_tight')) dataSubLoose = dataLoose.Clone(dataLoose.GetName().replace('data_loose','data_minus_prompt_loose')) dataSubTight.SetDirectory(0) dataSubLoose.SetDirectory(0) dataSubTight.Add(histosPerType['real_tight']['totSimBkg'], -1.0 if subtractReal else 0.0) dataSubLoose.Add(histosPerType['real_loose']['totSimBkg'], -1.0 if subtractReal else 0.0) effData = dataSubTight.Clone(outDataeffhistoname) effData.SetDirectory(0) effData.Divide(dataSubLoose) effSimu = simuTight.Clone(simuTight.GetName().replace('fake_tight','fake_eff')) effSimu.SetDirectory(0) effSimu.Divide(simuLoose) print "eff(T|L) vs. ",variable def formatFloat(floats): return ["%.4f"%f for f in floats] print "efficiency data : ",formatFloat(getBinContents(effData)) print "efficiency simu : ",formatFloat(getBinContents(effSimu)) ratio = effData.Clone(outRatiohistoname) ratio.SetDirectory(0) ratio.Divide(effSimu) print "sf data/simu : ",formatFloat(getBinContents(ratio)) print " +/- : ",formatFloat(getBinErrors(ratio)) can = r.TCanvas('c_'+outRatiohistoname, outRatiohistoname, 800, 600) botPad, topPad = rootUtils.buildBotTopPads(can) can.cd() topPad.Draw() topPad.cd() pm = effData pm.SetStats(0) pm.Draw('axis') xAx, yAx = pm.GetXaxis(), pm.GetYaxis() xAx.SetTitle('') xAx.SetLabelSize(0) yAx.SetRangeUser(0.0, 0.25) textScaleUp = 1.0/topPad.GetHNDC() yAx.SetLabelSize(textScaleUp*0.04) yAx.SetTitleSize(textScaleUp*0.04) yAx.SetTitle('#epsilon(T|L)') yAx.SetTitleOffset(yAx.GetTitleOffset()/textScaleUp) effSimu.SetLineColor(r.kRed) effSimu.SetMarkerStyle(r.kOpenCross) effSimu.SetMarkerColor(effSimu.GetLineColor()) effData.Draw('same') effSimu.Draw('same') leg = drawLegendWithDictKeys(topPad, {'data':effData, 'simulation':simuTight}, legWidth=0.4) leg.SetHeader('scale factor '+region+' '+('electron' if '_el_'in outRatiohistoname else 'muon' if '_mu_' in outRatiohistoname else '')) can.cd() botPad.Draw() botPad.cd() ratio.SetStats(0) ratio.Draw() textScaleUp = 1.0/botPad.GetHNDC() xAx, yAx = ratio.GetXaxis(), ratio.GetYaxis() yAx.SetRangeUser(0.0, 2.0) xAx.SetTitle({'pt1':'p_{T}', 'eta1':'|#eta|', 'pt1_eta1':'p_{T}'}[variable]) yAx.SetNdivisions(-202) yAx.SetTitle('Data/Sim') yAx.CenterTitle() xAx.SetLabelSize(textScaleUp*0.04) xAx.SetTitleSize(textScaleUp*0.04) yAx.SetLabelSize(textScaleUp*0.04) yAx.SetTitleSize(textScaleUp*0.04) refLine = rootUtils.referenceLine(xAx.GetXmin(), xAx.GetXmax()) refLine.Draw() can.Update() outFname = os.path.join(outputDir, region+'_'+outRatiohistoname) for ext in ['.eps','.png']: utils.rmIfExists(outFname+ext) can.SaveAs(outFname+ext) return {outRatiohistoname : ratio, outDataeffhistoname : effData, outDataeffhistoname.replace('_fake_rate_data_', '_tight_data_minus_prompt') : dataSubTight, outDataeffhistoname.replace('_fake_rate_data_', '_loose_data_minus_prompt') : dataSubLoose }
def plotHistRatioAndFit(histos, ratio, fitfunc, outfname, graphics_attributes={}): can = r.TCanvas('can_' + outfname, outfname, 800, 600) botPad, topPad = buildBotTopPads(can, splitFraction=0.35) can.cd() topPad.Draw() topPad.cd() pm = first(histos) pm.Draw('axis') xAx, yAx = pm.GetXaxis(), pm.GetYaxis() xAx.SetTitle('') xAx.SetLabelSize(0) yAx.SetRangeUser(0.0, 1.2) yAx.SetNdivisions( 505) # for some reason some of the inputs are already ratios with -201 textScaleUp = 1.0 / topPad.GetHNDC() yAx.SetLabelSize(textScaleUp * 0.04) yAx.SetTitleSize(textScaleUp * 0.04) yAx.SetTitle(graphics_attributes['ytitle']) yAx.SetTitleOffset(yAx.GetTitleOffset() / textScaleUp) for k, h in histos.iteritems(): h.SetMarkerStyle(graphics_attributes['markers'][k]) h.SetMarkerColor(graphics_attributes['colors'][k]) h.SetLineColor(graphics_attributes['colors'][k]) h.Draw('same') labels = graphics_attributes['labels'] drawLegendWithDictKeys(topPad, dict([(labels[s], histos[s]) for s in histos.keys()]), legWidth=0.4) can.cd() botPad.Draw() botPad.cd() ratio.Draw('axis') textScaleUp = 1.0 / botPad.GetHNDC() xAx, yAx = ratio.GetXaxis(), ratio.GetYaxis() yAx.SetRangeUser(0.0, 2.0) xAx.SetTitle(graphics_attributes['xtitle']) yAx.SetNdivisions(-202) yAx.SetTitle('Data/Sim') yAx.CenterTitle() for a in [xAx, yAx]: if a.GetLabelSize() > 0.04: continue a.SetLabelSize(a.GetLabelSize() * textScaleUp) a.SetTitleSize(a.GetTitleSize() * textScaleUp) a.SetTitleOffset(a.GetTitleOffset() / textScaleUp) ratio.SetMarkerStyle(graphics_attributes['markers']['data']) fitfunc.SetLineWidth(2) fitfunc.SetLineStyle(2) fitfunc.Draw('same') ratio.Draw('same') tex = r.TLatex() tex.SetNDC(True) p0, p0Err, chi2, ndf = fitResults(fitfunc) fitParLabel = "Const. fit : %s #pm %s" % (pdgRound(p0, p0Err)) fitGoodLabel = "#chi^{2}/DOF : %.2f / %d" % (chi2, ndf) tex.SetTextSize(yAx.GetTitleSize()) tex.SetTextFont(yAx.GetTitleFont()) tex.DrawLatex(0.15, 0.40, "#splitline{%s}{%s}" % (fitParLabel, fitGoodLabel)) can.Update() outfname = outfname + '.png' rmIfExists(outfname) # avoid root warnings can.SaveAs(outfname)
def plotStackedHistos(histosPerGroup={}, outputDir='', region='', verbose=False): groups = histosPerGroup.keys() variables = first(histosPerGroup).keys() leptonTypes = first(first(histosPerGroup)).keys() colors = getGroupColor() mkdirIfNeeded(outputDir) histosPerName = dict([ ( region + '_' + var + '_' + lt, # one canvas for each histo, so key with histoname w/out group dict([(g, histosPerGroup[g][var][lt]) for g in groups])) for var in variables for lt in leptonTypes ]) for histoname, histosPerGroup in histosPerName.iteritems(): missingGroups = [g for g, h in histosPerGroup.iteritems() if not h] if missingGroups: if verbose: print "skip %s, missing histos for %s" % (histoname, str(missingGroups)) continue bkgHistos = dict([(g, h) for g, h in histosPerGroup.iteritems() if g not in ['data', 'signal']]) totBkg = summedHisto(bkgHistos.values()) err_band = None # buildErrBandGraph(totBkg, computeStatErr2(totBkg)) emptyBkg = totBkg.Integral() == 0 if emptyBkg: if verbose: print "empty backgrounds, skip %s" % histoname continue can = r.TCanvas('c_' + histoname, histoname, 800, 600) can.cd() pm = totBkg # pad master pm.SetStats(False) pm.Draw('axis') can.Update() # necessary to fool root's dumb object ownership stack = r.THStack('stack_' + histoname, '') can.Update() r.SetOwnership(stack, False) for s, h in bkgHistos.iteritems(): h.SetFillColor(colors[s] if s in colors else r.kOrange) h.SetDrawOption('bar') h.SetDirectory(0) stack.Add(h) stack.Draw('hist same') # err_band.Draw('E2 same') data = histosPerGroup['data'] if data and data.GetEntries(): data.SetMarkerStyle(r.kFullDotLarge) data.Draw('p same') # yMin, yMax = getMinMax([h for h in [totBkg, data, err_band] if h]) # fixme with err_band yMin, yMax = 0.0, data.GetMaximum() pm.SetMinimum(0.0) pm.SetMaximum(1.1 * yMax) can.Update() topRightLabel(can, histoname, xpos=0.125, align=13) # drawLegendWithDictKeys(can, dictSum(bkgHistos, {'stat err':err_band}), opt='f') drawLegendWithDictKeys(can, bkgHistos, opt='f') can.RedrawAxis() can._stack = stack can._histos = [h for h in stack.GetHists()] + [data] can.Update() outFname = os.path.join(outputDir, histoname + '.png') utils.rmIfExists(outFname) can.SaveAs(outFname)
def plotPerSourceEff(histosPerVar={}, outputDir='', lepton='', region='', sample='', verbose=False, zoomIn=True): "plot efficiency for each source (and 'anysource') as a function of each var; expect histos[var][source][loose,tight]" variables = histosPerVar.keys() sources = [s for s in first(histosPerVar).keys() if s != 'real'] # only fake eff really need a scale factor colors = colorsLineSources mkdirIfNeeded(outputDir) for var in filter(lambda x: x in ['pt1', 'eta1'], histosPerVar.keys()): histosPerSource = dict((s, histosPerVar[var][s]) for s in sources) canvasBasename = region + '_efficiency_' + lepton + '_' + var + ( "_%s" % sample if sample else '') missingSources = [ s for s, h in histosPerSource.iteritems() if not h['loose'] or not h['tight'] ] if missingSources: if verbose: print "skip %s, missing histos for %s" % (var, str(missingSources)) continue anySourceLoose = summedHisto( [h['loose'] for h in histosPerSource.values()]) anySourceTight = summedHisto( [h['tight'] for h in histosPerSource.values()]) anySourceLoose.SetName(histoNamePerSource(var, 'any', 'loose', region)) anySourceTight.SetName(histoNamePerSource(var, 'any', 'tight', region)) histosPerSource['any'] = { 'loose': anySourceLoose, 'tight': anySourceTight } emptyBkg = anySourceLoose.Integral() == 0 or anySourceTight.Integral( ) == 0 if emptyBkg: if verbose: print "empty backgrounds, skip %s" % canvasBasename continue def computeEfficiencies(histosPerSource={}): sources = histosPerSource.keys() num = dict((s, histosPerSource[s]['tight']) for s in sources) den = dict((s, histosPerSource[s]['loose']) for s in sources) eff = dict( (s, h.Clone(h.GetName().replace('tight', 'tight_over_loose'))) for s, h in num.iteritems()) [eff[s].Divide(den[s]) for s in sources] return eff effs = computeEfficiencies(histosPerSource) can = r.TCanvas('c_' + canvasBasename, canvasBasename, 800, 600) can.cd() pm = first(effs) # pad master pm.SetStats(False) pm.Draw('axis') can.Update() for s, h in effs.iteritems(): h.SetMarkerColor(colors[s] if s in colors else r.kBlack) h.SetLineColor(h.GetMarkerColor()) h.SetLineWidth(2 * h.GetLineWidth()) h.SetMarkerStyle(markersSources[s] if s in markersSources else r.kDot) h.Draw('ep same') h.SetDirectory(0) #pprint.pprint(effs) yMin, yMax = getMinMax(effs.values()) pm.SetMinimum(0.0) pm.SetMaximum(0.25 if yMax < 0.5 and zoomIn else 1.1) can.Update() topRightLabel(can, canvasBasename, xpos=0.125, align=13) drawLegendWithDictKeys(can, effs, opt='lp') can.RedrawAxis() can._histos = effs can.Update() outFname = os.path.join(outputDir, canvasBasename + '.png') utils.rmIfExists(outFname) can.SaveAs(outFname)
def subtractRealAndComputeScaleFactor(histosPerGroup={}, variable='', outRatiohistoname='', outDataeffhistoname='', outputDir='./', region='', subtractReal=True, verbose=False): "efficiency scale factor" groups = histosPerGroup.keys() mkdirIfNeeded(outputDir) histosPerType = dict([(lt, dict([(g, histosPerGroup[g][variable][lt]) for g in groups])) for lt in leptonTypes]) for lt in leptonTypes: histosPerType[lt]['totSimBkg'] = summedHisto([ histo for group, histo in histosPerType[lt].iteritems() if group not in ['data', 'signal'] ]) simuTight = histosPerType['fake_tight']['totSimBkg'] simuLoose = histosPerType['fake_loose']['totSimBkg'] dataTight = histosPerType['tight']['data'] dataLoose = histosPerType['loose']['data'] # subtract real contribution from data # _Note to self_: currently estimating the real contr from MC; in # the past also used iterative corr, which might be more # appropriate in cases like here, where the normalization is # so-so. Todo: investigate the normalization. dataSubTight = dataTight.Clone(dataTight.GetName().replace( 'data_tight', 'data_minus_prompt_tight')) dataSubLoose = dataLoose.Clone(dataLoose.GetName().replace( 'data_loose', 'data_minus_prompt_loose')) dataSubTight.SetDirectory(0) dataSubLoose.SetDirectory(0) dataSubTight.Add(histosPerType['real_tight']['totSimBkg'], -1.0 if subtractReal else 0.0) dataSubLoose.Add(histosPerType['real_loose']['totSimBkg'], -1.0 if subtractReal else 0.0) effData = dataSubTight.Clone(outDataeffhistoname) effData.SetDirectory(0) effData.Divide(dataSubLoose) effSimu = simuTight.Clone(simuTight.GetName().replace( 'fake_tight', 'fake_eff')) effSimu.SetDirectory(0) effSimu.Divide(simuLoose) print "eff(T|L) vs. ", variable def formatFloat(floats): return ["%.4f" % f for f in floats] print "efficiency data : ", formatFloat(getBinContents(effData)) print "efficiency simu : ", formatFloat(getBinContents(effSimu)) ratio = effData.Clone(outRatiohistoname) ratio.SetDirectory(0) ratio.Divide(effSimu) print "sf data/simu : ", formatFloat(getBinContents(ratio)) print " +/- : ", formatFloat(getBinErrors(ratio)) can = r.TCanvas('c_' + outRatiohistoname, outRatiohistoname, 800, 600) botPad, topPad = rootUtils.buildBotTopPads(can) can.cd() topPad.Draw() topPad.cd() pm = effData pm.SetStats(0) pm.Draw('axis') xAx, yAx = pm.GetXaxis(), pm.GetYaxis() xAx.SetTitle('') xAx.SetLabelSize(0) yAx.SetRangeUser(0.0, 0.25) textScaleUp = 1.0 / topPad.GetHNDC() yAx.SetLabelSize(textScaleUp * 0.04) yAx.SetTitleSize(textScaleUp * 0.04) yAx.SetTitle('#epsilon(T|L)') yAx.SetTitleOffset(yAx.GetTitleOffset() / textScaleUp) effSimu.SetLineColor(r.kRed) effSimu.SetMarkerStyle(r.kOpenCross) effSimu.SetMarkerColor(effSimu.GetLineColor()) effData.Draw('same') effSimu.Draw('same') leg = drawLegendWithDictKeys(topPad, { 'data': effData, 'simulation': simuTight }, legWidth=0.4) leg.SetHeader('scale factor ' + region + ' ' + ('electron' if '_el_' in outRatiohistoname else 'muon' if '_mu_' in outRatiohistoname else '')) can.cd() botPad.Draw() botPad.cd() ratio.SetStats(0) ratio.Draw() textScaleUp = 1.0 / botPad.GetHNDC() xAx, yAx = ratio.GetXaxis(), ratio.GetYaxis() yAx.SetRangeUser(0.0, 2.0) xAx.SetTitle({ 'pt1': 'p_{T}', 'eta1': '|#eta|', 'pt1_eta1': 'p_{T}' }[variable]) yAx.SetNdivisions(-202) yAx.SetTitle('Data/Sim') yAx.CenterTitle() xAx.SetLabelSize(textScaleUp * 0.04) xAx.SetTitleSize(textScaleUp * 0.04) yAx.SetLabelSize(textScaleUp * 0.04) yAx.SetTitleSize(textScaleUp * 0.04) refLine = rootUtils.referenceLine(xAx.GetXmin(), xAx.GetXmax()) refLine.Draw() can.Update() outFname = os.path.join(outputDir, region + '_' + outRatiohistoname) for ext in ['.eps', '.png']: utils.rmIfExists(outFname + ext) can.SaveAs(outFname + ext) return { outRatiohistoname: ratio, outDataeffhistoname: effData, outDataeffhistoname.replace('_fake_rate_data_', '_tight_data_minus_prompt'): dataSubTight, outDataeffhistoname.replace('_fake_rate_data_', '_loose_data_minus_prompt'): dataSubLoose }