From e704655dae26d26bd1d369e94c7f514a2ebd2ad5 Mon Sep 17 00:00:00 2001 From: Arvind-t33 Date: Sat, 6 Jun 2026 16:15:38 -0400 Subject: [PATCH 1/2] tutorial: add Python example showing thread-safe Define using rdfslot_ (closes #20839) --- tutorials/dataframe/DefineSlotPython.py | 47 +++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 tutorials/dataframe/DefineSlotPython.py diff --git a/tutorials/dataframe/DefineSlotPython.py b/tutorials/dataframe/DefineSlotPython.py new file mode 100644 index 0000000000000..7204c01138632 --- /dev/null +++ b/tutorials/dataframe/DefineSlotPython.py @@ -0,0 +1,47 @@ +""" +DefineSlotPython.py + +Demonstrate a thread-safe Define pattern for Python users using `rdfslot_`. + +This shows how to declare a small C++ functor and use it from PyROOT via +`RDataFrame.Define` so each thread gets a thread-local RNG seeded by the slot. + +Run with: + + python3 DefineSlotPython.py + +Requires a working PyROOT installation (ROOT with Python bindings). +""" +from __future__ import print_function + +import ROOT + +def main(): + # Declare a small C++ function that uses a thread_local TRandom3 per slot. + ROOT.gInterpreter.Declare(""" + double myfunctor(unsigned int rdfslot) { + static thread_local TRandom3 r3(rdfslot); + return r3.Gaus(); + } + """) + + # Create an RDataFrame and use Define passing the C++ functor by name. + # Note: the expression uses the helper column `rdfslot_` which is different + # for each thread when implicit multi-threading is enabled. + rdf = ROOT.RDataFrame(100000) + + # Enable implicit multi-threading for example (optional) + try: + ROOT.EnableImplicitMT() + except Exception: + # If ROOT was built without implicit MT, continue single-threaded + pass + + rdf_x = rdf.Define("x", "myfunctor(rdfslot_)") + h = rdf_x.Histo1D(("h", "Gaussian per-slot test", 100, -5, 5), "x") + # Trigger event loop + h.Draw() + print("Histogram entries:", int(h.GetEntries())) + +if __name__ == '__main__': + main() From e95bad7444a7ca6ddadfd7bc1650a84e76865ae5 Mon Sep 17 00:00:00 2001 From: Arvind-t33 Date: Sun, 7 Jun 2026 13:32:28 -0400 Subject: [PATCH 2/2] tutorial: fix DefineSlot example by enabling implicit MT before RDataFrame creation --- tutorials/dataframe/DefineSlotPython.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tutorials/dataframe/DefineSlotPython.py b/tutorials/dataframe/DefineSlotPython.py index 7204c01138632..b49dbbcca1e42 100644 --- a/tutorials/dataframe/DefineSlotPython.py +++ b/tutorials/dataframe/DefineSlotPython.py @@ -28,20 +28,19 @@ def main(): # Create an RDataFrame and use Define passing the C++ functor by name. # Note: the expression uses the helper column `rdfslot_` which is different # for each thread when implicit multi-threading is enabled. - rdf = ROOT.RDataFrame(100000) - - # Enable implicit multi-threading for example (optional) + # Enable implicit multi-threading for example (optional). + # This must happen before constructing the RDataFrame. try: ROOT.EnableImplicitMT() except Exception: # If ROOT was built without implicit MT, continue single-threaded pass + rdf = ROOT.RDataFrame(100000) rdf_x = rdf.Define("x", "myfunctor(rdfslot_)") h = rdf_x.Histo1D(("h", "Gaussian per-slot test", 100, -5, 5), "x") - # Trigger event loop - h.Draw() - print("Histogram entries:", int(h.GetEntries())) + # Trigger event loop by accessing the filled histogram. + print("Histogram entries:", int(h.GetValue().GetEntries())) if __name__ == '__main__': main()