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

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

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 1306 of file pydraw.py.

1306def _excepthook (exctype, value, traceb):
1307 """Exception hook used by pydraw to process drawing commands."""
1308
1309 # If it's a syntax error, try interpreting as a drawing command.
1310 if isinstance (value, SyntaxError):
1311 val = value.text
1312 if val[-1] == '\n':
1313 val = val[:-1] #pragma: NO COVER
1314 if cmd (val):
1315 # Success --- update root stuff and return.
1316 # (This will swallow the original syntax error.)
1317 ROOT.gInterpreter.EndOfLineAction()
1318 return
1319
1320 # No luck --- pass it on to the original exception handler.
1321 _orig_ehook (exctype, value, traceb)
1322
1323

◆ _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 425 of file pydraw.py.

425def _find_outer (haystack, needle, ignore_delim = False):
426 """Look for NEEDLE in HAYSTACK (token-based. Return pair (HEAD, TAIL).
427
428 HAYSTACK and NEEDLE are both strings. Look for a token in HAYSTACK with
429 a value matching NEEDLE that is outside of any paired delimiters.
430 Also ignores things in strings.
431 If IGNORE_DELIM is True, then we do find things inside delimiters
432 (strings are still ignored).
433
434 Returns a pair (HEAD, TAIL) of the pieces of the string before and
435 after NEEDLE. If there is no match, returns (HAYSTACK, None).
436 Note that whitespace and formatting in HEAD and TAIL may differ
437 from the original string.
438
439 Examples:
440 >>> _find_outer ("head.tail1.tail2", ".")
441 ('head', 'tail1.tail2')
442 >>> _find_outer ("(head.tail1).tail2", ".")
443 ('(head.tail1)', 'tail2')
444 >>> _find_outer ("[a for a in foo if good(a)] if bar", "if")
445 ('[a for a in foo if good(a)]', 'bar')
446 >>> _find_outer ("(a [b {c . d } ] ) . e", ".")
447 ('(a [b {c . d } ] )', 'e')
448 >>> _find_outer ("a.b", ";")
449 ('a.b', None)
450 >>> _find_outer ("a '$' b", '$')
451 ("a '$' b", None)
452 >>> _find_outer ("a $ b", '$')
453 ('a', 'b')
454 >>> _find_outer ("(head.tail1).tail2", ".", True)
455 ('(head', 'tail1).tail2')
456 >>> _find_outer ('a; 1 -1 1', ';')
457 ('a', '1 -1 1')
458"""
459 tlist = tokenize.generate_tokens (StringIO(haystack).readline)
460 pend = []
461 head = []
462 for (i, (tnum, val, a, b, c)) in enumerate (tlist):
463 if tnum != token.STRING and not pend and val == needle:
464 col1 = a[1]
465 col2 = b[1]
466 return (haystack[:col1].strip(),
467 haystack[col2:].strip())
468 if not ignore_delim:
469 if val == '(':
470 pend.append (')')
471 elif val == '[':
472 pend.append (']')
473 elif val == '{':
474 pend.append ('}')
475 elif pend and val == pend[-1]:
476 pend.pop()
477 head.append ((tnum, val))
478 return (haystack, None)
479
480

◆ _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 995 of file pydraw.py.

