Pure virtual method called on hadding TFiles with TFriendElements

Dear experts

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

To prove TFriendElements exist in both files:

Bkg_diboson_mc16a.root
#Tree.GetName()
Tree: diboson_JET_Rtrk_Baseline_frozen_mass__1down 
# TFriends.Print()
Name: diboson_JET_Rtrk_Baseline_frozen_mass__1down Title: /atlas/shatlas/NTUP_SUSY/StrongMultiB/JMS_Production/Bkg_diboson_mc16a_21.2.87-1_output_histfitter_LHEweighted.root
Name: diboson_JET_Rtrk_Baseline_frozen_mass__1down Title: /atlas/shatlas/NTUP_SUSY/StrongMultiB/JMS_Production_NN_files/weights//Bkg_diboson_mc16a_21.2.87-1_output_histfitter_LHEweighted.weight_NN.root

and for the other file in the merge:

Tree: diboson_nominal
Name: diboson_nominal Title: /atlas/shatlas/NTUP_SUSY/StrongMultiB/SkimmedNTuples_M200_3j_2b//Bkg_diboson_mc16a_21.2.87-1_output_histfitter.root
Name: diboson_nominal Title: /atlas/shatlas/NTUP_SUSY/StrongMultiB/NN_files/weight_NN//Bkg_diboson_mc16a_21.2.87-1_output_histfitter.root.weight_NN.root

Reading both sets of TFiles seems fine independently, and they otherwise close ok, but I’m not sure what object is effectively a null type.

Does anyone know how to rectify this at all?
Thanks

Matt A.

Can you provide access to the 2 files so that we can reproduce the problem? Thanks.

Hi PCanal

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:

https://cernbox.cern.ch/index.php/s/ee76WevUpMJHOH8
(since I can’t attach directly the tar as it is too large)
the two files consist of two trees structured like so:

root [2] diboson_nominal->Print()
******************************************************************************
*Tree    :diboson_nominal: diboson_nominal                                        *
*Entries :      536 : Total =          178437 bytes  File  Size =     164821 *
*        :          : Tree compression factor =   1.05                       *
******************************************************************************
*Br    0 :NNoutput_0_1500_1400 : NNoutput_0_1500_1400[8]/F                   *
*Entries :      536 : Total  Size=      17801 bytes  File Size  =      16371 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   1.05     *
*............................................................................*
*Br    1 :NNoutput_0_2000_1800 : NNoutput_0_2000_1800[8]/F                   *
*Entries :      536 : Total  Size=      17801 bytes  File Size  =      16377 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   1.05     *
*............................................................................*
*Br    2 :NNoutput_0_2100_1600 : NNoutput_0_2100_1600[8]/F                   *
*Entries :      536 : Total  Size=      17801 bytes  File Size  =      16367 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   1.05     *
*............................................................................*
*Br    3 :NNoutput_0_2300_1000 : NNoutput_0_2300_1000[8]/F                   *
*Entries :      536 : Total  Size=      17801 bytes  File Size  =      16417 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   1.05     *
*............................................................................*
*Br    4 :NNoutput_0_2800_1400 : NNoutput_0_2800_1400[8]/F                   *
*Entries :      536 : Total  Size=      17801 bytes  File Size  =      16423 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   1.05     *
*............................................................................*
*Br    5 :NNoutput_1_1800_1 : NNoutput_1_1800_1[8]/F                         *
*Entries :      536 : Total  Size=      17786 bytes  File Size  =      16394 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   1.05     *
*............................................................................*
*Br    6 :NNoutput_1_1900_1400 : NNoutput_1_1900_1400[8]/F                   *
*Entries :      536 : Total  Size=      17801 bytes  File Size  =      16356 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   1.05     *
*............................................................................*
*Br    7 :NNoutput_1_2000_1600 : NNoutput_1_2000_1600[8]/F                   *
*Entries :      536 : Total  Size=      17801 bytes  File Size  =      16373 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   1.05     *
*............................................................................*
*Br    8 :NNoutput_1_2100_1 : NNoutput_1_2100_1[8]/F                         *
*Entries :      536 : Total  Size=      17786 bytes  File Size  =      16406 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   1.05     *
*............................................................................*

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)

Thanks
Matt A.

Hi

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()

Hi

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?

Thanks

Matt A.

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).

See https://github.com/root-project/root/issues/9017 and the final solution https://github.com/root-project/root/pull/9021

The problem is now resolved in v6.22, v6.24 and master branches.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.