def MergeSamples(hists,options,requireFullyMerged=False) : # # Yeah so this adds the samples together that you specify, in a resonable # order close to the one you specify in the command line "bkgs" # If you require that the samples are fully merged, this means that N # inputs is merged into one output (a check we require for data). # import math import ROOT import PyHelpers import re if not options.mergesamples : return hists hists_new = [] keys_new = [] hists_index = dict() for i in hists : added = False for j in options.mergesamples.keys() : # Compare to regexp if type(options.mergesamples[j]) == type('') : if not re.match(options.mergesamples[j].replace('%','.*'),i.GetTitle()) : continue # Compare to list of samples if type(options.mergesamples[j]) == type([]) : match = False for mergesample in options.mergesamples[j] : if re.match(mergesample.replace('%','.*'),i.GetTitle()) : match = True if not match : continue if j in hists_index.keys() : #print 'adding to existing histo' hists_new[hists_index[j]].Add(i) added = True else : #print 'starting a new histo' hists_index[j] = len(hists_new) hists_new.append(i) keys_new.append(j) hists_new[-1].SetTitle(j) hists_new[-1].SetName(CleanUpName(j)) added = True if not added : hists_new.append(i) keys_new.append(i.GetTitle()) for i in hists_index.keys() : PyHelpers.PrintNumberOfEvents(hists_new[hists_index[i]]) if requireFullyMerged and len(hists_new) > 1 : print 'Error! Failed to merge histograms into one histogram! (Usually required for data.) Check your sample merging.' SafeExit(options.xAODInit) return hists_new
def main(options, args): plotfunc.SetupStyle() files_b, trees_b, keys_b = anaplot.GetTreesFromFiles( options.bkgs, treename=options.treename) files_s, trees_s, keys_s = anaplot.GetTreesFromFiles( options.signal, treename=options.treename) file_d, tree_d, key_d = anaplot.GetChainFromFiles( options.data, treename=options.treename) scales_b = anaplot.GetScales(files_b, trees_b, keys_b, options) scales_s = anaplot.GetScales(files_s, trees_s, keys_s, options) dweight = '' # weight value (and cuts) applied to data weight = options.weight if ''.join(options.cuts): weight = (weight + '*(%s)' % (' && '.join(options.cuts + options.truthcuts))).lstrip('*') dweight = '(' + ' && '.join(options.cuts + options.blindcut) + ')' cans = [] v1 = 'HGamEventInfoAuxDyn.m_yy/1000' v2 = 'HGamEventInfoAuxDyn.catCoup_Moriond2017BDT' bkg_hists = [] sig_hists = [] data_hist = None if options.data: data_hist = anaplot.Get2dVariableHistsFromTrees( tree_d, key_d, v1, v2, dweight, options)[0] data_hist.SetLineWidth(2) data_hist.SetLineColor(1) data_hist.SetMarkerColor(1) if options.bkgs: bkg_hists = anaplot.Get2dVariableHistsFromTrees(trees_b, keys_b, v1, v2, weight, options, scales=scales_b) bkg_hists, keys_b = anaplot.MergeSamples(bkg_hists, options) anaplot.PrepareBkgHistosForStack(bkg_hists, options) if options.signal: sig_hists = anaplot.Get2dVariableHistsFromTrees(trees_s, keys_s, v1, v2, weight, options, scales=scales_s) sig_hists, keys_s = anaplot.MergeSamples(sig_hists, options) sig_hists[-1].SetLineColor(2) sig_hists[-1].SetMarkerColor(2) # get the histograms from the files for c in range(len(CouplingsHelpers.categories)): #if not categories[c] : continue lo_bin = c + 1 hi_bin = c + 1 if c == 0: # inclusive case. lo_bin = 0 hi_bin = 10000 # just to be safe, 10k categories # MERGE VH DILEP CATEGORIES (23 and 24 --> 23): if CouplingsHelpers.categories[c] == 'M17_VHdilep_LOW': hi_bin = hi_bin + 1 # MERGE VH MET HIGH and BSM CATEGORIES (19 and 20 --> 19): if CouplingsHelpers.categories[c] == 'M17_VHMET_HIGH': hi_bin = hi_bin + 1 name = 'c%d_%s' % (c, CouplingsHelpers.categories[c]) bkg_projs = [] sig_projs = [] data_proj = None if options.data: data_proj = data_hist.ProjectionX('%s_data' % (name), lo_bin, hi_bin) PyHelpers.PrintNumberOfEvents(data_proj) if options.bkgs: for i, b in enumerate(bkg_hists): bkg_projs.append( b.ProjectionX('%s_%s' % (name, keys_b[i]), lo_bin, hi_bin)) PyHelpers.PrintNumberOfEvents(bkg_projs[-1]) if options.signal: for i, s in enumerate(sig_hists): sig_projs.append( s.ProjectionX('%s_%s' % (name, keys_s[i]), lo_bin, hi_bin)) PyHelpers.PrintNumberOfEvents(sig_projs[-1]) cans.append( anaplot.DrawHistos(v1, options, bkg_projs, sig_projs, data_proj, name=name)) cans[-1].SetName(anaplot.CleanUpName(name)) anaplot.UpdateCanvases(options, cans) if not options.batch: raw_input('Press enter to exit') anaplot.doSaving(options, cans) # Do this afterwards, to make sure the outdir exists. f = ROOT.TFile('%s/couplings.root' % (options.outdir), 'RECREATE') for can in cans: for i in can.GetListOfPrimitives(): if i.GetName()[-6:] == '_error': continue if 'stack' in i.GetName(): if not issubclass(type(i), ROOT.THStack): continue for j in range(i.GetNhists()): print 'writing from stack:', i.GetHists()[j].GetName() i.GetHists()[j].Write() if issubclass(type(i), ROOT.TH1): print 'writing:', i.GetName() i.Write() f.Close() print 'done.' return
def Get2dVariableHistsFromTrees(trees,keys,variable1,variable2,weight,options,scales=0,inputname='',files=None) : import ROOT from array import array import PlotFunctions as plotfunc import math import PyHelpers if not options.macro : if not options.limits.get(variable1,None) or not options.limits.get(variable2,None) : print 'Error - you need to specify limits for both %s and %s.'%(variable1,variable2) print '(Note you probably have to add these variables to the list of variables as well.)' SafeExit(options.xAODInit) n1,low1,high1 = options.limits.get(variable1) n2,low2,high2 = options.limits.get(variable2) if not inputname : inputname = '%s_%s'%(variable1,variable2) hists = [] for k in keys : k_clean = CleanUpName(k,originalIsDirectoryName=True) name = CleanUpName('%s_%s'%(inputname,k_clean)) if issubclass(type(ROOT.gDirectory.Get(name)),ROOT.TH1) : print 'Using existing histogram, %s'%(name) # will load the histogram later... elif options.macro : RunMacro(options.macro,files[k],CleanUpName(k)) # if Draw did not work, then exit. if not issubclass(type(ROOT.gDirectory.Get(name)),ROOT.TH1) : print 'ERROR Macro failed trying to create %s Exiting.'%(name) SafeExit(options.xAODInit) else : arg1 = '%s:%s>>%s(%s,%s,%s,%s,%s,%s)'%(variable2,variable1,name, n1,low1,high1,n2,low2,high2) arg2 = weight arg3 = 'egoff' print 'tree.Draw(\'%s\',\'%s\',\'%s\')'%(arg1,arg2,arg3) tmp = ROOT.gErrorIgnoreLevel ROOT.gErrorIgnoreLevel = ROOT.kFatal trees[k].Draw(arg1,arg2,arg3) ROOT.gErrorIgnoreLevel = tmp # if Draw did not work, then exit. if not issubclass(type(ROOT.gDirectory.Get(name)),ROOT.TH1) : print 'ERROR TTree::Draw failed trying to draw %s Exiting.'%(name) SafeExit(options.xAODInit) hists.append(ROOT.gDirectory.Get(name)) hists[-1].SetDirectory(0) hists[-1].SetTitle(k) if scales and (scales[k] != 1) : hists[-1].Scale(scales[k]) # print the yield and error after cuts (includes overflow) PyHelpers.PrintNumberOfEvents(hists[-1]) if options.normalize : try : hists[-1].Scale(1/float(hists[-1].Integral())) except ZeroDivisionError : pass return hists
def GetVariableHistsFromTrees(trees,keys,variable,weight,options=None,scales=0,inputname='',files=None) : import ROOT from array import array import PlotFunctions as plotfunc import TAxisFunctions as taxisfunc import math import PyHelpers # Parse options n,low,high = -1,-1,-1 if hasattr(options,'limits') : n,low,high = options.limits.get(variable,[-1,-1,-1]) rebin = options.rebin.get(variable,[]) if hasattr(options,'rebin') else [] showflows = hasattr(options,'showflows') and options.showflows if not inputname : inputname = variable hists = [] for k in keys : k_clean = CleanUpName(k,originalIsDirectoryName=True) name = CleanUpName('%s_%s'%(inputname,k_clean)) if issubclass(type(ROOT.gDirectory.Get(name)),ROOT.TH1) : print 'Using existing histogram, %s'%(name) # will load the histogram later... elif options.macro : RunMacro(options.macro,files[k],CleanUpName(k)) # if Draw did not work, then exit. if not issubclass(type(ROOT.gDirectory.Get(name)),ROOT.TH1) : print 'ERROR Macro failed trying to create %s Exiting.'%(name) SafeExit(options.xAODInit) else : if rebin and type(rebin) == type([]) : name = name+'_unrebinned' bins = '(%s,%s,%s)'%(n,low,high) if (n <= 0) : bins = '' arg1,arg2,arg3 = '%s>>%s%s'%(variable,name,bins),weight,'egoff' # Reset the default binning to 100, if "n" is not specified. ROOT.gEnv.SetValue('Hist.Binning.1D.x','100') print 'tree.Draw(\'%s\',\'%s\',\'%s\')'%(arg1,arg2,arg3) tmp = ROOT.gErrorIgnoreLevel ROOT.gErrorIgnoreLevel = ROOT.kFatal trees[k].Draw(arg1,arg2,arg3) ROOT.gErrorIgnoreLevel = tmp # if Draw did not work, then exit. if not issubclass(type(ROOT.gDirectory.Get(name)),ROOT.TH1) : print 'ERROR TTree::Draw failed trying to draw %s Exiting.'%(name) SafeExit(options.xAODInit) if rebin and type(rebin) == type([]) : tmp = ROOT.gDirectory.Get(name) name = name.replace('_unrebinned','') tmp.Rebin(len(rebin)-1,name,array('d',rebin)) hists.append(ROOT.gDirectory.Get(name)) hists[-1].SetDirectory(0) if rebin and type(rebin) == type(1) : hists[-1].Rebin(rebin) if (n <= 0) : print 'Changing limits to match those from the first plot.' n = hists[-1].GetNbinsX() low = hists[-1].GetBinLowEdge(1) high = hists[-1].GetBinLowEdge(n+1) if hasattr(options,'limits') : options.limits[variable] = [n,low,high] if showflows : taxisfunc.PutOverflowIntoLastBin(hists[-1]) taxisfunc.PutUnderflowIntoFirstBin(hists[-1]) #RebinSmoothlyFallingFunction(hists[-1]) hists[-1].SetTitle(k) if scales and (scales[k] != 1) : hists[-1].Scale(scales[k]) # print the yield and error after cuts (includes overflow) PyHelpers.PrintNumberOfEvents(hists[-1]) return hists