ATLAS Offline Software
Loading...
Searching...
No Matches
python.pydraw Namespace Reference

Classes

class  _Bins
class  _Loopvar
class  AthenaLoopWrapper
class  Draw_Cmd
class  TreeLoopWrapper

Functions

 _setCanRebin (h)
 _hasCanRebin (h)
 _sanitize_hname (s)
 _untokenize (tokens)
 _find_outer (haystack, needle, ignore_delim=False)
 _split_outer (haystack, needle)
 _get_bins (args, ndim, axis)
 _get_hist (ndim, args, hname, htitle)
 draw (arg)
 _scan_print (f, i, *args)
 scan (arg)
 loop (arg)
 cmd (s)
 _excepthook (exctype, value, traceb)
 cmdhook ()

Variables

 ScatterH2 = ROOT.RootUtils.ScatterH2
 last_hist = None
 _globals = sys.modules['__main__'].__dict__
str _idchars = string.ascii_letters + string.digits + '_'
str _evtvar = '_ev'
bool _debug = False
dict _cmddict
 _orig_ehook = None
 The stuff here sets things up so that after calling cmdhook(), the user can enter drawing commands directly at the python prompt.

Detailed Description

Interactive python commands for plotting from a tuple-like object.
This module provides in python functionality similar to TTree::Draw
and TTree::Scan.  The major conceptual differences are:

 - All expressions are written in python (and not the specialized
   TTree::Draw language).
 - This can be applied to any type of object providing a simple loop
   interface (explained below), not just to TTree's.  (A TTree will work;
   there is also a wrapper for the Athena event loop.)

In addition, this style of query may be somewhat
easier to type interactively.


Quick start
===========

Here are some examples of plotting commands to give you the flavor:

  d tt.metx
  d tt.ele_pt$i; 50 0 100*gev
  d tt.metx:mety
  d tt[100:1000].muo$i.pt() if abs(muo.eta)<2
  d tt.(ele$i+ele$j).m() if $i<$j; same
  scan tt.metx:mety

To use these commands, you can pass them as strings to pydraw.cmd:

  from pydraw import cmd
  cmd('d tt.metx')

Alternatively, if you execute the cmdhook function, you can type them
directly:

  from pydraw import cmdhook
  cmdhook()
  d tt.metx

(Note that this second form doesn't work in general for code that's read
from a file.)


Draw syntax
===========

The general syntax for drawing a histogram looks like this:

  d TUPLESPEC.[STMT@ ...]EXPR[:EXPR] [if EXPR] [; HISTSPEC]

These pieces are explained in more detail below.


Tuple specifications
--------------------

The object on which the draw operation is to be performed is given
by TUPLESPEC.  This should be the name of some object in the python
global dictionary.  Note that if the expression for the tuple
itself contains a period or brackets, you'll need to enclose it in parentheses:

  d (trees.tt[1])[:100].ele_pt$i

Optionally, this can include a slice-like notation
to restrict the rows to which the draw applies:

  tuple[i:j]  --- process rows i <= n < j
  tuple[:j]   --- process rows n < j
  tuple[i:]   --- process rows n >= i
  tuple[i]    --- process row i

i and j can be expressions as well.

The tuple object should contain a method like this:

  def loop (self, func, looplo, loophi)

This function should loop over rows [looplo, loophi) and
call func on each.  func will take two arguments, the first
being the row number and the second being the event object
(which may just be the tuple itself).

If a method named loop is not available, but GetEntry and GetEntries
methods are available, then those will be used instead.
Similarly, if size and seekEvent are available, a wrapper
appropriate for the Athena event loop will be used.

Thus, you can make plots from within Athena like this:
    
   d theApp.ElectronAODCollection$i.eta()


Expressions
-----------

Once a tuple is specified, one then needs to specify what to plot.
This is done with an arbitrary python expression, with some extensions.

To plot a simple numeric variable from the tuple, just give its name.
For example:

  d tt.foo

