- A recent version of ROOT compiled using the C++17 standard
- C++17 compiler
make
Ranger can be imported into C++ and python scripts. User-friendly python bindings are defined in root_ranger.py
.
The working principle of Ranger is to define one or multiple "jobs" for each tree that should be applied in sequence and to execute them on one or multiple files.
Ranger is especially useful when working with array variables in root files that were created by the DecayTreeFitter
Features
- Copying trees with selections and branch selections
- Flattening of leaves with array dimension
- Best primary vertex selection
- Adding branches using arbitrarily complex formulas
Ranger does not yet support boolean leaves
Copy a tree with a selection and rename the tree in the new file
from root_ranger import Ranger
ranger = Ranger("DTT.root")
ranger.copy_tree("DecayTree", cut="BKGCAT==0", dest="DecayTreeSignal")
ranger.run("DTT_signal.root")
Copy the tree containing the integrated luminosity, perform a best primary vertex selection (assuming we used DecayTreeFitter) on another tree and only keep a subset of branches and apply a selection and repeat this procedure with 10 different files that have a similar structure.
from root_ranger import Ranger
ranger = Ranger("DTT_0.root")
ranger.bpv_selection("DecayTree", branches=["B0_Fit*", "piminus*"],
bpv_branches="B0_Fit*",
cut=["some_chi2<30", "piminus_PT>1000"])
ranger.copy_tree("GetIntegratedLuminosity/LumiTuple", dest="LumiTuple")
ranger.run("DTT_truth_0.root")
for i in range(1, 10):
ranger.set_input_file("DTT_{0}.root".format(i))
ranger.run("DTT_out{0}.root".format(i))
Here, we are keeping all branches that start with "B0_Fit" or "piminus". Wildcards can be used anywhere in the selection strings.
Do a bpv selection and flatten the array dimension of the same tree, but store the results in two different trees in the output file.
from root_ranger import Ranger
ranger = Ranger("DTT.root")
ranger.bpv_selection("DecayTree", bpv_branches="B0_Fit*", dest="DecayTree_bpv")
ranger.flatten_tree("DecayTree", flat_branches="B0_Fit*", dest="DecayTree_flat")
ranger.run("DTT_out.root")
The same is possible using only the method 'add_selection'.
from root_ranger import Ranger
ranger = Ranger("DTT.root")
ranger.add_selection("DecayTree", dest="DecayTree", cut="B0_M>5000", flat_branches="", bpv_branches="")
ranger.add_selection("DecayTree", dest="DecayTree_flat", cut="B0_M>5000", flat_branches="B0_Fit*", bpv_branches="")
ranger.add_selection("DecayTree", dest="DecayTree_bpv", cut="B0_M>5000", flat_branches="", bpv_branches="B0_Fit*")
ranger.run("DTT_out.root")
It is not possible to flatten a tree and perform a best PV selection at the same time.
Apply a certain operation to a tree in a file, but then do something different with another file.
from root_ranger import Ranger
ranger = Ranger("DTT.root")
ranger.bpv_selection("DecayTree", bpv_branches="B0_Fit*")
ranger.run("DTT_out.root")
ranger.reset() # Reset all previous job descriptions
ranger.change_file("DTT_2.root")
ranger.flatten_tree("DecayTree", flat_branches="B0_Fit*")
ranger.run("DTT_2_out.root")
Alternatively, multiple Ranger instances can be used
Add the transverse momentum of kaons to the tuple and simultaneously apply a cut to it. Only write a certain list of branches to the new file.
from root_ranger import Ranger
keep_branches = [
"*PT", # All branches ending with PT
"*M", # All branches ending with M
"KS0_P[XY]", # KS0_PX and KS0_PY
"Kaon_PT"
]
ranger = Ranger("DTT.root")
ranger.add_formula("Kaon_PT", "TMath::Sqrt(#KS0_PX**2+#KS0_PY**2)")
ranger.copy_tree("DecayTree", branches=keep_branches, cut="Kaon_PT>500")
ranger.run("DTT_out.root")
The add_formula
command adds another formula to a list of formulas
that are added when the next tree is written. Branch names in formulas must start with '#'