When I attempt to merge two TFiles using hadd, I find that I get a “Pure virtual method called” error.
I suspect it relates to TFriendElements associated to TTrees that I am hadding together, but cannot see why this would be the case:
[anthony@hep4 SuperMerge]$ hadd -v -f Bkg_diboson_mc16a.root ../Bkg_diboson_mc16a.root /atlas/shatlas/NTUP_SUSY/StrongMultiB/NN_files/NNoutput/Bkg_diboson_mc16a_21.2.87-1_output_histfitter.root.1.NNoutput.root
hadd Target file: Bkg_diboson_mc16a.root
hadd compression setting for all output: 1
hadd Source file 1: ../Bkg_diboson_mc16a.root
hadd Source file 2: /atlas/shatlas/NTUP_SUSY/StrongMultiB/NN_files/NNoutput/Bkg_diboson_mc16a_21.2.87-1_output_histfitter.root.1.NNoutput.root
hadd Target path: Bkg_diboson_mc16a.root:/
pure virtual method called
terminate called without an active exception
In ROOT version:
/cvmfs/sft.cern.ch/lcg/releases/LCG_97a/ROOT/v6.20.06/x86_64-centos7-gcc8-opt/bin/root
Since TFriendElement specifically is very sensitive to file system location (because the TFriendElement pointer points to an absolute file path), I have removed the TFriendElement (script attached), but the files still demonstrate the pure virtual error:
I can also produce a minimal working example involving TFriends as well, but the TFriends I assume will have to be defined locally w.r.t your local filesystem, given their explicit path dependence.
In principle, this hadd should work, since both TFriendElements are explicitly deleted (see removeFriends.py), the tree is cloned after the deletion and both output files were checked to have no TFriendElements associated to them (testroot_1.root, test_root_2.root), so in principle this should be a hadd of two TFiles with no reference to TFriends, but still produces a pure virtual error
[manthony@lxplus719 ROOTFORUM_46836]$ which root
/cvmfs/sft.cern.ch/lcg/releases/LCG_97a/ROOT/v6.20.06/x86_64-centos7-gcc8-opt/bin/root
[manthony@lxplus719 ROOTFORUM_46836]$ hadd output.root testroot_1,root testroot_2.root
hadd Target file: output.root
hadd compression setting for all output: 1
hadd Source file 1: testroot_1,root
hadd Source file 2: testroot_2.root
hadd Target path: output.root:/
pure virtual method called
terminate called without an active exception
Aborted (core dumped)
This might be related, but I’ve tried a script based instead of using TTree::CloneTree, I used the TTree.SetDirectory, which led to a correct set of output tree headers, but corrupt file content (although readable TFriends).
Is there a workaround to hadd/merge files which contain TFriends?
The structure of the files is such that first tree contains
X_nominal
X_blahh
and the second:
X_Y_foo (so different tree)
X_Y_bar
X_Y_baz
So, the expected end result is to merge them to look like:
X_nominal
X_blahh
X_Y_foo
X_Y_baz
etc.
Thanks
Matt A.
import ROOT
import sys
import os
inputfile_1=sys.argv[1]
inputfile_2=sys.argv[2]
outpath=sys.argv[3]
rtf_in_1=ROOT.TFile(inputfile_1,"READ")
rtf_in_2=ROOT.TFile(inputfile_2,"READ")
rtf_out=ROOT.TFile("{}".format(outpath),"RECREATE")
for key in rtf_in_1.GetListOfKeys():
if("nominal" in key.GetName()):
continue
print("LOOP START")
tree1=key.ReadObj()
print("READ OBJ")
tree1.SetDirectory(0)
print("DIR SET")
print("remove friends")
rtf_out.cd()
tree1.Write()
print("Written")
print("now doing file 2")
rtf_out.Close()
rtf_out=ROOT.TFile("{}".format(outpath),"UPDATE")
for key in rtf_in_2.GetListOfKeys():
tree2=key.ReadObj()
print("READ OBJ")
tree2.SetDirectory(0)
print("DIR SET")
print("remove friends")
rtf_out.cd()
tree2.Write()
print("Written")
rtf_out.Close()
rtf_in_1.Close()
rtf_in_2.Close()
rtf_out=ROOT.TFile("{}".format(outpath),"READ")
print("validation")
for key in rtf_out.GetListOfKeys():
tree=key.ReadObj()
print("tree {}".format(tree.GetName()))
if(len(list(tree.GetListOfFriends()))>0):
for friend in tree.GetListOfFriends():
print("Friend {}".format(friend.GetTitle()))
rtf_out.Close()
It appears that the given bug is related to ROOT 6.18/6.20 as running in an older version (6.10) does not produce this error and successfully hadds the files with TFriends, and both are readable in the output.
I presume there was some change between this to the TFriendElements or the TFile class relating to them between these releases?
The problem is still per se present in current version but it is greatly alleviated (i.e. you should no longer see it in your exact use case) in version v6.22/08 and v6/24.00 (and later).