will plot the variable `foo' from each row of the tuple.  You can of course
also use more complicated expressions:

  d tt.r*cos(phi)

In the common case, though, the members of the tuple will be vectors
of numbers of objects over which you want to iterate.  You can iterate
plotting over such a vector by specifying a dummy index.  This is an
identifier starting with a dollar sign:

  d tt.pt_e$i

(Making the dummy indices explicit was a deliberate change from the
implicit iteration of root/paw.  Such implicit iteration sometimes
caused confusion about just what was being iterated over, and also
when people needed to distinguish between accessing attributes
of a container and attributes of the contained objects.)

This will automatically step $i over the contents of the vector pt_e,
plotting each one.  The vector being iterated over may contain objects
as well as numbers:

  d tt.ele$i.pt()

Note that the limits of the iteration are handled automatically.
The index $i can also be used in contexts other than that of an index.
For example, to limit the iteration in the above example to the first
four items, one can use:

  d tt.ele$i.pt() if $i<4

(This uses a selection clause.  This is to be described later, but the meaning
should be obvious.)

If a dummy index is used for more than one vector, the iteration limit
will be taken from whichever vector is smaller.  For example:

  d tt.ele$i+muo$i

will iterate min(len(ele),len(muo)) times.

Multiple dummy indices may be used.  In that case, all possible index
combinations are used (a simple nested loop).  If there is a symmetry
involved, a selection clause may be used to eliminate duplicates.
For example (given an appropriate ele definition), this will plot the
invariant masses of all electron pairs:

  d tt.(ele$i+ele$j).m() if $i>$j

One can also reference individual elements of a vector using the
notation $N.  Here, the indexing is 1-based (so $1 is the first element).
Example: to plot the pt of the leading electron

  d tt.ele$1.pt()

Note that one can do something similar just using standard python
indexing directly:

  d tt.ele[0].pt()

This, however, will crash if ele is empty; if the $N form is used,
an implicit selection is added to ensure that the index is in range.
Thus, the proper equivalent of the $N-form example is:

  d tt.ele[0].pt() if len(ele)>0

You can also use $nCONT as an abbreviation for len(CONT):

  d tt.ele[0].pt() if $nele>0

Names used in expressions will be looked up first in the tuple object,
then in the global dictionary.  Note that the lookup in the tuple happens
before looping starts, so all needed variables must already be present
in the tuple.  If you want to refer to the tuple object itself,
you can use the special variable `_ev'.  (This can be changed by assigning
a string to pydraw._evtvar.)

Multiple expressions may be given, separated by `:'.  For drawing histograms,
you can give two expressions, for the x and y axis expressions.  For scanning
tuples (see below), you give the list of expressions to be scanned.


Selections
----------

You can select items to be filled using a boolean expression, set off
with an `if' keyword:

  d tt.ele$i.pt() if abs(ele$i.eta())<2

All dummy variables are common between the variable expressions
and the selection.


Statements
----------

You can specify arbitrary Python expressions to be executed before looping
starts.  These come before the variables expressions, and are delimited
with `@'.  This is useful mostly for defining short aliases for tuple
variables.  For example:

  d tt.ele=ElectronAODCollection@ele$i.eta() if ele$i.pt()>100*gev


Histogram specifications
------------------------

Histogram specifications follow a semicolon.  They can have the forms:

  ! OPTIONS...
  >>NAME OPTIONS...
  NX XLO XHI OPTIONS...
  NX XLO XHI NY YLO YHI OPTIONS...
  OPTIONS...

For the first form, specifying ! reuses the same histogram that was used
for the last plot.

For the second form, specifying >>NAME looks in the global dictionary
for a histogram NAME and uses that.

Otherwise, a new histogram is created.  The binning for this histogram
may be specified by NX XLO XHI and NY YLO YHI.

Plotting options may also be given.  The special option `prof' means
to create a profile histogram.  Otherwise, root drawing options may
be used.  This package uses PyAnalysisUtils.draw_obj to draw the
histograms, so the extra options supported by that function may
also be used.  See draw_obj.py for details.

The last histogram to have been drawn is available is pydraw.last_hist.


Scan syntax
===========

The scan command is very similar to draw:

  scan TUPLESPEC.[STMT@ ...]EXPR[:EXPR] [if EXPR] [; REDIRECT]

Instead of drawing a histogram, scan prints out a table of the expression
values.

A semicolon may be followed by a redirection of the form >FNAME to write
to file FNAME rather than printing, of >>FNAME to append to it.

