Skip to content

Commit

Permalink
Merge pull request #41 from FAST-HEP/BK_alias_out_dot_operator
Browse files Browse the repository at this point in the history
Pre-process away the dot operator in expressions
  • Loading branch information
benkrikler authored May 22, 2019
2 parents 272b2bd + c16320c commit e2f5a88
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 7 deletions.
29 changes: 24 additions & 5 deletions fast_carpenter/expressions.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import re
import numexpr
import tokenize
import awkward
Expand Down Expand Up @@ -34,21 +35,23 @@ class TreeToDictAdaptor():
"""
Make an uproot tree look like a dict for numexpr
"""
def __init__(self, tree):
def __init__(self, tree, alias_dict):
self.tree = tree
self.starts = None
self.stops = None
self.aliases = alias_dict

def __getitem__(self, item):
array = self.tree.array(item)
full_item = self.aliases.get(item, item)
array = self.tree.array(full_item)
starts = getattr(array, "starts", None)
if starts is not None:
self.set_starts_stop(starts, array.stops)
return array.content
return array

def __contains__(self, item):
return item in self.tree
return item in self.tree or item in self.aliases

def __iter__(self):
for i in self.tree:
Expand All @@ -63,9 +66,25 @@ def set_starts_stop(self, starts, stops):
self.stops = stops


attribute_re = re.compile(r"([a-zA-Z]\w*)\s*\.\s*(\w+)")


def preprocess_expression(expression):
alias_dict = {}
replace_dict = {}
for match in attribute_re.finditer(expression):
original = match.group(0)
alias = match.expand(r"\1__DOT__\2")
alias_dict[alias] = original
replace_dict[original] = alias
clean_expr = attribute_re.sub(lambda x: replace_dict[x.group(0)], expression)
return clean_expr, alias_dict


def evaluate(tree, expression):
adaptor = TreeToDictAdaptor(tree)
result = numexpr.evaluate(expression, local_dict=adaptor)
cleaned_expression, alias_dict = preprocess_expression(expression)
adaptor = TreeToDictAdaptor(tree, alias_dict)
result = numexpr.evaluate(cleaned_expression, local_dict=adaptor)
if adaptor.starts is not None:
result = awkward.JaggedArray(adaptor.starts, adaptor.stops, result)
return result
2 changes: 1 addition & 1 deletion fast_carpenter/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ def split_version(version):
return tuple(result)


__version__ = '0.11.0'
__version__ = '0.11.1'
version_info = split_version(__version__) # noqa
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.11.0-rc5
current_version = 0.11.1
commit = True
tag = False

Expand Down
6 changes: 6 additions & 0 deletions tests/test_expressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,9 @@ def test_evaluate(wrapped_tree):
def test_evaluate_bool(wrapped_tree):
all_true = expressions.evaluate(wrapped_tree, "Muon_Px == Muon_Px")
assert all(all_true.all())


def test_evaluate_dot(wrapped_tree):
wrapped_tree.new_variable("Muon.Px", wrapped_tree.array("Muon_Px"))
all_true = expressions.evaluate(wrapped_tree, "Muon.Px == Muon_Px")
assert all(all_true.all())

0 comments on commit e2f5a88

Please sign in to comment.