995def _get_bins (args, ndim, axis):
996 """Parse bin specifications from split list of arguments ARGS.
997 NDIM is 1 or 2, and AXIS is 0 or 1, for the x or y axis.
998
999 Examples:
1000 >>> from PyAnalysisUtils import pydraw
1001 >>> pydraw._globals = globals()
1002 >>> import ROOT
1003 >>> ROOT.gPad.Range(0, 1,2,3)
1004 >>> b = _get_bins (["50", "10", "100"], 1, 0)
1005 >>> print (b.nbins, b.lo, b.hi, b.rebin)
1006 50 10.0 100.0 0
1007 >>> b = _get_bins ([], 1, 0)
1008 >>> print (b.nbins, b.lo, b.hi, b.rebin)
1009 50 0 1 1
1010 >>> b = _get_bins (["!", "10"], 1, 0)
1011 >>> print (b.nbins, b.lo, b.hi, b.rebin)
1012 50 10.0 11.0 1
1013 >>> b = _get_bins (["!", "!", "10"], 1, 0)
1014 >>> print (b.nbins, b.lo, b.hi, b.rebin)
1015 50 0 10.0 0
1016 >>> scale = 10
1017 >>> b = _get_bins (["50", "0", "2*scale"], 1, 0)
1018 >>> print (b.nbins, b.lo, b.hi, b.rebin)
1019 50 0.0 20.0 0
1020 >>> b = _get_bins ([], 2, 0)
1021 >>> print (b.nbins, b.lo, b.hi, b.rebin)
1022 50 0.0 2.0 1
1023 >>> b = _get_bins ([], 2, 1)
1024 >>> print (b.nbins, b.lo, b.hi, b.rebin)
1025 50 1.0 3.0 1
1026 >>> b = _get_bins ([], 2, 2)
1027 Traceback (most recent call last):
1028 ...
1029 AssertionError
1030 """
1031
1032 g = copy.copy (_globals)
1033
1034 bins = _Bins()
1035
1036 bins.nbins = 0
1037 if len(args) >= 1 and args[0] != '!' and len(args[0]) > 0:
1038 bins.nbins = int (eval (args[0], g))
1039 if bins.nbins <= 0:
1040 bins.nbins = 50
1041
1042 bins.lo = 0
1043 if len(args) >= 2 and args[1] != '!' and len(args[1]) > 0:
1044 bins.lo = float (eval (args[1], g))
1045
1046 bins.hi = 0
1047 if len(args) >= 3 and args[2] != '!' and len(args[2]) > 0:
1048 bins.hi = float (eval (args[2], g))
1049
1050 bins.rebin = 0
1051 if bins.hi <= bins.lo:
1052 bins.rebin = 1
1053 if ndim == 1:
1054 bins.hi = bins.lo + 1
1055 elif axis == 0:
1056 bins.lo = ROOT.gPad.GetUxmin()
1057 bins.hi = ROOT.gPad.GetUxmax()
1058 elif axis == 1:
1059 bins.lo = ROOT.gPad.GetUymin()
1060 bins.hi = ROOT.gPad.GetUymax()
1061 else:
1062 assert 0
1063
1064 return bins
1065
1066

◆ _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 1067 of file pydraw.py.

1067def _get_hist (ndim, args, hname, htitle):
1068 """Create a new histogram from options.
1069
1070 NDIM is the dimensionality of the histogram (1 or 2).
1071 ARGS is a list of the arguments given to specify the histogram.
1072 HNAME and HTITLE are the histogram name and title, respectively.
1073 """
1074 get_canvas()
1075
1076 # Get the x-axis bin specifications.
1077 xbins = _get_bins (args, ndim, 0)
1078 rebin = xbins.rebin
1079
1080 # Get the y-axis bin specifications.
1081 if ndim >= 2:
1082 ybins = _get_bins (args[3:], ndim, 1)
1083 rebin = rebin or ybins.rebin
1084
1085 profile = 0
1086 # Look for drawing options.
1087 options = ''
1088 for i in range (0, len(args)):
1089 if args[i][0] in string.ascii_letters:
1090 for j in range (i, len(args)):
1091 if ndim == 2 and args[j].lower() == "prof":
1092 profile = 1
1093 args[j] = ''
1094 options = ' '.join (args[i:])
1095 break
1096
1097 # Delete any old object of the same name.
1098 hold = ROOT.gROOT.FindObject (hname)
1099 if hold:
1100 ROOT.gROOT.Remove (hold)
1101
1102 # Create the histogram.
1103 if profile:
1104 hist = ROOT.TProfile (hname, htitle, xbins.nbins, xbins.lo, xbins.hi)
1105 if not ybins.rebin:
1106 hist.SetMinimum (ybins.lo)
1107 hist.SetMaximum (ybins.hi)
1108 elif ndim == 1:
1109 hist = ROOT.TH1F (hname, htitle, xbins.nbins, xbins.lo, xbins.hi)
1110 elif ndim == 2:
1111 hist = ScatterH2 (hname, htitle,
1112 xbins.nbins, xbins.lo, xbins.hi,
1113 ybins.nbins, ybins.lo, ybins.hi)
1114 if hasattr (hist, 'scatter'):
1115 hist.scatter (1)
1116
1117 # Automatic rebinning?
1118 if rebin:
1119 _setCanRebin (hist)
1120
1121 return (hist, options)
1122
1123

◆ _hasCanRebin()

python.pydraw._hasCanRebin ( h)
protected

Definition at line 345 of file pydraw.py.