The formatting of the data printed by scan is currently pretty rudimentary.
This should probably be improved.


Loop syntax
===========

There is also a loop command:

  loop TUPLESPEC.[STMT@ ...]EXPR[:EXPR] [if EXPR]

Loop will evaluate the given expressions in the same manner as draw and scan,
but the results of this are ignored.  So it only makes sense to use loop
to evaluate expressions for their side effects.  This can be used,
for example, to call a function that fills some large set of histograms.


Running commands
================

The general interface to execute one of these commands is the `cmd' function,
which takes the command as a string:

  from pydraw import cmd
  cmd ('d tt.foo')

Each command is also implemented by a single function, which may be called
directly.  The command name should not be included in this case:

  from pydraw import draw
  draw ('tt.foo')

Finally, if you call the function cmdhook(), then you can give the commands
directly on the python command line:

  from pydraw import cmdhook
  cmdhook()
  d tt.foo


Bugs/stuff missing
==================
 - No way to specify an event weight when filling a histogram using
   the draw command.

 - Hoist selection code out of the dummy index loops, when they don't
   depend on the index?  For example,

     d tt.foo$i if ht>100

   gets implemented like:

     for _it_foo in foo:
       if _ev.ht>100:
         Fill(_it_foo)

   but it would be more efficient to pull the selection out of the loop.

 - In an expr like d em.foo$i if em.bar$i>1
   then foo always gets evaluated even if the condition is false.

 - Scan formatting.

Function Documentation

◆ _excepthook()

python.pydraw._excepthook ( exctype,
value,
traceb )
protected
Exception hook used by pydraw to process drawing commands.

Definition at line 1331 of file pydraw.py.

1331def _excepthook (exctype, value, traceb):
1332 """Exception hook used by pydraw to process drawing commands."""
1333
1334 # If it's a syntax error, try interpreting as a drawing command.
1335 if isinstance (value, SyntaxError):
1336 val = value.text
1337 if val[-1] == '\n':
1338 val = val[:-1] #pragma: NO COVER
1339 if cmd (val):
1340 # Success --- update root stuff and return.
1341 # (This will swallow the original syntax error.)
1342 ROOT.gInterpreter.EndOfLineAction()
1343 return
1344
1345 # No luck --- pass it on to the original exception handler.
1346 _orig_ehook (exctype, value, traceb)
1347
1348

◆ _find_outer()

python.pydraw._find_outer ( haystack,
needle,
ignore_delim = False )
protected
Look for NEEDLE in HAYSTACK (token-based.  Return pair (HEAD, TAIL).

HAYSTACK and NEEDLE are both strings.  Look for a token in HAYSTACK with
a value matching NEEDLE that is outside of any paired delimiters.
Also ignores things in strings.
If IGNORE_DELIM is True, then we do find things inside delimiters
(strings are still ignored).

Returns a pair (HEAD, TAIL) of the pieces of the string before and
after NEEDLE.  If there is no match, returns (HAYSTACK, None).
Note that whitespace and formatting in HEAD and TAIL may differ
from the original string.

Examples:
>>> _find_outer ("head.tail1.tail2", ".")
('head', 'tail1.tail2')
>>> _find_outer ("(head.tail1).tail2", ".")
('(head.tail1)', 'tail2')
>>> _find_outer ("[a for a in foo if good(a)] if bar", "if")
('[a for a in foo if good(a)]', 'bar')
>>> _find_outer ("(a [b {c . d } ] ) . e", ".")
('(a [b {c . d } ] )', 'e')
>>> _find_outer ("a.b", ";")
('a.b', None)
>>> _find_outer ("a '$' b", '$')
("a '$' b", None)
>>> _find_outer ("a $ b", '$')
('a', 'b')
>>> _find_outer ("(head.tail1).tail2", ".", True)
('(head', 'tail1).tail2')
>>> _find_outer ('a; 1 -1 1', ';')
('a', '1 -1 1')

Definition at line 428 of file pydraw.py.

428def _find_outer (haystack, needle, ignore_delim = False):
429 """Look for NEEDLE in HAYSTACK (token-based. Return pair (HEAD, TAIL).
430
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).
436
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.
441
442 Examples:
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", ";")
452 ('a.b', None)
453 >>> _find_outer ("a '$' b", '$')
454 ("a '$' b", None)
455 >>> _find_outer ("a $ b", '$')
456 ('a', 'b')
457 >>> _find_outer ("(head.tail1).tail2", ".", True)
458 ('(head', 'tail1).tail2')
459 >>> _find_outer ('a; 1 -1 1', ';')
460 ('a', '1 -1 1')
461"""
462 tlist = tokenize.generate_tokens (StringIO(haystack).readline)
463 pend = []
464 head = []
465 for (i, (tnum, val, a, b, c)) in enumerate (tlist):
466 if tnum != token.STRING and not pend and val == needle:
467 col1 = a[1]
468 col2 = b[1]
469 return (haystack[:col1].strip(),
470 haystack[col2:].strip())
471 if not ignore_delim:
472 if val == '(':
473 pend.append (')')
474 elif val == '[':
475 pend.append (']')
476 elif val == '{':
477 pend.append ('}')
478 elif pend and val == pend[-1]:
479 pend.pop()
480 head.append ((tnum, val))
481 return (haystack, None)
482
483

◆ _get_bins()

python.pydraw._get_bins ( args,
ndim,
axis )
protected
Parse bin specifications from split list of arguments ARGS.
NDIM is 1 or 2, and AXIS is 0 or 1, for the x or y axis.

Examples:
>>> from PyAnalysisUtils import pydraw
>>> pydraw._globals = globals()
>>> import ROOT
>>> ROOT.gPad.Range(0, 1,2,3)
>>> b = _get_bins (["50", "10", "100"], 1, 0)
>>> print (b.nbins, b.lo, b.hi, b.rebin)
50 10.0 100.0 0
>>> b = _get_bins ([], 1, 0)
>>> print (b.nbins, b.lo, b.hi, b.rebin)
50 0 1 1
>>> b = _get_bins (["!", "10"], 1, 0)
>>> print (b.nbins, b.lo, b.hi, b.rebin)
50 10.0 11.0 1
>>> b = _get_bins (["!", "!", "10"], 1, 0)
>>> print (b.nbins, b.lo, b.hi, b.rebin)
50 0 10.0 0
>>> scale = 10
>>> b = _get_bins (["50", "0", "2*scale"], 1, 0)
>>> print (b.nbins, b.lo, b.hi, b.rebin)
50 0.0 20.0 0
>>> b = _get_bins ([], 2, 0)
>>> print (b.nbins, b.lo, b.hi, b.rebin)
50 0.0 2.0 1
>>> b = _get_bins ([], 2, 1)
>>> print (b.nbins, b.lo, b.hi, b.rebin)
50 1.0 3.0 1
>>> b = _get_bins ([], 2, 2)
Traceback (most recent call last):
    ...
AssertionError

Definition at line 998 of file pydraw.py.

998def _get_bins (args, ndim, axis):
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.
1001
1002 Examples:
1003 >>> from PyAnalysisUtils import pydraw
1004 >>> pydraw._globals = globals()
1005 >>> import ROOT
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)
1009 50 10.0 100.0 0
1010 >>> b = _get_bins ([], 1, 0)
1011 >>> print (b.nbins, b.lo, b.hi, b.rebin)
1012 50 0 1 1
1013 >>> b = _get_bins (["!", "10"], 1, 0)
1014 >>> print (b.nbins, b.lo, b.hi, b.rebin)
1015 50 10.0 11.0 1
1016 >>> b = _get_bins (["!", "!", "10"], 1, 0)
1017 >>> print (b.nbins, b.lo, b.hi, b.rebin)
1018 50 0 10.0 0
1019 >>> scale = 10
1020 >>> b = _get_bins (["50", "0", "2*scale"], 1, 0)
1021 >>> print (b.nbins, b.lo, b.hi, b.rebin)
1022 50 0.0 20.0 0
1023 >>> b = _get_bins ([], 2, 0)
1024 >>> print (b.nbins, b.lo, b.hi, b.rebin)
1025 50 0.0 2.0 1
1026 >>> b = _get_bins ([], 2, 1)
1027 >>> print (b.nbins, b.lo, b.hi, b.rebin)
1028 50 1.0 3.0 1
1029 >>> b = _get_bins ([], 2, 2)
1030 Traceback (most recent call last):
1031 ...
1032 AssertionError
1033 """
1034
1035 g = copy.copy (_globals)
1036
1037 bins = _Bins()
1038
1039 bins.nbins = 0
1040 if len(args) >= 1 and args[0] != '!' and len(args[0]) > 0:
1041 bins.nbins = int (eval (args[0], g))
1042 if bins.nbins <= 0:
1043 bins.nbins = 50
1044
1045 bins.lo = 0
1046 if len(args) >= 2 and args[1] != '!' and len(args[1]) > 0:
1047 bins.lo = float (eval (args[1], g))
1048
1049 bins.hi = 0
1050 if len(args) >= 3 and args[2] != '!' and len(args[2]) > 0:
1051 bins.hi = float (eval (args[2], g))
1052
1053 bins.rebin = 0
1054 if bins.hi <= bins.lo:
1055 bins.rebin = 1
1056 if ndim == 1:
1057 bins.hi = bins.lo + 1
1058 elif axis == 0:
1059 bins.lo = ROOT.gPad.GetUxmin()
1060 bins.hi = ROOT.gPad.GetUxmax()
1061 elif axis == 1:
1062 bins.lo = ROOT.gPad.GetUymin()
1063 bins.hi = ROOT.gPad.GetUymax()
1064 else:
1065 assert 0
1066
1067 return bins
1068
1069

◆ _get_hist()

python.pydraw._get_hist ( ndim,
args,
hname,
htitle )
protected
Create a new histogram from options.

NDIM is the dimensionality of the histogram (1 or 2).
ARGS is a list of the arguments given to specify the histogram.
HNAME and HTITLE are the histogram name and title, respectively.

Definition at line 1070 of file pydraw.py.

1070def _get_hist (ndim, args, hname, htitle):
1071 """Create a new histogram from options.
1072
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.
1076 """
1077 get_canvas()
1078
1079 # Get the x-axis bin specifications.
1080 xbins = _get_bins (args, ndim, 0)
1081 rebin = xbins.rebin
1082
1083 # Get the y-axis bin specifications.
1084 if ndim >= 2:
1085 ybins = _get_bins (args[3:], ndim, 1)
1086 rebin = rebin or ybins.rebin
1087
1088 profile = 0
1089 # Look for drawing options.
1090 options = ''
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":
1095 profile = 1
1096 args[j] = ''
1097 options = ' '.join (args[i:])
1098 break
1099
1100 # Delete any old object of the same name.
1101 hold = ROOT.gROOT.FindObject (hname)
1102 if hold:
1103 ROOT.gROOT.Remove (hold)
1104
1105 # Create the histogram.
1106 if profile:
1107 hist = ROOT.TProfile (hname, htitle, xbins.nbins, xbins.lo, xbins.hi)
1108 if not ybins.rebin:
1109 hist.SetMinimum (ybins.lo)
1110 hist.SetMaximum (ybins.hi)
1111 elif ndim == 1:
1112 hist = ROOT.TH1F (hname, htitle, xbins.nbins, xbins.lo, xbins.hi)
1113 elif ndim == 2:
1114 hist = ScatterH2 (hname, htitle,
1115 xbins.nbins, xbins.lo, xbins.hi,
1116 ybins.nbins, ybins.lo, ybins.hi)
1117 if hasattr (hist, 'scatter'):
1118 hist.scatter (1)
1119
1120 # Automatic rebinning?
1121 if rebin:
1122 _setCanRebin (hist)
1123
1124 return (hist, options)
1125
1126

◆ _hasCanRebin()

python.pydraw._hasCanRebin ( h)
protected

Definition at line 348 of file pydraw.py.

348 def _hasCanRebin (h): #pragma: NO COVER
349 return h.TestBit (ROOT.TH1.kCanRebin) #pragma: NO COVER

◆ _sanitize_hname()

python.pydraw._sanitize_hname ( s)
protected
Name a string safe to use as a histogram name.

Root does bad things if you put / in a histogram name, so we remove them.
Examples:
>>> print (_sanitize_hname('foo'))
foo
>>> print (_sanitize_hname('foo/bar'))
foo DIV bar

Definition at line 374 of file pydraw.py.

374def _sanitize_hname(s):
375 """Name a string safe to use as a histogram name.
376
377 Root does bad things if you put / in a histogram name, so we remove them.
378 Examples:
379 >>> print (_sanitize_hname('foo'))
380 foo
381 >>> print (_sanitize_hname('foo/bar'))
382 foo DIV bar
383 """
384 return s.replace ('/', ' DIV ')
385
386

◆ _scan_print()

python.pydraw._scan_print ( f,
i,
* args )
protected
Helper to print out one row of a scan.

F is the file object to which to write, I is the row number,
and ARGS is a tuple of the column values.

Definition at line 1192 of file pydraw.py.

1192def _scan_print (f, i, *args):
1193 """Helper to print out one row of a scan.
1194
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."""
1197
1198 s = '%6d' % i
1199 for a in args:
1200 if isinstance(a, int):
1201 s += ' %8d' % a
1202 elif isinstance(a, str):
1203 s += ' %8s' % a
1204 else:
1205 s += ' %8g' % a
1206 print (s, file=f)
1207 return
1208
1209

◆ _setCanRebin()

python.pydraw._setCanRebin ( h)
protected

Definition at line 346 of file pydraw.py.

346 def _setCanRebin (h): #pragma: NO COVER
347 h.SetBit (ROOT.TH1.kCanRebin) #pragma: NO COVER

◆ _split_outer()

python.pydraw._split_outer ( haystack,
needle )
protected
Split HAYSTACK at the delimiters NEEDLE, as in _find_outer.

Examples:
>>> _split_outer ("a,(b,c),d", ",")
['a', '(b,c)', 'd']
>>> _split_outer ("a,,b", ",")
['a', '', 'b']
>>> _split_outer ("a", ",")
['a']
>>> #_split_outer ("", ",")
[]

Definition at line 484 of file pydraw.py.

484def _split_outer (haystack, needle):
485 """Split HAYSTACK at the delimiters NEEDLE, as in _find_outer.
486
487 Examples:
488 >>> _split_outer ("a,(b,c),d", ",")
489 ['a', '(b,c)', 'd']
490 >>> _split_outer ("a,,b", ",")
491 ['a', '', 'b']
492 >>> _split_outer ("a", ",")
493 ['a']
494 >>> #_split_outer ("", ",")
495 []
496"""
497 out = []
498 while True:
499 (head, tail) = _find_outer (haystack, needle)
500 head = head.strip()
501 out.append (head)
502 if tail is None:
503 break
504 else:
505 haystack = tail
506 return out
507
508

◆ _untokenize()

python.pydraw._untokenize ( tokens)
protected
Transform tokens back into Python source code.

Each element returned by the iterable must be a token sequence
with at least two elements, a token number and token value.

Unlike tokenize.untokenize(), this does not handle multiple lines.
It also tries not to add unneeded spaces.

Examples:
>>> from tokenize import generate_tokens, untokenize
>>> from io import StringIO
>>> def untokenize1(tt):
...   tt=list(tt)
...   if tt[-1][0]==0: tt=tt[:-1]
...   return untokenize(tt)
>>> untokenize1(generate_tokens(StringIO('1+1').readline))
'1+1'
>>> _untokenize(generate_tokens(StringIO('1+1').readline))
'1+1'
>>> untokenize1(generate_tokens(StringIO('foo$i>2*h').readline))
'foo$i>2*h'
>>> _untokenize(generate_tokens(StringIO('foo$i>2*h').readline))
'foo$i>2*h'

Definition at line 387 of file pydraw.py.

387def _untokenize (tokens):
388 """Transform tokens back into Python source code.
389
390 Each element returned by the iterable must be a token sequence
391 with at least two elements, a token number and token value.
392
393 Unlike tokenize.untokenize(), this does not handle multiple lines.
394 It also tries not to add unneeded spaces.
395
396 Examples:
397 >>> from tokenize import generate_tokens, untokenize
398 >>> from io import StringIO
399 >>> def untokenize1(tt):
400 ... tt=list(tt)
401 ... if tt[-1][0]==0: tt=tt[:-1]
402 ... return untokenize(tt)
403 >>> untokenize1(generate_tokens(StringIO('1+1').readline))
404 '1+1'
405 >>> _untokenize(generate_tokens(StringIO('1+1').readline))
406 '1+1'
407 >>> untokenize1(generate_tokens(StringIO('foo$i>2*h').readline))
408 'foo$i>2*h'
409 >>> _untokenize(generate_tokens(StringIO('foo$i>2*h').readline))
410 'foo$i>2*h'
411 """
412 lastname = False
413 toks = []
414 toks_append = toks.append
415 for tok in tokens:
416 toknum, tokval = tok[:2]
417 tokval = tokval.strip()
418 if toknum in (token.NAME, token.NUMBER):
419 if lastname:
420 tokval = ' ' + tokval
421 lastname = True
422 else:
423 lastname = False
424 toks_append (tokval)
425 return ''.join(toks)
426
427

◆ cmd()

python.pydraw.cmd ( s)
Process a command S.

Returns True if the command was handled, False otherwise.
See the header comments for the command syntax.

Definition at line 1294 of file pydraw.py.

1294def cmd (s):
1295 """Process a command S.
1296
1297 Returns True if the command was handled, False otherwise.
1298 See the header comments for the command syntax.
1299 """
1300
1301 ssplit = s.split (None, 1)
1302
1303 if len(ssplit) < 2:
1304 return False
1305
1306 cmd, args = ssplit
1307
1308 func = _cmddict.get (cmd)
1309 if func:
1310 return func (args)
1311
1312 return False
1313
1314
1315

◆ cmdhook()

python.pydraw.cmdhook ( )
Enable entering drawing commands directly at the python prompt.

Definition at line 1349 of file pydraw.py.

1349def cmdhook():
1350 """Enable entering drawing commands directly at the python prompt."""
1351
1352 # Store the old value of the exception hook (only if we haven't
1353 # done so already).
1354 global _orig_ehook
1355 if _orig_ehook is None:
1356 _orig_ehook = sys.excepthook
1357
1358 # Install our handler.
1359 sys.excepthook = _excepthook
1360 return
1361
1362

◆ draw()

python.pydraw.draw ( arg)
Process a draw command.

ARG is the command arguments (without the command word itself).
See the header comments for the command syntax.

Definition at line 1127 of file pydraw.py.

1127def draw (arg):
1128 """Process a draw command.
1129
1130 ARG is the command arguments (without the command word itself).
1131 See the header comments for the command syntax.
1132 """
1133
1134 global last_hist
1135
1136 # Initial parsing of the arguments.
1137 c = Draw_Cmd (arg)
1138 if c.errstr:
1139 print (c.errstr)
1140 return False
1141
1142 # Construct the expression to use to fill the histogram.
1143 if len (c.exprs) == 1:
1144 ndim = 1
1145 payload = "_hfill (%s)" % c.exprs[0]
1146 else:
1147 ndim = 2
1148 payload = "_hfill ((%s),(%s))" % (c.exprs[0], c.exprs[1])
1149
1150 # Construct the histogram title.
1151 htitle = "%s.%s" % (c.tuple, c.expr_orig)
1152 if c.sel_orig:
1153 htitle = htitle + '{%s}' % c.sel_orig
1154
1155 # Make the histogram.
1156 # If it's `!', then we just use the last one.
1157 if len(c.histspec) >= 1 and c.histspec[0] == "!" and last_hist is not None:
1158 hist = last_hist
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:])
1164 else:
1165 (hist, options) = _get_hist (ndim, c.histspec,
1166 _sanitize_hname(c.tuple+'.'+c.expr_orig), htitle)
1167
1168 # Remember it.
1169 last_hist = hist
1170
1171 # Generate the function.
1172 # It will be defined as _loopfunc in g.
1173 g = copy.copy (_globals)
1174 g['_hfill'] = hist.Fill
1175 ftext = c._make_func (payload, ', _hfill = _hfill')
1176 exec (ftext, g)
1177
1178 # Execute the loop over the data.
1179 c.tuple_o.loop (g['_loopfunc'], c.lo, c.hi)
1180
1181 # Adjust binning, if requested.
1182 if _hasCanRebin (hist):
1183 hist.LabelsDeflate ("X")
1184 if ndim > 1:
1185 hist.LabelsDeflate ("Y")
1186
1187 # Draw the histogram.
1188 draw_obj (hist, options)
1189 return True
1190
1191

