RDataFrame: upload external variables to the Define

Dear experts,

I am trying to upload some variables from the python code to the Define. I found this thread: here and tried to reproduce it without any success.

import ROOT

def weight(rf):  
    x = 0
    y = 1
    ROOT.gInterpreter.Declare("""
       const double x = double(TPython::Exec("x"));
       const double y = double(TPython::Exec("y"));
    """) 
    
    new_rf = rf.Define("weight", "x+y")
    return new_rf

rf = ROOT.RDataFrame(...)

weight(rf)

I get the error

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<string> in <module>

NameError: name 'x' is not defined

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<string> in <module>

NameError: name 'y' is not defined

Thank you in advance for help

Lera


Please read tips for efficient and successful posting and posting code

_ROOT Version: 6.20/02
Platform: Not Provided
Compiler: Not Provided


Hi,
I think that’s because TPython cannot access those function-local variables.
A possible workaround is to make them global by moving them outside of the weight function (or you could also make them attributes of a global object).

Cheers,
Enrico

EDIT: @swunsch or @etejedor might be able to suggest a more pythonic approach

@eguiraud It works as a global variable. Thanks!

1 Like

Hi!

If you want to “upload” constants, you can use numba and just in time compile your python code!

import ROOT

x = 1.0
y = -2.0

@ROOT.Numba.Declare([], 'float')
def weights():
    return x + y

df = ROOT.RDataFrame(3).Define('foo', 'Numba::weights()')
print(df.AsNumpy())

The example above (try it! but you need ROOT 6.22) will give you this:

{'foo': ndarray([-1., -1., -1.], dtype=float32)}

Note that you have quite some restrictions due to numba (you cannot jit everything from python!). Also the values are fixed to the ones at the time of declaration, which may be unexpected from a pythonic point of view (e.g., try to put x = 999 after the def weights(): ..., won’t change anything).

Best
Stefan

1 Like