Repository: rootpy/rootpy

Issue:
Ternary operator in tree draw expression
In the present master:

  https://github.com/rootpy/rootpy/blob/cfe3b304ca7a8b2f6622ab6698ba5798d32bf582/rootpy/tree/tree.py

The order of an expression is reversed by

```
fields = re.split('(?<!:):(?!:)', exprdict['branches'])
num_dimensions = len(fields)
expression = ':'.join(fields[:3][::-1] + fields[3:])
```

This breaks an expression with a ternary operator, like "x:a?y:z"

I can't figure out a regex to count this.  Hints?



Discussion:
Yikes. I honestly didn't think of this...

Let's see if we can cook something up.... Or maybe an option should be included to revert to the original TTree behaviour.

Yeah, or probably accepting a list as an alternative, like ["x", "a?y:z"] ?

I like your idea more. Probably the cleanest way forward.


Resolving patch:
diff --git a/rootpy/tree/tree.py b/rootpy/tree/tree.py
--- a/rootpy/tree/tree.py
+++ b/rootpy/tree/tree.py
@@ -720,19 +720,31 @@ def Draw(self,
         which is then returned.
 
         """
-        # Check that we have a valid draw expression and pick out components
-        exprmatch = re.match(BaseTree.DRAW_PATTERN, expression)
-        if not exprmatch:
-            raise ValueError(
-                "not a valid draw expression: `{0}`".format(expression))
-
-        # Reverse variable order to match order in hist constructor
-        exprdict = exprmatch.groupdict()
-        fields = re.split('(?<!:):(?!:)', exprdict['branches'])
-        num_dimensions = len(fields)
-        expression = ':'.join(fields[:3][::-1] + fields[3:])
-        if exprdict['redirect'] is not None:
-            expression += exprdict['redirect']
+        if isinstance(expression, string_types):
+            # Check that we have a valid draw expression
+            exprmatch = re.match(BaseTree.DRAW_PATTERN, expression)
+            if not exprmatch:
+                raise ValueError(
+                    "not a valid draw expression: `{0}`".format(expression))
+            exprdict = exprmatch.groupdict()
+
+            # Reverse variable order to match order in hist constructor
+            fields = re.split('(?<!:):(?!:)', exprdict['branches'])
+            num_dimensions = len(fields)
+            expression = ':'.join(fields[:3][::-1] + fields[3:])
+            if exprdict['redirect'] is not None:
+                expression += exprdict['redirect']
+
+        else:  # expression is list, tuple, ...
+            fields = expression
+            num_dimensions = len(fields)
+            expression = ':'.join(fields[:3][::-1] + fields[3:])
+            exprdict = {
+                'branches': None,
+                'redirect': None,
+                'name': None,
+                'binning': None,
+                }
 
         if not isinstance(selection, Cut):
             # Let Cut handle any extra processing (i.e. ternary operators)


Test patch:
diff --git a/rootpy/tree/tests/test_tree.py b/rootpy/tree/tests/test_tree.py
--- a/rootpy/tree/tests/test_tree.py
+++ b/rootpy/tree/tests/test_tree.py
@@ -183,6 +183,14 @@ def test_draw():
         assert_equal(hist.Integral() > 0, True)
         assert_equal(hist.name, 'new_hist_2')
 
+        # test list/tuple expression
+        hist1 = tree.draw('a_x:a_y:a_z', create_hist=True)
+        hist2 = tree.draw(['a_x', 'a_y', 'a_z'], create_hist=True)
+        hist3 = tree.draw(('a_x', 'a_y', 'a_z'), create_hist=True)
+        assert_equal(hist1.Integral() > 0, True)
+        assert_equal(hist2.Integral(), hist1.Integral())
+        assert_equal(hist3.Integral(), hist1.Integral())
+
 
 @with_setup(create_chain, cleanup)
 def test_chain_draw():