◆ loop()

python.pydraw.loop ( arg)
Process a loop command.

ARG is the command arguments (without the command word itself).
See the header comments for the command syntax.

Definition at line 1258 of file pydraw.py.

1258def loop (arg):
1259 """Process a loop command.
1260
1261 ARG is the command arguments (without the command word itself).
1262 See the header comments for the command syntax.
1263 """
1264
1265 # Initial parsing of the arguments.
1266 c = Draw_Cmd (arg)
1267 if c.errstr:
1268 print (c.errstr)
1269 return False
1270
1271 payload = "(%s,)" % ','.join (c.exprs)
1272
1273 # Generate the function.
1274 # It will be defined as _loopfunc in g.
1275 g = copy.copy (_globals)
1276 ftext = c._make_func (payload)
1277 exec (ftext, g)
1278
1279 # Execute the loop over the data.
1280 c.tuple_o.loop (g['_loopfunc'], c.lo, c.hi)
1281
1282 return True
1283
1284
1285# Dictionary of command handlers.
1286# Should return True if cmd was handled.

◆ scan()

python.pydraw.scan ( arg)
Process a scan command.

ARG is the command arguments (without the command word itself).
See the header comments for the command syntax.

Definition at line 1210 of file pydraw.py.

1210def scan (arg):
1211 """Process a scan command.
1212
1213 ARG is the command arguments (without the command word itself).
1214 See the header comments for the command syntax.
1215 """
1216
1217 # Initial parsing of the arguments.
1218 c = Draw_Cmd (arg)
1219 if c.errstr:
1220 print (c.errstr)
1221 return False
1222
1223 payload = "_print (_i, %s)" % \
1224 ','.join (['(%s)'%e for e in c.exprs])
1225
1226 # Output file handling
1227 fname = None
1228 append = False
1229 if len(c.histspec) > 0:
1230 if c.histspec[0].startswith ('>>'):
1231 append = True
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]
1237 if fname:
1238 fout = open (fname, 'a' if append else 'w')
1239 else:
1240 fout = sys.stdout
1241
1242 # Generate the function.
1243 # It will be defined as _loopfunc in g.
1244 g = copy.copy (_globals)
1245 g['_print'] = lambda i, *args: _scan_print (fout, i, *args)
1246 ftext = c._make_func (payload, ', _print = _print')
1247 exec (ftext, g)
1248
1249 # Execute the loop over the data.
1250 c.tuple_o.loop (g['_loopfunc'], c.lo, c.hi)
1251
1252 if fname:
1253 fout.close()
1254
1255 return True
1256
1257
void scan(TDirectory *td=0, int depth=0)
Definition listroot.cxx:440

