def blind(self,bmin=None,bmax=None,**kwargs): """Return selection string that blinds some window (bmin,bmax), making sure the cuts match the bin edges of some (nbins,xmin,xmax) binning.""" verbosity = LOG.getverbosity(self,kwargs) if bmin==None: bmin = self.blindcuts[0] if bmax<bmin: bmax, bmin = bmin, bmax LOG.insist(bmax>bmin,'Variable.blind: "%s" has window a = %s <= %s = b !'%(self._name,bmin,bmax)) blindcut = "" xlow, xhigh = bmin, bmax nbins, xmin, xmax = self.nbins, self.min, self.max if self.hasvariablebins(): bins = self.bins for xval in bins: if xval>bmin: break xlow = xval for xval in reversed(bins): if xval<bmax: break xhigh = xval else: binwidth = float(xmax-xmin)/nbins if xmin<bmin<xmax: bin, rem = divmod(bmin-xmin,binwidth) xlow = bin*binwidth if xmin<bmax<xmax: bin, rem = divmod(bmax-xmin,binwidth) if rem>0: bin += 1 xhigh = bin*binwidth blindcut = "(%s<%s || %s<%s)"%(self.name,xlow,xhigh,self.name) LOG.verb('Variable.blind: blindcut = "%s" for a (%s,%s) window and (%s,%s,%s) binning'%(blindcut,bmin,bmax,nbins,xmin,xmax),verbosity,2) return blindcut
def joincuts(*cuts, **kwargs): """Joins selection strings and apply weight if needed.""" verbosity = LOG.getverbosity(kwargs) cuts = [c for c in cuts if c and isinstance(c, str)] weight = kwargs.get('weight', False) if any('||' in c and not ('(' in c and ')' in c) for c in cuts): LOG.warning( 'joincuts: Be careful with those "or" statements in %s! Not sure how to join...' % (cuts, )) for i, cut in enumerate(cuts): if '||' in cut and not ('(' in cut and ')' in cut): cuts[i] = "(%s)" % (cut) if weight: string = re.sub("\(.+\)", "", weight) if any(c in string for c in '=<>+-&|'): weight = "(%s)" % (weight) if cuts: cuts = " && ".join(cuts) if weight: string = re.sub("\(.+\)", "", cuts) cuts = "(%s)*%s" % (cuts, weight) elif weight: cuts = weight else: cuts = "" #print cuts return cuts
def getedge(self,i): """Get edge. 0=first edge, nbins+1=last edge""" LOG.insist(i>=0,"getedge: Number of bin edge has to be >= 0! Got: %s"%(i)) LOG.insist(i<=self.nbins+1,"getedge: Number of bin edge has to be <= %d! Got: %s"%(self.nbins+1,i)) if self.hasvariablebins(): return self.bins[i] return self.min+i*(self.max-self.min)/self.nbins
def plothist(xtitle,hists,ratio=False,logy=False,norm=False,**kwargs): # SETTING outdir = ensuredir("plots/") fname = outdir+"testLegend" rrange = 0.5 header = "Gaussians" # legend header text = "#mu#tau_{h}" # corner text grid = True and False staterr = True and False # add uncertainty band to first histogram lstyle = 1 # solid lines panel = 1 # 1 = main (top) panel, 2 = ratio (bottom) panel hists = [h.Clone("%s_clone%d"%(h.GetName(),i)) for i, h in enumerate(hists)] if kwargs.get('pos',False): fname += "_"+kwargs['pos'].replace(';','') header = kwargs['pos'] if ratio: fname += "_ratio" # PLOT LOG.header(fname) plot = Plot(xtitle,hists,norm=norm) plot.draw(ratio=ratio,logy=logy,ratiorange=rrange,lstyle=lstyle,grid=grid,staterr=staterr) plot.drawlegend(border=True,header=header,panel=panel,**kwargs) plot.drawtext(text) plot.saveas(fname+".png") #plot.saveas(fname+".pdf") plot.close() print
def plothist(xtitle,hists,ratio=False,logy=False,norm=False): # SETTING outdir = ensuredir("plots/") fname = outdir+"testPlot" if ratio: fname += "_ratio" if logy: fname += "_logy" if norm: fname += "_norm" # normalize each histogram rrange = 0.5 width = 0.2 # legend width position = 'topright' # legend position header = "Gaussians" # legend header text = "#mu#tau_{h}" # corner text grid = True #and False staterr = True and False # add uncertainty band to first histogram lstyle = 1 # solid lines # PLOT LOG.header(fname) plot = Plot(xtitle,hists,norm=norm) plot.draw(ratio=ratio,logy=logy,ratiorange=rrange,lstyle=lstyle,grid=grid,staterr=staterr) plot.drawlegend(position,header=header,width=width) plot.drawtext(text) plot.saveas(fname+".png") plot.saveas(fname+".pdf") #plot.saveas(fname+".C") #plot.saveas(fname+".png",fname+".C") #plot.saveas(fname,ext=['png','pdf']) plot.close() print
def checklatex(texts, tag=""): """Check legend entries: colors, titles, ...""" # https://root.cern.ch/doc/master/classTPaveText.html LOG.header("checklegend" + tag.replace('_', ' ')) output = ensuredir('plots') fname = "%s/testLatex%s" % (output, tag) xdim = 500 ydim = 50 * (len(texts) + 2.5) print ">>> Canvas: %sx%s (nlines=%d)" % (xdim, ydim, len(texts)) canvas = TCanvas('canvas', 'canvas', xdim, int(ydim)) #pave1 = TPaveText(0.0,0,0.5,1,'ARC') #,'BR') pave2 = TPaveText(0.04, 0.04, 0.96, 0.96) #'ARC') #,'BR') #pave1.SetBorderSize(0) pave2.SetBorderSize(0) #pave1.SetTextAlign(12) pave2.SetTextAlign(12) #pave1.SetTextFont(42) pave2.SetTextFont(42) #pave1.SetFillColor(0) pave2.SetFillColor(0) #pave1.SetCornerRadius(0.05) #pave2.SetCornerRadius(0.05) #pave1.SetMargin(0.12) #pave1.SetTextSize(tsize) #pave2.Copy(pave1) for line in texts: latex = makelatex(line) print ">>> %r -> %r" % (line, latex) #pave1.AddText(line) pave2.AddText(latex) #pave1.Draw() pave2.Draw() canvas.SaveAs(fname + ".png") #canvas.SaveAs(fname+".pdf") canvas.Close()
def __init__(self, context_dict, *args, **kwargs): if not isinstance(context_dict, dict): LOG.warning("Context.init: No dictionary given!") self.context = context_dict self.default = args[0] if len(args) > 0 else context_dict.get( 'default', None) self.regex = kwargs.get('regex', False)
def plotstack(xname,xtitle,datahist,exphists,ratio=False,logy=False): """Plot Stack objects for a given data hisogram and list of MC histograms.""" # SETTING outdir = ensuredir("plots") fname = "%s/testStack_%s"%(outdir,xname) if ratio: fname += "_ratio" if logy: fname += "_logy" rrange = 0.5 text = "#mu#tau_{h} baseline" grid = True and False position = 'topright' if logy else 'right' # PLOT LOG.header(fname) plot = Stack(xtitle,datahist,exphists) plot.draw(ratio=ratio,logy=logy,ratiorange=rrange,grid=grid) plot.drawlegend(position=position) plot.drawtext(text) plot.saveas(fname+".png") plot.saveas(fname+".pdf") #plot.saveas(fname+".C") #plot.saveas(fname+".png",fname+".C") #plot.saveas(fname,ext=['png','pdf']) plot.close() print
def wrapvariable(*args,**kwargs): """Help function to wrap variable arguments into a Variable object.""" if len(args)==4 or len(args)==5: return Variable(args) # (xvar,nxbins,xmin,xmax) elif len(args)==1 and isinstance(args[0],Variable): return args[0] LOG.warning('wrapvariable: Could not unwrap arguments "%s" to a Variable object. Returning None.'%args) return None
def unwrap_variable_bins(*args,**kwargs): """Help function to unwrap variable arguments to return variable name, number of bins, minumum and maximum x axis value.""" if len(args)==4: return args # (xvar,nxbins,xmin,xmax) elif len(args)==1 and isintance(args[0],Variable): return args[0].unwrap() LOG.throw(IOError,'unwrap_variable_bins: Could not unwrap arguments "%s" to a Variable object.'%args)
def invertcharge(oldcuts, target='SS', **kwargs): """Help function to find, invert and replace charge selections.""" verbosity = LOG.getverbosity(kwargs) oldcuts = getselstr(oldcuts) newcuts = oldcuts if oldcuts == "": newcuts = "q_1*q_2<0" if target == 'OS' else "q_1*q_2>0" if target == 'OS' else "" else: matchOS = re.findall(r"q_[12]\s*\*\s*q_[12]\s*<\s*0", oldcuts) matchSS = re.findall(r"q_[12]\s*\*\s*q_[12]\s*>\s*0", oldcuts) LOG.verbose("invertcharge: oldcuts=%r" % (oldcuts), verbosity, 2) LOG.verbose( "invertcharge: matchOS=%r, matchSS=%r" % (matchOS, matchSS), verbosity, 2) if (len(matchOS) + len(matchSS)) > 1: LOG.warning( 'invertcharge: more than one charge match (%d OS, %d SS) in %r' % (len(matchOS), len(matchSS), oldcuts)) if target == 'OS': for match in matchSS: newcuts = oldcuts.replace(match, "q_1*q_2<0") # invert SS to OS elif target == 'SS': for match in matchOS: newcuts = oldcuts.replace(match, "q_1*q_2>0") # invert OS to SS else: for match in matchOS: newcuts = oldcuts.replace(match, "") # REMOVE for match in matchSS: newcuts = oldcuts.replace(match, "") # REMOVE newcuts = cleanbool(newcuts) LOG.verbose(' %r\n>>> -> %r %s\n>>>' % (oldcuts, newcuts, target), verbosity, 2) return newcuts
def addoverflow(self,**kwargs): """Modify variable name in order to add the overflow to the last bin.""" verbosity = LOG.getverbosity(self,kwargs) if self.hasvariablebins(): width = self.bins[-1]-self.bins[-2] threshold = self.bins[-2] + 0.90*width else: width = (self.max-self.min)/float(self.nbins) threshold = self.max - 0.90*width self.name = "min(%s,%s)"%(self._name,threshold) LOG.verb("Variable.addoverflow: '%s' -> '%s' for binning '%s'"%(self._name,self.name,self.getbins()),verbosity,2) return self.name
def stackinputs(file, variable, processes, **kwargs): """Stack histograms from ROOT file. file: TFile or TDirectory object variable: Variables object processes: list of strings (name of processes) e.g. stackinputs(file,variable,['ZTT','TTT','W','QCD','data_obs']) """ text = kwargs.get('text', None) tag = kwargs.get('tag', "") groups = kwargs.get('group', []) # e.g. [(['^TT','ST'],'Top')] dname = kwargs.get('dname', None) # directory ('bin') name pname = kwargs.get('save', "stack$TAG.png") # save as image file wname = kwargs.get('write', "stack$TAG") # write to file style = kwargs.get('style', False) # write style to file exphists = [] datahist = None tdir = ensureTDirectory(file, dname, cd=True) if dname else file if style: gStyle.Write( 'style', TH1.kOverwrite) # write current TStyle object to reproduce plots for process in processes: hname = process hist = gethist(tdir, process, fatal=False, warn=False) if not hist: LOG.warning( "stackinputs: Could not find %r in %s. Skipping stacked plot..." % (process, tdir.GetPath())) return hist.SetDirectory(0) hist.SetLineColor(kBlack) hist.SetFillStyle(1001) # assume fill color is already correct if process == 'data_obs': datahist = hist else: exphists.append(hist) for group in groups: grouphists(exphists, *group, replace=True, regex=True, verb=0) stack = Stack(variable, datahist, exphists) stack.draw() stack.drawlegend(ncols=2, twidth=0.9) if text: stack.drawtext(text) if pname: pname = repkey(pname, TAG=tag) stack.saveas(pname, ext=['png']) if wname: wname = repkey(wname, TAG=tag) stack.canvas.Write(wname, TH1.kOverwrite) stack.close()
def filtervars(vars,filters,**kwargs): """Filter list of variables. Allow glob patterns.""" verbosity = LOG.getverbosity(kwargs) newvars = [ ] if not filters: return vars[:] for var in vars: if any(match(f,[var.name,var.filename]) for f in filters): newvars.append(var) LOG.verb("filtervars: Matched %r, including..."%(var),verbosity,2) else: LOG.verb("filtervars: No match to %r, ignoring..."%(var),verbosity,2) return newvars #from TauFW.Plotter.plot.Selection import Selection
def ensurevar(*args,**kwargs): """Help function to ensure arguments are one Variable object: - xvar, nxbins, xmin, xmax (str, int, float, float) - xvar, xbins (str, list) - var (str) """ args = unwraplistargs(args) if len(args)==4: return Variable(*args) # (xvar,nxbins,xmin,xmax) elif len(args)==2 and islist(args[1]): return Variable(*args) # (xvar,xbins) elif len(args)==1 and isinstance(args[0],Variable): return args[0] else: LOG.throw(IOError,'unwrap_variable_args: Could not unwrap arguments %s, len(args)=%d. Returning None.'%(args,len(args)))
def shift(oldstr, shift, vars=["\w+"], **kwargs): """Shift all jet variable in a given string (e.g. to propagate JEC/JER). E.g. shift('jpt_1>50 && met<50','jecUp',['jpt_[12]','met']) -> 'jpt_1_jecUp>50 && met_jecUp<50' """ verbosity = LOG.getverbosity(kwargs) newstr = oldstr vars = ensurelist(vars) if re.search(r"(Up|Down)",oldstr): print "shift: already shifts in %r"%(oldstr) if kwargs.get('us',True) and len(shift)>0 and shift[0]!='_': # ensure underscore in front shift = '_'+shift for oldvar in vars: # shift each jet/MET variable oldexp = r"\b("+oldvar+r")\b" newexp = r"\1%s"%(shift) newstr = re.sub(oldexp,newexp,newstr) if verbosity>=1: verbstr = ">>> shift: shift with %r shift: "%(newstr) if len(newstr)<20: verbstr += " %r -> %r"%(oldstr,newstr) elif len(newstr)<35: verbstr += "\n>>> %r -> %r"%(oldstr,newstr) else: verbstr += "\n>>> %r\n>>> -> %r"%(oldstr,newstr) print verbstr return newstr
def clone(self,*args,**kwargs): """Shallow copy.""" verbosity = LOG.getverbosity(self,kwargs) if not args: args = self.getbins() cut = kwargs.get('cut',None) if cut and self.ctxbins: # change context based on extra cut bins = self.ctxbins.getcontext(cut) # get bins in this context if args!=bins and verbosity>=2: print ">>> Variable.clone: Changing binning %r -> %r because of context %r"%(args,bins,cut) args = bins if isinstance(args,list): # assume list is bin edges args = (args,) newdict = self.__dict__.copy() if 'fname' in kwargs: kwargs['filename'] = kwargs['fname'] if 'filename' in kwargs: kwargs['filename'] = kwargs['filename'].replace('$FILE',self.filename) if kwargs.get('combine',True) and 'weight' in kwargs and self.weight: kwargs['weight'] = combineWeights(kwargs['weight'],self.weight) for key in kwargs.keys()+['nbins','min','max','bins']: # to be reset with args if key in newdict: newdict.pop(key) if 'cbins' in kwargs: newdict.pop('ctxbins') elif self.ctxbins: newdict['ctxbins'] = self.ctxbins.clone() # create new dictionary newdict['ctxbins'].default = args # change default context newvar = Variable(self.name,*args,**kwargs) newvar.__dict__.update(newdict) if verbosity>=2: print ">>> Variable.clone: Cloned %r -> %r"%(self,newvar) return newvar
def comparevars(file, variable, processes, systag, **kwargs): """Compare up/down variations of input histograms from ROOT file. file: TFile or TDirectory object variable: Variables object processes: list of strings (name of processes) systag: string of systematic (file must contain up/down variation) e.g. comparevars(file,variable,['ZTT','TTT'],'TES') """ text = kwargs.get('text', None) pname = kwargs.get('pname', "stack.png") tag = kwargs.get('tag', "") groups = kwargs.get('group', []) # e.g. [(['^TT','ST'],'Top')] dname = kwargs.get('dname', None) # directory ('bin') name pname = kwargs.get('save', "plot_$PROC$SYST$TAG.png") # save as image file wname = kwargs.get('write', "plot_$PROC$SYST$TAG") # write to file processes = ensurelist(processes) uptag = systag + "Up" downtag = systag + "Down" tdir = ensureTDirectory(file, dname, cd=True) if dname else file for process in processes: hists = [] skip = False for var in [uptag, "", downtag]: hname = process + var hist = gethist(tdir, hname, fatal=False, warn=False) if not hist: skip = True break hists.append(hist) if skip: LOG.warning( "comparevars: Could not find %r in %s. Skipping shape comparison..." % (hname, tdir.GetPath())) continue plot = Plot(variable, hists) plot.draw(ratio=2, lstyle=1) plot.drawlegend() if text: plot.drawtext(text) if pname: pname_ = repkey(pname, PROC=process, TAG=tag) plot.saveas(pname_, ext=['png']) if wname: wname_ = repkey(wname, PROC=process, TAG=tag) plot.canvas.Write(wname_, TH1.kOverwrite) plot.close()
def getcontext(ctxdict, *default, **kwargs): """Check for context in ctxdict. If a dictionary is given, make a Context object. Else return None.""" ckey = kwargs.get('key', 'context') regex = kwargs.get('regex', False) context = ctxdict.get(ckey, None) # context-dependent if isinstance(context, Context): return context if isinstance(context, dict): if len(default) == 0: default = context.get('default', None) else: default = default[0] context = Context(context, default, regex=regex) return context elif not context: return None LOG.error('No valid arguments: ctxdict=%s, ckey=%r, default=%s' % (ctxdict, ckey, default)) return None
def plotfor(self, *strings, **kwargs): """Check if given string is filtered (with 'only') or vetoed (with 'veto') for this variable.""" verbosity = LOG.getverbosity(self, kwargs) strings = list(strings) LOG.verbose('Variable.plotfor: strings=%s, veto=%s, only=%s' % (strings, self.veto, self.only), verbosity, level=2) for i, string in enumerate(strings): if string.__class__.__name__ == 'Selection': string = string.selection strings[i] = string for searchterm in self.veto: if re.search(searchterm, string): LOG.verbose( 'Variable.plotfor: Regex match of string "%s" to "%s"' % (string, searchterm), verbosity, level=2) return False if len(self.only) == 0: return True for i, string in enumerate(strings): for searchterm in self.only: if re.search(searchterm, string): LOG.verbose( 'Variable.plotfor: Regex match of string "%s" to "%s"' % (string, searchterm), verbosity, level=2) return True return False
def setbins(self, *args): """Set binning: (N,min,max), or bins if it is set""" numbers = [a for a in args if isnumber(a)] bins = [a for a in args if islist(a)] if len(numbers) == 3: self.nbins = numbers[0] self.min = numbers[1] self.max = numbers[2] self.bins = None elif len(bins) > 0: bins = list(bins[0]) self.nbins = len(bins) - 1 self.min = bins[0] self.max = bins[-1] self.bins = bins else: LOG.throw(IOError, 'Variable: bad arguments "%s" for binning!' % (args, ))
def setbins(self,*args): """Set binning: (N,min,max), or bins if it is set""" LOG.verb('Variable.setbins: setting binning to %s'%(args,),level=2) numbers = [a for a in args if isnumber(a)] bins = [a for a in args if islist(a) ] if len(numbers)==3: self.nbins = numbers[0] self.min = numbers[1] self.max = numbers[2] self.bins = None elif len(bins)>0: edges = list(bins[0]) self.nbins = len(edges)-1 self.min = edges[0] self.max = edges[-1] self.bins = edges else: LOG.throw(IOError,'Variable: bad arguments "%s" for binning!'%(args,))
def shiftjetvars(var, jshift, **kwargs): """Shift all jet variable in a given string (e.g. to propagate JEC/JER).""" vars = [r'mt_1',r'met(?!filter)'] if "unclusten" in jshift.lower() else\ [r'jpt_[12]',r'jeta_[12]',r'jets\w*',r'nc?btag\w*',r'mt_1',r'met(?!filter)',r'dphi_ll_bj'] verbosity = LOG.getverbosity(kwargs) vars = kwargs.get('vars', vars) varshift = var[:] if re.search(r"(Up|Down)", var): LOG.warning("shiftjetvars: Already shifts in %r" % (var)) if len(jshift) > 0 and jshift[0] != '_': jshift = '_' + jshift for jvar in vars: oldvarpattern = r'(' + jvar + r')' newvarpattern = r"\1%s" % (jshift) varshift = re.sub(oldvarpattern, newvarpattern, varshift) if verbosity > 0: print "shiftjetvars with %r shift" % varshift print ">>> %r" % var print ">>> -> %r" % jshift return varshift
def joinweights(*weights, **kwargs): """Join weight strings multiplicatively.""" verbosity = LOG.getverbosity(kwargs) weights = [w for w in weights if w and isinstance(w, str)] if weights: weights = "*".join(weights) weights = weights.replace('*/', '/') else: weights = "" return weights
def getcontext(self, *args, **kwargs): """Get the contextual object for a set of ordered arguments. If it is not available, return Default.""" regex = kwargs.get('regex', self.regex) # CHECK if len(args) == 0: LOG.warning("Context.getcontext: No arguments given!") return self.default if not self.context: LOG.warning("Context.getcontext: No context dictionary!") return None # MATCH ckey = args[0] if ckey.__class__.__name__ == 'Selection': ckey = ckey.selection result = None if regex: for key in sorted(self.context, key=lambda x: len(x) if isinstance(x, str) else 1, reverse=True): #LOG.verbose('Context.getcontext: Matching "%s" to "%s"'%(key,ckey),True) if key == ckey or (isinstance(key, str) and isinstance( ckey, str) and re.search(key, ckey)): #LOG.verbose('Context.getcontext: Regex match of key "%s" to "%s"'%(key,ckey),True) ckey = key result = self.context[ckey] break else: result = self.default # TODO: check for multiple args ! elif ckey not in self.context: result = self.default else: result = self.context[ckey] # RESULT if isinstance(result, Context): return result.getcontext(*args[1:], **kwargs) # recursive elif len(args) > 1 and result == self.default: return self.getcontext(*args[1:], **kwargs) # recursive return result
def main(): #### Test several initializations of Variable object. #### Note that key-word arguments starting with 'c' are used for context-dependent attributes ###mvisbins = [0,30,40,50,60,70,75,80,90,100,120,200] ###variables = [ ### Variable('m_vis', "m_{vis} [GeV]", 40, 0,200), ### Variable('njets', "Number of jets", 8, 0, 8), ### Variable('m_vis', 40, 0,200), ### Variable('njets', 8, 0, 8), ### Variable('njets', 8, 0, 8, veto='njets'), ### Variable('st', 20, 0,800, title="S_{T}",only="njets",blind="st>600"), ### Variable('m_vis', 40, 0,200, cbins={'njets':mvisbins},blind=(70,90)), ### Variable('m_vis', mvisbins, cbins={"njets[^&]*2":(40,0,200)},), ### Variable('pt_1+pt_2', 20, 0,800, title="S_{T}^{tautau}",ctitle={"njets":"S_{T}"}), ###] selections = [ Selection(""), Selection("baseline", "pt_1>50 && pt_2>50"), Selection("njets>=1", "pt_1>50 && pt_2>50 && njets>=1"), Selection("1 b tags", "pt_1>50 && pt_2>50 && njets>=2 && nbtags>=1", weight="btagweight"), ] for selection in selections: LOG.header(selection.name) print ">>> name='%s', filename='%s', title='%s', cut='%s'" % (color( selection.name), color(selection.filename), color( selection.title), color(selection.selection)) print ">>> weight=%r, drawcmd=%r" % (selection.weight, selection.drawcmd()) sum1 = selection + "dzeta>-40" print '>>> sum1 = selection + "dzeta>-40"' print ">>> name=%r, filename=%r, title=%r" % ( sum1.name, sum1.filename, sum1.title) print ">>> cut=%r" % (sum1.selection) sum2 = selection + Selection("dzeta", "dzeta>-40") print '>>> sum2 = selection + Selection("dzeta","dzeta>-40")' print ">>> name=%r, filename=%r, title=%r" % ( sum2.name, sum2.filename, sum2.title) print ">>> cut=%r" % (sum2.selection)
def plotfor(self, variable, **kwargs): """Check is variable is vetoed for this variable.""" verbosity = LOG.getverbosity(kwargs) if not isinstance(variable, str): variable = variable.name for searchterm in self.veto: if re.search(searchterm, variable): LOG.verb("Variable.plotFor: Regex match of variable %r to %r" % (variable, searchterm), verbosity, level=2) return False for searchterm in self.only: if re.search(searchterm, variable): LOG.verb("Variable.plotFor: Regex match of variable %r to %r" % (variable, searchterm), verbosity, level=2) return True return len(self.only) == 0
def createhists(procs,binning,nevts): """Prepare histograms for simulated data-MC comparison.""" # BINNING if len(binning)==3: # constant binning nbins, xmin, xmax = binning elif len(binning)==1: # variable binning nbins = len(binning[0])-1 binning = (nbins,array('d',list(binning[0]))) else: raise IOError("Wrong binning: %s"%(binning)) # EXPECTED: PSEUDO MC exphists = [ ] tothist = None gRandom.SetSeed(1777) for hname, htitle, scale, generator, args in procs: hist = TH1D(hname,htitle,*binning) hist.Sumw2() for j in xrange(nevts): hist.Fill(generator(*args)) hist.Scale(scale) hist.SetFillColor(coldict.get(hname,kWhite)) exphists.append(hist) if tothist: tothist.Add(hist) else: tothist = hist.Clone('total') # OBSERVED: PSEUDO DATA datahist = TH1D('data','Observed',*binning) datahist.SetBinErrorOption(TH1D.kPoisson) if LOG.verbosity>=1: print ">>> createhists: Creating pseudo data:" TAB = LOG.table("%5s [%5s, %5s] %-14s %-20s", "%5d [%5s, %5s] %8.1f +- %5.1f %8d +%5.1f -%5.1f") TAB.printheader('bin','xlow','xup','exp','data') for ibin in xrange(0,nbins+2): exp = tothist.GetBinContent(ibin) xlow = hist.GetXaxis().GetBinLowEdge(ibin) xup = hist.GetXaxis().GetBinUpEdge(ibin) experr = tothist.GetBinError(ibin) #if ibin==int(0.3*nbins): # add a large deviation to test points falling off ratio plot # exp *= 0.5 #elif ibin==int(0.8*nbins): # add a large deviation to test points falling off ratio plot # exp *= 1.51 data = int(gRandom.Poisson(exp)) datahist.SetBinContent(ibin,data) if LOG.verbosity>=1: TAB.printrow(ibin,xlow,xup,exp,experr,data,datahist.GetBinErrorUp(ibin),datahist.GetBinErrorLow(ibin)) return datahist, exphists
def makelatex(string, **kwargs): """Convert patterns in a string to LaTeX format.""" global var_dict_sorted verbosity = LOG.getverbosity(kwargs) if not isinstance(string, str) or not string: return string if string and string[0] == '{' and string[-1] == '}': return string[1:-1] units = kwargs.get('units', True) split = kwargs.get('split', False) GeV = False cm = False oldstr = string # PREDEFINED if len(var_dict_sorted) != len(var_dict): var_dict_sorted = sorted(var_dict, key=lambda x: len(x), reverse=True) for var in var_dict_sorted: if var in string: string = string.replace(var, var_dict[var]) #string = re.sub(r"\b%s\b"%var,var_dict[var],string,re.IGNORECASE) break # SPLIT LINE if split: while '\n' in string: string = "#splitline{%s}" % (string.replace('\n', '}{', 1)) if 'splitline' not in string and len(string) > 30: part1 = string[:len(string) / 2] part2 = string[len(string) / 2:] if ' ' in part2: string = "#splitline{" + part1 + part2.replace(' ', '}{', 1) + "}" elif ' ' in part1: i = part1.rfind(' ') string = "#splitline{" + string[:i] + '}{' + string[i + 1:] + "}" # REPLACE PATTERNS (RECURSIVELY) match = funcexpr.match(string) # for min(), max(), ... if ' / ' in string: kwargs['units'] = False string = ' / '.join( makelatex(s, **kwargs) for s in string.split(' / ')) elif match: kwargs['units'] = False func = makelatex(match.group(1), **kwargs) arg1 = makelatex(match.group(2), **kwargs) arg2 = makelatex(match.group(3), **kwargs) old = "%s(%s,%s)" % (match.group(1), match.group(2), match.group(3)) new = "%s(%s,%s)" % (func, arg1, arg2) string = string.replace(old, new) #print ">>> %r -> %r, %r -> %r, %r -> %r, %r"%(match.group(2),arg1,match.group(3),arg2,old,new,string) elif '+' in string: kwargs['units'] = False string = '+'.join(makelatex(s, **kwargs) for s in string.split('+')) else: strlow = string.lower().strip() if "p_" in strlow: string = re.sub(r"(?<!i)(p)_([^{}()|<>=\ ]+)", r"\1_{\2}", string, flags=re.IGNORECASE).replace('{t}', '{T}') GeV = True if re.search(r"(?<!le)(?<!byphoton)(?<!dee)pt(?!weight)", strlow): # pt string = re.sub( r"(?<!k)(?<!Dee)(?<!OverTau)(p)[tT]_([^{}()|<>=_\ ]+)", r"\1_{T}^{\2}", string, flags=re.IGNORECASE) string = re.sub(r"\b(?<!Dee)(p)[tT]\b", r"\1_{T}", string, flags=re.IGNORECASE) GeV = True if strlow == "mt": string = re.sub(r"(m)(t)", r"\1_{T}", string, flags=re.IGNORECASE) GeV = True elif "m_" in strlow: string = re.sub(r"(?<!u)(m)_([^{}()|<>=\ \^]+)", r"\1_{\2}", string, flags=re.IGNORECASE).replace('{t}', '{T}') GeV = True elif "mt_" in strlow: string = re.sub(r"(m)t_([^{}()|<>=\ ]+)", r"\1_{T}^{\2}", string, flags=re.IGNORECASE) GeV = True if re.search(r"(?<!weig)(?<!daug)ht(?!au)", strlow): # HT string = re.sub(r"\b(h)t\b", r"\1_{T}", string, flags=re.IGNORECASE) GeV = True if strlow[0] == 's' and 't' in strlow[1:3]: # scalar sum pT string = re.sub(r"s_?t(?!at)", r"S_{T}", string, flags=re.IGNORECASE) string = re.sub(r"met", r"^{MET}", string, flags=re.IGNORECASE) GeV = True if " d_" in strlow: string = re.sub(r"(\ d)_([^{}()\|<>=\ ]+)", r"\1_{\2}", string, flags=re.IGNORECASE) cm = True if "deltar_" in strlow: string = re.sub(r"(?<!\#)deltar_([^{}()|<>=\ ]+)", r"#DeltaR_{\1}", string, flags=re.IGNORECASE) elif "deltar" in strlow: string = re.sub(r"(?<!\#)deltar", r"#DeltaR", string, flags=re.IGNORECASE) elif "dr_" in strlow: string = re.sub(r"(?<!\w)dr_([^{}()|<>=\ ]+)", r"#DeltaR_{\1}", string, flags=re.IGNORECASE) elif "dr" in strlow: string = re.sub(r"(?<![a-z])dr(?![a-z])", r"#DeltaR", string, flags=re.IGNORECASE) if "chi" in strlow: string = re.sub(r"(?<!#)chi(?!ng)", r"#chi", string, flags=re.IGNORECASE) string = re.sub(r"chi_([^{}()^|<>=\ ]+)", r"chi_{\1}", string, flags=re.IGNORECASE) if "phi" in strlow: if "dphi" in strlow: string = string.replace("dphi", "#Delta#phi") else: string = string.replace("phi", "#phi") string = re.sub(r"phi_([^{}()|<>=\ ]+)", r"phi_{\1}", string, flags=re.IGNORECASE) if "zeta" in strlow and "#zeta" not in strlow: if "Dzeta" in string: string = string.replace("Dzeta", "D_{zeta}") GeV = True if "zeta_" in strlow: string = re.sub(r"(?<!#)(zeta)_([^{}()|<>=\ ]+)", r"#\1_{\2}", string, flags=re.IGNORECASE) else: string = re.sub(r"(?<!#)(zeta)", r"#\1", string, flags=re.IGNORECASE) GeV = True if "eta" in strlow: #and "#eta" not in strlow and "#zeta" not in strlow and "deta" not in strlow: string = string.replace("deta", "#Deltaeta") string = re.sub(r"(?<!\#[Bbz])eta", r"#eta", string) string = re.sub(r"eta_([^{}()|<>=\ ]+)", r"eta_{\1}", string) if "tau" in strlow: #string = re.sub(r"(?<!^)tau(?!\ )",r"#tau",string,re.IGNORECASE) string = re.sub(r"(?<!Deep)(?<!Over)tau", r"#tau", string, flags=re.IGNORECASE) #string = re.sub(r" #tau ",r" tau ",string,flags=re.IGNORECASE) #string = re.sub(r"^#tau ",r"tau ",string,flags=re.IGNORECASE) string = re.sub(r"tau_([^{}()^|<>=\ ]+)", r"tau_{\1}", string, flags=re.IGNORECASE) string = re.sub(r"#tauh", r"#tau_{h}", string, flags=re.IGNORECASE) if "abs(" in string and ")" in string: string = re.sub(r"abs\(([^)]+)\)", r"|\1|", string) #string = string.replace("abs(","|").replace(")","") + "|" # TODO: split at next space if "mu" in strlow: string = re.sub(r"(?<!VS)mu(?![lo])", r"#mu", string) #string = string.replace("mu","#mu").replace("Mu","#mu") #string = string.replace("si#mulation","simulation") if "nu" in strlow: string = re.sub(r"nu(?![pm])", r"#nu", string) if "ttbar" in strlow: string = re.sub(r"ttbar", "t#bar{t}", string, flags=re.IGNORECASE) if "npv" in strlow: string = re.sub(r"npvs?", "Number of primary vertices", string) if '->' in string: string = string.replace('->', '#rightarrow') if '=' in string: string = string.replace(">=", "#geq").replace("<=", "#leq") string = string.replace('##', '#') # UNITS if isinstance(units, str): if re.search(r"[(\[].*[)\]]", units): string += " " + units.strip() else: string += " [%s]" % units.strip() elif units and not '/' in string: if GeV or "mass" in string or "p_{T}" in string or "S_{T}" in string or ( any(m in string.lower() for m in ["met", "p_{t}^{miss}"]) and "phi" not in string): if "GeV" not in string: string += " [GeV]" if cm: LOG.warning("makelatex: Flagged units are both GeV and cm!") elif cm: #or 'd_' in string string += " [cm]" if (verbosity >= 2 and string != oldstr) or verbosity >= 3: print ">>> makelatex: %r -> %r" % (oldstr, string) return string
def match(terms, labels, **kwargs): """Match given search terms (strings) to some given list of labels.""" verbosity = LOG.getverbosity(kwargs) terms = ensurelist(terms, nonzero=True) # search terms labels = ensurelist(labels, nonzero=True) # labels to match to found = True regex = kwargs.get('regex', False) # use regexpr patterns (instead of glob) incl = kwargs.get( 'incl', True ) # match at least one term; if incl=False ("exclusive"), match every term start = kwargs.get('start', False) # match only beginning of string LOG.verb( "match: compare labels=%s -> searchterms=%s (incl=%s,regex=%s)" % (labels, terms, incl, regex), verbosity, 3) if not terms: return False for i, searchterm in enumerate(terms): if not searchterm: continue if not regex: # convert glob to regexp #fnmatch.translate( '*.foo' ) #searchterm = re.sub(r"(?<!\\)\+",r"\+",searchterm) # replace + with \+ #searchterm = re.sub(r"([^\.])\*",r"\1.*",searchterm) # replace * with .* searchterm = re.escape(searchterm).replace(r'\?', '.').replace( r'\*', '.*?').replace(r'\^', '^') if start and not searchterm.startswith('^'): searchterm = '^' + searchterm terms[i] = searchterm if incl: # inclusive: match only one search term for searchterm in terms: for label in labels: matches = re.findall(searchterm, label) if matches: LOG.verb( " matched %r -> %r; return True" % (label, searchterm), verbosity, 3) return True # one search terms is matched else: LOG.verb(" not matched %r -> %r" % (label, searchterm), verbosity, 3) return False # no search term was matched else: # exclusive: match all search terms for searchterm in terms: for label in labels: matches = re.findall(searchterm, label) if matches: LOG.verb(" matched %r -> %r" % (label, searchterm), verbosity, 3) break else: LOG.verb(" not matched %r -> %r" % (label, searchterm), verbosity, 3) else: return False # this search terms was not matched return True # all search terms were matched