10"""Interactive python commands for plotting from a tuple-like object.
11This module provides in python functionality similar to TTree::Draw
12and TTree::Scan. The major conceptual differences are:
14 - All expressions are written in python (and not the specialized
15 TTree::Draw language).
16 - This can be applied to any type of object providing a simple loop
17 interface (explained below), not just to TTree's. (A TTree will work;
18 there is also a wrapper for the Athena event loop.)
20In addition, this style of query may be somewhat
21easier to type interactively.
27Here are some examples of plotting commands to give you the flavor:
30 d tt.ele_pt$i; 50 0 100*gev
32 d tt[100:1000].muo$i.pt() if abs(muo.eta)<2
33 d tt.(ele$i+ele$j).m() if $i<$j; same
36To use these commands, you can pass them as strings to pydraw.cmd:
38 from pydraw import cmd
41Alternatively, if you execute the cmdhook function, you can type them
44 from pydraw import cmdhook
48(Note that this second form doesn't work in general for code that's read
55The general syntax for drawing a histogram looks like this:
57 d TUPLESPEC.[STMT@ ...]EXPR[:EXPR] [if EXPR] [; HISTSPEC]
59These pieces are explained in more detail below.
65The object on which the draw operation is to be performed is given
66by TUPLESPEC. This should be the name of some object in the python
67global dictionary. Note that if the expression for the tuple
68itself contains a period or brackets, you'll need to enclose it in parentheses:
70 d (trees.tt[1])[:100].ele_pt$i
72Optionally, this can include a slice-like notation
73to restrict the rows to which the draw applies:
75 tuple[i:j] --- process rows i <= n < j
76 tuple[:j] --- process rows n < j
77 tuple[i:] --- process rows n >= i
78 tuple[i] --- process row i
80i and j can be expressions as well.
82The tuple object should contain a method like this:
84 def loop (self, func, looplo, loophi)
86This function should loop over rows [looplo, loophi) and
87call func on each. func will take two arguments, the first
88being the row number and the second being the event object
89(which may just be the tuple itself).
91If a method named loop is not available, but GetEntry and GetEntries
92methods are available, then those will be used instead.
93Similarly, if size and seekEvent are available, a wrapper
94appropriate for the Athena event loop will be used.
96Thus, you can make plots from within Athena like this:
98 d theApp.ElectronAODCollection$i.eta()
104Once a tuple is specified, one then needs to specify what to plot.
105This is done with an arbitrary python expression, with some extensions.
107To plot a simple numeric variable from the tuple, just give its name.
112will plot the variable `foo' from each row of the tuple. You can of course
113also use more complicated expressions:
117In the common case, though, the members of the tuple will be vectors
118of numbers of objects over which you want to iterate. You can iterate
119plotting over such a vector by specifying a dummy index. This is an
120identifier starting with a dollar sign:
124(Making the dummy indices explicit was a deliberate change from the
125implicit iteration of root/paw. Such implicit iteration sometimes
126caused confusion about just what was being iterated over, and also
127when people needed to distinguish between accessing attributes
128of a container and attributes of the contained objects.)
130This will automatically step $i over the contents of the vector pt_e,
131plotting each one. The vector being iterated over may contain objects
136Note that the limits of the iteration are handled automatically.
137The index $i can also be used in contexts other than that of an index.
138For example, to limit the iteration in the above example to the first
139four items, one can use:
141 d tt.ele$i.pt() if $i<4
143(This uses a selection clause. This is to be described later, but the meaning
146If a dummy index is used for more than one vector, the iteration limit
147will be taken from whichever vector is smaller. For example:
151will iterate min(len(ele),len(muo)) times.
153Multiple dummy indices may be used. In that case, all possible index
154combinations are used (a simple nested loop). If there is a symmetry
155involved, a selection clause may be used to eliminate duplicates.
156For example (given an appropriate ele definition), this will plot the
157invariant masses of all electron pairs:
159 d tt.(ele$i+ele$j).m() if $i>$j
161One can also reference individual elements of a vector using the
162notation $N. Here, the indexing is 1-based (so $1 is the first element).
163Example: to plot the pt of the leading electron
167Note that one can do something similar just using standard python
172This, however, will crash if ele is empty; if the $N form is used,
173an implicit selection is added to ensure that the index is in range.
174Thus, the proper equivalent of the $N-form example is:
176 d tt.ele[0].pt() if len(ele)>0
178You can also use $nCONT as an abbreviation for len(CONT):
180 d tt.ele[0].pt() if $nele>0
182Names used in expressions will be looked up first in the tuple object,
183then in the global dictionary. Note that the lookup in the tuple happens
184before looping starts, so all needed variables must already be present
185in the tuple. If you want to refer to the tuple object itself,
186you can use the special variable `_ev'. (This can be changed by assigning
187a string to pydraw._evtvar.)
189Multiple expressions may be given, separated by `:'. For drawing histograms,
190you can give two expressions, for the x and y axis expressions. For scanning
191tuples (see below), you give the list of expressions to be scanned.
197You can select items to be filled using a boolean expression, set off
200 d tt.ele$i.pt() if abs(ele$i.eta())<2
202All dummy variables are common between the variable expressions
209You can specify arbitrary Python expressions to be executed before looping
210starts. These come before the variables expressions, and are delimited
211with `@'. This is useful mostly for defining short aliases for tuple
212variables. For example:
214 d tt.ele=ElectronAODCollection@ele$i.eta() if ele$i.pt()>100*gev
217Histogram specifications
218------------------------
220Histogram specifications follow a semicolon. They can have the forms:
224 NX XLO XHI OPTIONS...
225 NX XLO XHI NY YLO YHI OPTIONS...
228For the first form, specifying ! reuses the same histogram that was used
231For the second form, specifying >>NAME looks in the global dictionary
232for a histogram NAME and uses that.
234Otherwise, a new histogram is created. The binning for this histogram
235may be specified by NX XLO XHI and NY YLO YHI.
237Plotting options may also be given. The special option `prof' means
238to create a profile histogram. Otherwise, root drawing options may
239be used. This package uses PyAnalysisUtils.draw_obj to draw the
240histograms, so the extra options supported by that function may
241also be used. See draw_obj.py for details.
243The last histogram to have been drawn is available is pydraw.last_hist.
249The scan command is very similar to draw:
251 scan TUPLESPEC.[STMT@ ...]EXPR[:EXPR] [if EXPR] [; REDIRECT]
253Instead of drawing a histogram, scan prints out a table of the expression
256A semicolon may be followed by a redirection of the form >FNAME to write
257to file FNAME rather than printing, of >>FNAME to append to it.
259The formatting of the data printed by scan is currently pretty rudimentary.
260This should probably be improved.
266There is also a loop command:
268 loop TUPLESPEC.[STMT@ ...]EXPR[:EXPR] [if EXPR]
270Loop will evaluate the given expressions in the same manner as draw and scan,
271but the results of this are ignored. So it only makes sense to use loop
272to evaluate expressions for their side effects. This can be used,
273for example, to call a function that fills some large set of histograms.
279The general interface to execute one of these commands is the `cmd' function,
280which takes the command as a string:
282 from pydraw import cmd
285Each command is also implemented by a single function, which may be called
286directly. The command name should not be included in this case:
288 from pydraw import draw
291Finally, if you call the function cmdhook(), then you can give the commands
292directly on the python command line:
294 from pydraw import cmdhook
301 - No way to specify an event weight when filling a histogram using
304 - Hoist selection code out of the dummy index loops, when they don't
305 depend on the index? For example,
309 gets implemented like:
315 but it would be more efficient to pull the selection out of the loop.
317 - In an expr like d em.foo$i if em.bar$i>1
318 then foo always gets evaluated even if the condition is false.
333from io
import StringIO
334from PyAnalysisUtils.draw_obj
import draw_obj, get_canvas
338 ScatterH2 = ROOT.RootUtils.ScatterH2
339except AttributeError:
340 ScatterH2 = ROOT.TH2F
341 print (
"WARNING: RootUtils::ScatterH2 not available; using TH2F instead")
347 h.SetBit (ROOT.TH1.kCanRebin)
349 return h.TestBit (ROOT.TH1.kCanRebin)
350except AttributeError:
352 h.GetXaxis().SetCanExtend(
True)
354 return h.GetXaxis().CanExtend()
362_globals = sys.modules[
'__main__'].__dict__
366_idchars = string.ascii_letters + string.digits +
'_'
375 """Name a string safe to use as a histogram name.
377 Root does bad things if you put / in a histogram name, so we remove them.
379 >>> print (_sanitize_hname('foo'))
381 >>> print (_sanitize_hname('foo/bar'))
384 return s.replace (
'/',
' DIV ')
388 """Transform tokens back into Python source code.
390 Each element returned by the iterable must be a token sequence
391 with at least two elements, a token number and token value.
393 Unlike tokenize.untokenize(), this does not handle multiple lines.
394 It also tries not to add unneeded spaces.
397 >>> from tokenize import generate_tokens, untokenize
398 >>> from io import StringIO
399 >>> def untokenize1(tt):
401 ... if tt[-1][0]==0: tt=tt[:-1]
402 ... return untokenize(tt)
403 >>> untokenize1(generate_tokens(StringIO('1+1').readline))
405 >>> _untokenize(generate_tokens(StringIO('1+1').readline))
407 >>> untokenize1(generate_tokens(StringIO('foo$i>2*h').readline))
409 >>> _untokenize(generate_tokens(StringIO('foo$i>2*h').readline))
414 toks_append = toks.append
416 toknum, tokval = tok[:2]
417 tokval = tokval.strip()
418 if toknum
in (token.NAME, token.NUMBER):
420 tokval =
' ' + tokval
429 """Look for NEEDLE in HAYSTACK (token-based. Return pair (HEAD, TAIL).
431 HAYSTACK and NEEDLE are both strings. Look for a token in HAYSTACK with
432 a value matching NEEDLE that is outside of any paired delimiters.
433 Also ignores things in strings.
434 If IGNORE_DELIM is True, then we do find things inside delimiters
435 (strings are still ignored).
437 Returns a pair (HEAD, TAIL) of the pieces of the string before and
438 after NEEDLE. If there is no match, returns (HAYSTACK, None).
439 Note that whitespace and formatting in HEAD and TAIL may differ
440 from the original string.
443 >>> _find_outer ("head.tail1.tail2", ".")
444 ('head', 'tail1.tail2')
445 >>> _find_outer ("(head.tail1).tail2", ".")
446 ('(head.tail1)', 'tail2')
447 >>> _find_outer ("[a for a in foo if good(a)] if bar", "if")
448 ('[a for a in foo if good(a)]', 'bar')
449 >>> _find_outer ("(a [b {c . d } ] ) . e", ".")
450 ('(a [b {c . d } ] )', 'e')
451 >>> _find_outer ("a.b", ";")
453 >>> _find_outer ("a '$' b", '$')
455 >>> _find_outer ("a $ b", '$')
457 >>> _find_outer ("(head.tail1).tail2", ".", True)
458 ('(head', 'tail1).tail2')
459 >>> _find_outer ('a; 1 -1 1', ';')
462 tlist = tokenize.generate_tokens (StringIO(haystack).readline)
465 for (i, (tnum, val, a, b, c))
in enumerate (tlist):
466 if tnum != token.STRING
and not pend
and val == needle:
469 return (haystack[:col1].
strip(),
470 haystack[col2:].
strip())
478 elif pend
and val == pend[-1]:
480 head.append ((tnum, val))
481 return (haystack,
None)
485 """Split HAYSTACK at the delimiters NEEDLE, as in _find_outer.
488 >>> _split_outer ("a,(b,c),d", ",")
490 >>> _split_outer ("a,,b", ",")
492 >>> _split_outer ("a", ",")
494 >>> #_split_outer ("", ",")
499 (head, tail) = _find_outer (haystack, needle)
510 """Wrapper for TTree, supplying a loop method.
512 This class wraps a TTree class and provides a loop method
513 that will work with pydraw.
517 """Make a wrapper for a tree."""
521 def loop (self, f, looplo=0, loophi=sys.maxsize):
522 """Call f(i,tree) on rows [looplo, loophi)"""
524 loophi = min (loophi, tree.GetEntries())
525 getentry = tree.GetEntry
526 for i
in range(looplo, loophi):
533 """Wrapper for the Athena event loop, supplying a loop method.
535 This class wraps an application manager object and provides a loop method
536 that will work with pydraw.
539 from AthenaPython
import PyAthena
541 from AthenaCommon.AppMgr
import theApp
544 self.
_sg = PyAthena.py_svc(
'StoreGateSvc')
548 def loop (self, f, looplo=0, loophi=sys.maxsize):
549 """Call f(i,tree) on rows [looplo, loophi)"""
550 loophi = min (loophi, self.
_app.size())
551 getentry = self.
_app.seekEvent
552 for i
in range(looplo, loophi):
559 if not v.startswith(
'_'):
561 raise AttributeError()
565 """Holds information about a dummy loop variable.
568 name - The name of the dummy variable.
569 ids - Set of loop identifiers (`foo' in `foo$i') with which
570 this dummy has been used.
571 explicit - Set to true if this variable is ever used on its own
576 """Initialize given the name."""
583 """Return the iterator variable for this dummy and loop identifier ID.
585 return "_it_%s_%s" % (self.
name, id)
588 """Return the dummy variable name for this dummy."""
589 return "_dum_" + self.
name
592 """Notice this this dummy is used with loop identifier ID.
594 Return the iterator variable.
600 """Return the list of loop identifiers with which we've been used."""
601 return list (self.
ids)
605 """Holds information used to implement a draw/scan/loop command.
607 Pass the draw string to the constructor. See the file-level comments
608 for details on the syntax of this. This will define the
609 following attributes:
611 errstr - If set to a string, there was an error.
612 Should be None if everything's ok.
613 tuple - The name of the tuple object.
614 tuple_o - Tuple object.
615 lo - The lower bound for row iteration.
616 hi - The upper bound for row iteration.
617 stmts - List of additional statements.
618 exprs - List of draw expressions.
619 sel - Selection expression or None.
620 sel_orig - Untransformed selection expression or None.
621 expr_orig- Untransformed plotting expression.
622 histspec - The text following `;', split into space-separated words.
625 _iddict - Map from loop identifiers (`foo' in `foo$i')
626 to temp variables used to reference
627 them in the loop function.
628 _limdict - Map from loop identifiers (`foo' in `foo$2')
629 to the largest explicit index seen.
630 _loopdict - Map of loop dummy variable names to _Loopvar instances.
634 """Initialize from a draw string. See above for more details."""
645 except Exception
as e:
654 """Parse a draw string. See above for more details."""
670 self.
errstr =
"Empty draw string."
674 (tuple, s) = _find_outer (s,
'.')
676 self.
errstr =
"Missing period in tuple specification."
707 if hasattr (self.
tuple_o,
'loop'):
710 elif (hasattr (self.
tuple_o,
'GetEntry')
and
711 hasattr (self.
tuple_o,
'GetEntries')):
714 elif (hasattr (self.
tuple_o,
'size')
and
715 hasattr (self.
tuple_o,
'seekEvent')):
721 " doesn't have a correct interface.")
729 """Parse the range part of a draw string.
731 See above for more details.
732 Fills self.tuple, self.lo, self.hi.
736 (tuple, tail) = _find_outer (tuple,
'[')
738 g = copy.copy (_globals)
740 pos = tail.find (
':')
741 pos2 = tail.find (
']')
745 slo = tail[:pos2].
strip()
747 lo = int (eval (slo, g))
750 slo = tail[:pos].
strip()
752 lo = int (eval (slo, g))
753 shi = tail[pos+1:pos2].
strip()
755 hi = int (eval (shi, g))
757 if tuple[0] ==
'(' and tuple[-1] ==
')':
758 tuple = tuple[1:-1].
strip()
766 """Given a loop identifier (`foo' in `foo$i'), return the identifier
767 used to reference it in loop functions.
777 """Handle an explicit index reference; i.e., `foo$2'.
779 S1 and S2 are pieces of the string before and after the `$'.
780 Returns the modified string.
783 while pos2 < len(s2)
and s2[pos2]
in string.digits:
792 s = (
"[%d]" % (i-1)) + s2[pos2:]
794 while pos2 >= 0
and s1[pos2]
in _idchars:
801 s = s1[:pos2] + self.
_mung_id (id) + s
807 """Handle a length reference; i.e., `$nfoo'.
809 S1 and S2 are pieces of the string before and after the `$'.
810 Returns the modified string.
813 while pos2 < len(s2)
and s2[pos2]
in _idchars:
816 s = s1 + (
" len(%s)" % self.
_mung_id(id)) + s2[pos2:]
821 """Handle use of a dummy loop variable, such as foo$i.
823 S1 and S2 are pieces of the string before and after the `$'.
824 Returns the modified string.
829 while pos2 < len(s2)
and s2[pos2]
in _idchars:
832 self.
errstr =
"Bad loop var"
843 if len(s1) > 0
and s1[-1]
in _idchars:
846 while pos3 >= 0
and s1[pos3]
in _idchars:
849 assert (len(s1) - pos3 >= 1)
853 s = s1[:pos3] + ll.add_id(id) + s2[pos2:]
858 s = s1 + (
"%s" % ll.dumname()) + s2[pos2:]
864 """Process $ constructions in string S.
866 Returns the modified string.
872 (s1, s2) = _find_outer (s[pos:],
'$',
True)
877 if s2[0]
in string.digits:
879 elif (s2[0] ==
'n' and
880 (
not (len(s1) > 0
and s1[-1]
in _idchars)
or
881 s1.endswith (
' and')
or
882 s1.endswith (
' or')
or
883 s1.endswith (
'not'))):
885 elif s2[0]
in string.ascii_letters:
890 pos = pos + len(s1)+1
896 """Perform id substitution in S.
898 For identifiers in S that are attributes of our tuple,
899 replace them with references to the tuple attribute
902 Returns the modified string.
907 tlist = tokenize.generate_tokens (StringIO(s).readline)
910 for tnum, val, a, b, c
in tlist:
911 if tnum == token.NAME
and not afterDot:
912 if hasattr (self.
tuple_o, val):
915 out.append ((tnum, val))
918 if tnum == token.OP
and val ==
'.':
922 return _untokenize (out)
926 """Process $ constructions and id substitution in string S.
928 Returns the modified string.
935 """Create the text for the function to process this query.
937 PAYLOAD is the payload expression to plug in.
938 EXTARGS is an additional string to add to the end of the
939 function's argument list (to set default values, for example).
940 Returns the function definition as a string.
945 limsel =
' and '.join ([
"len(%s)>=%d" % (self.
_iddict[p[0]], p[1])
950 sel = limsel +
" and (" + sel +
")"
952 ftext =
"def _loopfunc(_i, %s%s):\n" % (_evtvar, extargs)
953 for (id1, id2)
in sorted(self.
_iddict.items()):
954 ftext +=
" %s = %s.%s\n" % (id2, _evtvar, id1)
957 for (i,l)
in sorted(self.
_loopdict.items()):
958 ids = sorted(l.get_ids())
961 vars = l.itname (ids[0])
964 vars =
"(" +
','.join([l.itname (id)
for id
in ids]) +
")"
965 lists = (
"zip(" +
','.join([self.
_iddict[id]
for id
in ids])
968 vars =
"(%s,%s)" % (l.dumname(), vars)
969 lists =
"enumerate(%s)" % lists
970 ftext +=
' '*indent +
"for %s in %s:\n" % (vars, lists)
974 ftext +=
' '*indent + s +
'\n'
976 if sel
and sel !=
'1':
977 ftext +=
' '*indent +
"if (%s):\n" % sel
980 ftext +=
' '*indent +
"%s\n" % payload
989 """Holds the results of _get_bins. Defined attributes:
999 """Parse bin specifications from split list of arguments ARGS.
1000 NDIM is 1 or 2, and AXIS is 0 or 1, for the x or y axis.
1003 >>> from PyAnalysisUtils import pydraw
1004 >>> pydraw._globals = globals()
1006 >>> ROOT.gPad.Range(0, 1,2,3)
1007 >>> b = _get_bins (["50", "10", "100"], 1, 0)
1008 >>> print (b.nbins, b.lo, b.hi, b.rebin)
1010 >>> b = _get_bins ([], 1, 0)
1011 >>> print (b.nbins, b.lo, b.hi, b.rebin)
1013 >>> b = _get_bins (["!", "10"], 1, 0)
1014 >>> print (b.nbins, b.lo, b.hi, b.rebin)
1016 >>> b = _get_bins (["!", "!", "10"], 1, 0)
1017 >>> print (b.nbins, b.lo, b.hi, b.rebin)
1020 >>> b = _get_bins (["50", "0", "2*scale"], 1, 0)
1021 >>> print (b.nbins, b.lo, b.hi, b.rebin)
1023 >>> b = _get_bins ([], 2, 0)
1024 >>> print (b.nbins, b.lo, b.hi, b.rebin)
1026 >>> b = _get_bins ([], 2, 1)
1027 >>> print (b.nbins, b.lo, b.hi, b.rebin)
1029 >>> b = _get_bins ([], 2, 2)
1030 Traceback (most recent call last):
1035 g = copy.copy (_globals)
1040 if len(args) >= 1
and args[0] !=
'!' and len(args[0]) > 0:
1041 bins.nbins = int (eval (args[0], g))
1046 if len(args) >= 2
and args[1] !=
'!' and len(args[1]) > 0:
1047 bins.lo = float (eval (args[1], g))
1050 if len(args) >= 3
and args[2] !=
'!' and len(args[2]) > 0:
1051 bins.hi = float (eval (args[2], g))
1054 if bins.hi <= bins.lo:
1057 bins.hi = bins.lo + 1
1059 bins.lo = ROOT.gPad.GetUxmin()
1060 bins.hi = ROOT.gPad.GetUxmax()
1062 bins.lo = ROOT.gPad.GetUymin()
1063 bins.hi = ROOT.gPad.GetUymax()
1071 """Create a new histogram from options.
1073 NDIM is the dimensionality of the histogram (1 or 2).
1074 ARGS is a list of the arguments given to specify the histogram.
1075 HNAME and HTITLE are the histogram name and title, respectively.
1080 xbins = _get_bins (args, ndim, 0)
1085 ybins = _get_bins (args[3:], ndim, 1)
1086 rebin = rebin
or ybins.rebin
1091 for i
in range (0, len(args)):
1092 if args[i][0]
in string.ascii_letters:
1093 for j
in range (i, len(args)):
1094 if ndim == 2
and args[j].lower() ==
"prof":
1097 options =
' '.join (args[i:])
1101 hold = ROOT.gROOT.FindObject (hname)
1103 ROOT.gROOT.Remove (hold)
1107 hist = ROOT.TProfile (hname, htitle, xbins.nbins, xbins.lo, xbins.hi)
1109 hist.SetMinimum (ybins.lo)
1110 hist.SetMaximum (ybins.hi)
1112 hist = ROOT.TH1F (hname, htitle, xbins.nbins, xbins.lo, xbins.hi)
1114 hist = ScatterH2 (hname, htitle,
1115 xbins.nbins, xbins.lo, xbins.hi,
1116 ybins.nbins, ybins.lo, ybins.hi)
1117 if hasattr (hist,
'scatter'):
1124 return (hist, options)
1128 """Process a draw command.
1130 ARG is the command arguments (without the command word itself).
1131 See the header comments for the command syntax.
1143 if len (c.exprs) == 1:
1145 payload =
"_hfill (%s)" % c.exprs[0]
1148 payload =
"_hfill ((%s),(%s))" % (c.exprs[0], c.exprs[1])
1151 htitle =
"%s.%s" % (c.tuple, c.expr_orig)
1153 htitle = htitle +
'{%s}' % c.sel_orig
1157 if len(c.histspec) >= 1
and c.histspec[0] ==
"!" and last_hist
is not None:
1159 options =
' '.join (c.histspec[1:])
1160 elif len(c.histspec) >= 1
and c.histspec[0][:2] ==
'>>':
1161 hname = c.histspec[0][2:]
1162 hist = _globals.get (hname)
1163 options =
' '.join (c.histspec[1:])
1165 (hist, options) = _get_hist (ndim, c.histspec,
1173 g = copy.copy (_globals)
1174 g[
'_hfill'] = hist.Fill
1175 ftext = c._make_func (payload,
', _hfill = _hfill')
1179 c.tuple_o.loop (g[
'_loopfunc'], c.lo, c.hi)
1182 if _hasCanRebin (hist):
1183 hist.LabelsDeflate (
"X")
1185 hist.LabelsDeflate (
"Y")
1188 draw_obj (hist, options)
1193 """Helper to print out one row of a scan.
1195 F is the file object to which to write, I is the row number,
1196 and ARGS is a tuple of the column values."""
1200 if isinstance(a, int):
1202 elif isinstance(a, str):
1211 """Process a scan command.
1213 ARG is the command arguments (without the command word itself).
1214 See the header comments for the command syntax.
1223 payload =
"_print (_i, %s)" % \
1224 ','.join ([
'(%s)'%e
for e
in c.exprs])
1229 if len(c.histspec) > 0:
1230 if c.histspec[0].startswith (
'>>'):
1232 fname = c.histspec[0][2:]
1233 elif c.histspec[0].startswith (
'>'):
1234 fname = c.histspec[0][1:]
1235 if fname ==
'' and len(c.histspec) >= 2:
1236 fname = c.histspec[1]
1238 fout = open (fname,
'a' if append
else 'w')
1244 g = copy.copy (_globals)
1245 g[
'_print'] =
lambda i, *args: _scan_print (fout, i, *args)
1246 ftext = c._make_func (payload,
', _print = _print')
1250 c.tuple_o.loop (g[
'_loopfunc'], c.lo, c.hi)
1259 """Process a loop command.
1261 ARG is the command arguments (without the command word itself).
1262 See the header comments for the command syntax.
1271 payload =
"(%s,)" %
','.join (c.exprs)
1275 g = copy.copy (_globals)
1276 ftext = c._make_func (payload)
1280 c.tuple_o.loop (g[
'_loopfunc'], c.lo, c.hi)
1287_cmddict = {
'd': draw,
1295 """Process a command S.
1297 Returns True if the command was handled, False otherwise.
1298 See the header comments for the command syntax.
1301 ssplit = s.split (
None, 1)
1308 func = _cmddict.get (cmd)
1327if '_orig_ehook' not in globals():
1332 """Exception hook used by pydraw to process drawing commands."""
1335 if isinstance (value, SyntaxError):
1342 ROOT.gInterpreter.EndOfLineAction()
1346 _orig_ehook (exctype, value, traceb)
1350 """Enable entering drawing commands directly at the python prompt."""
1355 if _orig_ehook
is None:
1356 _orig_ehook = sys.excepthook
1359 sys.excepthook = _excepthook
loop(self, f, looplo=0, loophi=sys.maxsize)
_mung_expr_dollar(self, s)
_mung_index(self, s1, s2)
_make_func(self, payload, extargs='')
loop(self, f, looplo=0, loophi=sys.maxsize)
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
_get_bins(args, ndim, axis)
_get_hist(ndim, args, hname, htitle)
_split_outer(haystack, needle)
_find_outer(haystack, needle, ignore_delim=False)
_excepthook(exctype, value, traceb)