New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Suggestion for rtree: convert a string into a formula a la TTreeFormula #634
Comments
it should be a relatively easy thing to implement, using e.g. the go/scanner, go/parser and/or go/ast packages (or even directly the yaegi interpreter or the gomacro one). |
Thanks for the update! I tried it and I like it. But ... :) there is something which is a bit annoying from the user side: the type assertion needed in the event loop. I am not sure if that can be shortcut, but it practically prevents the user of having just a string to declare in order to have the value. I just based this statement on this example, but maybe there are other syntax (?) |
well... Go is a statically typed language, w/o generics (think, one way around it is to wrap a closure around your r, err := rtree.NewReader(...)
form, err := r.Formula("float64(br1) + br2", nil)
eval := func() float64 { return form.Eval().(float64) }
var sum float64
err = r.Read(func(ctx rtree.RCtx) error {
sum += eval()
return nil
}) |
OK I didnt realise that the syntax |
converting a boolean into a number is relatively easy: i := map[bool]int{true: 1, false:0}[v]
f := map[bool]float64{true: 1, false:-666.6}[v] it's a mouthful. but you could also just create a r, err := rtree.NewReader(...)
form, err := r.Formula(
"math.Abs(eta) > 2.5 && len(lep_pt)>0 && lep_pt[0] > 2.5",
[]string{"math"},
)
filter := func() bool { return form.Eval().(bool) } |
Indeed, one has to decide in advance whether the string will correspond to a boolean or not (which is not the case in ROOT right now - but maybe this kind of things are good, leading to a better organisation). I have realized something else: if the variable called in the formula is not loaded explicitly in the tree.Reader, then it doesn't seems to work (unless I did something wrong). There is an example: I think this point - if I did things correctly - is an important one for the formula. Do you think it is something doable, even if in it's done in a next iteration? |
see #642 |
Perfect, thanks a lot! |
Here is a bit benchmark performance (home-made) about the
Few comments:
So it is relatively expensive - but ok, we cannot get everything. For comparison:
But to be fair, when I decrease the number of cuts, I decrease the number of |
so a x4 factor going from compiled to "compiled+interpreted" code. not too shaby for a first stab. let me loosen a bit the requirement on the non-zero-len slice of some additional performance could be recouped by analyzing the expression to determine its type ( func (form Form) Func() interface{} { return form.evalFunc }
my, err := r.Formula("math.Abs(eta) > 2.5", nil)
cut := mu.Func().(func() bool)
err = r.Read(func (rtree.RCtx) error {
if cut() { n++ }
return nil
}) |
After the improvement obtained in #690, the factor ~ 4-5 is reduced to a factor 3, so not bad at all! For 15 variables, 1 cut and 4 samples: before improvement (8b07e3f)
after improvement (75db704)
|
cool: almost a x2 improvement. |
When building a small tool on
rtree
module, I realized that it would be very convenient to have an equivalent ofTTreeForumula()
in ROOT in order to do things like:Would that be feasible? Would there be a performance cost compared to explicitly declare a reader with the variables
var1
andvar2
?The text was updated successfully, but these errors were encountered: