Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
#!/usr/bin/env python
#--------# # SCHEME # #--------#
""" Repeating palette of colors, modulo around. Change to obey the active palette, allowing local change of color.
>>> COLORS(0) 1 >>> COLORS(3) # qhist's 28
""" # return (1, 2, 4, 28, 6, ROOT.kGreen+3, ROOT.kAzure+7 )[i%7] # return ( 1,2,8,4,6,7,9 )[i%7] # return ROOT.gStyle.GetColorPalette( i*100 ) # return (0,5,7,3,6,2,4,1)[i%8] ## From LHCb.style
""" Repeating choices of marker.
>>> MARKERS(0) == ROOT.kMultiply True >>> MARKERS(2) == ROOT.kPlus True
"""
""" Choice of line style.
>>> LINES(0) 1
"""
""" Repeating choice of fill style, modulo 7.
>>> FILLS(0) 3001
""" # return (3001, 3254, 3245, 3305, 3395, 3012, 3016)[i%7] # return (3003,3004,3005,3006,3007,3012,3016)[i%7]
#-------------# # COMPUTATION # #-------------#
""" Given the list of event size (counts), return appropriate num of bins, which is calculated from sqrt of smallest event size, rounded in 5. min of 20, max of 100.
>>> auto_bin_size(100) 20 >>> auto_bin_size(5000) 70 >>> auto_bin_size(1E6) 100 >>> auto_bin_size(0) # Even null plot, return minimum number of bins 20
"""
#-------------------------------------------------------------------------------
""" Deduce whether the log scale should be used or not, judging from given range.
>>> auto_log(0, 10) # has zero, don't. False >>> auto_log(0.0, 1.0) # has zero, don't. False >>> auto_log(-1.0, 1.0) # has negative, don't. False >>> auto_log(1E-4, 1E1) # positive & wide, do it. True >>> auto_log(10, 50) # arbitary, don't False
>>> ## If both are not initialize (e.g., null-stats), return None >>> ## in order to have same default as QHist.xlog >>> auto_log( 10, None ) is None True >>> auto_log( None, 100 ) is None True >>> auto_log( None, None ) is None True
""" ## Uninitialize case ## If bound within [0,1], don't ## Crossing zero. No log ## Large magnitude ## Don't do log, by default
#-------------------------------------------------------------------------------
""" Wrapper around TAxis.SetMoreLogLabels Configure automatically whether this axis should have detail label or not. Perferable do so in small scale.
>>> axis = ROOT.TAxis(20, 1, 1000) >>> axis.moreLogLabels False >>> auto_morelog(axis) >>> axis.moreLogLabels True
"""
#-------------------------------------------------------------------------------
""" Important method to provide the binnings for given spec. The cue is to have pretty-log axis. http://root.cern.ch/root/roottalk/roottalk06/1213.html
Usage::
## Simple >>> make_bins(0, 100, 20) array('d', [0.0, 5.0, 10.0, ...
## Restrict the extreme one >>> make_bins(-1e12, 1, nbins=1) array('d', [-1000000.0, 1.0]) >>> make_bins(1, 1e12, nbins=1) array('d', [1.0, 1000000.0])
## Grace allowance >>> make_bins(10, 10, nbins=1) array('d', [9.9, 10.1]) >>> make_bins(0, 0, nbins=1) array('d', [-0.1, 0.1])
## Ignore log on negative >>> make_bins(-1, 10, nbins=1, is_log=True) array('d', [-1.0, 10.0])
## absurd >>> make_bins(-1e12, -1e12, 100) Traceback (most recent call last): ... ValueError: Data range seems absurd. The script will halt.
""" ### Validate and abort if it seems very suspicious
### Some fine adjustment of data ## If it's too extreme, restrict the domain
## If the min==max, do the grace allowance (+-1% each side) else:
## If x is logarithm, disable if math domain conflict
## Finally, make a array out of it. else:
#-------------------------------------------------------------------------------
""" Return the axis-min/max of the given TPC tuple.
Note: TTree::GetMinimum is NOT what we want because cannot use cut c Note: Y-min/max is more complicate because of ybin, normalization Note: For SetEstimate hack, see TTree::Draw documantation Note: To ensure, use the vanilla TTree (not rootpy Tree), force mother call.
""" # n = ROOT.TTree.Draw(t, p, c, "goff") # n = t.Draw(p, c, "goff") # raise ValueError('Null plots!! Please recheck the TPC settings.') # axis = ROOT.gROOT.FindObject('htemp').GetXaxis() # return n, axis.GetXmin(), axis.GetXmax()
#-------------------------------------------------------------------------------
""" This idiom is used so often... Pick fist value unles it's None.
Usage::
>>> prefer_first( True, 42 ) True >>> prefer_first( None, 42 ) 42
## Still pick 1st one if it's not None >>> prefer_first( False, 42 ) False
>>> prefer_first( 1, 2, 3 ) 1 >>> prefer_first( None, 2, 3 ) 2 >>> prefer_first( None, None, 3 ) 3 >>> prefer_first( None, None, None ) is None True
"""
#--------# # STRING # #--------#
""" Simply parse 3 strings together in form of 'valmin < p && p < valmax'. Skip if val is None. Return empty string if both null.
>>> cut_minmax( 'X', 10, 20 ) '(X >= 10) & (X <= 20)'
>>> cut_minmax( 'X', 12.3, None ) 'X >= 12.3'
>>> cut_minmax( 'X', None, None ) ''
"""
#-------------------------------------------------------------------------------
""" Pretty-print an array('d') to not be too long, for logging.
>>> from array import array >>> arr = array('d', [10*x**-2 for x in xrange(5,10)]) >>> arr array('d', [0.4, 0.2777777777777778, 0.2040816326530612, 0.15625, 0.12345679012345678]) >>> print(pretty_array(arr)) array(0.40, 0.28, 0.20, 0.16, 0.12)
"""
#-------------------------------------------------------------------------------
""" Return string used in mean/RMS, with my custom format.
>>> pretty_round(None) # Nice null '---' >>> pretty_round(1234567) # Too large '> 1E6' >>> pretty_round(-1234567) # Too large '< -1E6' >>> pretty_round(2E-7) # Tiny than 1E-6 '< 1E-6' >>> pretty_round(3E-5) # Small '3.00E-05' >>> pretty_round(12345) # Large '1.23E+04' >>> pretty_round(1.4142) # Natural scale '1.41'
"""
#-------------------------------------------------------------------------------
""" Custom method to concatenate list of string together, such that null is ignore ( being basestring or not ). Provide flag `delim` to change delimiter
Use primarily on logic of QHist's naming
>>> concat('prefix', 'root', 'suffix') 'prefix_root_suffix'
>>> concat(None, 'root', 'suffix', delim='/') 'root/suffix'
"""
#-------------------------------------------------------------------------------
""" Given list of string (cuts), join them and parenthesis guard (guard only the inner element, not the full outer, to avoid verbose double-guard) If the iterable is LIST/TUPLE/GEN, join with AND If the iterable is SET , join with OR Designed for recursive usage.
Note: - No using double-op '&&' to be LoKi-compatible. - The root argument, *args, by python's design, is intrinsically a tuple. So that's why one can pass arguments instead of list-of-string as arg.
Args: cuts (iterable): Iterable (tuple/list/set) of string to join.
Usage::
## Test basics >>> join([ 'a', 'b' ]) == join('a','b') True >>> join( 'a', 'b' ) '(a) & (b)' >>> join({'a', 'b'}) '(a) | (b)'
## Handle effective null >>> join() '' >>> join([]) '' >>> join(['']) '' >>> join([None]) '' >>> join({''}) # List of null-cuts '' >>> join([('',),{''}]) # Super null! '' >>> join(['c > 0', ('',), '']) 'c > 0'
## Simplify idempotent nesting >>> join([[( 'a > 3' )]]) 'a > 3' >>> join([ {'b1','b2'} ]) '(b1) | (b2)'
## Handle nested >>> join( 'a', {'b1','b2'}, 'c' ) '(a) & ((b1) | (b2)) & (c)'
## Trim whitespace >>> join( 'a > 5', 'b < 10' ) '(a > 5) & (b < 10)'
"""
## Early kill the null-value on any case, string or not: ## De-equip if it's single-tuple ## Early deal with recursive: String is the atomic unit ## Simple aesthetic on string: Trim all multiple-whitespace to single one
## Given now an iterable, determine the operator # (need this info before the cleansing). else: # pragma: no cover raise ValueError('Invalid iterable type: %r' % type(cuts))
## Apply recursion here, kill bad one before passing. ## Kill bad ones after recursion is applied ## Empty list is discarded at this point ## Early deal with collection with one item: Extract it. ## Finally join with current op. Wrap inner item here, and only here
#-------------------------------------------------------------------------------
""" Return safename for ROOT.TFile creation
>>> safename('Hello(world)') # ROOT use bracket for something else 'Hello{world}'
>>> safename('PT/P') # Bad for sys 'PT_over_P'
>>> safename('TMath::Log10(PT)') 'Log10{PT}'
>>> safename('P/1e3') 'P' """ ## remove const ## replace bad ones
#-------------------------------------------------------------------------------
""" Helper method to shorten string (to 78 chars, terminal width) for pretty-printing.
>>> print(shorten('abcdefghijklmnopqrstuvwxyz')) # not 78 abcdefghijklmnopqrstuvwxyz
>>> print(shorten('abcdefghijklmnopqrstuvwxyz'*10)) abcdefghijklmnopqrstuvwxyzabcdefghijkl...pqrstuvwxyzabcdefghijklmnopqrstuvwxyz
"""
#-------------------------------------------------------------------------------
""" Safe method to split multi-dim params string. Do not change any order
>>> split_dim('MM:PT') ['MM', 'PT'] >>> split_dim('TMath::Log10(MM): PT') ['TMath::Log10(MM)', 'PT']
"""
#-------------------------------------------------------------------------------
""" Short-cut method of above: Return integer dimension of given string. Note that in this case, it can detect dim-0
>>> dim('PT') 1 >>> dim('PT:PZ') 2 >>> dim('') 0 >>> dim( 'TMath::Log10(PT)' ) 1 >>> dim( 'TMath::Log10(PT):PZ' ) 2 """
#=============================================================================== |