345 def _hasCanRebin (h): #pragma: NO COVER
346 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 371 of file pydraw.py.

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

◆ _scan_print()

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

I is the row number and ARGS is a tuple of the column values.

Definition at line 1189 of file pydraw.py.

1189def _scan_print (i, *args):
1190 """Helper to print out one row of a scan.
1191
1192 I is the row number and ARGS is a tuple of the column values."""
1193
1194 s = '%6d' % i
1195 for a in args:
1196 if isinstance(a, int):
1197 s += ' %8d' % a
1198 else:
1199 s += ' %8g' % a
1200 print (s)
1201 return
1202
1203

◆ _setCanRebin()

python.pydraw._setCanRebin ( h)
protected

Definition at line 343 of file pydraw.py.

343 def _setCanRebin (h): #pragma: NO COVER
344 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 481 of file pydraw.py.

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

◆ _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 384 of file pydraw.py.

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

◆ 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 1269 of file pydraw.py.

1269def cmd (s):
1270 """Process a command S.
1271
1272 Returns True if the command was handled, False otherwise.
1273 See the header comments for the command syntax.
1274 """
1275
1276 ssplit = s.split (None, 1)
1277
1278 if len(ssplit) < 2:
1279 return False
1280
1281 cmd, args = ssplit
1282
1283 func = _cmddict.get (cmd)
1284 if func:
1285 return func (args)
1286
1287 return False
1288
1289
1290

◆ cmdhook()

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

Definition at line 1324 of file pydraw.py.

1324def cmdhook():
1325 """Enable entering drawing commands directly at the python prompt."""
1326
1327 # Store the old value of the exception hook (only if we haven't
1328 # done so already).
1329 global _orig_ehook
1330 if _orig_ehook is None:
1331 _orig_ehook = sys.excepthook
1332
1333 # Install our handler.
1334 sys.excepthook = _excepthook
1335 return
1336
1337

◆ 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 1124 of file pydraw.py.

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

◆ 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 1233 of file pydraw.py.

1233def loop (arg):
1234 """Process a loop command.
1235
1236 ARG is the command arguments (without the command word itself).
1237 See the header comments for the command syntax.
1238 """
1239
1240 # Initial parsing of the arguments.
1241 c = Draw_Cmd (arg)
1242 if c.errstr:
1243 print (c.errstr)
1244 return False
1245
1246 payload = "(%s,)" % ','.join (c.exprs)
1247
1248 # Generate the function.
1249 # It will be defined as _loopfunc in g.
1250 g = copy.copy (_globals)
1251 ftext = c._make_func (payload)
1252 exec (ftext, g)
1253
1254 # Execute the loop over the data.
1255 c.tuple_o.loop (g['_loopfunc'], c.lo, c.hi)
1256
1257 return True
1258
1259
1260# Dictionary of command handlers.
1261# 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 1204 of file pydraw.py.

1204def scan (arg):
1205 """Process a scan command.
1206
1207 ARG is the command arguments (without the command word itself).
1208 See the header comments for the command syntax.
1209 """
1210
1211 # Initial parsing of the arguments.
1212 c = Draw_Cmd (arg)
1213 if c.errstr:
1214 print (c.errstr)
1215 return False
1216
1217 payload = "_print (_i, %s)" % \
1218 ','.join (['(%s)'%e for e in c.exprs])
1219
1220 # Generate the function.
1221 # It will be defined as _loopfunc in g.
1222 g = copy.copy (_globals)
1223 g['_print'] = _scan_print
1224 ftext = c._make_func (payload, ', _print = _print')
1225 exec (ftext, g)
1226
1227 # Execute the loop over the data.
1228 c.tuple_o.loop (g['_loopfunc'], c.lo, c.hi)
1229
1230 return True
1231
1232
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 1262 of file pydraw.py.

◆ _debug

bool python.pydraw._debug = False
protected

Definition at line 369 of file pydraw.py.

◆ _evtvar

str python.pydraw._evtvar = '_ev'
protected

Definition at line 366 of file pydraw.py.

◆ _globals

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

Definition at line 359 of file pydraw.py.

◆ _idchars

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

Definition at line 363 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 1303 of file pydraw.py.

◆ last_hist

python.pydraw.last_hist = None

Definition at line 355 of file pydraw.py.

◆ ScatterH2

python.pydraw.ScatterH2 = ROOT.RootUtils.ScatterH2

Definition at line 335 of file pydraw.py.