Dear ROOT experts,
My analysis uses RDF and it involves creating a vector of structs and perform selections on the structs. All this while I have been using ROOT version 6.24.06
from one of the LCG releases (LCG_101
) [1] on lxplus7
and I am in the process of migrating to version 6.26.08
using LCG_102a
release [2]. The problem I am facing right now is that my RDF analysis script crashes when using version 6.26.08
and I have no idea on how to debug this crash . Through trial and error, I could only pin it down to the part where it involves the vector of structs.
I have included a python script reproducer below [3], which is just a highly simplified version of my analysis script, and you will find that it will work with version 6.24.06
but crashes and gives a segfault with 6.26.08
on lxplus7
. Oddly enough, if I were to remove two out of the three RVec<int>
in the PVEvent
struct, the script runs fine.
Kind regards,
Fikri
[1] /cvmfs/sft.cern.ch/lcg/views/LCG_101/x86_64-centos7-gcc10-opt/setup.sh
[2] /cvmfs/sft.cern.ch/lcg/views/LCG_102a/x86_64-centos7-gcc11-opt/setup.sh
[3]
import ROOT
#########################
#
# Make a test tree
#
#########################
fill_tree_code = '''
using namespace ROOT::VecOps;
using namespace ROOT::Math;
void fill_tree(const char *filename, const char *treeName){
TRandom3 R(1);
auto PVchannel = [&](){
RVec<int> channel;
const auto nPV = R.Integer(5);
channel.reserve(nPV);
for (int j = 0; j < nPV; ++j) {
channel.emplace_back(R.Integer(4));
}
return channel;
};
ROOT::RDataFrame df(200);
df.Define("PV_channel", PVchannel).Snapshot<RVec<int>>(treeName, filename, {"PV_channel"});
}
'''
ROOT.gInterpreter.Declare(fill_tree_code)
fileName = "ntuple.root"
treeName = "anaTree"
ROOT.fill_tree(fileName, treeName)
#########################
#
# Read the ttree
#
#########################
df = ROOT.RDataFrame(treeName, fileName)
#########################
#
# Construct the vector of struct
#
#########################
pvevent_code = '''
using namespace ROOT::VecOps;
struct PVEvent {
int channel;
RVec<int> idxA1;
RVec<int> idxA2;
RVec<int> idxA3;
PVEvent() : channel{0} {}
};
RVec<PVEvent> ConstructPVEvents(const RVec<int>& PV_channel){
RVec<PVEvent> rvec_pvEvent;
for (unsigned int i = 0; i < PV_channel.size(); i++){
PVEvent pvEvent;
pvEvent.channel = PV_channel[i];
rvec_pvEvent.emplace_back(pvEvent);
}
return rvec_pvEvent;
}
'''
ROOT.gInterpreter.Declare(pvevent_code)
df = df.Define("PVEventVec", "ConstructPVEvents(PV_channel)")
df = df.Define("PVEvent_chan", "return Map(PVEventVec, [](const PVEvent& v){return v.channel;});")
df = df.Define("PVEventChan1Vec", "PVEventVec[PVEvent_chan==1]")
df = df.Define("nPVEventChan1Vec", "PVEventChan1Vec.size()")
histoChan1 = df.Histo1D(ROOT.RDF.TH1DModel("histoChan1","", 8,0,8), "nPVEventChan1Vec")
outHistoFile = ROOT.TFile("Histo.root","RECREATE")
histoChan1.Write()
outHistoFile.Close()