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 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 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 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 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 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 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 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
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 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 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 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 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