/ formulate Public

Easy conversions between different styles of expressions

You must be signed in to change notification settings

scikit-hep/formulate

Folders and files

NameName
Last commit message
Last commit date

Formulate

Easy conversions between different styles of expressions. Formulate currently supports converting between ROOT and numexpr style expressions.

Installation

Install formulate like any other Python package:

`pip install --user formulate`

or similar (use ``sudo`, ``virtualenv`, or ``conda`` if you wish).

Usage

Command line usage

```\$ python -m formulate --from-root '(A && B) || TMath::Sqrt(A)' --to-numexpr
(A & B) | sqrt(A)

\$ python -m formulate --from-numexpr '(A & B) | sqrt(A)' --to-root
(A && B) || TMath::Sqrt(A)

\$ python -m formulate --from-root '(A && B) || TMath::Sqrt(1.23) * e**1.2 + 5*pi' --variables
A
B

\$ python -m formulate --from-root '(A && B) || TMath::Sqrt(1.23) * e**1.2 + 5*pi' --named-constants
E
PI

\$ python -m formulate --from-root '(A && B) || TMath::Sqrt(1.23) * e**1.2 + 5*pi' --unnamed-constants
1.2
1.23
5```

API

The most basic usage involves calling `from_\$BACKEND` and then `to_\$BACKEND`, for example when starting with a ROOT style expression:

```>>> import formulate
>>> momentum = formulate.from_root('TMath::Sqrt(X_PX**2 + X_PY**2 + X_PZ**2)')
>>> momentum
Expression<SQRT>(Expression<ADD>(Expression<POW>(Variable(X_PX), UnnamedConstant(2)), Expression<POW>(Variable(X_PY), UnnamedConstant(2)), Expression<POW>(Variable(X_PZ), UnnamedConstant(2))))
>>> momentum.to_numexpr()
'sqrt(((X_PX ** 2) + (X_PY ** 2) + (X_PZ ** 2)))'
>>> momentum.to_root()
'TMath::Sqrt(((X_PX ** 2) + (X_PY ** 2) + (X_PZ ** 2)))'```

Similarly, when starting with a `numexpr` style expression:

```>>> my_selection = formulate.from_numexpr('X_PT > 5 & (Mu_NHits > 3 | Mu_PT > 10)')
>>> my_selection.to_root()
'(X_PT > 5) && ((Mu_NHits > 3) || (Mu_PT > 10))'
>>> my_selection.to_numexpr()
'(X_PT > 5) & ((Mu_NHits > 3) | (Mu_PT > 10))'```

If the the type of expression isn't known in advance `formulate` can also auto detect it:

```>>> my_sum = formulate.from_auto('True + False')
>>> my_sum.to_root()
'true + false'
>>> my_sum.to_numexpr()
'True + False'```

The `Expression` Object

When calling `from_*` the returned object is derived from `formulate.ExpressionComponent`. From this object you can inspect the expression to find it's dependencies:

```>>> my_check = formulate.from_auto('(X_THETA*TMath::DegToRad() > pi/4) && D_PE > 9.2')
>>> my_check.variables
{'D_PE', 'X_THETA'}
>>> my_check.named_constants
>>> my_check.unnamed_constants
{'4', '9.2'}```

Additionally `ExpressionComponent` s can be combined using both operators and `numpy` functions:

```>>> new_selection = (momentum > 100) and (my_check or (numpy.sqrt(my_sum) < 1))
>>> new_selection.to_numexpr()
'((X_THETA * 0.017453292519943295) > (3.141592653589793 / 4)) & (D_PE > 9.2)'```

As the `==` operator returns a new expression, it can't be used to check for equality. Instead the `.equivalent` method should be used:

TODO: Implement this using `expression.equivalent` !

Easy conversions between different styles of expressions

Packages 0

No packages published

•
•
•
•