Variable Documentation

◆ _cmddict

dict python.pydraw._cmddict
protected
Initial value:
1= {'d': draw,
2 'draw' : draw,
3 'scan' : scan,
4 'loop' : loop,
5 }

Definition at line 1287 of file pydraw.py.

◆ _debug

bool python.pydraw._debug = False
protected

Definition at line 372 of file pydraw.py.

◆ _evtvar

str python.pydraw._evtvar = '_ev'
protected

Definition at line 369 of file pydraw.py.

◆ _globals

python.pydraw._globals = sys.modules['__main__'].__dict__
protected

Definition at line 362 of file pydraw.py.

◆ _idchars

str python.pydraw._idchars = string.ascii_letters + string.digits + '_'
protected

Definition at line 366 of file pydraw.py.

◆ _orig_ehook

python.pydraw._orig_ehook = None
protected

The stuff here sets things up so that after calling cmdhook(), the user can enter drawing commands directly at the python prompt.

We do this by catching syntax errors; when we get a syntax error, we try to parse the input as one of our commands.

Definition at line 1328 of file pydraw.py.

◆ last_hist

python.pydraw.last_hist = None

Definition at line 358 of file pydraw.py.

◆ ScatterH2

python.pydraw.ScatterH2 = ROOT.RootUtils.ScatterH2

Definition at line 338 of file pydraw.py.